diff --git a/Arepacoin-qt.pro b/Arepacoin-qt.pro new file mode 100644 index 0000000..4a3d72e --- /dev/null +++ b/Arepacoin-qt.pro @@ -0,0 +1,434 @@ +TEMPLATE = app +TARGET = Arepacoin-qt +VERSION = 1.0.1.8 +INCLUDEPATH += src src/json src/qt +DEFINES += QT_GUI BOOST_THREAD_USE_LIB BOOST_SPIRIT_THREADSAFE +CONFIG += no_include_pwd +CONFIG += thread + +greaterThan(QT_MAJOR_VERSION, 4) { + QT += widgets + DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0 +} + +QMAKE_LFLAGS += -no-pie + +# for boost 1.37, add -mt to the boost libraries +# use: qmake BOOST_LIB_SUFFIX=-mt +# for boost thread win32 with _win32 sufix +# use: BOOST_THREAD_LIB_SUFFIX=_win32-... +# or when linking against a specific BerkelyDB version: BDB_LIB_SUFFIX=-4.8 + +# Dependency library locations can be customized with: +# BOOST_INCLUDE_PATH, BOOST_LIB_PATH, BDB_INCLUDE_PATH, +# BDB_LIB_PATH, OPENSSL_INCLUDE_PATH and OPENSSL_LIB_PATH respectively + +OBJECTS_DIR = build +MOC_DIR = build +UI_DIR = build + +# use: qmake "RELEASE=1" +contains(RELEASE, 1) { + # Mac: compile for maximum compatibility (10.13, 64-bit) + macx:QMAKE_CXXFLAGS += -mmacosx-version-min=10.13 -arch x86_64 -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.14.sdk + + !windows:!macx { + # Linux: static link + LIBS += -Wl,-Bstatic + } +} + +!win32 { +# for extra security against potential buffer overflows: enable GCCs Stack Smashing Protection +QMAKE_CXXFLAGS *= -fstack-protector-all --param ssp-buffer-size=1 +QMAKE_LFLAGS *= -fstack-protector-all --param ssp-buffer-size=1 +# We need to exclude this for Windows cross compile with MinGW 4.2.x, as it will result in a non-working executable! +# This can be enabled for Windows, when we switch to MinGW >= 4.4.x. +} +# for extra security on Windows: enable ASLR and DEP via GCC linker flags +win32:QMAKE_LFLAGS *= -Wl,--dynamicbase -Wl,--nxcompat +win32:QMAKE_LFLAGS += -static -static-libgcc -static-libstdc++ -lpthread + +# use: qmake "USE_QRCODE=1" +# libqrencode (http://fukuchi.org/works/qrencode/index.en.html) must be installed for support +contains(USE_QRCODE, 1) { + message(Building with QRCode support) + DEFINES += USE_QRCODE + LIBS += -lqrencode +} + +# use: qmake "USE_UPNP=1" ( enabled by default; default) +# or: qmake "USE_UPNP=0" (disabled by default) +# or: qmake "USE_UPNP=-" (not supported) +# miniupnpc (http://miniupnp.free.fr/files/) must be installed for support +contains(USE_UPNP, -) { + message(Building without UPNP support) +} else { + message(Building with UPNP support) + count(USE_UPNP, 0) { + USE_UPNP=1 + } + DEFINES += USE_UPNP=$$USE_UPNP STATICLIB + INCLUDEPATH += $$MINIUPNPC_INCLUDE_PATH + LIBS += $$join(MINIUPNPC_LIB_PATH,,-L,) -lminiupnpc + win32:LIBS += -liphlpapi +} + +# use: qmake "USE_DBUS=1" or qmake "USE_DBUS=0" +linux:count(USE_DBUS, 0) { + USE_DBUS=1 +} +contains(USE_DBUS, 1) { + message(Building with DBUS (Freedesktop notifications) support) + DEFINES += USE_DBUS + QT += dbus +} + +contains(BITCOIN_NEED_QT_PLUGINS, 1) { + DEFINES += BITCOIN_NEED_QT_PLUGINS + QTPLUGIN += qcncodecs qjpcodecs qtwcodecs qkrcodecs qtaccessiblewidgets +} + +INCLUDEPATH += src/leveldb/include src/leveldb/helpers +LIBS += $$PWD/src/leveldb/libleveldb.a $$PWD/src/leveldb/libmemenv.a +SOURCES += src/txdb-leveldb.cpp +!win32 { + # we use QMAKE_CXXFLAGS_RELEASE even without RELEASE=1 because we use RELEASE to indicate linking preferences not -O preferences + genleveldb.commands = cd $$PWD/src/leveldb && CC=$$QMAKE_CC CXX=$$QMAKE_CXX $(MAKE) OPT=\"$$QMAKE_CXXFLAGS $$QMAKE_CXXFLAGS_RELEASE\" libleveldb.a libmemenv.a +} else { + # make an educated guess about what the ranlib command is called + isEmpty(QMAKE_RANLIB) { + QMAKE_RANLIB = $$replace(QMAKE_STRIP, strip, ranlib) + } + LIBS += -lshlwapi + genleveldb.commands = cd $$PWD/src/leveldb && CC=$$QMAKE_CC CXX=$$QMAKE_CXX TARGET_OS=OS_WINDOWS_CROSSCOMPILE $(MAKE) OPT=\"$$QMAKE_CXXFLAGS $$QMAKE_CXXFLAGS_RELEASE\" libleveldb.a libmemenv.a && $$QMAKE_RANLIB $$PWD/src/leveldb/libleveldb.a && $$QMAKE_RANLIB $$PWD/src/leveldb/libmemenv.a +} +genleveldb.target = $$PWD/src/leveldb/libleveldb.a +genleveldb.depends = FORCE +PRE_TARGETDEPS += $$PWD/src/leveldb/libleveldb.a +QMAKE_EXTRA_TARGETS += genleveldb +# Gross ugly hack that depends on qmake internals, unfortunately there is no other way to do it. +QMAKE_CLEAN += $$PWD/src/leveldb/libleveldb.a; cd $$PWD/src/leveldb ; $(MAKE) clean + +# regenerate src/build.h +!windows|contains(USE_BUILD_INFO, 1) { + genbuild.depends = FORCE + genbuild.commands = cd $$PWD; /bin/sh share/genbuild.sh $$OUT_PWD/build/build.h + genbuild.target = $$OUT_PWD/build/build.h + PRE_TARGETDEPS += $$OUT_PWD/build/build.h + QMAKE_EXTRA_TARGETS += genbuild + DEFINES += HAVE_BUILD_INFO +} + +contains(USE_O3, 1) { + message(Building O3 optimization flag) + QMAKE_CXXFLAGS_RELEASE -= -O2 + QMAKE_CFLAGS_RELEASE -= -O2 + QMAKE_CXXFLAGS += -O3 + QMAKE_CFLAGS += -O3 +} + +*-g++-32 { + message("32 platform, adding -msse2 flag") + + QMAKE_CXXFLAGS += -msse2 + QMAKE_CFLAGS += -msse2 +} + +QMAKE_CXXFLAGS_WARN_ON = -fdiagnostics-show-option -Wall -Wextra -Wno-ignored-qualifiers -Wformat -Wformat-security -Wno-unused-parameter -Wstack-protector -Wno-reorder + +# Input +DEPENDPATH += src src/json src/qt +HEADERS += src/qt/bitcoingui.h \ + src/qt/transactiontablemodel.h \ + src/qt/addresstablemodel.h \ + src/qt/optionsdialog.h \ + src/qt/coincontroldialog.h \ + src/qt/coincontroltreewidget.h \ + src/qt/sendcoinsdialog.h \ + src/qt/addressbookpage.h \ + src/qt/signverifymessagedialog.h \ + src/qt/aboutdialog.h \ + src/qt/editaddressdialog.h \ + src/qt/bitcoinaddressvalidator.h \ + src/alert.h \ + src/addrman.h \ + src/base58.h \ + src/bignum.h \ + src/checkpoints.h \ + src/compat.h \ + src/coincontrol.h \ + src/sync.h \ + src/util.h \ + src/uint256.h \ + src/kernel.h \ + src/scrypt.h \ + src/pbkdf2.h \ + src/zerocoin/Accumulator.h \ + src/zerocoin/AccumulatorProofOfKnowledge.h \ + src/zerocoin/Coin.h \ + src/zerocoin/CoinSpend.h \ + src/zerocoin/Commitment.h \ + src/zerocoin/ParamGeneration.h \ + src/zerocoin/Params.h \ + src/zerocoin/SerialNumberSignatureOfKnowledge.h \ + src/zerocoin/SpendMetaData.h \ + src/zerocoin/ZeroTest.h \ + src/zerocoin/Zerocoin.h \ + src/serialize.h \ + src/strlcpy.h \ + src/main.h \ + src/miner.h \ + src/net.h \ + src/key.h \ + src/db.h \ + src/txdb.h \ + src/walletdb.h \ + src/script.h \ + src/init.h \ + src/mruset.h \ + src/json/json_spirit_writer_template.h \ + src/json/json_spirit_writer.h \ + src/json/json_spirit_value.h \ + src/json/json_spirit_utils.h \ + src/json/json_spirit_stream_reader.h \ + src/json/json_spirit_reader_template.h \ + src/json/json_spirit_reader.h \ + src/json/json_spirit_error_position.h \ + src/json/json_spirit.h \ + src/qt/clientmodel.h \ + src/qt/guiutil.h \ + src/qt/transactionrecord.h \ + src/qt/guiconstants.h \ + src/qt/optionsmodel.h \ + src/qt/monitoreddatamapper.h \ + src/qt/trafficgraphwidget.h \ + src/qt/transactiondesc.h \ + src/qt/transactiondescdialog.h \ + src/qt/bitcoinamountfield.h \ + src/wallet.h \ + src/keystore.h \ + src/qt/transactionfilterproxy.h \ + src/qt/transactionview.h \ + src/qt/walletmodel.h \ + src/bitcoinrpc.h \ + src/qt/overviewpage.h \ + src/qt/csvmodelwriter.h \ + src/crypter.h \ + src/qt/sendcoinsentry.h \ + src/qt/qvalidatedlineedit.h \ + src/qt/bitcoinunits.h \ + src/qt/qvaluecombobox.h \ + src/qt/askpassphrasedialog.h \ + src/protocol.h \ + src/qt/notificator.h \ + src/qt/qtipcserver.h \ + src/allocators.h \ + src/ui_interface.h \ + src/qt/rpcconsole.h \ + src/version.h \ + src/netbase.h \ + src/clientversion.h \ + src/threadsafety.h + +SOURCES += src/qt/bitcoin.cpp src/qt/bitcoingui.cpp \ + src/qt/transactiontablemodel.cpp \ + src/qt/addresstablemodel.cpp \ + src/qt/optionsdialog.cpp \ + src/qt/sendcoinsdialog.cpp \ + src/qt/coincontroldialog.cpp \ + src/qt/coincontroltreewidget.cpp \ + src/qt/addressbookpage.cpp \ + src/qt/signverifymessagedialog.cpp \ + src/qt/aboutdialog.cpp \ + src/qt/editaddressdialog.cpp \ + src/qt/bitcoinaddressvalidator.cpp \ + src/alert.cpp \ + src/version.cpp \ + src/sync.cpp \ + src/util.cpp \ + src/netbase.cpp \ + src/key.cpp \ + src/script.cpp \ + src/main.cpp \ + src/miner.cpp \ + src/init.cpp \ + src/net.cpp \ + src/checkpoints.cpp \ + src/addrman.cpp \ + src/db.cpp \ + src/walletdb.cpp \ + src/qt/clientmodel.cpp \ + src/qt/guiutil.cpp \ + src/qt/transactionrecord.cpp \ + src/qt/optionsmodel.cpp \ + src/qt/monitoreddatamapper.cpp \ + src/qt/trafficgraphwidget.cpp \ + src/qt/transactiondesc.cpp \ + src/qt/transactiondescdialog.cpp \ + src/qt/bitcoinstrings.cpp \ + src/qt/bitcoinamountfield.cpp \ + src/wallet.cpp \ + src/keystore.cpp \ + src/qt/transactionfilterproxy.cpp \ + src/qt/transactionview.cpp \ + src/qt/walletmodel.cpp \ + src/bitcoinrpc.cpp \ + src/rpcdump.cpp \ + src/rpcnet.cpp \ + src/rpcmining.cpp \ + src/rpcwallet.cpp \ + src/rpcblockchain.cpp \ + src/rpcrawtransaction.cpp \ + src/qt/overviewpage.cpp \ + src/qt/csvmodelwriter.cpp \ + src/crypter.cpp \ + src/qt/sendcoinsentry.cpp \ + src/qt/qvalidatedlineedit.cpp \ + src/qt/bitcoinunits.cpp \ + src/qt/qvaluecombobox.cpp \ + src/qt/askpassphrasedialog.cpp \ + src/protocol.cpp \ + src/qt/notificator.cpp \ + src/qt/qtipcserver.cpp \ + src/qt/rpcconsole.cpp \ + src/noui.cpp \ + src/kernel.cpp \ + src/scrypt-arm.S \ + src/scrypt-x86.S \ + src/scrypt-x86_64.S \ + src/scrypt.cpp \ + src/pbkdf2.cpp \ + src/zerocoin/Accumulator.cpp \ + src/zerocoin/AccumulatorProofOfKnowledge.cpp \ + src/zerocoin/Coin.cpp \ + src/zerocoin/CoinSpend.cpp \ + src/zerocoin/Commitment.cpp \ + src/zerocoin/ParamGeneration.cpp \ + src/zerocoin/Params.cpp \ + src/zerocoin/SerialNumberSignatureOfKnowledge.cpp \ + src/zerocoin/SpendMetaData.cpp \ + src/zerocoin/ZeroTest.cpp + +RESOURCES += \ + src/qt/bitcoin.qrc + +FORMS += \ + src/qt/forms/coincontroldialog.ui \ + src/qt/forms/sendcoinsdialog.ui \ + src/qt/forms/addressbookpage.ui \ + src/qt/forms/signverifymessagedialog.ui \ + src/qt/forms/aboutdialog.ui \ + src/qt/forms/editaddressdialog.ui \ + src/qt/forms/transactiondescdialog.ui \ + src/qt/forms/overviewpage.ui \ + src/qt/forms/sendcoinsentry.ui \ + src/qt/forms/askpassphrasedialog.ui \ + src/qt/forms/rpcconsole.ui \ + src/qt/forms/optionsdialog.ui + +contains(USE_QRCODE, 1) { +HEADERS += src/qt/qrcodedialog.h +SOURCES += src/qt/qrcodedialog.cpp +FORMS += src/qt/forms/qrcodedialog.ui +} + +CODECFORTR = UTF-8 + +# for lrelease/lupdate +# also add new translations to src/qt/bitcoin.qrc under translations/ +TRANSLATIONS = $$files(src/qt/locale/bitcoin_*.ts) + +isEmpty(QMAKE_LRELEASE) { + win32:QMAKE_LRELEASE = $$[QT_INSTALL_BINS]\\lrelease.exe + else:QMAKE_LRELEASE = $$[QT_INSTALL_BINS]/lrelease +} +isEmpty(QM_DIR):QM_DIR = $$PWD/src/qt/locale +# automatically build translations, so they can be included in resource file +TSQM.name = lrelease ${QMAKE_FILE_IN} +TSQM.input = TRANSLATIONS +TSQM.output = $$QM_DIR/${QMAKE_FILE_BASE}.qm +TSQM.commands = $$QMAKE_LRELEASE ${QMAKE_FILE_IN} -qm ${QMAKE_FILE_OUT} +TSQM.CONFIG = no_link +QMAKE_EXTRA_COMPILERS += TSQM + +# "Other files" to show in Qt Creator +OTHER_FILES += \ + doc/*.rst doc/*.txt doc/README README.md res/bitcoin-qt.rc + +# platform specific defaults, if not overridden on command line +isEmpty(BOOST_LIB_SUFFIX) { + macx:BOOST_LIB_SUFFIX = -mt + windows:BOOST_LIB_SUFFIX = -mgw44-mt-s-1_57 +} + +isEmpty(BOOST_THREAD_LIB_SUFFIX) { + BOOST_THREAD_LIB_SUFFIX = $$BOOST_LIB_SUFFIX +} + +isEmpty(BDB_LIB_PATH) { + macx:BDB_LIB_PATH = /opt/local/lib/db48 +} + +isEmpty(BDB_LIB_SUFFIX) { + macx:BDB_LIB_SUFFIX = -4.8 +} + +isEmpty(BDB_INCLUDE_PATH) { + macx:BDB_INCLUDE_PATH = /opt/local/include/db48 +} + +isEmpty(BOOST_LIB_PATH) { + macx:BOOST_LIB_PATH = /opt/local/lib +} + +isEmpty(BOOST_INCLUDE_PATH) { + macx:BOOST_INCLUDE_PATH = /opt/local/include +} + +windows:DEFINES += WIN32 +windows:RC_FILE = src/qt/res/bitcoin-qt.rc + +windows:!contains(MINGW_THREAD_BUGFIX, 0) { + # At least qmake's win32-g++-cross profile is missing the -lmingwthrd + # thread-safety flag. GCC has -mthreads to enable this, but it doesn't + # work with static linking. -lmingwthrd must come BEFORE -lmingw, so + # it is prepended to QMAKE_LIBS_QT_ENTRY. + # It can be turned off with MINGW_THREAD_BUGFIX=0, just in case it causes + # any problems on some untested qmake profile now or in the future. + DEFINES += _MT BOOST_THREAD_PROVIDES_GENERIC_SHARED_MUTEX_ON_WIN + QMAKE_LIBS_QT_ENTRY = -lmingwthrd $$QMAKE_LIBS_QT_ENTRY +} + +macx:HEADERS += src/qt/macdockiconhandler.h src/qt/macnotificationhandler.h +macx:OBJECTIVE_SOURCES += src/qt/macdockiconhandler.mm src/qt/macnotificationhandler.mm +macx:LIBS += -framework Foundation -framework ApplicationServices -framework AppKit +macx:DEFINES += MAC_OSX MSG_NOSIGNAL=0 +macx:ICON = src/qt/res/icons/arepa.icns +macx:TARGET = "arepacoin-Qt" +macx:QMAKE_CFLAGS_THREAD += -pthread +macx:QMAKE_LFLAGS_THREAD += -pthread +macx:QMAKE_CXXFLAGS_THREAD += -pthread + +# Set libraries and includes at end, to use platform-defined defaults if not overridden +INCLUDEPATH += $$BOOST_INCLUDE_PATH $$BDB_INCLUDE_PATH $$OPENSSL_INCLUDE_PATH $$QRENCODE_INCLUDE_PATH +LIBS += $$join(BOOST_LIB_PATH,,-L,) $$join(BDB_LIB_PATH,,-L,) $$join(OPENSSL_LIB_PATH,,-L,) $$join(QRENCODE_LIB_PATH,,-L,) +LIBS += -lssl -lcrypto -ldb_cxx$$BDB_LIB_SUFFIX +# -lgdi32 has to happen after -lcrypto (see #681) +windows:LIBS += -lws2_32 -lshlwapi -lmswsock -lole32 -loleaut32 -luuid -lgdi32 +LIBS += -lboost_system$$BOOST_LIB_SUFFIX -lboost_filesystem$$BOOST_LIB_SUFFIX -lboost_program_options$$BOOST_LIB_SUFFIX -lboost_thread$$BOOST_THREAD_LIB_SUFFIX +windows:LIBS += -lboost_chrono$$BOOST_LIB_SUFFIX + +contains(RELEASE, 1) { + !windows:!macx { + # Linux: turn dynamic linking back on for c/c++ runtime libraries + LIBS += -Wl,-Bdynamic + } +} + +!windows:!macx { + DEFINES += LINUX + LIBS += -lrt -ldl +} + +system($$QMAKE_LRELEASE -silent $$_PRO_FILE_) diff --git a/COPYING b/COPYING new file mode 100644 index 0000000..c376cbd --- /dev/null +++ b/COPYING @@ -0,0 +1,22 @@ +Copyright (c) 2014 arepacoin Developers +Copyright (c) 2013-2014 NovaCoin Developers +Copyright (c) 2011-2012 PPCoin Developers +Copyright (c) 2009-2014 Bitcoin Developers + +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. diff --git a/Compile.sh b/Compile.sh new file mode 100755 index 0000000..bca54be --- /dev/null +++ b/Compile.sh @@ -0,0 +1,108 @@ +#!/bin/bash +# Script for compile Daemon and WalletQt for ArepaCoin + +installAptLibs16Qt() { + sudo apt-get -y update + sudo apt-get -y install \ + qt5-default qt5-qmake qtbase5-dev-tools qttools5-dev-tools software-properties-common build-essential \ + libssl-dev libdb++-dev libboost-all-dev libqrencode-dev qrencode libminiupnpc-dev automake autoconf \ + git pkg-config libcurl4-openssl-dev libjansson-dev libgmp-dev make g++ gcc +} + +installAptLibs18Qt() { + sudo apt-get -y update + sudo apt-get -y install \ + qt5-default qt5-qmake qtbase5-dev-tools qttools5-dev-tools software-properties-common build-essential \ + libssl1.0-dev libdb++-dev libboost-all-dev libqrencode-dev qrencode libminiupnpc-dev automake autoconf \ + git pkg-config libcurl-openssl1.0-dev libjansson-dev libgmp-dev make g++ gcc +} + +installLibsQt() { + echo "Installing prerequisites" + . /etc/os-release + case "$ID-$VERSION_ID" in + ubuntu-16.04 ) installAptLibs16 ;; + ubuntu-18.04 ) installAptLibs18 ;; + * ) echo "ERROR: only Ubuntu 16.04 or 18.04 are supported now."; exit 1;; + esac +} + +installAptLibs16() { + sudo apt-get -y update + sudo apt-get -y install \ + software-properties-common build-essential \ + libssl-dev libdb++-dev libboost-all-dev libminiupnpc-dev automake autoconf \ + git pkg-config libcurl4-openssl-dev libjansson-dev libgmp-dev make g++ gcc +} + +installAptLibs18() { + sudo apt-get -y update + sudo apt-get -y install \ + software-properties-common build-essential \ + libssl1.0-dev libdb++-dev libboost-all-dev libminiupnpc-dev automake autoconf \ + git pkg-config libcurl-openssl1.0-dev libjansson-dev libgmp-dev make g++ gcc +} + +installLibs() { + echo "Installing prerequisites" + . /etc/os-release + case "$ID-$VERSION_ID" in + ubuntu-16.04 ) installAptLibs16 ;; + ubuntu-18.04 ) installAptLibs18 ;; + * ) echo "ERROR: only Ubuntu 16.04 or 18.04 are supported now."; exit 1;; + esac +} + +installBerkeleyDB() { + echo "Installing Berkeley DB" + sudo env LC_ALL=C.UTF-8 add-apt-repository -y ppa:bitcoin/bitcoin + sudo apt-get -y update + sudo apt-get -y install libdb4.8-dev libdb4.8++-dev +} + +compileDaemonWallet() { + echo "Compile Arepa Daemon Wallet" + cd src + make -j$(nproc) -f makefile.unix + strip arepacoind +} + +compileQtWallet() { + echo "Compile Arepa Qt Wallet" + qmake "USE_QRCODE=1" + make -j$(nproc) +} + +PS3='Please enter your choice: ' +options=("Compile Qt Wallet" "Compile Daemon Wallet" "Compile Qt and Daemon Wallet") +select opt in "${options[@]}" +do + case $opt in + "Compile Qt Wallet") + echo "Compile Qt Wallet" + installLibsQt + installBerkeleyDB + compileQtWallet + echo "Complete!" + break + ;; + "Compile Daemon Wallet") + echo "Compile Daemon Wallet" + installLibs + installBerkeleyDB + compileDaemonWallet + echo "Complete!" + break + ;; + "Compile Qt and Daemon Wallet") + echo "Compile Qt and Daemon Wallet" + installLibsQt + installBerkeleyDB + compileQtWallet + compileDaemonWallet + echo "Complete!" + break + ;; + *) echo "invalid option $REPLY";; + esac +done \ No newline at end of file diff --git a/INSTALL b/INSTALL new file mode 100644 index 0000000..469d694 --- /dev/null +++ b/INSTALL @@ -0,0 +1,9 @@ +Building arepacoin + +See doc/readme-qt.rst for instructions on building arepacoin QT, +the intended-for-end-users, nice-graphical-interface, reference +implementation of arepacoin. + +See doc/build-*.txt for instructions on building arepacoind, +the intended-for-services, no-graphical-interface, reference +implementation of arepacoin. diff --git a/README.md b/README.md new file mode 100644 index 0000000..6e9e515 --- /dev/null +++ b/README.md @@ -0,0 +1,38 @@ +# Arepacoin + +![logo](https://chainz.cryptoid.info/logo/arepa.png) + +Arepacoin nace el 25 de septiembre del 2016 con el fin de convertirse en una moneda referente de Venezuela en el mundo, con una emisión total de 60.000.000 de Arepas y un PoS del 3% de interés anual. Esta desarrollada con el algoritmo Scrypt PoW-PoS, que le permite ser una moneda robusta con un crecimiento de forma orgánica y con gran solidez. Puerto RPC: 8586 y Puerto P2P: 8585. + +Los bloques minables mediante PoW tienen una recompensa generada de la siguiente manera: +========================= +* Bloques 1 hasta 10000 tiene una recompensa de 325 Arepas. +* Bloques 10001 hasta 250000 tienen una recompensa de 50 Arepas. +* Bloques 250001 hasta 500000 tendran una recompensa de 25 Arepas. +* Bloques 500001 hasta 700000 tendran una recompensa de 12 Arepas. +* Bloques 700001 hasta 1000000 tendran una recompensa de 6 Arepas. +* Bloques 1000001 hasta 2000000 tendran una recompensa de 3 Arepas. +* Bloques 2000001 en adelante tendran una recompensa de 1 Arepa. + +LINKS +========================== +* Pagina Oficial (https://arepacoinve.info/) +* Foro Oficial (https://bitcointalk.org/index.php?topic=2931570) +* Twitter Arepacoin (https://twitter.com/arepacoinve) +* Grupo Telegram Arepacoin (https://t.me/ArepacoinVE_ES) + +Procedimiento para compilar la billeterá virtual en Ubuntu GNU/Linux: +========================== +Escribir en la terminal los siguientes comandos: + +```bash +sudo apt-get update +sudo apt-get upgrade +sudo apt-get install git +git clone https://github.com/ProjectArepa/Arepacoin +cd Arepacoin + +## Para Ubuntu 16.04 y 18.04. +./Compile.sh +./Arepacoin-qt +``` \ No newline at end of file diff --git a/contrib/bitrpc/bitrpc.py b/contrib/bitrpc/bitrpc.py new file mode 100644 index 0000000..b02b299 --- /dev/null +++ b/contrib/bitrpc/bitrpc.py @@ -0,0 +1,324 @@ +from jsonrpc import ServiceProxy +import sys +import string + +# ===== BEGIN USER SETTINGS ===== +# if you do not set these you will be prompted for a password for every command +rpcuser = "" +rpcpass = "" +# ====== END USER SETTINGS ====== + + +if rpcpass == "": + access = ServiceProxy("http://127.0.0.1:8332") +else: + access = ServiceProxy("http://"+rpcuser+":"+rpcpass+"@127.0.0.1:8332") +cmd = sys.argv[1].lower() + +if cmd == "backupwallet": + try: + path = raw_input("Enter destination path/filename: ") + print access.backupwallet(path) + except: + print "\n---An error occurred---\n" + +elif cmd == "getaccount": + try: + addr = raw_input("Enter a Bitcoin address: ") + print access.getaccount(addr) + except: + print "\n---An error occurred---\n" + +elif cmd == "getaccountaddress": + try: + acct = raw_input("Enter an account name: ") + print access.getaccountaddress(acct) + except: + print "\n---An error occurred---\n" + +elif cmd == "getaddressesbyaccount": + try: + acct = raw_input("Enter an account name: ") + print access.getaddressesbyaccount(acct) + except: + print "\n---An error occurred---\n" + +elif cmd == "getbalance": + try: + acct = raw_input("Enter an account (optional): ") + mc = raw_input("Minimum confirmations (optional): ") + try: + print access.getbalance(acct, mc) + except: + print access.getbalance() + except: + print "\n---An error occurred---\n" + +elif cmd == "getblockbycount": + try: + height = raw_input("Height: ") + print access.getblockbycount(height) + except: + print "\n---An error occurred---\n" + +elif cmd == "getblockcount": + try: + print access.getblockcount() + except: + print "\n---An error occurred---\n" + +elif cmd == "getblocknumber": + try: + print access.getblocknumber() + except: + print "\n---An error occurred---\n" + +elif cmd == "getconnectioncount": + try: + print access.getconnectioncount() + except: + print "\n---An error occurred---\n" + +elif cmd == "getdifficulty": + try: + print access.getdifficulty() + except: + print "\n---An error occurred---\n" + +elif cmd == "getgenerate": + try: + print access.getgenerate() + except: + print "\n---An error occurred---\n" + +elif cmd == "gethashespersec": + try: + print access.gethashespersec() + except: + print "\n---An error occurred---\n" + +elif cmd == "getinfo": + try: + print access.getinfo() + except: + print "\n---An error occurred---\n" + +elif cmd == "getnewaddress": + try: + acct = raw_input("Enter an account name: ") + try: + print access.getnewaddress(acct) + except: + print access.getnewaddress() + except: + print "\n---An error occurred---\n" + +elif cmd == "getreceivedbyaccount": + try: + acct = raw_input("Enter an account (optional): ") + mc = raw_input("Minimum confirmations (optional): ") + try: + print access.getreceivedbyaccount(acct, mc) + except: + print access.getreceivedbyaccount() + except: + print "\n---An error occurred---\n" + +elif cmd == "getreceivedbyaddress": + try: + addr = raw_input("Enter a Bitcoin address (optional): ") + mc = raw_input("Minimum confirmations (optional): ") + try: + print access.getreceivedbyaddress(addr, mc) + except: + print access.getreceivedbyaddress() + except: + print "\n---An error occurred---\n" + +elif cmd == "gettransaction": + try: + txid = raw_input("Enter a transaction ID: ") + print access.gettransaction(txid) + except: + print "\n---An error occurred---\n" + +elif cmd == "getwork": + try: + data = raw_input("Data (optional): ") + try: + print access.gettransaction(data) + except: + print access.gettransaction() + except: + print "\n---An error occurred---\n" + +elif cmd == "help": + try: + cmd = raw_input("Command (optional): ") + try: + print access.help(cmd) + except: + print access.help() + except: + print "\n---An error occurred---\n" + +elif cmd == "listaccounts": + try: + mc = raw_input("Minimum confirmations (optional): ") + try: + print access.listaccounts(mc) + except: + print access.listaccounts() + except: + print "\n---An error occurred---\n" + +elif cmd == "listreceivedbyaccount": + try: + mc = raw_input("Minimum confirmations (optional): ") + incemp = raw_input("Include empty? (true/false, optional): ") + try: + print access.listreceivedbyaccount(mc, incemp) + except: + print access.listreceivedbyaccount() + except: + print "\n---An error occurred---\n" + +elif cmd == "listreceivedbyaddress": + try: + mc = raw_input("Minimum confirmations (optional): ") + incemp = raw_input("Include empty? (true/false, optional): ") + try: + print access.listreceivedbyaddress(mc, incemp) + except: + print access.listreceivedbyaddress() + except: + print "\n---An error occurred---\n" + +elif cmd == "listtransactions": + try: + acct = raw_input("Account (optional): ") + count = raw_input("Number of transactions (optional): ") + frm = raw_input("Skip (optional):") + try: + print access.listtransactions(acct, count, frm) + except: + print access.listtransactions() + except: + print "\n---An error occurred---\n" + +elif cmd == "move": + try: + frm = raw_input("From: ") + to = raw_input("To: ") + amt = raw_input("Amount:") + mc = raw_input("Minimum confirmations (optional): ") + comment = raw_input("Comment (optional): ") + try: + print access.move(frm, to, amt, mc, comment) + except: + print access.move(frm, to, amt) + except: + print "\n---An error occurred---\n" + +elif cmd == "sendfrom": + try: + frm = raw_input("From: ") + to = raw_input("To: ") + amt = raw_input("Amount:") + mc = raw_input("Minimum confirmations (optional): ") + comment = raw_input("Comment (optional): ") + commentto = raw_input("Comment-to (optional): ") + try: + print access.sendfrom(frm, to, amt, mc, comment, commentto) + except: + print access.sendfrom(frm, to, amt) + except: + print "\n---An error occurred---\n" + +elif cmd == "sendmany": + try: + frm = raw_input("From: ") + to = raw_input("To (in format address1:amount1,address2:amount2,...): ") + mc = raw_input("Minimum confirmations (optional): ") + comment = raw_input("Comment (optional): ") + try: + print access.sendmany(frm,to,mc,comment) + except: + print access.sendmany(frm,to) + except: + print "\n---An error occurred---\n" + +elif cmd == "sendtoaddress": + try: + to = raw_input("To (in format address1:amount1,address2:amount2,...): ") + amt = raw_input("Amount:") + comment = raw_input("Comment (optional): ") + commentto = raw_input("Comment-to (optional): ") + try: + print access.sendtoaddress(to,amt,comment,commentto) + except: + print access.sendtoaddress(to,amt) + except: + print "\n---An error occurred---\n" + +elif cmd == "setaccount": + try: + addr = raw_input("Address: ") + acct = raw_input("Account:") + print access.setaccount(addr,acct) + except: + print "\n---An error occurred---\n" + +elif cmd == "setgenerate": + try: + gen= raw_input("Generate? (true/false): ") + cpus = raw_input("Max processors/cores (-1 for unlimited, optional):") + try: + print access.setgenerate(gen, cpus) + except: + print access.setgenerate(gen) + except: + print "\n---An error occurred---\n" + +elif cmd == "settxfee": + try: + amt = raw_input("Amount:") + print access.settxfee(amt) + except: + print "\n---An error occurred---\n" + +elif cmd == "stop": + try: + print access.stop() + except: + print "\n---An error occurred---\n" + +elif cmd == "validateaddress": + try: + addr = raw_input("Address: ") + print access.validateaddress(addr) + except: + print "\n---An error occurred---\n" + +elif cmd == "walletpassphrase": + try: + pwd = raw_input("Enter wallet passphrase: ") + access.walletpassphrase(pwd, 60) + print "\n---Wallet unlocked---\n" + except: + print "\n---An error occurred---\n" + +elif cmd == "walletpassphrasechange": + try: + pwd = raw_input("Enter old wallet passphrase: ") + pwd2 = raw_input("Enter new wallet passphrase: ") + access.walletpassphrasechange(pwd, pwd2) + print + print "\n---Passphrase changed---\n" + except: + print + print "\n---An error occurred---\n" + print + +else: + print "Command not found or not supported" \ No newline at end of file diff --git a/contrib/debian/arepacoin-qt.desktop b/contrib/debian/arepacoin-qt.desktop new file mode 100644 index 0000000..c04e0e3 --- /dev/null +++ b/contrib/debian/arepacoin-qt.desktop @@ -0,0 +1,11 @@ +[Desktop Entry] +Encoding=UTF-8 +Name=ArepaCoin +Comment=ArepaCoin P2P Cryptocurrency +Exec=/usr/bin/arepacoin-qt +Terminal=false +Type=Application +Icon=/usr/share/pixmaps/bitcoin80.xpm +MimeType=x-scheme-handler/arepacoin; +Categories=Office; +Name[es]=arepacoin-qt.desktop diff --git a/contrib/debian/arepacoin-qt.install b/contrib/debian/arepacoin-qt.install new file mode 100644 index 0000000..b5ac3ad --- /dev/null +++ b/contrib/debian/arepacoin-qt.install @@ -0,0 +1,5 @@ +arepacoin-qt usr/bin +share/pixmaps/bitcoin32.xpm usr/share/pixmaps +share/pixmaps/bitcoin80.xpm usr/share/pixmaps +debian/arepacoin-qt.desktop usr/share/applications +debian/arepacoin-qt.protocol usr/share/kde4/services/ diff --git a/contrib/debian/arepacoin-qt.lintian-overrides b/contrib/debian/arepacoin-qt.lintian-overrides new file mode 100644 index 0000000..3521f72 --- /dev/null +++ b/contrib/debian/arepacoin-qt.lintian-overrides @@ -0,0 +1,2 @@ +# Linked code is Expat - only Debian packaging is GPL-2+ +arepacoin-qt: possible-gpl-code-linked-with-openssl diff --git a/contrib/debian/arepacoin-qt.protocol b/contrib/debian/arepacoin-qt.protocol new file mode 100644 index 0000000..e9a6ac7 --- /dev/null +++ b/contrib/debian/arepacoin-qt.protocol @@ -0,0 +1,11 @@ +[Protocol] +exec=arepacoin-qt '%u' +protocol=arepacoin +input=none +output=none +helper=true +listing= +reading=false +writing=false +makedir=false +deleting=false diff --git a/contrib/debian/arepacoind.examples b/contrib/debian/arepacoind.examples new file mode 100644 index 0000000..161b0d0 --- /dev/null +++ b/contrib/debian/arepacoind.examples @@ -0,0 +1 @@ +debian/examples/arepacoin.conf diff --git a/contrib/debian/arepacoind.install b/contrib/debian/arepacoind.install new file mode 100644 index 0000000..dcef2da --- /dev/null +++ b/contrib/debian/arepacoind.install @@ -0,0 +1,2 @@ +debian/bin/arepacoind usr/bin +src/arepacoind usr/lib/arepacoin diff --git a/contrib/debian/arepacoind.lintian-overrides b/contrib/debian/arepacoind.lintian-overrides new file mode 100644 index 0000000..ac88ec8 --- /dev/null +++ b/contrib/debian/arepacoind.lintian-overrides @@ -0,0 +1,2 @@ +# Linked code is Expat - only Debian packaging is GPL-2+ +arepacoind: possible-gpl-code-linked-with-openssl diff --git a/contrib/debian/arepacoind.manpages b/contrib/debian/arepacoind.manpages new file mode 100644 index 0000000..1f14184 --- /dev/null +++ b/contrib/debian/arepacoind.manpages @@ -0,0 +1,2 @@ +debian/manpages/arepacoind.1 +debian/manpages/arepacoin.conf.5 diff --git a/contrib/debian/bin/arepacoin-qt b/contrib/debian/bin/arepacoin-qt new file mode 100644 index 0000000..39459b0 --- /dev/null +++ b/contrib/debian/bin/arepacoin-qt @@ -0,0 +1,16 @@ +#!/bin/sh + +set -e + +umask 077 + +basedir=~/.arepacoin +dbfile="$basedir/DB_CONFIG" +cfgfile="$basedir/arepacoin.conf" + +[ -e "$basedir" ] || mkdir "$basedir" + +# Novacoin does not clean up DB log files by default +[ -e "$dbfile" ] || echo 'set_flags DB_LOG_AUTOREMOVE' > "$dbfile" + +exec /usr/lib/arepacoin/arepacoin-qt "$@" diff --git a/contrib/debian/bin/arepacoind b/contrib/debian/bin/arepacoind new file mode 100644 index 0000000..7b3ab39 --- /dev/null +++ b/contrib/debian/bin/arepacoind @@ -0,0 +1,14 @@ +#!/bin/sh + +set -e + +umask 077 + +basedir=~/.arepacoin +cfgfile="$basedir/arepacoin.conf" + +[ -e "$basedir" ] || mkdir "$basedir" + +[ -e "$cfgfile" ] || perl -le 'print"rpcpassword=",map{(a..z,A..Z,0..9)[rand 62]}0..9' > "$cfgfile" + +exec /usr/lib/arepacoin/arepacoind "$@" diff --git a/contrib/debian/changelog b/contrib/debian/changelog new file mode 100644 index 0000000..22abed1 --- /dev/null +++ b/contrib/debian/changelog @@ -0,0 +1,6 @@ +arepacoin (0.4.0~dfsg-1) unstable; urgency=low + + [ Balthazar ] + * Initial release. + + -- Balthazar Mon, 15 Apr 2013 22:15:22 +0100 diff --git a/contrib/debian/compat b/contrib/debian/compat new file mode 100644 index 0000000..7f8f011 --- /dev/null +++ b/contrib/debian/compat @@ -0,0 +1 @@ +7 diff --git a/contrib/debian/control b/contrib/debian/control new file mode 100644 index 0000000..eeed8b4 --- /dev/null +++ b/contrib/debian/control @@ -0,0 +1,59 @@ +Source: arepacoin +Section: utils +Priority: optional +Maintainer: Jonas Smedegaard +Uploaders: Micah Anderson +Build-Depends: debhelper, + devscripts, + bash-completion, + libboost-system-dev (>> 1.35) | libboost-system1.35-dev, + libdb4.8++-dev, + libssl-dev, + pkg-config, + libminiupnpc8-dev, + libboost-filesystem-dev (>> 1.35) | libboost-filesystem1.35-dev, + libboost-program-options-dev (>> 1.35) | libboost-program-options1.35-dev, + libboost-thread-dev (>> 1.35) | libboost-thread1.35-dev, + libboost-test-dev (>> 1.35) | libboost-test1.35-dev, + qt4-qmake, + libqt4-dev, + libqrencode-dev +Standards-Version: 3.9.2 +Homepage: http://www.arepacoin.su/ +Vcs-Git: git://github.com/CryptoManiac/arepacoin.git +Vcs-Browser: http://github.com/CryptoManiac/arepacoin + +Package: arepacoind +Architecture: any +Depends: ${shlibs:Depends}, ${misc:Depends} +Description: peer-to-peer network based digital currency - daemon + Novacoin is a free open source peer-to-peer electronic cash system that + is completely decentralized, without the need for a central server or + trusted parties. Users hold the crypto keys to their own money and + transact directly with each other, with the help of a P2P network to + check for double-spending. + . + By default connects to an IRC network to discover other peers. + . + Full transaction history is stored locally at each client. This + requires 2+ GB of space, slowly growing. + . + This package provides arepacoind, a combined daemon and CLI tool to + interact with the daemon. + +Package: arepacoin-qt +Architecture: any +Depends: ${shlibs:Depends}, ${misc:Depends} +Description: peer-to-peer network based digital currency - Qt GUI + Novacoin is a free open source peer-to-peer electronic cash system that + is completely decentralized, without the need for a central server or + trusted parties. Users hold the crypto keys to their own money and + transact directly with each other, with the help of a P2P network to + check for double-spending. + . + By default connects to an IRC network to discover other peers. + . + Full transaction history is stored locally at each client. This + requires 2+ GB of space, slowly growing. + . + This package provides Novacoin-Qt, a GUI for Novacoin based on Qt. diff --git a/contrib/debian/copyright b/contrib/debian/copyright new file mode 100644 index 0000000..5b402d4 --- /dev/null +++ b/contrib/debian/copyright @@ -0,0 +1,166 @@ +Format: http://svn.debian.org/wsvn/dep/web/deps/dep5.mdwn?rev=174 +Upstream-Name: Bitcoin +Upstream-Contact: Satoshi Nakamoto + irc://#bitcoin@freenode.net +Source: http://sourceforge.net/projects/bitcoin/files/ + https://github.com/bitcoin/bitcoin + +Files: * +Copyright: 2009-2012, Bitcoin Developers +License: Expat +Comment: The Bitcoin Developers encompasses the current developers listed on bitcoin.org, + as well as the numerous contributors to the project. + +Files: src/json/* +Copyright: 2007-2009, John W. Wilkinson +License: Expat + +Files: src/strlcpy.h +Copyright: 1998, Todd C. Miller +License: ISC + +Files: debian/* +Copyright: 2010-2011, Jonas Smedegaard + 2011, Matt Corallo +License: GPL-2+ + +Files: debian/manpages/* +Copyright: Micah Anderson +License: GPL-3+ + +Files: src/qt/res/icons/clock*.png, src/qt/res/icons/tx*.png, + src/qt/res/src/*.svg +Copyright: Wladimir van der Laan +License: Expat + +Files: src/qt/res/icons/address-book.png, src/qt/res/icons/export.png, + src/qt/res/icons/history.png, src/qt/res/icons/key.png, + src/qt/res/icons/lock_*.png, src/qt/res/icons/overview.png, + src/qt/res/icons/receive.png, src/qt/res/icons/send.png, + src/qt/res/icons/synced.png, src/qt/res/icons/filesave.png +Copyright: David Vignoni (david@icon-king.com) + ICON KING - www.icon-king.com +License: LGPL +Comment: NUVOLA ICON THEME for KDE 3.x + Original icons: kaddressbook, klipper_dock, view-list-text, + key-password, encrypted/decrypted, go-home, go-down, + go-next, dialog-ok + Site: http://www.icon-king.com/projects/nuvola/ + +Files: src/qt/res/icons/connect*.png +Copyright: schollidesign +License: GPL-3+ +Comment: Icon Pack: Human-O2 + Site: http://findicons.com/icon/93743/blocks_gnome_netstatus_0 + +Files: src/qt/res/icons/transaction*.png +Copyright: md2k7 +License: Expat +Comment: Site: https://bitcointalk.org/index.php?topic=15276.0 + +Files: src/qt/res/icons/configure.png, src/qt/res/icons/quit.png, + src/qt/res/icons/editcopy.png, src/qt/res/icons/editpaste.png, + src/qt/res/icons/add.png, src/qt/res/icons/edit.png, + src/qt/res/icons/remove.png +Copyright: http://www.everaldo.com +License: LGPL +Comment: Icon Pack: Crystal SVG + +Files: src/qt/res/icons/bitcoin.png, src/qt/res/icons/toolbar.png +Copyright: Bitboy (optimized for 16x16 by Wladimir van der Laan) +License: PUB-DOM +Comment: Site: https://bitcointalk.org/?topic=1756.0 + +Files: scripts/img/reload.xcf, src/qt/res/movies/update_spinner.mng +Copyright: Everaldo (Everaldo Coelho) +License: GPL-3+ +Comment: Icon Pack: Kids + Site: http://findicons.com/icon/17102/reload?id=17102 + +Files: src/qt/res/images/splash2.png +License: PUB-DOM +Copyright: Crobbo (forum) +Comment: Site: https://bitcointalk.org/index.php?topic=32273.0 + + +License: Expat + 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. + +License: ISC + Permission to use, copy, modify, and distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + . + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR + BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES + OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, + WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, + ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + SOFTWARE. + +License: GPL-2+ + This program is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the + Free Software Foundation; either version 2, or (at your option) any + later version. + . + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. +Comment: + On Debian systems the GNU General Public License (GPL) version 2 is + located in '/usr/share/common-licenses/GPL-2'. + . + You should have received a copy of the GNU General Public License along + with this program. If not, see . + +License: GPL-3+ + Permission is granted to copy, distribute and/or modify this document + under the terms of the GNU General Public License, Version 3 or any + later version published by the Free Software Foundation. +Comment: + On Debian systems the GNU General Public License (GPL) version 3 is + located in '/usr/share/common-licenses/GPL-3'. + . + You should have received a copy of the GNU General Public License along + with this program. If not, see . + +License: LGPL + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + . + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. +Comment: + On Debian systems the GNU Lesser General Public License (LGPL) is + located in '/usr/share/common-licenses/LGPL'. + . + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +License: PUB-DOM + This work is in the public domain. diff --git a/contrib/debian/examples/arepacoin.conf b/contrib/debian/examples/arepacoin.conf new file mode 100644 index 0000000..310509e --- /dev/null +++ b/contrib/debian/examples/arepacoin.conf @@ -0,0 +1,81 @@ +# arepacoin.conf configuration file. Lines beginning with # are comments. + + +# Network-related settings: + +# Run on the test network instead of the real arepacoin network. +#testnet=1 + +# Connect via a socks4 proxy +#proxy=127.0.0.1:9050 + +# Use as many addnode= settings as you like to connect to specific peers +#addnode=188.120.246.137:34957 + +# ... or use as many connect= settings as you like to connect ONLY +# to specific peers: +#connect=188.120.246.137:34957 + +# Do not use Internet Relay Chat (irc.lfnet.org #arepacoin channel) to +# find other peers. +#noirc=1 + +# Maximum number of inbound+outbound connections. +#maxconnections= + + +# JSON-RPC options (for controlling a running process) + +# server=1 tells ArepaCoin to accept JSON-RPC commands. +#server=1 + +# You must set rpcuser and rpcpassword to secure the JSON-RPC api +#rpcuser=Ulysseys +#rpcpassword=YourSuperGreatPasswordNumber_385593 + +# By default, only RPC connections from localhost are allowed. Specify +# as many rpcallowip= settings as you like to allow connections from +# other hosts (and you may use * as a wildcard character): +#rpcallowip=10.1.1.34 +#rpcallowip=192.168.1.* + +# Listen for RPC connections on this TCP port: +rpcport=8332 + +# You can use ArepaCoin or arepacoind to send commands to Bitcoin/bitcoindArepaCoin/arepacoind +# running on another host using this option: +rpcconnect=127.0.0.1 + +# Use Secure Sockets Layer (also known as TLS or HTTPS) to communicate +# with ArepaCoin -server or arepacoind +#rpcssl=1 + +# OpenSSL settings used when rpcssl=1 +rpcsslciphers=TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH +rpcsslcertificatechainfile=server.cert +rpcsslprivatekeyfile=server.pem + + +# Miscellaneous options + +# Set gen=1 to attempt to generate arepacoins +gen=0 + +# Pre-generate this many public/private key pairs, so wallet backups will be valid for +# both prior transactions and several dozen future transactions. +keypool=100 + +# Pay an optional transaction fee every time you send arepacoins. +paytxfee=0.01 + +# Allow direct connections for the 'pay via IP address' feature. +#allowreceivebyip=1 + + +# User interface options + +# Start ArepaCoin minimized +#min=1 + +# Minimize to the system tray +#minimizetotray=1 diff --git a/contrib/debian/gbp.conf b/contrib/debian/gbp.conf new file mode 100644 index 0000000..a7281f9 --- /dev/null +++ b/contrib/debian/gbp.conf @@ -0,0 +1,5 @@ +# Configuration file for git-buildpackage and friends + +[DEFAULT] +pristine-tar = True +sign-tags = True diff --git a/contrib/debian/manpages/arepacoin.conf.5 b/contrib/debian/manpages/arepacoin.conf.5 new file mode 100644 index 0000000..5a3dcf0 --- /dev/null +++ b/contrib/debian/manpages/arepacoin.conf.5 @@ -0,0 +1,91 @@ +.TH AREPACOIN.CONF "8" "April 2013" "arepacoin.conf 3.19" +.SH NAME +arepacoin.conf \- arepacoin configuration file +.SH SYNOPSIS +All command-line options (except for '-datadir' and '-conf') may be specified in a configuration file, and all configuration file options may also be specified on the command line. Command-line options override values set in the configuration file. +.TP +The configuration file is a list of 'setting=value' pairs, one per line, with optional comments starting with the '#' character. +.TP +The configuration file is not automatically created; you can create it using your favorite plain-text editor. By default, arepacoind(1) will look for a file named arepacoin.conf(5) in the arepacoin data directory, but both the data directory and the configuration file path may be changed using the '-datadir' and '-conf' command-line arguments. +.SH LOCATION +arepacoin.conf should be located in $HOME/.arepacoin +.SH NETWORK-RELATED SETTINGS +.TP +.TP +\fBtestnet=\fR[\fI'1'\fR|\fI'0'\fR] +Enable or disable run on the test network instead of the real *arepacoin* network. +.TP +\fBproxy=\fR\fI'127.0.0.1:9050'\fR +Connect via a socks4 proxy. +.TP +\fBaddnode=\fR\fI'10.0.0.2:8333'\fR +Use as many *addnode=* settings as you like to connect to specific peers. +.TP +\fBconnect=\fR\fI'10.0.0.1:8333'\fR +Use as many *connect=* settings as you like to connect ONLY to specific peers. +.TP +\fBnoirc=\fR[\fI'1'\fR|\fI'0'\fR] +Use or Do not use Internet Relay Chat (irc.lfnet.org #arepacoin channel) to find other peers. +.TP +\fRmaxconnections=\fR\fI'value'\fR +Maximum number of inbound+outbound connections. +.SH JSON-RPC OPTIONS +.TP +\fBserver=\fR[\fI'1'\fR|\fI'0'\fR] +Tells *arepacoin* to accept or not accept JSON-RPC commands. +.TP +\fBrpcuser=\fR\fI'username'\fR +You must set *rpcuser* to secure the JSON-RPC api. +.TP +\fBrpcpassword=\fR\fI'password'\fR +You must set *rpcpassword* to secure the JSON-RPC api. +.TP +\fBrpctimeout=\fR\fI'30'\fR +How many seconds *arepacoin* will wait for a complete RPC HTTP request, after the HTTP connection is established. +.TP +\fBrpcallowip=\fR\fI'192.168.1.*'\fR +By default, only RPC connections from localhost are allowed. Specify as many *rpcallowip=* settings as you like to allow connections from other hosts (and you may use * as a wildcard character). +.TP +\fBrpcport=\fR\fI'8332'\fR +Listen for RPC connections on this TCP port. +.TP +\fBrpcconnect=\fR\fI'127.0.0.1'\fR +You can use *arepacoin* or *arepacoind(1)* to send commands to *arepacoin*/*arepacoind(1)* running on another host using this option. +.TP +\fBrpcssl=\fR\fI'1'\fR +Use Secure Sockets Layer (also known as TLS or HTTPS) to communicate with *arepacoin* '-server' or *arepacoind(1)*. Example of OpenSSL settings used when *rpcssl*='1': +.TP +\fBrpcsslciphers=\fR\fI'TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH'\fR +.TP +\fBrpcsslcertificatechainfile=\fR\fI'server.cert'\fR +.TP +\fBrpcsslprivatekeyfile=\fR\fI'server.pem'\fR +.TP +.SH MISCELLANEOUS OPTIONS +.TP +\fBgen=\fR[\fI'0'\fR|\fI'1'\fR] +Enable or disable attempt to generate arepacoins. +.TP +\fBkeypool=\fR\fI'100'\fR +Pre-generate this many public/private key pairs, so wallet backups will be valid for both prior transactions and several dozen future transactions. +.TP +\fBpaytxfee=\fR\fI'0.00'\fR +Pay an optional transaction fee every time you send arepacoins. Transactions with fees are more likely than free transactions to be included in generated blocks, so may be validated sooner. +.TP +\fBallowreceivebyip=\fR\fI'1'\fR +Allow direct connections for the 'pay via IP address' feature. +.TP +.SH USER INTERFACE OPTIONS +.TP +\fBmin=\fR[\fI'0'\fR|\fI'1'\fR] +Enable or disable start arepacoind minimized. +.TP +\fBminimizetotray=\fR[\fI'0'\fR|\fI'1'\fR] +Enable or disable minimize to the system tray. +.SH "SEE ALSO" +arepacoind(1) +.SH AUTHOR +This manual page was written by Micah Anderson for the Debian system (but may be used by others). Permission is granted to copy, distribute and/or modify this document under the terms of the GNU General Public License, Version 3 or any later version published by the Free Software Foundation. + +On Debian systems, the complete text of the GNU General Public License can be found in /usr/share/common-licenses/GPL. + diff --git a/contrib/debian/manpages/arepacoind.1 b/contrib/debian/manpages/arepacoind.1 new file mode 100644 index 0000000..50a30cd --- /dev/null +++ b/contrib/debian/manpages/arepacoind.1 @@ -0,0 +1,206 @@ +.TH AREPACOIND "7" "April 2013" "arepacoind 3.19" +.SH NAME +arepacoind \- peer-to-peer network based digital currency +.SH SYNOPSIS +arepacoin [options] [params] +.TP +arepacoin [options] help - Get help for a command +.SH DESCRIPTION +This manual page documents the arepacoind program. Novacoin is a peer-to-peer digital currency. Peer-to-peer (P2P) means that there is no central authority to issue new money or keep track of transactions. Instead, these tasks are managed collectively by the nodes of the network. Advantages: + +Novacoins can be sent easily through the Internet, without having to trust middlemen. Transactions are designed to be irreversible. Be safe from instability caused by fractional reserve banking and central banks. The limited inflation of the Novacoin system’s money supply is distributed evenly (by CPU power) throughout the network, not monopolized by banks. + +.SH OPTIONS +.TP +\fB\-conf=\fR +Specify configuration file (default: arepacoin.conf) +.TP +\fB\-gen\fR +Generate coins +.TP +\fB\-gen\fR=\fI0\fR +Don't generate coins +.TP +\fB\-min\fR +Start minimized +.TP +\fB\-datadir=\fR +Specify data directory +.TP +\fB\-proxy=\fR +Connect through socks4 proxy +.TP +\fB\-addnode=\fR +Add a node to connect to +.TP +\fB\-connect=\fR +Connect only to the specified node +.TP +\fB\-paytxfee=\fR +Fee per KB to add to transactions you send +.TP +\fB\-server\fR +Accept command line and JSON\-RPC commands +.TP +\fB\-daemon\fR +Run in the background as a daemon and accept commands +.TP +\fB\-testnet\fR +Use the test network +.TP +\fB\-rpcuser=\fR +Username for JSON\-RPC connections +.TP +\fB\-rpcpassword=\fR +Password for JSON\-RPC connections +.TP +\fB\-rpcport=\fR +Listen for JSON\-RPC connections on +.TP +\fB\-rpcallowip=\fR +Allow JSON\-RPC connections from specified IP address +.TP +\fB\-rpcconnect=\fR +Send commands to node running on +.PP +SSL options: (see the Bitcoin Wiki for SSL setup instructions) +.TP +\fB\-rpcssl\fR=\fI1\fR +Use OpenSSL (https) for JSON\-RPC connections +.TP +\fB\-rpcsslcertificatchainfile=\fR +Server certificate file (default: server.cert) +.TP +\fB\-rpcsslprivatekeyfile=\fR +Server private key (default: server.pem) +.TP +\fB\-rpcsslciphers=\fR +Acceptable ciphers (default: TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH) +.TP +\-? +This help message +.SH COMMANDS +.TP +\fBbackupwallet 'destination'\fR +Safely copies *wallet.dat* to 'destination', which can be a directory or a path with filename. +.TP +\fBgetaccount 'arepacoinaddress'\fR +Returns the account associated with the given address. +.TP +\fBsetaccount 'arepacoinaddress' ['account']\fR +Sets the ['account'] associated with the given address. ['account'] may be omitted to remove an address from ['account']. +.TP +\fBgetaccountaddress 'account'\fR +Returns a new arepacoin address for 'account'. +.TP +\fBgetaddressesbyaccount 'account'\fR +Returns the list of addresses associated with the given 'account'. +.TP +\fBgetbalance 'account'\fR +Returns the server's available balance, or the balance for 'account'. +.TP +\fBgetblockcount\fR +Returns the number of blocks in the longest block chain. +.TP +\fBgetblocknumber\fR +Returns the block number of the latest block in the longest block chain. +.TP +\fBgetconnectioncount\fR +Returns the number of connections to other nodes. +.TP +\fBgetdifficulty\fR +Returns the proof-of-work difficulty as a multiple of the minimum difficulty. +.TP +\fBgetgenerate\fR +Returns boolean true if server is trying to generate arepacoins, false otherwise. +.TP +\fBsetgenerate 'generate' ['genproclimit']\fR +Generation is limited to ['genproclimit'] processors, -1 is unlimited. +.TP +\fBgethashespersec\fR +Returns a recent hashes per second performance measurement while generating. +.TP +\fBgetinfo\fR +Returns an object containing server information. +.TP +\fBgetnewaddress 'account'\fR +Returns a new arepacoin address for receiving payments. If 'account' is specified (recommended), it is added to the address book so payments received with the address will be credited to 'account'. +.TP +\fBgetreceivedbyaccount 'account' ['minconf=1']\fR +Returns the total amount received by addresses associated with 'account' in transactions with at least ['minconf'] confirmations. +.TP +\fBgetreceivedbyaddress 'arepacoinaddress' ['minconf=1']\fR +Returns the total amount received by 'arepacoinaddress' in transactions with at least ['minconf'] confirmations. +.TP +\fBgettransaction 'txid'\fR +Returns information about a specific transaction, given hexadecimal transaction ID. +.TP +\fBgetwork 'data'\fR +If 'data' is specified, tries to solve the block and returns true if it was successful. If 'data' is not specified, returns formatted hash 'data' to work on: + + "midstate" : precomputed hash state after hashing the first half of the data. + "data" : block data. + "hash1" : formatted hash buffer for second hash. + "target" : little endian hash target. +.TP +\fBhelp 'command'\fR +List commands, or get help for a command. +.TP +\fBlistaccounts ['minconf=1']\fR +List accounts and their current balances. +.TP +\fBlistreceivedbyaccount ['minconf=1'] ['includeempty=false']\fR +['minconf'] is the minimum number of confirmations before payments are included. ['includeempty'] whether to include addresses that haven't received any payments. Returns an array of objects containing: + + "account" : the account of the receiving address. + "amount" : total amount received by the address. + "confirmations" : number of confirmations of the most recent transaction included. +.TP +\fBlistreceivedbyaddress ['minconf=1'] ['includeempty=false']\fR +['minconf'] is the minimum number of confirmations before payments are included. ['includeempty'] whether to include addresses that haven't received any payments. Returns an array of objects containing: + + "address" : receiving address. + "account" : the account of the receiving address. + "amount" : total amount received by the address. + "confirmations" : number of confirmations of the most recent transaction included. +.TP +\fBlisttransactions 'account' ['count=10']\fR +Returns a list of the last ['count'] transactions for 'account' - for all accounts if 'account' is not specified or is "*". Each entry in the list may contain: + + "category" : will be generate, send, receive, or move. + "amount" : amount of transaction. + "fee" : Fee (if any) paid (only for send transactions). + "confirmations" : number of confirmations (only for generate/send/receive). + "txid" : transaction ID (only for generate/send/receive). + "otheraccount" : account funds were moved to or from (only for move). + "message" : message associated with transaction (only for send). + "to" : message-to associated with transaction (only for send). +.TP +\fBmove <'fromaccount'> <'toaccount'> <'amount'> ['minconf=1'] ['comment']\fR +Moves funds between accounts. +.TP +\fBsendfrom* <'account'> <'arepacoinaddress'> <'amount'> ['minconf=1'] ['comment'] ['comment-to']\fR +Sends amount from account's balance to 'arepacoinaddress'. This method will fail if there is less than amount arepacoins with ['minconf'] confirmations in the account's balance (unless account is the empty-string-named default account; it behaves like the *sendtoaddress* method). Returns transaction ID on success. +.TP +\fBsendtoaddress 'arepacoinaddress' 'amount' ['comment'] ['comment-to']\fR +Sends amount from the server's available balance to 'arepacoinaddress'. amount is a real and is rounded to the nearest 0.01. Returns transaction id on success. +.TP +\fBstop\fR +Stops the arepacoin server. +.TP +\fBvalidateaddress 'arepacoinaddress'\fR +Checks that 'arepacoinaddress' looks like a proper arepacoin address. Returns an object containing: + + "isvalid" : true or false. + "ismine" : true if the address is in the server's wallet. + "address" : arepacoinaddress. + + *note: ismine and address are only returned if the address is valid. + +.SH "SEE ALSO" +arepacoin.conf(5) +.SH AUTHOR +This manual page was written by Micah Anderson for the Debian system (but may be used by others). Permission is granted to copy, distribute and/or modify this document under the terms of the GNU General Public License, Version 3 or any later version published by the Free Software Foundation. + +On Debian systems, the complete text of the GNU General Public License can be found in /usr/share/common-licenses/GPL. + diff --git a/contrib/debian/patches/README b/contrib/debian/patches/README new file mode 100644 index 0000000..80c1584 --- /dev/null +++ b/contrib/debian/patches/README @@ -0,0 +1,3 @@ +0xxx: Grabbed from upstream development. +1xxx: Possibly relevant for upstream adoption. +2xxx: Only relevant for official Debian release. diff --git a/contrib/debian/patches/series b/contrib/debian/patches/series new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/contrib/debian/patches/series @@ -0,0 +1 @@ + diff --git a/contrib/debian/rules b/contrib/debian/rules new file mode 100644 index 0000000..f5e9a42 --- /dev/null +++ b/contrib/debian/rules @@ -0,0 +1,33 @@ +#!/usr/bin/make -f +# -*- mode: makefile; coding: utf-8 -*- + +#DEB_MAKE_CHECK_TARGET = test_bitcoin +#build/bitcoind:: +# $(if $(filter nocheck,$(DEB_BUILD_OPTIONS)),,src/test_bitcoin) + +DEB_INSTALL_EXAMPLES_arepacoind += debian/examples/* +DEB_INSTALL_MANPAGES_arepacoind += debian/manpages/* + +%: + dh --with bash-completion $@ + +override_dh_auto_build: + cd src; $(MAKE) -f makefile.unix arepacoind + $(MAKE) + +override_dh_auto_clean: + if [ -f Makefile ]; then $(MAKE) clean; else rm -rf build/; rm -f arepacoin-qt; fi + cd src; $(MAKE) -f makefile.unix clean + +override_dh_auto_configure: + qmake arepacoin-qt.pro USE_QRCODE=1 + +override_dh_auto_test: + cd src; $(MAKE) -f makefile.unix test_arepacoin + src/test_arepacoin + +# Ensure wrapper is set executable +binary-post-install/arepacoind: + chmod +x $(cdbs_curdestdir)usr/bin/arepacoind +binary-post-install/arepacoin-qt: + chmod +x $(cdbs_curdestdir)usr/bin/arepacoin-qt diff --git a/contrib/debian/source/format b/contrib/debian/source/format new file mode 100644 index 0000000..163aaf8 --- /dev/null +++ b/contrib/debian/source/format @@ -0,0 +1 @@ +3.0 (quilt) diff --git a/contrib/debian/watch b/contrib/debian/watch new file mode 100644 index 0000000..df46780 --- /dev/null +++ b/contrib/debian/watch @@ -0,0 +1,4 @@ +# Run the "uscan" command to check for upstream updates and more. +version=4 +opts=uversionmangle=s/(\d)(alpha|beta|rc)/$1~$2/,dversionmangle=s/~dfsg\d*// \ + http://githubredir.debian.net/github/CryptoManiac/arepacoin v(.*).tar.gz diff --git a/contrib/gitian-descriptors/README b/contrib/gitian-descriptors/README new file mode 100644 index 0000000..a2d902e --- /dev/null +++ b/contrib/gitian-descriptors/README @@ -0,0 +1,31 @@ +Gavin's notes on getting gitian builds up and running: + +You need the right hardware: you need a 64-bit-capable CPU with hardware virtualization support (Intel VT-x or AMD-V). Not all modern CPUs support hardware virtualization. + +You probably need to enable hardware virtualization in your machine's BIOS. + +You need to be running a recent version of 64-bit-Ubuntu, and you need to install several prerequisites: + sudo apt-get install apache2 git apt-cacher-ng python-vm-builder qemu-kvm + +Sanity checks: + sudo service apt-cacher-ng status # Should return apt-cacher-ng is running + ls -l /dev/kvm # Should show a /dev/kvm device + +Once you've got the right hardware and software: + + git clone git://github.com/bitcoin/bitcoin.git + git clone git://github.com/devrandom/gitian-builder.git + mkdir gitian-builder/inputs + wget 'http://miniupnp.tuxfamily.org/files/download.php?file=miniupnpc-1.6.tar.gz' -O gitian-builder/inputs/miniupnpc-1.6.tar.gz + + cd gitian-builder + bin/make-base-vm --arch i386 + bin/make-base-vm --arch amd64 + cd .. + + # To build + cd bitcoin + git pull + cd ../gitian-builder + git pull + ./bin/gbuild --commit bitcoin=HEAD ../bitcoin/contrib/gitian.yml diff --git a/contrib/gitian-descriptors/boost-win32.yml b/contrib/gitian-descriptors/boost-win32.yml new file mode 100644 index 0000000..61ea50e --- /dev/null +++ b/contrib/gitian-descriptors/boost-win32.yml @@ -0,0 +1,38 @@ +--- +name: "boost" +suites: +- "lucid" +architectures: +- "i386" +packages: +- "mingw32" +- "faketime" +- "zip" +reference_datetime: "2011-01-30 00:00:00" +remotes: [] +files: +- "boost_1_47_0.tar.bz2" +script: | + TMPDIR="$HOME/tmpdir" + mkdir -p $TMPDIR/bin/$GBUILD_BITS $TMPDIR/include + tar xjf boost_1_47_0.tar.bz2 + cd boost_1_47_0 + echo "using gcc : 4.4 : i586-mingw32msvc-g++ + : + i586-mingw32msvc-windres + i586-mingw32msvc-ar + -frandom-seed=boost1 + ;" > user-config.jam + ./bootstrap.sh --without-icu + ./bjam toolset=gcc target-os=windows threadapi=win32 threading=multi variant=release link=static --user-config=user-config.jam --without-mpi --without-python -sNO_BZIP2=1 -sNO_ZLIB=1 --layout=tagged --build-type=complete $MAKEOPTS stage + for lib in chrono date_time exception filesystem graph iostreams math_c99f math_c99l math_c99 math_tr1f math_tr1l math_tr1 prg_exec_monitor program_options random regex serialization signals system test_exec_monitor thread_win32 unit_test_framework wave wserialization; do + mkdir $lib + (cd $lib ; ar xf ../stage/lib/libboost_${lib}-mt-s.a) + mv $lib $TMPDIR/bin/$GBUILD_BITS + done + cp -a boost $TMPDIR/include + cd $TMPDIR + export LD_PRELOAD=/usr/lib/faketime/libfaketime.so.1 + export FAKETIME=$REFERENCE_DATETIME + zip -r boost-win32-1.47.0-gitian.zip * + cp boost-win32-1.47.0-gitian.zip $OUTDIR diff --git a/contrib/gitian-descriptors/deps-win32.yml b/contrib/gitian-descriptors/deps-win32.yml new file mode 100644 index 0000000..62b67ee --- /dev/null +++ b/contrib/gitian-descriptors/deps-win32.yml @@ -0,0 +1,71 @@ +--- +name: "bitcoin-deps" +suites: +- "lucid" +architectures: +- "i386" +packages: +- "mingw32" +- "git-core" +- "zip" +- "faketime" +- "wine" +reference_datetime: "2011-01-30 00:00:00" +remotes: [] +files: +- "openssl-1.0.1b.tar.gz" +- "db-4.8.30.NC.tar.gz" +- "miniupnpc-1.6.tar.gz" +- "zlib-1.2.7.tar.gz" +- "libpng-1.5.12.tar.gz" +- "qrencode-3.2.0.tar.bz2" +script: | + # + export LD_PRELOAD=/usr/lib/faketime/libfaketime.so.1 + export FAKETIME=$REFERENCE_DATETIME + export TZ=UTC + # + tar xzf openssl-1.0.1b.tar.gz + cd openssl-1.0.1b + ./Configure --cross-compile-prefix=i586-mingw32msvc- mingw + make + cd .. + # + tar xzf db-4.8.30.NC.tar.gz + cd db-4.8.30.NC/build_unix + ../dist/configure --enable-mingw --enable-cxx --host=i586-mingw32msvc CFLAGS="-I/usr/i586-mingw32msvc/include" + make $MAKEOPTS + cd ../.. + # + tar xzf miniupnpc-1.6.tar.gz + cd miniupnpc-1.6 + sed 's/dllwrap -k --driver-name gcc/$(DLLWRAP) -k --driver-name $(CC)/' -i Makefile.mingw + sed 's|wingenminiupnpcstrings $< $@|./wingenminiupnpcstrings $< $@|' -i Makefile.mingw + make -f Makefile.mingw DLLWRAP=i586-mingw32msvc-dllwrap CC=i586-mingw32msvc-gcc AR=i586-mingw32msvc-ar + cd .. + mv miniupnpc-1.6 miniupnpc + # + tar xzf zlib-1.2.7.tar.gz + cd zlib-1.2.7 + make -f win32/Makefile.gcc PREFIX=i586-mingw32msvc- $MAKEOPTS + cd .. + # + tar xzf libpng-1.5.12.tar.gz + cd libpng-1.5.12 + ./configure -disable-shared CC=i586-mingw32msvc-cc AR=i586-mingw32msvc-ar STRIP=i586-mingw32msvc-strip RANLIB=i586-mingw32msvc-ranlib OBJDUMP=i586-mingw32msvc-objdump LD=i586-mingw32msvc-ld LDFLAGS="-L../zlib-1.2.7/" CFLAGS="-I../zlib-1.2.7/" + make $MAKEOPTS + cd .. + # + tar xjf qrencode-3.2.0.tar.bz2 + cd qrencode-3.2.0 + ./configure CC=i586-mingw32msvc-cc AR=i586-mingw32msvc-ar STRIP=i586-mingw32msvc-strip RANLIB=i586-mingw32msvc-ranlib OBJDUMP=i586-mingw32msvc-objdump LD=i586-mingw32msvc-ld png_LIBS="../libpng-1.5.12/.libs/libpng15.a ../zlib-1.2.7/libz.a" png_CFLAGS="-I../libpng-1.5.12" + make $MAKEOPTS + cd .. + # + zip -r $OUTDIR/ppcoin-deps-0.0.1.zip \ + $(ls qrencode-*/{qrencode.h,.libs/libqrencode.{,l}a} | sort) \ + $(ls db-*/build_unix/{libdb_cxx.a,db.h,db_cxx.h,libdb.a,.libs/libdb_cxx-?.?.a} | sort) \ + $(find openssl-* -name '*.a' -o -name '*.h' | sort) \ + $(find miniupnpc -name '*.h' -o -name 'libminiupnpc.a' | sort) + # Kill wine processes as gitian won't figure out we are done otherwise + killall wineserver services.exe explorer.exe winedevice.exe diff --git a/contrib/gitian-descriptors/gitian-win32.yml b/contrib/gitian-descriptors/gitian-win32.yml new file mode 100644 index 0000000..2bf3a7d --- /dev/null +++ b/contrib/gitian-descriptors/gitian-win32.yml @@ -0,0 +1,74 @@ +--- +name: "ppcoin" +suites: +- "lucid" +architectures: +- "i386" +packages: +- "mingw32" +- "git-core" +- "unzip" +- "nsis" +- "faketime" +reference_datetime: "2011-01-30 00:00:00" +remotes: +- "url": "https://github.com/ppcoin/ppcoin.git" + "dir": "ppcoin" +files: +- "qt-win32-4.7.4-gitian.zip" +- "boost-win32-1.47.0-gitian.zip" +- "ppcoin-deps-0.0.1.zip" +script: | + # + mkdir $HOME/qt + cd $HOME/qt + unzip ../build/qt-win32-4.7.4-gitian.zip + cd $HOME/build/ + export PATH=$PATH:$HOME/qt/bin/ + # + mkdir boost_1_47_0 + cd boost_1_47_0 + mkdir -p stage/lib + unzip ../boost-win32-1.47.0-gitian.zip + cd bin/$GBUILD_BITS + for lib in *; do + i586-mingw32msvc-ar rc ../../stage/lib/libboost_${lib}-mt-s.a $lib/*.o + i586-mingw32msvc-ranlib ../../stage/lib/libboost_${lib}-mt-s.a + done + cd ../.. + mv include/boost . + cd .. + # + unzip ppcoin-deps-0.0.1.zip + # + find -type f | xargs touch --date="$REFERENCE_DATETIME" + # + cd ppcoin + mkdir -p $OUTDIR/src + git archive HEAD | tar -x -C $OUTDIR/src + cp $OUTDIR/src/doc/README_windows.txt $OUTDIR/readme.txt + cp $OUTDIR/src/COPYING $OUTDIR/license.txt + export LD_PRELOAD=/usr/lib/faketime/libfaketime.so.1 + export FAKETIME=$REFERENCE_DATETIME + export TZ=UTC + $HOME/qt/src/bin/qmake -spec unsupported/win32-g++-cross MINIUPNPC_LIB_PATH=$HOME/build/miniupnpc MINIUPNPC_INCLUDE_PATH=$HOME/build/ BDB_LIB_PATH=$HOME/build/db-4.8.30.NC/build_unix BDB_INCLUDE_PATH=$HOME/build/db-4.8.30.NC/build_unix BOOST_LIB_PATH=$HOME/build/boost_1_47_0/stage/lib BOOST_INCLUDE_PATH=$HOME/build/boost_1_47_0 BOOST_LIB_SUFFIX=-mt-s BOOST_THREAD_LIB_SUFFIX=_win32-mt-s OPENSSL_LIB_PATH=$HOME/build/openssl-1.0.1b OPENSSL_INCLUDE_PATH=$HOME/build/openssl-1.0.1b/include QRENCODE_LIB_PATH=$HOME/build/qrencode-3.2.0/.libs QRENCODE_INCLUDE_PATH=$HOME/build/qrencode-3.2.0 USE_QRCODE=1 INCLUDEPATH=$HOME/build DEFINES=BOOST_THREAD_USE_LIB BITCOIN_NEED_QT_PLUGINS=1 QMAKE_LRELEASE=lrelease QMAKE_CXXFLAGS=-frandom-seed=ppcoin QMAKE_LFLAGS=-frandom-seed=ppcoin USE_BUILD_INFO=1 + make $MAKEOPTS + cp release/ppcoin-qt.exe $OUTDIR/ + # + cd src + export LD_PRELOAD=/usr/lib/faketime/libfaketime.so.1 + export FAKETIME=$REFERENCE_DATETIME + export TZ=UTC + make -f makefile.linux-mingw $MAKEOPTS DEPSDIR=$HOME/build ppcoind.exe USE_UPNP=1 DEBUGFLAGS="-frandom-seed=ppcoin" + i586-mingw32msvc-strip ppcoind.exe + mkdir $OUTDIR/daemon + cp ppcoind.exe $OUTDIR/daemon + cd .. + mkdir nsis + git archive HEAD | tar -x -C nsis + cd nsis/src + mkdir ../release + cp ../../release/* ../release/ + cp ../../src/*.exe . + makensis ../share/setup.nsi + cp ../share/ppcoin-*-win32-setup.exe $OUTDIR/ diff --git a/contrib/gitian-descriptors/gitian.yml b/contrib/gitian-descriptors/gitian.yml new file mode 100644 index 0000000..340de5e --- /dev/null +++ b/contrib/gitian-descriptors/gitian.yml @@ -0,0 +1,56 @@ +--- +name: "ppcoin" +suites: +- "lucid" +architectures: +- "i386" +- "amd64" +packages: +- "libdb4.8++-dev" +- "qt4-qmake" +- "libqt4-dev" +- "libboost-system-dev" +- "libboost-filesystem-dev" +- "libboost-program-options-dev" +- "libboost-thread-dev" +- "libssl-dev" +- "git-core" +- "unzip" +- "pkg-config" +- "libpng12-dev" +reference_datetime: "2011-01-30 00:00:00" +remotes: +- "url": "https://github.com/ppcoin/ppcoin.git" + "dir": "ppcoin" +files: +- "miniupnpc-1.6.tar.gz" +- "qrencode-3.2.0.tar.bz2" +script: | + INSTDIR="$HOME/install" + export LIBRARY_PATH="$INSTDIR/lib" + # + tar xzf miniupnpc-1.6.tar.gz + cd miniupnpc-1.6 + INSTALLPREFIX=$INSTDIR make $MAKEOPTS install + cd .. + # + tar xjf qrencode-3.2.0.tar.bz2 + cd qrencode-3.2.0 + ./configure --prefix=$INSTDIR --enable-static --disable-shared + make $MAKEOPTS install + cd .. + # + cd ppcoin + mkdir -p $OUTDIR/src + git archive HEAD | tar -x -C $OUTDIR/src + cp $OUTDIR/src/doc/README $OUTDIR + cp $OUTDIR/src/COPYING $OUTDIR + cd src + make -f makefile.unix STATIC=1 OPENSSL_INCLUDE_PATH="$INSTDIR/include" OPENSSL_LIB_PATH="$INSTDIR/lib" $MAKEOPTS ppcoind USE_UPNP=1 DEBUGFLAGS= + mkdir -p $OUTDIR/bin/$GBUILD_BITS + install -s ppcoind $OUTDIR/bin/$GBUILD_BITS + # + cd .. + qmake INCLUDEPATH="$INSTDIR/include" LIBS="-L$INSTDIR/lib" RELEASE=1 USE_QRCODE=1 + make $MAKEOPTS + install ppcoin-qt $OUTDIR/bin/$GBUILD_BITS diff --git a/contrib/gitian-descriptors/qt-win32.yml b/contrib/gitian-descriptors/qt-win32.yml new file mode 100644 index 0000000..6eb76b2 --- /dev/null +++ b/contrib/gitian-descriptors/qt-win32.yml @@ -0,0 +1,54 @@ +--- +name: "qt" +suites: +- "lucid" +architectures: +- "i386" +packages: +- "mingw32" +- "zip" +- "faketime" +reference_datetime: "2011-01-30 00:00:00" +remotes: [] +files: +- "qt-everywhere-opensource-src-4.7.4.tar.gz" +script: | + INSTDIR="$HOME/qt/" + mkdir $INSTDIR + SRCDIR="$INSTDIR/src/" + mkdir $SRCDIR + # + tar xzf qt-everywhere-opensource-src-4.7.4.tar.gz + cd qt-everywhere-opensource-src-4.7.4 + sed 's/$TODAY/2011-01-30/' -i configure + sed 's/i686-pc-mingw32-/i586-mingw32msvc-/' -i mkspecs/unsupported/win32-g++-cross/qmake.conf + sed --posix 's|QMAKE_CFLAGS\t\t= -pipe|QMAKE_CFLAGS\t\t= -pipe -isystem /usr/i586-mingw32msvc/include/ -frandom-seed=qtbuild|' -i mkspecs/unsupported/win32-g++-cross/qmake.conf + sed 's/QMAKE_CXXFLAGS_EXCEPTIONS_ON = -fexceptions -mthreads/QMAKE_CXXFLAGS_EXCEPTIONS_ON = -fexceptions/' -i mkspecs/unsupported/win32-g++-cross/qmake.conf + sed 's/QMAKE_LFLAGS_EXCEPTIONS_ON = -mthreads/QMAKE_LFLAGS_EXCEPTIONS_ON = -lmingwthrd/' -i mkspecs/unsupported/win32-g++-cross/qmake.conf + sed --posix 's/QMAKE_MOC\t\t= i586-mingw32msvc-moc/QMAKE_MOC\t\t= moc/' -i mkspecs/unsupported/win32-g++-cross/qmake.conf + sed --posix 's/QMAKE_RCC\t\t= i586-mingw32msvc-rcc/QMAKE_RCC\t\t= rcc/' -i mkspecs/unsupported/win32-g++-cross/qmake.conf + sed --posix 's/QMAKE_UIC\t\t= i586-mingw32msvc-uic/QMAKE_UIC\t\t= uic/' -i mkspecs/unsupported/win32-g++-cross/qmake.conf + # ar adds timestamps to every object file included in the static library + # providing -D as ar argument is supposed to solve it, but doesn't work as qmake strips off the arguments and adds -M to pass a script... + # which somehow cannot be combined with other flags. + # use faketime only for ar, as it confuses make/qmake into hanging sometimes + sed --posix "s|QMAKE_LIB\t\t= i586-mingw32msvc-ar -ru|QMAKE_LIB\t\t= $HOME/ar -Dr|" -i mkspecs/unsupported/win32-g++-cross/qmake.conf + echo '#!/bin/bash' > $HOME/ar + echo 'export LD_PRELOAD=/usr/lib/faketime/libfaketime.so.1' >> $HOME/ar + echo 'i586-mingw32msvc-ar "$@"' >> $HOME/ar + chmod +x $HOME/ar + #export LD_PRELOAD=/usr/lib/faketime/libfaketime.so.1 + export FAKETIME=$REFERENCE_DATETIME + export TZ=UTC + ./configure -prefix $INSTDIR -confirm-license -release -opensource -static -no-qt3support -xplatform unsupported/win32-g++-cross -no-multimedia -no-audio-backend -no-phonon -no-phonon-backend -no-declarative -no-script -no-scripttools -no-javascript-jit -no-webkit -no-svg -no-xmlpatterns -no-sql-sqlite -no-nis -no-cups -no-iconv -no-dbus -no-gif -no-libtiff -opengl no -nomake examples -nomake demos -nomake docs + find . -name *.prl | xargs -l sed 's|/\.||' -i + find . -name *.prl | xargs -l sed 's|/$||' -i + make $MAKEOPTS install + cp -a bin $SRCDIR/ + cd $INSTDIR + find . -name *.prl | xargs -l sed 's|/$||' -i + #sed 's|QMAKE_PRL_LIBS.*|QMAKE_PRL_LIBS = -lQtDeclarative -lQtScript -lQtSvg -lQtSql -lQtXmlPatterns -lQtGui -lgdi32 -lcomdlg32 -loleaut32 -limm32 -lwinmm -lwinspool -lmsimg32 -lQtNetwork -lQtCore -lole32 -luuid -lws2_32 -ladvapi32 -lshell32 -luser32 -lkernel32|' -i imports/Qt/labs/particles/qmlparticlesplugin.prl + + # as zip stores file timestamps, use faketime to intercept stat calls to set dates for all files to reference date + export LD_PRELOAD=/usr/lib/faketime/libfaketime.so.1 + zip -r $OUTDIR/qt-win32-4.7.4-gitian.zip * diff --git a/contrib/gitian-downloader/bluematt-key.pgp b/contrib/gitian-downloader/bluematt-key.pgp new file mode 100644 index 0000000..fb6d9eb Binary files /dev/null and b/contrib/gitian-downloader/bluematt-key.pgp differ diff --git a/contrib/gitian-downloader/devrandom-key.pgp b/contrib/gitian-downloader/devrandom-key.pgp new file mode 100644 index 0000000..7189812 Binary files /dev/null and b/contrib/gitian-downloader/devrandom-key.pgp differ diff --git a/contrib/gitian-downloader/gavinandresen-key.pgp b/contrib/gitian-downloader/gavinandresen-key.pgp new file mode 100644 index 0000000..f81f44e Binary files /dev/null and b/contrib/gitian-downloader/gavinandresen-key.pgp differ diff --git a/contrib/gitian-downloader/laanwj-key.pgp b/contrib/gitian-downloader/laanwj-key.pgp new file mode 100644 index 0000000..5592951 --- /dev/null +++ b/contrib/gitian-downloader/laanwj-key.pgp @@ -0,0 +1,28 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: SKS 1.1.0 + +mQENBE5UtMEBCADOUz2i9l/D8xYINCmfUDnxi+DXvX5LmZ39ZdvsoE+ugO0SRRGdIHEFO2is +0xezX50wXu9aneb+tEqM0BuiLo6VxaXpxrkxHpr6c4jf37SkE/H0qsi/txEUp7337y3+4HMG +lUjiuh802I72p1qusjsKBnmnnR0rwNouTcoDmGUDh7jpKCtzFv+2TR2dRthJn7vmmjq3+bG6 +PYfqoFY1yHrAGT1lrDBULZsQ/NBLI2+J4oo2LYv3GCq8GNnzrovqvTvui50VSROhLrOe58o2 +shE+sjQShAy5wYkPt1R1fQnpfx+5vf+TPnkxVwRb3h5GhCp0YL8XC/BXsd5vM4KlVH2rABEB +AAG0K1dsYWRpbWlyIEouIHZhbiBkZXIgTGFhbiA8bGFhbndqQGdtYWlsLmNvbT6JATgEEwEC +ACIFAk5UtMECGwMGCwkIBwMCBhUIAgkKCwQWAgMBAh4BAheAAAoJEHSBCwEjRsmmy6YIAK09 +buNXyYQrJBsX16sXxEhx5QPKyF3uHJDFJv66SdnpvIkNoznsaPiRJkbTANop93FZmaGa6wVn +zGDiz7jPA8Dpxx5aAYPhIT+zPJAdXWM3wJ/Gio9besRNzniai8Lwi5MZ9R/5yFGBobm6/AcN +4sUoqA3NSV2U3I29R0Vwlzo8GVtmyi9ENSi6Oo7AcXNTRt69cxW4nAHkB+amwwDJlcAb31ex +bogYXPhScwqQZixRr+JBkKxBjkTXXnQypT4KI5SegYwQVYfyiZmDP7UHKe/u6pSKKbVphLg8 +xLB5spcXse8/a2+onrbNlw6y8TXiJ++Z54PE7zztWTXf2huakeG5AQ0ETlS0wQEIAMNO3OkP +xoPRKWzBLcI7JRITAW+HNaLTq3uN2+4WxA57DEjbL9EDoAv+7wTkDAL40f0T+xiu6GJcLFjw +GJZu/tYu7+mErHjrdo+K4suCQt7w5EXCBvOLjhW4tyYMzNx8hP+oqzOW9iEC+6VV91+DYeqt +EkJuyVXOI4vzBlTw8uGow8aMMsCq8XVvKUZFTPsjGl197Q5B3A+ZOFCR8xqiqdPjuz6MglVV +oFdDNu3EZn8zkGsQlovXoE9ndVeVzx/XMNmsxFaMYsReUs253RIf1FEfgExID0fg2OnyLCjS +2iFW1RgajS+/saIkKl+N1iuMzJA7wMAM0plhRueOG0MtZSsAEQEAAYkBHwQYAQIACQUCTlS0 +wQIbDAAKCRB0gQsBI0bJpmsDB/4waenn2CvSHXyomykfpwf5lMte1V5LvH3z5R2LY+1NopRv +LSz3iC39x69XWiTbhywDfgafnGPW4pWBOff2/bu5/A6z1Hnan1vyrRRD/hx1uMJ7S6q+bIvZ +iVIg1p0jH6tdIIhwX3cydhdRZHo7e9oSMgOUWsr6Ar59NRo9CENwGPE4U61HXfOnxWdrFWoA +XdwZczBeLxmUy6Vo6sKqv+gE4bqrtAM0sY/MsQ9cU95x+52ox/sq44lQMwd3ZBYUP7B1qbHI +hZSZuch6MLi5scLPeau0ZvCaljiaMeivP5+x0gWPRs0kI+9sZxInbqvrsJ6oOBJM3xYGhtn1 +zZ7qmZR7 +=si/k +-----END PGP PUBLIC KEY BLOCK----- diff --git a/contrib/gitian-downloader/linux-download-config b/contrib/gitian-downloader/linux-download-config new file mode 100644 index 0000000..aef614d --- /dev/null +++ b/contrib/gitian-downloader/linux-download-config @@ -0,0 +1,38 @@ +--- +name: bitcoin +urls: +- http://bitcoin.org/bitcoin-latest-linux-gitian.zip +rss: +- url: http://sourceforge.net/api/file/index/project-id/244765/mtime/desc/limit/100/rss + xpath: //item/link/text() + pattern: bitcoin-\d+.\d+.\d+-linux-gitian.zip +signers: + 0A82509767C7D4A5D14DA2301AE1D35043E08E54: + weight: 40 + name: BlueMatt + key: bluematt + BF6273FAEF7CC0BA1F562E50989F6B3048A116B5: + weight: 40 + name: Devrandom + key: devrandom + E463A93F5F3117EEDE6C7316BD02942421F4889F: + weight: 40 + name: Luke-Jr + key: luke-jr + D762373D24904A3E42F33B08B9A408E71DAAC974: + weight: 40 + name: "Pieter Wuille" + key: sipa + 77E72E69DA7EE0A148C06B21B34821D4944DE5F7: + weight: 40 + name: tcatm + key: tcatm + 01CDF4627A3B88AAE4A571C87588242FBE38D3A8: + weight: 40 + name: "Gavin Andresen" + key: gavinandresen + 71A3B16735405025D447E8F274810B012346C9A6: + weight: 40 + name: "Wladimir J. van der Laan" + key: laanwj +minimum_weight: 120 diff --git a/contrib/gitian-downloader/luke-jr-key.pgp b/contrib/gitian-downloader/luke-jr-key.pgp new file mode 100644 index 0000000..c40917d Binary files /dev/null and b/contrib/gitian-downloader/luke-jr-key.pgp differ diff --git a/contrib/gitian-downloader/richardsmith-key.gpg b/contrib/gitian-downloader/richardsmith-key.gpg new file mode 100644 index 0000000..04d1d53 --- /dev/null +++ b/contrib/gitian-downloader/richardsmith-key.gpg @@ -0,0 +1,52 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: GnuPG v1.4.10 (GNU/Linux) + +mQINBFAsDREBEADD88DdBoGu/rMpNYWyzXNWfHI5su/JX1tfzM/pb/iSrC4ywOtZ +P7wCqqAB1lhuT94j2m8kpv/VSb98Q7ZURxbwY/zEQnDuifiBCj5hO4lWTdSKgmLy +8xVR7WHEYCscKFl92mG6tqDewnD2oX5NyJrFeXPAM9R9jBIDc2oyUVznv5Rb2YUp +D4rdIHbEMoe524Ucw8ez5Kxtf0OW0Zbrraq1utbcL3B99FMnoSaXq5AiGTmcI3Xm +Mx8T8E6I2gd6ZLEtJbgzG7B8so/0tbpGIYExzatjWEzuDEPAgAB028nNWf8q+SE+ +G3Zo/ZrCenGYPmDKIaSlqmdhqHe22AGtn+k6gzvLVN9MHY2exIWhu2R8uw6cGCbG +piw7HPDR0epgf5im50rr/k9ZgELhURqDezeHCwRBFtBZd+1sLgzMocYybq7XM9e6 +dcHRZoXamlMibKoYMp30jfyb5mVYwnOJAQNUkFxwZOJXONOvwEyO+89ep0c7H/I5 +h/4F7UGTpRB84HpkZCK+rxOg90UpOQEAA1OKi2od5DNBtu9JnXOD8Ki9lXHaGgL2 +H6Q+ugntvsYmcJZ22IkymZ1DPaEPJa8Y/pwovl9rYac1A1v9PFkl2XsE2EZyipmF +QjTSimnmvCCIXFSG7yN4iP/H/+vP8kdV2HuPfLnq7i0uIe9q9s0ogtZEpwARAQAB +tCVyaWNoYXJkc21pdGggPGljZWVhdHNjcmVhbUBnbWFpbC5jb20+iQI+BBMBAgAo +BQJQLA0RAhsDBQkSzAMABgsJCAcDAgYVCAIJCgsEFgIDAQIeAQIXgAAKCRCiiuz9 +atLt+MecD/9qO/1ALT4EH5MewKG6mMT9hrbsIf07Cc0uKl4/hpbElK2iEclcXdj6 +fXyxVF0+1Vl8Bfkj47n4sL8aOmVjZ8YpFcW59GqE9Me9Sw7bPE5x8Ly2Am+NMkhz +myq3aJX54bzUGvBxCNwZYV46DxKjsOLrw2I/Tzt2zjzROlCW/r4IpEuFAQY5zzNv +YryzWuaJF27pVZH2od9X0nEfn7qBoDYWEtvlI5jfsL4HI0bd4Ws9xMrkjHKBaFaC +H5sxZS7mxicTRf4qeP/XKxdEI461sg28wYewnIBqYm8OEkwFS3YB51hlA1ufi3Za +m5sMmiut8H5jq0QXH+LWWQAADOnCbMrr3zbkaueMvLzjUsR1EtbYlpGPHXwk9eVk +9XckZ1hMjUl5VCBLzquuGuJonUfb5plxEDJ2MCkkkhBJ6DR3yMpjS//ogi52fwlI +0yltpyXUXcgURwvQ1pwpTkjbD09KqUmxViULFMLXT3e6vRc5pH9e7mja5LxSe/No +Kqm0RdFlM/2CMDQ0ByNUGWjAPozuxm5PeO0ypS3+tDBiLcgZnayWelsuHzR4BCmk +LkXiNTrIlXSJpBWsg5D99ni8VrFGLwn9PBaDrOsztfL8iDFgVUzPbizbEEAbKiYq +lo/qnq2nrxR7YtChJQwhKlc0NHOWmqJOp2+AIW+L1LfDiVo3wuH6XrkCDQRQLA0R +ARAA0e4sHZQDTZZ9DdmML1yhL9C0DqsBaDTiKQY+s9lanrjSs7HKgv8bK+gTNvng +/O0M1/xhSOsgepq5lpdl7h5QqGZ1oCSF3QYxCeGe85g9SKBsUFNbYwdS2JXBwO3V +1euBM2pNSmNL0PYiTsWylUQPymUZ4ww2n6giVYWmsEqSF/Ld/kkfODzJAP4AwBIJ +f+2GY+vWcvxNKES1JT98p/dlMMMXeDKqcXIIzoZbnpk5gd21oGXbMwaf9s8bK8ob +BMqZCORmSnG9npRSfFXDHSa2983nGPUoL8bMzeyDu/1PViclxTWtI012gYp99pRm +JXzGiGdBmuLItAQW5o8DWXfiiobYd5H0+PfAX62H5oXTWH1T5jblyxcyA+fYU71t +wCRZ93OEHv0Q/RafH6Fr+ltZVnpPmYpJ4gyWpyoP2j91N6KaVyrfbCaN0Cyv4bQG +JCg8Ss8UqOnsFj88KikYwRMVxJp5E6MpM0yEuIU+vrB+58yOmeNCQ+LwBNnltCmC +9v0YYibMbmUv4wRvScGHPAfJ3CWndRbIObXoMlLs9nayMCqpBTEDGhTKheocQdMo +aLt3OJsaTmFKE7iFGKImGgUdD94kbkzb7R+ZRlI9mNNiq+Kuj19CSAVdM9vttjyt +whPYPR6d4GNWZFS+Gg9k2Bv7O2cDYh78Go7ywuAtPkcTMv8AEQEAAYkCJQQYAQIA +DwUCUCwNEQIbDAUJEswDAAAKCRCiiuz9atLt+PAXEACLd967Sz06DpjMHqgHahCr +m1Kt13EM/mbrnoFJWePTp1JAtlzSMXKsWo7zOCC71dyI8PEfjylsZiuC3uL54DDl +JlQmlXa6/qi1KnqroJEkZ+YoDnIy/jiN1L3SqMVwUeQrd5N0koPZflpnoAq1np97 +wWDwK8NqALq5VsqXhVWvXeqjDM1q9+7fO7xDQLFZ0MNhqoMBdE4QRRkw55XWJKS9 +RI/hxDFuCJlK04eFTU/5pUSksEZZ0vl43YkXlN54qiyOvkVL2Aq9gVgvdaqGbG8x +kVSEtJK9XTwlo+BA/sFCMlR4NL1XCrrvv9/1SwiFAFSV4dz6Cg9ObAonNh0mbnwj +IaaBzS18pqRzqZg69aZzlKp6LxBYOmZTQuPiwdF0Cn/b5VNtgLKInmOvDvpHFWE2 +H4dU3Al/B+3o1Bm24mAgLQHGFh4GN4BV1ge+Lijiz+N0sUfPsqtHaP3RNZsm/4oL +zyVuoSMRL+NtkB03SID7CBzrVLGWRGgeWjLfLz+wnrDGlWz0N7dKJx76nayTvsM2 +xd81jat8FyHFFoB5D4xn+czbkCq1k3giyKqilz2NNXX0G7kUiU0D+tvIb76qP389 +9uiMAuC5q1Ibo+k3pOZrWWHX3c9HB1Qlry9Qw57Y4ncqjRcdMf884da5mTmCjl/d +EwL78xfzdw9iYRRwoeP+IQ== +=jMKy +-----END PGP PUBLIC KEY BLOCK----- diff --git a/contrib/gitian-downloader/scottnadal-key.gpg b/contrib/gitian-downloader/scottnadal-key.gpg new file mode 100644 index 0000000..678ec7e --- /dev/null +++ b/contrib/gitian-downloader/scottnadal-key.gpg @@ -0,0 +1,52 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: GnuPG v1.4.10 (GNU/Linux) + +mQINBFAs/eYBEADJq87tlE9Lu4dtgzKcnLrY6m7Eab3fPL4aW+g1PC3O4rMn2jjT +vp4TU+DHBgt9r+DBpiK48v9fd3BNpg8mB25pDgdWtoBj64D1YxlU/NxbwnR4SGDD +nSCjp/Z+ZxTCjUHfAu384P9nsSvMFksVhhzgd9JXvxJzB61odjgPRVs5buJtLzrg +v7jJdBZPDC2R9kJIggdrrN4sWhE9o3VQ4kFMxEu3KGJSLZuGRdwr1Ni5jxpo1Hio +Xf1LDKJ5+kTb2YpHL9trxe9ELt3HLa5mryCVff1wwN+MBwsXdvxTjF2RXJUWbKlC +M78DjLCCyM5T1XPb4D0dp/olEhNqI6IrBhR9rEOVR5Rbsl49lfhQIUEDAVlogAoG +yzwQMO/NGOD0NUgQV/7ZIN1fpKPuipJsCId2UvzuxzjwtMf20VUI5OPKRk122OOv +9c91y9fI9H6rgHKcS96HLM840pkQmr00CpsEtCjtYxvOKCakCcbq4SHZSrB2gjcK +msY/DfEjO5An/LXh5IbEiSSgSXfCTSXMU7yB36yX4CniIDTEe044DlTwhSGUnw65 +alTp4taaswjB+yhAWI5IXOGifFyOAFW0BhGpDHuWoevUHKYXMla9czB0Jn1VIX/E +bAPxi5sZKHjhhjZY6ngZAO2HXliWHXIeLvwjUdE0+AAP5B+eh7kyMV7mlQARAQAB +tCJzY290dG5hZGFsIDxzY290dC5uYWRhbEBnbWFpbC5jb20+iQI+BBMBAgAoBQJQ +LP3mAhsDBQkSzAMABgsJCAcDAgYVCAIJCgsEFgIDAQIeAQIXgAAKCRAu6TbaW7w+ +y477EAC9yNgDSSdSmqUVQdrPdEn1RyZl4sjAznuRk+CKffi83/ZwjZJkT12GapPF +9/wW/YXGGbb2wUK17xIz8ZcKCjZeSf8w0HNwFfy8bOOkewpJ3QMp+PO61KTa1sfn +hJvPKQTxKAM49tiq1O/x5hppKCrJjPzlH41+4rfrFk7+v5ZHusIDqxIzepS+MyNy +fhmCq1Pd2w/R3zHIDH7R8uuuJKDDkZhhJgQjjxGo4Mqo6UaJOHsmLNGmQi+at/Eu +BssrO2OHSShCvA6/fvKXN4XEFxm7w3WUylw3h47j1hXhQClqBJrLA08N7+iNqKKg +DX2ePpWIptwjJyqn/6UtEfFyeIBQITpxyrVoWCtdnNdo03AQpraPV8DICyxQY3e9 +FFKkrod+XKeGqs7Lsk5mPUOQVl7KoCfmW+M1vcvEpK7wElSRUdy0Fw0s6BiYN1xH +baOsBIvc1KWN9x//ctJPcjxEONiPDKv1dyWUYIWieSTrFjP6aOLoe0uGkDXxxlEs +4X4ZAgLUXs4j62on9lsFH1pVAQOpbmVS06vmmHQTR3skG9D8s4jVn1dyJQ35I0ml +P0IH4DazTTld6laYptd4CqlohotME+yh9VqiQ0Tg1u6L4VwYsBN6AKGgOq+T8T0b +VPNK1+Si9Poq4J/wPPqUQRzxSgWbX5Ho/k+6t0R8dpne6oFGrbkCDQRQLP3mARAA +mIA7DN9DT1xN0uazTRXV4lqFTuG+86iPU35eUtReGcChYwq0V56bV+gywObo4fAP +QsynzCUvtk+8FSL++SLysIaD/VAu3YAqsI/shzA/KG77ZqgR3/E6pnkaN8aFVPRf +dFFbBYioXP2MkOMd2MqPSnUI5+dMKnJ4HBQvucG5yxdR7VKP9VxBwQcfZEcE+l8a +yRyaAr3NNDm69Qxb6TeiJlwSQvcY4FhnP9EpIW11DEIvCEKKr6X0UoWFTm7dSfLk +n2e1IsK1kk3Uy45KzrR/4dYB7PhEP0VjLZ4bueXMjvZW8YBUoC6emOU/3B+/j3GO +N+62XE9u0Vsh2uzRnOqjucn+i83Og7+1VaXVRh77giWTlDTAeJARRGa6ScmxI9Vk +MJgbe2oseDxTv9QF5guqLUNe0MlUZ/9SXXjou/D+L/S9Beo775sfn57gANDbaGRm +9795YyAHphl26Qp7es3uj99mlK7tGDHajb2JkJutMtaevGuVNN9QlUrhr7klPOAd +6jdAxsU9Sn/gnUBZJbCFoQlUveEjkSu24/tYoo6Oy7VgMxwt/CMhB5HzVOpY20Ym +BDTO9P9MBeD0/wSPyanHc+XVepXWwsp4EC5RVnJFLf+o3vmeQYqiF0qXuapLmLnK +XqSD+M+uIr15XxTLLx9vsjUVN/xkLu7DCgyVeRA3ytUAEQEAAYkCJQQYAQIADwUC +UCz95gIbDAUJEswDAAAKCRAu6TbaW7w+yxsEEACu+7g6trtjYQZ3FStCK8OZOAJl +jefUONgZX8woSSmyeVlg5Ex9cSvAgfOhiM2J2+K8aI53woOsiE3LihElaX+Qi+hE +GgjsFdd6lNn3i5gFydDHs6uLvtVAXxAOOOaXWT/ucsTgBRGcY4H1QYlkTGD8Xsf8 +qyUOzP/s8RQbvIrGrQtLN3O9r8wDBzDdZZjp/IZZaY6VT1r3AvF2mX+ip8/OqxNc +Yd3qxf8s7Kyn0eChSq1DAp83XMWxCje2EwXXzDA7Jd0pMAppWevFks4INGyCxz+9 +jOZ4Ris2a907ShWmIg8bw40r5L69j59qPk0fr44X6XVguN9zmKpLV5fyY88Qy9iq +8uy/3UVprZ0LnPbBXhbDsFkgiDOo2zCJfaVhPirMlpPJg/T5pFyAt+klrq6bD+tD +50Hh9gOpXXg58bELJhOtDUCV6Froc99LeqoBvlKJWqr58QguO2mn1cFJcP+nVzxz +DBpB/dWsmQst/NQ3YlgfVr6CcgqlCqVI4yNT91Q5Ns8/pdkcUBIVDUC+4oyKwA4n +XZMmydPJDdUiluwVSeIw0N/jiZhBJvMJHlOQ3xmb8In0WXcnE5JbibCITTN/T224 +jL14ObF+aMWlFanqRDUwllEQFv0Wa9dgTaHzxl+l9Ojw+YaYt/96UTtEJaMaxmww +JzdBFnCP7RoNHIQ20A== +=CQsQ +-----END PGP PUBLIC KEY BLOCK----- diff --git a/contrib/gitian-downloader/sipa-key.pgp b/contrib/gitian-downloader/sipa-key.pgp new file mode 100644 index 0000000..a52a5de Binary files /dev/null and b/contrib/gitian-downloader/sipa-key.pgp differ diff --git a/contrib/gitian-downloader/sunnyking-key.gpg b/contrib/gitian-downloader/sunnyking-key.gpg new file mode 100644 index 0000000..16b2a40 --- /dev/null +++ b/contrib/gitian-downloader/sunnyking-key.gpg @@ -0,0 +1,52 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: GnuPG v1.4.10 (GNU/Linux) + +mQINBFAsDOMBEACysMqtJfC7ikO2o+ioQZvHSSbL2R2zdgYxPjtQvLqbNMiJyV3q +vwXGWh0Z3eGu/cpHvfN6mguwHqgh319AtU6wiOHX/1yGMf2MUNFhoh8RlDWhZ+ba +gMTv7pcZKE2Ca7JgDtLNWd+NpjYrlGDSEEFl2vTohKKd+V7hRjyMc8iLkLjVdtdd +OTuFQeyNB8DUMUr3GuaPr52RgidZdMbJ0QSnEQeN9/ZTYjmYfREO+mal+2G/OKMk +6naUcGrhwHimc02WDddkqMhe5eZsU3XG+WqrD5NkN3my72XjkqSE1++k2+XgnOon +pUOciWfF3R3RBlOn0MlfKvNa/GXZ7PFxke3tkxdym8BV10l8spV++tPuhxovR7Gp +XG8Mt66uxlFc4S9wTg5FJilk2W75LK+FjFLAk9gJ24IHUawdSpLdCM+a4/JL1Ys+ +CQUuQA06Xdq3x8iuZSduRrnLeFEkM/F6JmyH22L8b5ptIm/wgjCaa+R/8P5ROO/E +FM1z7sw2RK12ZNPqwrNysePSVze2MGNdPnmb2KDcxSlxoK6Nzcef5xGkP/WwdBnd +WN2iA70I0S8DEywpY3hrJ4YIDg+SvCsoRIBH90PUORQ5Uhfj15QbmT2bZrqoFaDY +1+dWmijsPJ6+6MYjDWte/WVDSqTJEa22R/SAjGETGmUig7OqE7FFaQFLPwARAQAB +tCNzdW5ueWtpbmcgPHN1bm55a2luZzk5OTlAZ21haWwuY29tPokCPgQTAQIAKAUC +UCwM4wIbAwUJEswDAAYLCQgHAwIGFQgCCQoLBBYCAwECHgECF4AACgkQGPNEBNK5 +Xmp4hg//f/rUs1ABrsd7ciHN0ByOH/WKdlUNNvf8jua86mHdPcHAFtZ3HC8ICVLe +7TAUMEgQ1Vsmk1QBILCaE50cD9iya4uCYCpBN6RZXUd09Te+ugb+VUYda4NmVbF+ +ZYidDjLwFZ3MV4uXZLWMGnxVDYVrBDHdfvFkZvi+/thtEME+Ea84diBZcAW/ncUb +AMNxNsmOTlTcPuB47UZVxg2vSJWkJe9O6IpuF782+49O14hsxidPMV+BKOaYWwoj +wGlJ+NDkobaQ/a0lI0aGHL1KXA58mNMB0i7SoYB8YJMfL2+lx0AZsvxaqFmuMcPf +zo7I9UCyf/gHorQaxsbz2/LUfpFL4T7IWt9IJkVe8TT9KQV8T0l9uUaQtX3iLwqQ +IRJWdQZMpnENhEgkSLRSkmCV/162ksYoboSpfI3Qhz1h0yqnwHAGBKSbE/2IGVo5 +3m/27xUFy5+7WeiON7DelYS6mx4UiAkhSWj4/u60YNnq5eTAYQFqawtSwIiO9pLH +C1gqOCoakESdFCQfABNsI6paIkfTylZhLd20qrr9qvBfvOgpMRXbO6xBPYp92/UK +9uRkFFCJORLBUl9saLfZa4Hw1CcY06IA3XXBx2/kp42aeAnWrfzqLvXwFZGtOJie +ajQsJUeDLFjbsYmw9FP8izK2H6plEa3PLFDz2gP+MSLZ5+13eES5Ag0EUCwM4wEQ +AMTFatCCzaUPwFpM9GyC7JwIWofDRpZBigXnzTC8RwHnb1ruWliFUkTEeSB8z7pC +3DaQ+owf0TUqj0c8Ui3SVfCcQqIJuWBycxxUnSaqWvz7wRaRN+WG4gaWgA2z7k4Q +CMmVhbxTaaZ67rfqtFOKM7EaIqOBE+AKg5BCCrxnja/xR0eZxRLwZKXqfakgqXy8 +HaWOzLPU6zMheTXu4YW5S6jvZOaMRkKI5xEUdQf/UPYkwYM6PaA/o70rTSGuQ/mc +zwFZp7FxKqKINPBSJLu1CjhnnrZM37y26I5O+nErDTinvYg5Rkq5wV3gMNbzpOdA +qPdw2qkVwKWDErNrA9amKuM0/fpvu/kXkGnfkugvt3Rokc3MQO2u5HI1eO571zaV +GoDt1oYjpKPuu6JMe2b5D1fLhyHicGaH8V2vpJi6+01Ww09srKemox54J4Z/Xjw6 +gyaWuPkCHO3roNjeGMtzbbJeOYEZC/AMTuqmnv3gHXENgrxKjCkkGddH8t7nZUNT +zmTMHrqOzhacRIp/6jpKCNXea2FaeRQECtDD2awNxUpmFFQeGpXJGsGc/GYHqvtV +HxWOiio1BpHhjCySHCYpqsq/GtGVdxNVz6o7H0/i4wipT7Q2dKVKbSuapaqI01jv +40019gtjOV7Gw8fX0MLt3ViCQVHpDxdMN/vkumw9YKA1ABEBAAGJAiUEGAECAA8F +AlAsDOMCGwwFCRLMAwAACgkQGPNEBNK5XmpymA//UXydFKX11RGloxzMfdgoFvjw +mNoZeS5Sv22hpsS2XswqAIbGdI/s2PbEzLv6nn0ck1PUFn9wL+TxB9GF2wWelpI4 +qe1mKsedJbj9PG6Wx2Invn6IcEInMrSLspBWiJJL2eP4y1hjAGG4v1wxPXQ4/FNe +OvXzAwShz79nVY35MDPBpL/dlhRJAIe/T7pYiI/HB8p4bI9MbtJcfp61oRPt17UC +vIQFnKKkwPT99i3PsOqAa8mVa2Ae4EElHG844Hr89ptHrGjudssfBf4kOaENMQqE +MFlyGaT9CLrD/2Qs/rXqFz3VAQykw/Cuw0kiRJjS5xKZZjVbz3Zd9suklk6YkSpI +jLzcPPON8nC6wvtUus5d0gtQeGx2DaX9n2+ubKlZgTSvT41PO/2Th9o3CgptHYJT +59ncrZP515yd0ZMknZ9bFt9BaE3V17hblOjFXoFqmAhwXyHQD9Ffd62AO1h2JNx5 +BAr4D7VyxJ3WX1yJFtdGsU7iD6ko4HahRepfp8UMtyVRLWVPGVmNq38Tozb4dhyh +fk3MxiatbEXQZbvFVr8WfGoNOIXB4Kg68NGxwZv6Jd5lobDOQjVYOykD2UpuOXmY +VRanFk5eIy0UWYAwUNP+XnjGHdwtX4ZYh+O4wDnWEZd4soVMXzOBuyWTSKahHhZi +KIjGheFAFTRFLgBmol4= +=Qxzm +-----END PGP PUBLIC KEY BLOCK----- diff --git a/contrib/gitian-downloader/tcatm-key.pgp b/contrib/gitian-downloader/tcatm-key.pgp new file mode 100644 index 0000000..baaec76 Binary files /dev/null and b/contrib/gitian-downloader/tcatm-key.pgp differ diff --git a/contrib/gitian-downloader/win32-download-config b/contrib/gitian-downloader/win32-download-config new file mode 100644 index 0000000..0f7032e --- /dev/null +++ b/contrib/gitian-downloader/win32-download-config @@ -0,0 +1,38 @@ +--- +name: bitcoin +urls: +- http://bitcoin.org/bitcoin-latest-win32-gitian.zip +rss: +- url: http://sourceforge.net/api/file/index/project-id/244765/mtime/desc/limit/100/rss + xpath: //item/link/text() + pattern: bitcoin-\d+.\d+.\d+-win32-gitian.zip +signers: + 0A82509767C7D4A5D14DA2301AE1D35043E08E54: + weight: 40 + name: BlueMatt + key: bluematt + BF6273FAEF7CC0BA1F562E50989F6B3048A116B5: + weight: 40 + name: Devrandom + key: devrandom + E463A93F5F3117EEDE6C7316BD02942421F4889F: + weight: 40 + name: Luke-Jr + key: luke-jr + D762373D24904A3E42F33B08B9A408E71DAAC974: + weight: 40 + name: "Pieter Wuille" + key: sipa + 77E72E69DA7EE0A148C06B21B34821D4944DE5F7: + weight: 40 + name: tcatm + key: tcatm + 01CDF4627A3B88AAE4A571C87588242FBE38D3A8: + weight: 40 + name: "Gavin Andresen" + key: gavinandresen + 71A3B16735405025D447E8F274810B012346C9A6: + weight: 40 + name: "Wladimir J. van der Laan" + key: laanwj +minimum_weight: 120 diff --git a/contrib/macdeploy/LICENSE b/contrib/macdeploy/LICENSE new file mode 100644 index 0000000..94a9ed0 --- /dev/null +++ b/contrib/macdeploy/LICENSE @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. diff --git a/contrib/macdeploy/background.png b/contrib/macdeploy/background.png new file mode 100644 index 0000000..51dc01a Binary files /dev/null and b/contrib/macdeploy/background.png differ diff --git a/contrib/macdeploy/background.psd b/contrib/macdeploy/background.psd new file mode 100644 index 0000000..e0a8c9a Binary files /dev/null and b/contrib/macdeploy/background.psd differ diff --git a/contrib/macdeploy/fancy.plist b/contrib/macdeploy/fancy.plist new file mode 100644 index 0000000..1cf72ac --- /dev/null +++ b/contrib/macdeploy/fancy.plist @@ -0,0 +1,32 @@ + + + + + window_bounds + + 300 + 300 + 800 + 620 + + background_picture + background.png + icon_size + 96 + applications_symlink + + items_position + + Applications + + 370 + 156 + + ArepaCoin-Qt.app + + 128 + 156 + + + + diff --git a/contrib/macdeploy/macdeployqtplus b/contrib/macdeploy/macdeployqtplus new file mode 100644 index 0000000..7981eca --- /dev/null +++ b/contrib/macdeploy/macdeployqtplus @@ -0,0 +1,758 @@ +#!/usr/bin/env python + +# +# Copyright (C) 2011 Patrick "p2k" Schneider +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + +import subprocess, sys, re, os, shutil, stat, os.path +from string import Template +from time import sleep +from argparse import ArgumentParser + +# This is ported from the original macdeployqt with modifications + +class FrameworkInfo(object): + def __init__(self): + self.frameworkDirectory = "" + self.frameworkName = "" + self.frameworkPath = "" + self.binaryDirectory = "" + self.binaryName = "" + self.binaryPath = "" + self.version = "" + self.installName = "" + self.deployedInstallName = "" + self.sourceFilePath = "" + self.destinationDirectory = "" + self.sourceResourcesDirectory = "" + self.destinationResourcesDirectory = "" + + def __eq__(self, other): + if self.__class__ == other.__class__: + return self.__dict__ == other.__dict__ + else: + return False + + def __str__(self): + return """ Framework name: %s + Framework directory: %s + Framework path: %s + Binary name: %s + Binary directory: %s + Binary path: %s + Version: %s + Install name: %s + Deployed install name: %s + Source file Path: %s + Deployed Directory (relative to bundle): %s +""" % (self.frameworkName, + self.frameworkDirectory, + self.frameworkPath, + self.binaryName, + self.binaryDirectory, + self.binaryPath, + self.version, + self.installName, + self.deployedInstallName, + self.sourceFilePath, + self.destinationDirectory) + + def isDylib(self): + return self.frameworkName.endswith(".dylib") + + def isQtFramework(self): + if self.isDylib(): + return self.frameworkName.startswith("libQt") + else: + return self.frameworkName.startswith("Qt") + + reOLine = re.compile(r'^(.+) \(compatibility version [0-9.]+, current version [0-9.]+\)$') + bundleFrameworkDirectory = "Contents/Frameworks" + bundleBinaryDirectory = "Contents/MacOS" + + @classmethod + def fromOtoolLibraryLine(cls, line): + # Note: line must be trimmed + if line == "": + return None + + # Don't deploy system libraries (exception for libQtuitools and libQtlucene). + if line.startswith("/System/Library/") or line.startswith("@executable_path") or (line.startswith("/usr/lib/") and "libQt" not in line): + return None + + m = cls.reOLine.match(line) + if m is None: + raise RuntimeError("otool line could not be parsed: " + line) + + path = m.group(1) + + info = cls() + info.sourceFilePath = path + info.installName = path + + if path.endswith(".dylib"): + dirname, filename = os.path.split(path) + info.frameworkName = filename + info.frameworkDirectory = dirname + info.frameworkPath = path + + info.binaryDirectory = dirname + info.binaryName = filename + info.binaryPath = path + info.version = "-" + + info.installName = path + info.deployedInstallName = "@executable_path/../Frameworks/" + info.binaryName + info.sourceFilePath = path + info.destinationDirectory = cls.bundleFrameworkDirectory + else: + parts = path.split("/") + i = 0 + # Search for the .framework directory + for part in parts: + if part.endswith(".framework"): + break + i += 1 + if i == len(parts): + raise RuntimeError("Could not find .framework or .dylib in otool line: " + line) + + info.frameworkName = parts[i] + info.frameworkDirectory = "/".join(parts[:i]) + info.frameworkPath = os.path.join(info.frameworkDirectory, info.frameworkName) + + info.binaryName = parts[i+3] + info.binaryDirectory = "/".join(parts[i+1:i+3]) + info.binaryPath = os.path.join(info.binaryDirectory, info.binaryName) + info.version = parts[i+2] + + info.deployedInstallName = "@executable_path/../Frameworks/" + os.path.join(info.frameworkName, info.binaryPath) + info.destinationDirectory = os.path.join(cls.bundleFrameworkDirectory, info.frameworkName, info.binaryDirectory) + + info.sourceResourcesDirectory = os.path.join(info.frameworkPath, "Resources") + info.destinationResourcesDirectory = os.path.join(cls.bundleFrameworkDirectory, info.frameworkName, "Resources") + + return info + +class ApplicationBundleInfo(object): + def __init__(self, path): + self.path = path + appName = os.path.splitext(os.path.basename(path))[0] + self.binaryPath = os.path.join(path, "Contents", "MacOS", appName) + if not os.path.exists(self.binaryPath): + raise RuntimeError("Could not find bundle binary for " + path) + self.resourcesPath = os.path.join(path, "Contents", "Resources") + self.pluginPath = os.path.join(path, "Contents", "PlugIns") + +class DeploymentInfo(object): + def __init__(self): + self.qtPath = None + self.pluginPath = None + self.deployedFrameworks = [] + + def detectQtPath(self, frameworkDirectory): + parentDir = os.path.dirname(frameworkDirectory) + if os.path.exists(os.path.join(parentDir, "translations")): + # Classic layout, e.g. "/usr/local/Trolltech/Qt-4.x.x" + self.qtPath = parentDir + elif os.path.exists(os.path.join(parentDir, "share", "qt4", "translations")): + # MacPorts layout, e.g. "/opt/local/share/qt4" + self.qtPath = os.path.join(parentDir, "share", "qt4") + elif os.path.exists(os.path.join(os.path.dirname(parentDir), "share", "qt4", "translations")): + # Newer Macports layout + self.qtPath = os.path.join(os.path.dirname(parentDir), "share", "qt4") + else: + self.qtPath = os.getenv("QTDIR", None) + + if self.qtPath is not None: + pluginPath = os.path.join(self.qtPath, "plugins") + if os.path.exists(pluginPath): + self.pluginPath = pluginPath + + def usesFramework(self, name): + nameDot = "%s." % name + libNameDot = "lib%s." % name + for framework in self.deployedFrameworks: + if framework.endswith(".framework"): + if framework.startswith(nameDot): + return True + elif framework.endswith(".dylib"): + if framework.startswith(libNameDot): + return True + return False + +def getFrameworks(binaryPath, verbose): + if verbose >= 3: + print "Inspecting with otool: " + binaryPath + otool = subprocess.Popen(["otool", "-L", binaryPath], stdout=subprocess.PIPE, stderr=subprocess.PIPE) + o_stdout, o_stderr = otool.communicate() + if otool.returncode != 0: + if verbose >= 1: + sys.stderr.write(o_stderr) + sys.stderr.flush() + raise RuntimeError("otool failed with return code %d" % otool.returncode) + + otoolLines = o_stdout.split("\n") + otoolLines.pop(0) # First line is the inspected binary + if ".framework" in binaryPath or binaryPath.endswith(".dylib"): + otoolLines.pop(0) # Frameworks and dylibs list themselves as a dependency. + + libraries = [] + for line in otoolLines: + info = FrameworkInfo.fromOtoolLibraryLine(line.strip()) + if info is not None: + if verbose >= 3: + print "Found framework:" + print info + libraries.append(info) + + return libraries + +def runInstallNameTool(action, *args): + subprocess.check_call(["install_name_tool", "-"+action] + list(args)) + +def changeInstallName(oldName, newName, binaryPath, verbose): + if verbose >= 3: + print "Using install_name_tool:" + print " in", binaryPath + print " change reference", oldName + print " to", newName + runInstallNameTool("change", oldName, newName, binaryPath) + +def changeIdentification(id, binaryPath, verbose): + if verbose >= 3: + print "Using install_name_tool:" + print " change identification in", binaryPath + print " to", id + runInstallNameTool("id", id, binaryPath) + +def runStrip(binaryPath, verbose): + if verbose >= 3: + print "Using strip:" + print " stripped", binaryPath + subprocess.check_call(["strip", "-x", binaryPath]) + +def copyFramework(framework, path, verbose): + if framework.sourceFilePath.startswith("Qt"): + #standard place for Nokia Qt installer's frameworks + fromPath = "/Library/Frameworks/" + framework.sourceFilePath + else: + fromPath = framework.sourceFilePath + + toDir = os.path.join(path, framework.destinationDirectory) + toPath = os.path.join(toDir, framework.binaryName) + + if not os.path.exists(fromPath): + raise RuntimeError("No file at " + fromPath) + + if os.path.exists(toPath): + return None # Already there + + if not os.path.exists(toDir): + os.makedirs(toDir) + + shutil.copy2(fromPath, toPath) + if verbose >= 3: + print "Copied:", fromPath + print " to:", toPath + + permissions = os.stat(toPath) + if not permissions.st_mode & stat.S_IWRITE: + os.chmod(toPath, permissions.st_mode | stat.S_IWRITE) + + if not framework.isDylib(): # Copy resources for real frameworks + fromResourcesDir = framework.sourceResourcesDirectory + if os.path.exists(fromResourcesDir): + toResourcesDir = os.path.join(path, framework.destinationResourcesDirectory) + shutil.copytree(fromResourcesDir, toResourcesDir) + if verbose >= 3: + print "Copied resources:", fromResourcesDir + print " to:", toResourcesDir + elif framework.frameworkName.startswith("libQtGui"): # Copy qt_menu.nib (applies to non-framework layout) + qtMenuNibSourcePath = os.path.join(framework.frameworkDirectory, "Resources", "qt_menu.nib") + qtMenuNibDestinationPath = os.path.join(path, "Contents", "Resources", "qt_menu.nib") + if os.path.exists(qtMenuNibSourcePath) and not os.path.exists(qtMenuNibDestinationPath): + shutil.copytree(qtMenuNibSourcePath, qtMenuNibDestinationPath) + if verbose >= 3: + print "Copied for libQtGui:", qtMenuNibSourcePath + print " to:", qtMenuNibDestinationPath + + return toPath + +def deployFrameworks(frameworks, bundlePath, binaryPath, strip, verbose, deploymentInfo=None): + if deploymentInfo is None: + deploymentInfo = DeploymentInfo() + + while len(frameworks) > 0: + framework = frameworks.pop(0) + deploymentInfo.deployedFrameworks.append(framework.frameworkName) + + if verbose >= 2: + print "Processing", framework.frameworkName, "..." + + # Get the Qt path from one of the Qt frameworks + if deploymentInfo.qtPath is None and framework.isQtFramework(): + deploymentInfo.detectQtPath(framework.frameworkDirectory) + + if framework.installName.startswith("@executable_path"): + if verbose >= 2: + print framework.frameworkName, "already deployed, skipping." + continue + + # install_name_tool the new id into the binary + changeInstallName(framework.installName, framework.deployedInstallName, binaryPath, verbose) + + # Copy farmework to app bundle. + deployedBinaryPath = copyFramework(framework, bundlePath, verbose) + # Skip the rest if already was deployed. + if deployedBinaryPath is None: + continue + + if strip: + runStrip(deployedBinaryPath, verbose) + + # install_name_tool it a new id. + changeIdentification(framework.deployedInstallName, deployedBinaryPath, verbose) + # Check for framework dependencies + dependencies = getFrameworks(deployedBinaryPath, verbose) + + for dependency in dependencies: + changeInstallName(dependency.installName, dependency.deployedInstallName, deployedBinaryPath, verbose) + + # Deploy framework if necessary. + if dependency.frameworkName not in deploymentInfo.deployedFrameworks and dependency not in frameworks: + frameworks.append(dependency) + + return deploymentInfo + +def deployFrameworksForAppBundle(applicationBundle, strip, verbose): + frameworks = getFrameworks(applicationBundle.binaryPath, verbose) + if len(frameworks) == 0 and verbose >= 1: + print "Warning: Could not find any external frameworks to deploy in %s." % (applicationBundle.path) + return DeploymentInfo() + else: + return deployFrameworks(frameworks, applicationBundle.path, applicationBundle.binaryPath, strip, verbose) + +def deployPlugins(appBundleInfo, deploymentInfo, strip, verbose): + # Lookup available plugins, exclude unneeded + plugins = [] + for dirpath, dirnames, filenames in os.walk(deploymentInfo.pluginPath): + pluginDirectory = os.path.relpath(dirpath, deploymentInfo.pluginPath) + if pluginDirectory == "designer": + # Skip designer plugins + continue + elif pluginDirectory == "phonon" or pluginDirectory == "phonon_backend": + # Deploy the phonon plugins only if phonon is in use + if not deploymentInfo.usesFramework("phonon"): + continue + elif pluginDirectory == "sqldrivers": + # Deploy the sql plugins only if QtSql is in use + if not deploymentInfo.usesFramework("QtSql"): + continue + elif pluginDirectory == "script": + # Deploy the script plugins only if QtScript is in use + if not deploymentInfo.usesFramework("QtScript"): + continue + elif pluginDirectory == "qmltooling": + # Deploy the qml plugins only if QtDeclarative is in use + if not deploymentInfo.usesFramework("QtDeclarative"): + continue + elif pluginDirectory == "bearer": + # Deploy the bearer plugins only if QtNetwork is in use + if not deploymentInfo.usesFramework("QtNetwork"): + continue + + for pluginName in filenames: + pluginPath = os.path.join(pluginDirectory, pluginName) + if pluginName.endswith("_debug.dylib"): + # Skip debug plugins + continue + elif pluginPath == "imageformats/libqsvg.dylib" or pluginPath == "iconengines/libqsvgicon.dylib": + # Deploy the svg plugins only if QtSvg is in use + if not deploymentInfo.usesFramework("QtSvg"): + continue + elif pluginPath == "accessible/libqtaccessiblecompatwidgets.dylib": + # Deploy accessibility for Qt3Support only if the Qt3Support is in use + if not deploymentInfo.usesFramework("Qt3Support"): + continue + elif pluginPath == "graphicssystems/libqglgraphicssystem.dylib": + # Deploy the opengl graphicssystem plugin only if QtOpenGL is in use + if not deploymentInfo.usesFramework("QtOpenGL"): + continue + + plugins.append((pluginDirectory, pluginName)) + + for pluginDirectory, pluginName in plugins: + if verbose >= 2: + print "Processing plugin", os.path.join(pluginDirectory, pluginName), "..." + + sourcePath = os.path.join(deploymentInfo.pluginPath, pluginDirectory, pluginName) + destinationDirectory = os.path.join(appBundleInfo.pluginPath, pluginDirectory) + if not os.path.exists(destinationDirectory): + os.makedirs(destinationDirectory) + + destinationPath = os.path.join(destinationDirectory, pluginName) + shutil.copy2(sourcePath, destinationPath) + if verbose >= 3: + print "Copied:", sourcePath + print " to:", destinationPath + + if strip: + runStrip(destinationPath, verbose) + + dependencies = getFrameworks(destinationPath, verbose) + + for dependency in dependencies: + changeInstallName(dependency.installName, dependency.deployedInstallName, destinationPath, verbose) + + # Deploy framework if necessary. + if dependency.frameworkName not in deploymentInfo.deployedFrameworks: + deployFrameworks([dependency], appBundleInfo.path, destinationPath, strip, verbose, deploymentInfo) + +qt_conf="""[Paths] +translations=Resources +plugins=PlugIns +""" + +ap = ArgumentParser(description="""Improved version of macdeployqt. + +Outputs a ready-to-deploy app in a folder "dist" and optionally wraps it in a .dmg file. +Note, that the "dist" folder will be deleted before deploying on each run. + +Optionally, Qt translation files (.qm) and additional resources can be added to the bundle.""") + +ap.add_argument("app_bundle", nargs=1, metavar="app-bundle", help="application bundle to be deployed") +ap.add_argument("-verbose", type=int, nargs=1, default=[1], metavar="<0-3>", help="0 = no output, 1 = error/warning (default), 2 = normal, 3 = debug") +ap.add_argument("-no-plugins", dest="plugins", action="store_false", default=True, help="skip plugin deployment") +ap.add_argument("-no-strip", dest="strip", action="store_false", default=True, help="don't run 'strip' on the binaries") +ap.add_argument("-dmg", nargs="?", const="", metavar="basename", help="create a .dmg disk image; if basename is not specified, a camel-cased version of the app name is used") +ap.add_argument("-fancy", nargs=1, metavar="plist", default=[], help="make a fancy looking disk image using the given plist file with instructions; requires -dmg to work") +ap.add_argument("-add-qt-tr", nargs=1, metavar="languages", default=[], help="add Qt translation files to the bundle's ressources; the language list must be separated with commas, not with whitespace") +ap.add_argument("-add-resources", nargs="+", metavar="path", default=[], help="list of additional files or folders to be copied into the bundle's resources; must be the last argument") + +config = ap.parse_args() + +verbose = config.verbose[0] + +# ------------------------------------------------ + +app_bundle = config.app_bundle[0] + +if not os.path.exists(app_bundle): + if verbose >= 1: + sys.stderr.write("Error: Could not find app bundle \"%s\"\n" % (app_bundle)) + sys.exit(1) + +app_bundle_name = os.path.splitext(os.path.basename(app_bundle))[0] + +# ------------------------------------------------ + +for p in config.add_resources: + if verbose >= 3: + print "Checking for \"%s\"..." % p + if not os.path.exists(p): + if verbose >= 1: + sys.stderr.write("Error: Could not find additional resource file \"%s\"\n" % (p)) + sys.exit(1) + +# ------------------------------------------------ + +if len(config.fancy) == 1: + if verbose >= 3: + print "Fancy: Importing plistlib..." + try: + import plistlib + except ImportError: + if verbose >= 1: + sys.stderr.write("Error: Could not import plistlib which is required for fancy disk images.\n") + sys.exit(1) + + if verbose >= 3: + print "Fancy: Importing appscript..." + try: + import appscript + except ImportError: + if verbose >= 1: + sys.stderr.write("Error: Could not import appscript which is required for fancy disk images.\n") + sys.stderr.write("Please install it e.g. with \"sudo easy_install appscript\".\n") + sys.exit(1) + + p = config.fancy[0] + if verbose >= 3: + print "Fancy: Loading \"%s\"..." % p + if not os.path.exists(p): + if verbose >= 1: + sys.stderr.write("Error: Could not find fancy disk image plist at \"%s\"\n" % (p)) + sys.exit(1) + + try: + fancy = plistlib.readPlist(p) + except: + if verbose >= 1: + sys.stderr.write("Error: Could not parse fancy disk image plist at \"%s\"\n" % (p)) + sys.exit(1) + + try: + assert not fancy.has_key("window_bounds") or (isinstance(fancy["window_bounds"], list) and len(fancy["window_bounds"]) == 4) + assert not fancy.has_key("background_picture") or isinstance(fancy["background_picture"], str) + assert not fancy.has_key("icon_size") or isinstance(fancy["icon_size"], int) + assert not fancy.has_key("applications_symlink") or isinstance(fancy["applications_symlink"], bool) + if fancy.has_key("items_position"): + assert isinstance(fancy["items_position"], dict) + for key, value in fancy["items_position"].iteritems(): + assert isinstance(value, list) and len(value) == 2 and isinstance(value[0], int) and isinstance(value[1], int) + except: + if verbose >= 1: + sys.stderr.write("Error: Bad format of fancy disk image plist at \"%s\"\n" % (p)) + sys.exit(1) + + if fancy.has_key("background_picture"): + bp = fancy["background_picture"] + if verbose >= 3: + print "Fancy: Resolving background picture \"%s\"..." % bp + if not os.path.exists(bp): + bp = os.path.join(os.path.dirname(p), bp) + if not os.path.exists(bp): + if verbose >= 1: + sys.stderr.write("Error: Could not find background picture at \"%s\" or \"%s\"\n" % (fancy["background_picture"], bp)) + sys.exit(1) + else: + fancy["background_picture"] = bp +else: + fancy = None + +# ------------------------------------------------ + +if os.path.exists("dist"): + if verbose >= 2: + print "+ Removing old dist folder +" + + shutil.rmtree("dist") + +# ------------------------------------------------ + +target = os.path.join("dist", app_bundle) + +if verbose >= 2: + print "+ Copying source bundle +" +if verbose >= 3: + print app_bundle, "->", target + +os.mkdir("dist") +shutil.copytree(app_bundle, target) + +applicationBundle = ApplicationBundleInfo(target) + +# ------------------------------------------------ + +if verbose >= 2: + print "+ Deploying frameworks +" + +try: + deploymentInfo = deployFrameworksForAppBundle(applicationBundle, config.strip, verbose) + if deploymentInfo.qtPath is None: + deploymentInfo.qtPath = os.getenv("QTDIR", None) + if deploymentInfo.qtPath is None: + if verbose >= 1: + sys.stderr.write("Warning: Could not detect Qt's path, skipping plugin deployment!\n") + config.plugins = False +except RuntimeError as e: + if verbose >= 1: + sys.stderr.write("Error: %s\n" % str(e)) + sys.exit(ret) + +# ------------------------------------------------ + +if config.plugins: + if verbose >= 2: + print "+ Deploying plugins +" + + try: + deployPlugins(applicationBundle, deploymentInfo, config.strip, verbose) + except RuntimeError as e: + if verbose >= 1: + sys.stderr.write("Error: %s\n" % str(e)) + sys.exit(ret) + +# ------------------------------------------------ + +if len(config.add_qt_tr) == 0: + add_qt_tr = [] +else: + qt_tr_dir = os.path.join(deploymentInfo.qtPath, "translations") + add_qt_tr = ["qt_%s.qm" % lng for lng in config.add_qt_tr[0].split(",")] + for lng_file in add_qt_tr: + p = os.path.join(qt_tr_dir, lng_file) + if verbose >= 3: + print "Checking for \"%s\"..." % p + if not os.path.exists(p): + if verbose >= 1: + sys.stderr.write("Error: Could not find Qt translation file \"%s\"\n" % (lng_file)) + sys.exit(1) + +# ------------------------------------------------ + +if verbose >= 2: + print "+ Installing qt.conf +" + +f = open(os.path.join(applicationBundle.resourcesPath, "qt.conf"), "wb") +f.write(qt_conf) +f.close() + +# ------------------------------------------------ + +if len(add_qt_tr) > 0 and verbose >= 2: + print "+ Adding Qt translations +" + +for lng_file in add_qt_tr: + if verbose >= 3: + print os.path.join(qt_tr_dir, lng_file), "->", os.path.join(applicationBundle.resourcesPath, lng_file) + shutil.copy2(os.path.join(qt_tr_dir, lng_file), os.path.join(applicationBundle.resourcesPath, lng_file)) + +# ------------------------------------------------ + +if len(config.add_resources) > 0 and verbose >= 2: + print "+ Adding additional resources +" + +for p in config.add_resources: + t = os.path.join(applicationBundle.resourcesPath, os.path.basename(p)) + if verbose >= 3: + print p, "->", t + if os.path.isdir(p): + shutil.copytree(p, t) + else: + shutil.copy2(p, t) + +# ------------------------------------------------ + +if config.dmg is not None: + def runHDIUtil(verb, image_basename, **kwargs): + hdiutil_args = ["hdiutil", verb, image_basename + ".dmg"] + if kwargs.has_key("capture_stdout"): + del kwargs["capture_stdout"] + run = subprocess.check_output + else: + if verbose < 2: + hdiutil_args.append("-quiet") + elif verbose >= 3: + hdiutil_args.append("-verbose") + run = subprocess.check_call + + for key, value in kwargs.iteritems(): + hdiutil_args.append("-" + key) + if not value is True: + hdiutil_args.append(str(value)) + + return run(hdiutil_args) + + if verbose >= 2: + if fancy is None: + print "+ Creating .dmg disk image +" + else: + print "+ Preparing .dmg disk image +" + + if config.dmg != "": + dmg_name = config.dmg + else: + spl = app_bundle_name.split(" ") + dmg_name = spl[0] + "".join(p.capitalize() for p in spl[1:]) + + if fancy is None: + try: + runHDIUtil("create", dmg_name, srcfolder="dist", format="UDBZ", volname=app_bundle_name, ov=True) + except subprocess.CalledProcessError as e: + sys.exit(e.returncode) + else: + if verbose >= 3: + print "Determining size of \"dist\"..." + size = 0 + for path, dirs, files in os.walk("dist"): + for file in files: + size += os.path.getsize(os.path.join(path, file)) + size += int(size * 0.1) + + if verbose >= 3: + print "Creating temp image for modification..." + try: + runHDIUtil("create", dmg_name + ".temp", srcfolder="dist", format="UDRW", size=size, volname=app_bundle_name, ov=True) + except subprocess.CalledProcessError as e: + sys.exit(e.returncode) + + if verbose >= 3: + print "Attaching temp image..." + try: + output = runHDIUtil("attach", dmg_name + ".temp", readwrite=True, noverify=True, noautoopen=True, capture_stdout=True) + except subprocess.CalledProcessError as e: + sys.exit(e.returncode) + + m = re.search("/Volumes/(.+$)", output) + disk_root = m.group(0) + disk_name = m.group(1) + + if verbose >= 2: + print "+ Applying fancy settings +" + + if fancy.has_key("background_picture"): + bg_path = os.path.join(disk_root, os.path.basename(fancy["background_picture"])) + if verbose >= 3: + print fancy["background_picture"], "->", bg_path + shutil.copy2(fancy["background_picture"], bg_path) + else: + bg_path = None + + if fancy.get("applications_symlink", False): + os.symlink("/Applications", os.path.join(disk_root, "Applications")) + + finder = appscript.app("Finder") + disk = finder.disks[disk_name] + disk.open() + window = disk.container_window + window.current_view.set(appscript.k.icon_view) + window.toolbar_visible.set(False) + window.statusbar_visible.set(False) + if fancy.has_key("window_bounds"): + window.bounds.set(fancy["window_bounds"]) + view_options = window.icon_view_options + view_options.arrangement.set(appscript.k.not_arranged) + if fancy.has_key("icon_size"): + view_options.icon_size.set(fancy["icon_size"]) + if bg_path is not None: + view_options.background_picture.set(disk.files[os.path.basename(bg_path)]) + if fancy.has_key("items_position"): + for name, position in fancy["items_position"].iteritems(): + window.items[name].position.set(position) + disk.close() + if bg_path is not None: + subprocess.call(["SetFile", "-a", "V", bg_path]) + disk.update(registering_applications=False) + sleep(2) + disk.eject() + + if verbose >= 2: + print "+ Finalizing .dmg disk image +" + + try: + runHDIUtil("convert", dmg_name + ".temp", format="UDBZ", o=dmg_name + ".dmg", ov=True) + except subprocess.CalledProcessError as e: + sys.exit(e.returncode) + + os.unlink(dmg_name + ".temp.dmg") + +# ------------------------------------------------ + +if verbose >= 2: + print "+ Done +" + +sys.exit(0) diff --git a/contrib/macdeploy/notes.txt b/contrib/macdeploy/notes.txt new file mode 100644 index 0000000..0b809b0 --- /dev/null +++ b/contrib/macdeploy/notes.txt @@ -0,0 +1,26 @@ + +macdeployqtplus works best on OS X Lion, for Snow Leopard you'd need to install +Python 2.7 and make it your default Python installation. + +You will need the appscript package for the fancy disk image creation to work. +Install it by invoking "sudo easy_install appscript". + +Ths script should be invoked in the target directory like this: +$source_dir/contrib/macdeploy/macdeployqtplus ArepaCoin-Qt.app -add-qt-tr da,de,es,hu,ru,uk,zh_CN,zh_TW -dmg -fancy $source_dir/contrib/macdeploy/fancy.plist -verbose 2 + +During the process, the disk image window will pop up briefly where the fancy +settings are applied. This is normal, please do not interfere. + +You can also set up Qt Creator for invoking the script. For this, go to the +"Projects" tab on the left side, switch to "Run Settings" above and add a +deploy configuration. Next add a deploy step choosing "Custom Process Step". +Fill in the following. + +Enable custom process step: [x] +Command: %{sourceDir}/contrib/macdeploy/macdeployqtplus +Working directory: %{buildDir} +Command arguments: ArepaCoin-Qt.app -add-qt-tr da,de,es,hu,ru,uk,zh_CN,zh_TW -dmg -fancy %{sourceDir}/contrib/macdeploy/fancy.plist -verbose 2 + +After that you can start the deployment process through the menu with +Build -> Deploy Project "arepacoin-qt" + diff --git a/contrib/qt_translations.py b/contrib/qt_translations.py new file mode 100644 index 0000000..fd8a8b7 --- /dev/null +++ b/contrib/qt_translations.py @@ -0,0 +1,22 @@ +#!/usr/bin/env python + +# Helpful little script that spits out a comma-separated list of +# language codes for Qt icons that should be included +# in binary bitcoin distributions + +import glob +import os +import re +import sys + +if len(sys.argv) != 3: + sys.exit("Usage: %s $QTDIR/translations $BITCOINDIR/src/qt/locale"%sys.argv[0]) + +d1 = sys.argv[1] +d2 = sys.argv[2] + +l1 = set([ re.search(r'qt_(.*).qm', f).group(1) for f in glob.glob(os.path.join(d1, 'qt_*.qm')) ]) +l2 = set([ re.search(r'bitcoin_(.*).qm', f).group(1) for f in glob.glob(os.path.join(d2, 'bitcoin_*.qm')) ]) + +print ",".join(sorted(l1.intersection(l2))) + diff --git a/contrib/wallettools/walletchangepass.py b/contrib/wallettools/walletchangepass.py new file mode 100644 index 0000000..30f3f5b --- /dev/null +++ b/contrib/wallettools/walletchangepass.py @@ -0,0 +1,5 @@ +from jsonrpc import ServiceProxy +access = ServiceProxy("http://127.0.0.1:8332") +pwd = raw_input("Enter old wallet passphrase: ") +pwd2 = raw_input("Enter new wallet passphrase: ") +access.walletpassphrasechange(pwd, pwd2) \ No newline at end of file diff --git a/contrib/wallettools/walletunlock.py b/contrib/wallettools/walletunlock.py new file mode 100644 index 0000000..f847c6f --- /dev/null +++ b/contrib/wallettools/walletunlock.py @@ -0,0 +1,4 @@ +from jsonrpc import ServiceProxy +access = ServiceProxy("http://127.0.0.1:8332") +pwd = raw_input("Enter wallet passphrase: ") +access.walletpassphrase(pwd, 60) \ No newline at end of file diff --git a/doc/Doxyfile b/doc/Doxyfile new file mode 100644 index 0000000..08d4f8c --- /dev/null +++ b/doc/Doxyfile @@ -0,0 +1,1752 @@ +# Doxyfile 1.7.4 + +# !!! Invoke doxygen from project root using: +# doxygen doc/Doxyfile + +# This file describes the settings to be used by the documentation system +# doxygen (www.doxygen.org) for a project +# +# All text after a hash (#) is considered a comment and will be ignored +# The format is: +# TAG = value [value, ...] +# For lists items can also be appended using: +# TAG += value [value, ...] +# Values that contain spaces should be placed between quotes (" ") + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- + +# This tag specifies the encoding used for all characters in the config file +# that follow. The default is UTF-8 which is also the encoding used for all +# text before the first occurrence of this tag. Doxygen uses libiconv (or the +# iconv built into libc) for the transcoding. See +# http://www.gnu.org/software/libiconv for the list of possible encodings. + +DOXYFILE_ENCODING = UTF-8 + +# The PROJECT_NAME tag is a single word (or a sequence of words surrounded +# by quotes) that should identify the project. + +PROJECT_NAME = Bitcoin + +# The PROJECT_NUMBER tag can be used to enter a project or revision number. +# This could be handy for archiving the generated documentation or +# if some version control system is used. + +PROJECT_NUMBER = 0.5.0 + +# Using the PROJECT_BRIEF tag one can provide an optional one line description +# for a project that appears at the top of each page and should give viewer +# a quick idea about the purpose of the project. Keep the description short. + +PROJECT_BRIEF = "P2P Digital Currency" + +# With the PROJECT_LOGO tag one can specify an logo or icon that is +# included in the documentation. The maximum height of the logo should not +# exceed 55 pixels and the maximum width should not exceed 200 pixels. +# Doxygen will copy the logo to the output directory. + +PROJECT_LOGO = doc/bitcoin_logo_doxygen.png + +# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) +# base path where the generated documentation will be put. +# If a relative path is entered, it will be relative to the location +# where doxygen was started. If left blank the current directory will be used. + +OUTPUT_DIRECTORY = doc/doxygen + +# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create +# 4096 sub-directories (in 2 levels) under the output directory of each output +# format and will distribute the generated files over these directories. +# Enabling this option can be useful when feeding doxygen a huge amount of +# source files, where putting all generated files in the same directory would +# otherwise cause performance problems for the file system. + +CREATE_SUBDIRS = NO + +# The OUTPUT_LANGUAGE tag is used to specify the language in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all constant output in the proper language. +# The default language is English, other supported languages are: +# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional, +# Croatian, Czech, Danish, Dutch, Esperanto, Farsi, Finnish, French, German, +# Greek, Hungarian, Italian, Japanese, Japanese-en (Japanese with English +# messages), Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian, +# Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrillic, Slovak, +# Slovene, Spanish, Swedish, Ukrainian, and Vietnamese. + +OUTPUT_LANGUAGE = English + +# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will +# include brief member descriptions after the members that are listed in +# the file and class documentation (similar to JavaDoc). +# Set to NO to disable this. + +BRIEF_MEMBER_DESC = YES + +# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend +# the brief description of a member or function before the detailed description. +# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the +# brief descriptions will be completely suppressed. + +REPEAT_BRIEF = YES + +# This tag implements a quasi-intelligent brief description abbreviator +# that is used to form the text in various listings. Each string +# in this list, if found as the leading text of the brief description, will be +# stripped from the text and the result after processing the whole list, is +# used as the annotated text. Otherwise, the brief description is used as-is. +# If left blank, the following values are used ("$name" is automatically +# replaced with the name of the entity): "The $name class" "The $name widget" +# "The $name file" "is" "provides" "specifies" "contains" +# "represents" "a" "an" "the" + +ABBREVIATE_BRIEF = "The $name class" \ + "The $name widget" \ + "The $name file" \ + is \ + provides \ + specifies \ + contains \ + represents \ + a \ + an \ + the + +# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then +# Doxygen will generate a detailed section even if there is only a brief +# description. + +ALWAYS_DETAILED_SEC = NO + +# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all +# inherited members of a class in the documentation of that class as if those +# members were ordinary class members. Constructors, destructors and assignment +# operators of the base classes will not be shown. + +INLINE_INHERITED_MEMB = NO + +# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full +# path before files name in the file list and in the header files. If set +# to NO the shortest path that makes the file name unique will be used. + +FULL_PATH_NAMES = YES + +# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag +# can be used to strip a user-defined part of the path. Stripping is +# only done if one of the specified strings matches the left-hand part of +# the path. The tag can be used to show relative paths in the file list. +# If left blank the directory from which doxygen is run is used as the +# path to strip. + +STRIP_FROM_PATH = + +# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of +# the path mentioned in the documentation of a class, which tells +# the reader which header file to include in order to use a class. +# If left blank only the name of the header file containing the class +# definition is used. Otherwise one should specify the include paths that +# are normally passed to the compiler using the -I flag. + +STRIP_FROM_INC_PATH = + +# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter +# (but less readable) file names. This can be useful if your file system +# doesn't support long names like on DOS, Mac, or CD-ROM. + +SHORT_NAMES = NO + +# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen +# will interpret the first line (until the first dot) of a JavaDoc-style +# comment as the brief description. If set to NO, the JavaDoc +# comments will behave just like regular Qt-style comments +# (thus requiring an explicit @brief command for a brief description.) + +JAVADOC_AUTOBRIEF = YES + +# If the QT_AUTOBRIEF tag is set to YES then Doxygen will +# interpret the first line (until the first dot) of a Qt-style +# comment as the brief description. If set to NO, the comments +# will behave just like regular Qt-style comments (thus requiring +# an explicit \brief command for a brief description.) + +QT_AUTOBRIEF = NO + +# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen +# treat a multi-line C++ special comment block (i.e. a block of //! or /// +# comments) as a brief description. This used to be the default behaviour. +# The new default is to treat a multi-line C++ comment block as a detailed +# description. Set this tag to YES if you prefer the old behaviour instead. + +MULTILINE_CPP_IS_BRIEF = NO + +# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented +# member inherits the documentation from any documented member that it +# re-implements. + +INHERIT_DOCS = YES + +# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce +# a new page for each member. If set to NO, the documentation of a member will +# be part of the file/class/namespace that contains it. + +SEPARATE_MEMBER_PAGES = NO + +# The TAB_SIZE tag can be used to set the number of spaces in a tab. +# Doxygen uses this value to replace tabs by spaces in code fragments. + +TAB_SIZE = 8 + +# This tag can be used to specify a number of aliases that acts +# as commands in the documentation. An alias has the form "name=value". +# For example adding "sideeffect=\par Side Effects:\n" will allow you to +# put the command \sideeffect (or @sideeffect) in the documentation, which +# will result in a user-defined paragraph with heading "Side Effects:". +# You can put \n's in the value part of an alias to insert newlines. + +ALIASES = + +# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C +# sources only. Doxygen will then generate output that is more tailored for C. +# For instance, some of the names that are used will be different. The list +# of all members will be omitted, etc. + +OPTIMIZE_OUTPUT_FOR_C = NO + +# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java +# sources only. Doxygen will then generate output that is more tailored for +# Java. For instance, namespaces will be presented as packages, qualified +# scopes will look different, etc. + +OPTIMIZE_OUTPUT_JAVA = NO + +# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran +# sources only. Doxygen will then generate output that is more tailored for +# Fortran. + +OPTIMIZE_FOR_FORTRAN = NO + +# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL +# sources. Doxygen will then generate output that is tailored for +# VHDL. + +OPTIMIZE_OUTPUT_VHDL = NO + +# Doxygen selects the parser to use depending on the extension of the files it +# parses. With this tag you can assign which parser to use for a given extension. +# Doxygen has a built-in mapping, but you can override or extend it using this +# tag. The format is ext=language, where ext is a file extension, and language +# is one of the parsers supported by doxygen: IDL, Java, Javascript, CSharp, C, +# C++, D, PHP, Objective-C, Python, Fortran, VHDL, C, C++. For instance to make +# doxygen treat .inc files as Fortran files (default is PHP), and .f files as C +# (default is Fortran), use: inc=Fortran f=C. Note that for custom extensions +# you also need to set FILE_PATTERNS otherwise the files are not read by doxygen. + +EXTENSION_MAPPING = + +# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want +# to include (a tag file for) the STL sources as input, then you should +# set this tag to YES in order to let doxygen match functions declarations and +# definitions whose arguments contain STL classes (e.g. func(std::string); v.s. +# func(std::string) {}). This also makes the inheritance and collaboration +# diagrams that involve STL classes more complete and accurate. + +BUILTIN_STL_SUPPORT = NO + +# If you use Microsoft's C++/CLI language, you should set this option to YES to +# enable parsing support. + +CPP_CLI_SUPPORT = NO + +# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only. +# Doxygen will parse them like normal C++ but will assume all classes use public +# instead of private inheritance when no explicit protection keyword is present. + +SIP_SUPPORT = NO + +# For Microsoft's IDL there are propget and propput attributes to indicate getter +# and setter methods for a property. Setting this option to YES (the default) +# will make doxygen replace the get and set methods by a property in the +# documentation. This will only work if the methods are indeed getting or +# setting a simple type. If this is not the case, or you want to show the +# methods anyway, you should set this option to NO. + +IDL_PROPERTY_SUPPORT = YES + +# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC +# tag is set to YES, then doxygen will reuse the documentation of the first +# member in the group (if any) for the other members of the group. By default +# all members of a group must be documented explicitly. + +DISTRIBUTE_GROUP_DOC = NO + +# Set the SUBGROUPING tag to YES (the default) to allow class member groups of +# the same type (for instance a group of public functions) to be put as a +# subgroup of that type (e.g. under the Public Functions section). Set it to +# NO to prevent subgrouping. Alternatively, this can be done per class using +# the \nosubgrouping command. + +SUBGROUPING = YES + +# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and +# unions are shown inside the group in which they are included (e.g. using +# @ingroup) instead of on a separate page (for HTML and Man pages) or +# section (for LaTeX and RTF). + +INLINE_GROUPED_CLASSES = NO + +# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum +# is documented as struct, union, or enum with the name of the typedef. So +# typedef struct TypeS {} TypeT, will appear in the documentation as a struct +# with name TypeT. When disabled the typedef will appear as a member of a file, +# namespace, or class. And the struct will be named TypeS. This can typically +# be useful for C code in case the coding convention dictates that all compound +# types are typedef'ed and only the typedef is referenced, never the tag name. + +TYPEDEF_HIDES_STRUCT = NO + +# The SYMBOL_CACHE_SIZE determines the size of the internal cache use to +# determine which symbols to keep in memory and which to flush to disk. +# When the cache is full, less often used symbols will be written to disk. +# For small to medium size projects (<1000 input files) the default value is +# probably good enough. For larger projects a too small cache size can cause +# doxygen to be busy swapping symbols to and from disk most of the time +# causing a significant performance penalty. +# If the system has enough physical memory increasing the cache will improve the +# performance by keeping more symbols in memory. Note that the value works on +# a logarithmic scale so increasing the size by one will roughly double the +# memory usage. The cache size is given by this formula: +# 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0, +# corresponding to a cache size of 2^16 = 65536 symbols + +SYMBOL_CACHE_SIZE = 0 + +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- + +# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in +# documentation are documented, even if no documentation was available. +# Private class members and static file members will be hidden unless +# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES + +EXTRACT_ALL = YES + +# If the EXTRACT_PRIVATE tag is set to YES all private members of a class +# will be included in the documentation. + +EXTRACT_PRIVATE = YES + +# If the EXTRACT_STATIC tag is set to YES all static members of a file +# will be included in the documentation. + +EXTRACT_STATIC = NO + +# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) +# defined locally in source files will be included in the documentation. +# If set to NO only classes defined in header files are included. + +EXTRACT_LOCAL_CLASSES = YES + +# This flag is only useful for Objective-C code. When set to YES local +# methods, which are defined in the implementation section but not in +# the interface are included in the documentation. +# If set to NO (the default) only methods in the interface are included. + +EXTRACT_LOCAL_METHODS = NO + +# If this flag is set to YES, the members of anonymous namespaces will be +# extracted and appear in the documentation as a namespace called +# 'anonymous_namespace{file}', where file will be replaced with the base +# name of the file that contains the anonymous namespace. By default +# anonymous namespaces are hidden. + +EXTRACT_ANON_NSPACES = NO + +# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all +# undocumented members of documented classes, files or namespaces. +# If set to NO (the default) these members will be included in the +# various overviews, but no documentation section is generated. +# This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_MEMBERS = NO + +# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all +# undocumented classes that are normally visible in the class hierarchy. +# If set to NO (the default) these classes will be included in the various +# overviews. This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_CLASSES = NO + +# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all +# friend (class|struct|union) declarations. +# If set to NO (the default) these declarations will be included in the +# documentation. + +HIDE_FRIEND_COMPOUNDS = NO + +# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any +# documentation blocks found inside the body of a function. +# If set to NO (the default) these blocks will be appended to the +# function's detailed documentation block. + +HIDE_IN_BODY_DOCS = NO + +# The INTERNAL_DOCS tag determines if documentation +# that is typed after a \internal command is included. If the tag is set +# to NO (the default) then the documentation will be excluded. +# Set it to YES to include the internal documentation. + +INTERNAL_DOCS = NO + +# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate +# file names in lower-case letters. If set to YES upper-case letters are also +# allowed. This is useful if you have classes or files whose names only differ +# in case and if your file system supports case sensitive file names. Windows +# and Mac users are advised to set this option to NO. + +CASE_SENSE_NAMES = NO + +# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen +# will show members with their full class and namespace scopes in the +# documentation. If set to YES the scope will be hidden. + +HIDE_SCOPE_NAMES = NO + +# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen +# will put a list of the files that are included by a file in the documentation +# of that file. + +SHOW_INCLUDE_FILES = YES + +# If the FORCE_LOCAL_INCLUDES tag is set to YES then Doxygen +# will list include files with double quotes in the documentation +# rather than with sharp brackets. + +FORCE_LOCAL_INCLUDES = NO + +# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] +# is inserted in the documentation for inline members. + +INLINE_INFO = YES + +# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen +# will sort the (detailed) documentation of file and class members +# alphabetically by member name. If set to NO the members will appear in +# declaration order. + +SORT_MEMBER_DOCS = YES + +# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the +# brief documentation of file, namespace and class members alphabetically +# by member name. If set to NO (the default) the members will appear in +# declaration order. + +SORT_BRIEF_DOCS = NO + +# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen +# will sort the (brief and detailed) documentation of class members so that +# constructors and destructors are listed first. If set to NO (the default) +# the constructors will appear in the respective orders defined by +# SORT_MEMBER_DOCS and SORT_BRIEF_DOCS. +# This tag will be ignored for brief docs if SORT_BRIEF_DOCS is set to NO +# and ignored for detailed docs if SORT_MEMBER_DOCS is set to NO. + +SORT_MEMBERS_CTORS_1ST = NO + +# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the +# hierarchy of group names into alphabetical order. If set to NO (the default) +# the group names will appear in their defined order. + +SORT_GROUP_NAMES = NO + +# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be +# sorted by fully-qualified names, including namespaces. If set to +# NO (the default), the class list will be sorted only by class name, +# not including the namespace part. +# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. +# Note: This option applies only to the class list, not to the +# alphabetical list. + +SORT_BY_SCOPE_NAME = NO + +# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to +# do proper type resolution of all parameters of a function it will reject a +# match between the prototype and the implementation of a member function even +# if there is only one candidate or it is obvious which candidate to choose +# by doing a simple string match. By disabling STRICT_PROTO_MATCHING doxygen +# will still accept a match between prototype and implementation in such cases. + +STRICT_PROTO_MATCHING = NO + +# The GENERATE_TODOLIST tag can be used to enable (YES) or +# disable (NO) the todo list. This list is created by putting \todo +# commands in the documentation. + +GENERATE_TODOLIST = YES + +# The GENERATE_TESTLIST tag can be used to enable (YES) or +# disable (NO) the test list. This list is created by putting \test +# commands in the documentation. + +GENERATE_TESTLIST = YES + +# The GENERATE_BUGLIST tag can be used to enable (YES) or +# disable (NO) the bug list. This list is created by putting \bug +# commands in the documentation. + +GENERATE_BUGLIST = YES + +# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or +# disable (NO) the deprecated list. This list is created by putting +# \deprecated commands in the documentation. + +GENERATE_DEPRECATEDLIST= YES + +# The ENABLED_SECTIONS tag can be used to enable conditional +# documentation sections, marked by \if sectionname ... \endif. + +ENABLED_SECTIONS = + +# The MAX_INITIALIZER_LINES tag determines the maximum number of lines +# the initial value of a variable or macro consists of for it to appear in +# the documentation. If the initializer consists of more lines than specified +# here it will be hidden. Use a value of 0 to hide initializers completely. +# The appearance of the initializer of individual variables and macros in the +# documentation can be controlled using \showinitializer or \hideinitializer +# command in the documentation regardless of this setting. + +MAX_INITIALIZER_LINES = 30 + +# Set the SHOW_USED_FILES tag to NO to disable the list of files generated +# at the bottom of the documentation of classes and structs. If set to YES the +# list will mention the files that were used to generate the documentation. + +SHOW_USED_FILES = YES + +# If the sources in your project are distributed over multiple directories +# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy +# in the documentation. The default is NO. + +SHOW_DIRECTORIES = NO + +# Set the SHOW_FILES tag to NO to disable the generation of the Files page. +# This will remove the Files entry from the Quick Index and from the +# Folder Tree View (if specified). The default is YES. + +SHOW_FILES = YES + +# Set the SHOW_NAMESPACES tag to NO to disable the generation of the +# Namespaces page. This will remove the Namespaces entry from the Quick Index +# and from the Folder Tree View (if specified). The default is YES. + +SHOW_NAMESPACES = YES + +# The FILE_VERSION_FILTER tag can be used to specify a program or script that +# doxygen should invoke to get the current version for each file (typically from +# the version control system). Doxygen will invoke the program by executing (via +# popen()) the command , where is the value of +# the FILE_VERSION_FILTER tag, and is the name of an input file +# provided by doxygen. Whatever the program writes to standard output +# is used as the file version. See the manual for examples. + +FILE_VERSION_FILTER = + +# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed +# by doxygen. The layout file controls the global structure of the generated +# output files in an output format independent way. The create the layout file +# that represents doxygen's defaults, run doxygen with the -l option. +# You can optionally specify a file name after the option, if omitted +# DoxygenLayout.xml will be used as the name of the layout file. + +LAYOUT_FILE = + +#--------------------------------------------------------------------------- +# configuration options related to warning and progress messages +#--------------------------------------------------------------------------- + +# The QUIET tag can be used to turn on/off the messages that are generated +# by doxygen. Possible values are YES and NO. If left blank NO is used. + +QUIET = NO + +# The WARNINGS tag can be used to turn on/off the warning messages that are +# generated by doxygen. Possible values are YES and NO. If left blank +# NO is used. + +WARNINGS = YES + +# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings +# for undocumented members. If EXTRACT_ALL is set to YES then this flag will +# automatically be disabled. + +WARN_IF_UNDOCUMENTED = YES + +# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for +# potential errors in the documentation, such as not documenting some +# parameters in a documented function, or documenting parameters that +# don't exist or using markup commands wrongly. + +WARN_IF_DOC_ERROR = YES + +# The WARN_NO_PARAMDOC option can be enabled to get warnings for +# functions that are documented, but have no documentation for their parameters +# or return value. If set to NO (the default) doxygen will only warn about +# wrong or incomplete parameter documentation, but not about the absence of +# documentation. + +WARN_NO_PARAMDOC = NO + +# The WARN_FORMAT tag determines the format of the warning messages that +# doxygen can produce. The string should contain the $file, $line, and $text +# tags, which will be replaced by the file and line number from which the +# warning originated and the warning text. Optionally the format may contain +# $version, which will be replaced by the version of the file (if it could +# be obtained via FILE_VERSION_FILTER) + +WARN_FORMAT = "$file:$line: $text" + +# The WARN_LOGFILE tag can be used to specify a file to which warning +# and error messages should be written. If left blank the output is written +# to stderr. + +WARN_LOGFILE = + +#--------------------------------------------------------------------------- +# configuration options related to the input files +#--------------------------------------------------------------------------- + +# The INPUT tag can be used to specify the files and/or directories that contain +# documented source files. You may enter file names like "myfile.cpp" or +# directories like "/usr/src/myproject". Separate the files or directories +# with spaces. + +INPUT = src + +# This tag can be used to specify the character encoding of the source files +# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is +# also the default input encoding. Doxygen uses libiconv (or the iconv built +# into libc) for the transcoding. See http://www.gnu.org/software/libiconv for +# the list of possible encodings. + +INPUT_ENCODING = UTF-8 + +# If the value of the INPUT tag contains directories, you can use the +# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank the following patterns are tested: +# *.c *.cc *.cxx *.cpp *.c++ *.d *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh +# *.hxx *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.dox *.py +# *.f90 *.f *.for *.vhd *.vhdl + +FILE_PATTERNS = *.c \ + *.cc \ + *.cxx \ + *.cpp \ + *.c++ \ + *.d \ + *.java \ + *.ii \ + *.ixx \ + *.ipp \ + *.i++ \ + *.inl \ + *.h \ + *.hh \ + *.hxx \ + *.hpp \ + *.h++ \ + *.idl \ + *.odl \ + *.cs \ + *.php \ + *.php3 \ + *.inc \ + *.m \ + *.mm \ + *.dox \ + *.py \ + *.f90 \ + *.f \ + *.for \ + *.vhd \ + *.vhdl + +# The RECURSIVE tag can be used to turn specify whether or not subdirectories +# should be searched for input files as well. Possible values are YES and NO. +# If left blank NO is used. + +RECURSIVE = YES + +# The EXCLUDE tag can be used to specify files and/or directories that should +# excluded from the INPUT source files. This way you can easily exclude a +# subdirectory from a directory tree whose root is specified with the INPUT tag. + +EXCLUDE = + +# The EXCLUDE_SYMLINKS tag can be used select whether or not files or +# directories that are symbolic links (a Unix file system feature) are excluded +# from the input. + +EXCLUDE_SYMLINKS = NO + +# If the value of the INPUT tag contains directories, you can use the +# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude +# certain files from those directories. Note that the wildcards are matched +# against the file with absolute path, so to exclude all test directories +# for example use the pattern */test/* + +EXCLUDE_PATTERNS = + +# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names +# (namespaces, classes, functions, etc.) that should be excluded from the +# output. The symbol name can be a fully qualified name, a word, or if the +# wildcard * is used, a substring. Examples: ANamespace, AClass, +# AClass::ANamespace, ANamespace::*Test + +EXCLUDE_SYMBOLS = + +# The EXAMPLE_PATH tag can be used to specify one or more files or +# directories that contain example code fragments that are included (see +# the \include command). + +EXAMPLE_PATH = + +# If the value of the EXAMPLE_PATH tag contains directories, you can use the +# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank all files are included. + +EXAMPLE_PATTERNS = * + +# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be +# searched for input files to be used with the \include or \dontinclude +# commands irrespective of the value of the RECURSIVE tag. +# Possible values are YES and NO. If left blank NO is used. + +EXAMPLE_RECURSIVE = NO + +# The IMAGE_PATH tag can be used to specify one or more files or +# directories that contain image that are included in the documentation (see +# the \image command). + +IMAGE_PATH = + +# The INPUT_FILTER tag can be used to specify a program that doxygen should +# invoke to filter for each input file. Doxygen will invoke the filter program +# by executing (via popen()) the command , where +# is the value of the INPUT_FILTER tag, and is the name of an +# input file. Doxygen will then use the output that the filter program writes +# to standard output. If FILTER_PATTERNS is specified, this tag will be +# ignored. + +INPUT_FILTER = + +# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern +# basis. Doxygen will compare the file name with each pattern and apply the +# filter if there is a match. The filters are a list of the form: +# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further +# info on how filters are used. If FILTER_PATTERNS is empty or if +# non of the patterns match the file name, INPUT_FILTER is applied. + +FILTER_PATTERNS = + +# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using +# INPUT_FILTER) will be used to filter the input files when producing source +# files to browse (i.e. when SOURCE_BROWSER is set to YES). + +FILTER_SOURCE_FILES = NO + +# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file +# pattern. A pattern will override the setting for FILTER_PATTERN (if any) +# and it is also possible to disable source filtering for a specific pattern +# using *.ext= (so without naming a filter). This option only has effect when +# FILTER_SOURCE_FILES is enabled. + +FILTER_SOURCE_PATTERNS = + +#--------------------------------------------------------------------------- +# configuration options related to source browsing +#--------------------------------------------------------------------------- + +# If the SOURCE_BROWSER tag is set to YES then a list of source files will +# be generated. Documented entities will be cross-referenced with these sources. +# Note: To get rid of all source code in the generated output, make sure also +# VERBATIM_HEADERS is set to NO. + +SOURCE_BROWSER = YES + +# Setting the INLINE_SOURCES tag to YES will include the body +# of functions and classes directly in the documentation. + +INLINE_SOURCES = NO + +# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct +# doxygen to hide any special comment blocks from generated source code +# fragments. Normal C and C++ comments will always remain visible. + +STRIP_CODE_COMMENTS = YES + +# If the REFERENCED_BY_RELATION tag is set to YES +# then for each documented function all documented +# functions referencing it will be listed. + +REFERENCED_BY_RELATION = NO + +# If the REFERENCES_RELATION tag is set to YES +# then for each documented function all documented entities +# called/used by that function will be listed. + +REFERENCES_RELATION = NO + +# If the REFERENCES_LINK_SOURCE tag is set to YES (the default) +# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from +# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will +# link to the source code. Otherwise they will link to the documentation. + +REFERENCES_LINK_SOURCE = YES + +# If the USE_HTAGS tag is set to YES then the references to source code +# will point to the HTML generated by the htags(1) tool instead of doxygen +# built-in source browser. The htags tool is part of GNU's global source +# tagging system (see http://www.gnu.org/software/global/global.html). You +# will need version 4.8.6 or higher. + +USE_HTAGS = NO + +# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen +# will generate a verbatim copy of the header file for each class for +# which an include is specified. Set to NO to disable this. + +VERBATIM_HEADERS = YES + +#--------------------------------------------------------------------------- +# configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- + +# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index +# of all compounds will be generated. Enable this if the project +# contains a lot of classes, structs, unions or interfaces. + +ALPHABETICAL_INDEX = YES + +# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then +# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns +# in which this list will be split (can be a number in the range [1..20]) + +COLS_IN_ALPHA_INDEX = 5 + +# In case all classes in a project start with a common prefix, all +# classes will be put under the same header in the alphabetical index. +# The IGNORE_PREFIX tag can be used to specify one or more prefixes that +# should be ignored while generating the index headers. + +IGNORE_PREFIX = + +#--------------------------------------------------------------------------- +# configuration options related to the HTML output +#--------------------------------------------------------------------------- + +# If the GENERATE_HTML tag is set to YES (the default) Doxygen will +# generate HTML output. + +GENERATE_HTML = YES + +# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `html' will be used as the default path. + +HTML_OUTPUT = html + +# The HTML_FILE_EXTENSION tag can be used to specify the file extension for +# each generated HTML page (for example: .htm,.php,.asp). If it is left blank +# doxygen will generate files with .html extension. + +HTML_FILE_EXTENSION = .html + +# The HTML_HEADER tag can be used to specify a personal HTML header for +# each generated HTML page. If it is left blank doxygen will generate a +# standard header. Note that when using a custom header you are responsible +# for the proper inclusion of any scripts and style sheets that doxygen +# needs, which is dependent on the configuration options used. +# It is adviced to generate a default header using "doxygen -w html +# header.html footer.html stylesheet.css YourConfigFile" and then modify +# that header. Note that the header is subject to change so you typically +# have to redo this when upgrading to a newer version of doxygen or when +# changing the value of configuration settings such as GENERATE_TREEVIEW! + +HTML_HEADER = + +# The HTML_FOOTER tag can be used to specify a personal HTML footer for +# each generated HTML page. If it is left blank doxygen will generate a +# standard footer. + +HTML_FOOTER = + +# The HTML_STYLESHEET tag can be used to specify a user-defined cascading +# style sheet that is used by each HTML page. It can be used to +# fine-tune the look of the HTML output. If the tag is left blank doxygen +# will generate a default style sheet. Note that doxygen will try to copy +# the style sheet file to the HTML output directory, so don't put your own +# stylesheet in the HTML output directory as well, or it will be erased! + +HTML_STYLESHEET = + +# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or +# other source files which should be copied to the HTML output directory. Note +# that these files will be copied to the base HTML output directory. Use the +# $relpath$ marker in the HTML_HEADER and/or HTML_FOOTER files to load these +# files. In the HTML_STYLESHEET file, use the file name only. Also note that +# the files will be copied as-is; there are no commands or markers available. + +HTML_EXTRA_FILES = + +# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. +# Doxygen will adjust the colors in the stylesheet and background images +# according to this color. Hue is specified as an angle on a colorwheel, +# see http://en.wikipedia.org/wiki/Hue for more information. +# For instance the value 0 represents red, 60 is yellow, 120 is green, +# 180 is cyan, 240 is blue, 300 purple, and 360 is red again. +# The allowed range is 0 to 359. + +HTML_COLORSTYLE_HUE = 220 + +# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of +# the colors in the HTML output. For a value of 0 the output will use +# grayscales only. A value of 255 will produce the most vivid colors. + +HTML_COLORSTYLE_SAT = 100 + +# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to +# the luminance component of the colors in the HTML output. Values below +# 100 gradually make the output lighter, whereas values above 100 make +# the output darker. The value divided by 100 is the actual gamma applied, +# so 80 represents a gamma of 0.8, The value 220 represents a gamma of 2.2, +# and 100 does not change the gamma. + +HTML_COLORSTYLE_GAMMA = 80 + +# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML +# page will contain the date and time when the page was generated. Setting +# this to NO can help when comparing the output of multiple runs. + +HTML_TIMESTAMP = YES + +# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, +# files or namespaces will be aligned in HTML using tables. If set to +# NO a bullet list will be used. + +HTML_ALIGN_MEMBERS = YES + +# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML +# documentation will contain sections that can be hidden and shown after the +# page has loaded. For this to work a browser that supports +# JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox +# Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari). + +HTML_DYNAMIC_SECTIONS = NO + +# If the GENERATE_DOCSET tag is set to YES, additional index files +# will be generated that can be used as input for Apple's Xcode 3 +# integrated development environment, introduced with OSX 10.5 (Leopard). +# To create a documentation set, doxygen will generate a Makefile in the +# HTML output directory. Running make will produce the docset in that +# directory and running "make install" will install the docset in +# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find +# it at startup. +# See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html +# for more information. + +GENERATE_DOCSET = NO + +# When GENERATE_DOCSET tag is set to YES, this tag determines the name of the +# feed. A documentation feed provides an umbrella under which multiple +# documentation sets from a single provider (such as a company or product suite) +# can be grouped. + +DOCSET_FEEDNAME = "Doxygen generated docs" + +# When GENERATE_DOCSET tag is set to YES, this tag specifies a string that +# should uniquely identify the documentation set bundle. This should be a +# reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen +# will append .docset to the name. + +DOCSET_BUNDLE_ID = org.doxygen.Project + +# When GENERATE_PUBLISHER_ID tag specifies a string that should uniquely identify +# the documentation publisher. This should be a reverse domain-name style +# string, e.g. com.mycompany.MyDocSet.documentation. + +DOCSET_PUBLISHER_ID = org.doxygen.Publisher + +# The GENERATE_PUBLISHER_NAME tag identifies the documentation publisher. + +DOCSET_PUBLISHER_NAME = Publisher + +# If the GENERATE_HTMLHELP tag is set to YES, additional index files +# will be generated that can be used as input for tools like the +# Microsoft HTML help workshop to generate a compiled HTML help file (.chm) +# of the generated HTML documentation. + +GENERATE_HTMLHELP = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can +# be used to specify the file name of the resulting .chm file. You +# can add a path in front of the file if the result should not be +# written to the html output directory. + +CHM_FILE = + +# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can +# be used to specify the location (absolute path including file name) of +# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run +# the HTML help compiler on the generated index.hhp. + +HHC_LOCATION = + +# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag +# controls if a separate .chi index file is generated (YES) or that +# it should be included in the master .chm file (NO). + +GENERATE_CHI = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING +# is used to encode HtmlHelp index (hhk), content (hhc) and project file +# content. + +CHM_INDEX_ENCODING = + +# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag +# controls whether a binary table of contents is generated (YES) or a +# normal table of contents (NO) in the .chm file. + +BINARY_TOC = NO + +# The TOC_EXPAND flag can be set to YES to add extra items for group members +# to the contents of the HTML help documentation and to the tree view. + +TOC_EXPAND = NO + +# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and +# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated +# that can be used as input for Qt's qhelpgenerator to generate a +# Qt Compressed Help (.qch) of the generated HTML documentation. + +GENERATE_QHP = NO + +# If the QHG_LOCATION tag is specified, the QCH_FILE tag can +# be used to specify the file name of the resulting .qch file. +# The path specified is relative to the HTML output folder. + +QCH_FILE = + +# The QHP_NAMESPACE tag specifies the namespace to use when generating +# Qt Help Project output. For more information please see +# http://doc.trolltech.com/qthelpproject.html#namespace + +QHP_NAMESPACE = org.doxygen.Project + +# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating +# Qt Help Project output. For more information please see +# http://doc.trolltech.com/qthelpproject.html#virtual-folders + +QHP_VIRTUAL_FOLDER = doc + +# If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to +# add. For more information please see +# http://doc.trolltech.com/qthelpproject.html#custom-filters + +QHP_CUST_FILTER_NAME = + +# The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the +# custom filter to add. For more information please see +# +# Qt Help Project / Custom Filters. + +QHP_CUST_FILTER_ATTRS = + +# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this +# project's +# filter section matches. +# +# Qt Help Project / Filter Attributes. + +QHP_SECT_FILTER_ATTRS = + +# If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can +# be used to specify the location of Qt's qhelpgenerator. +# If non-empty doxygen will try to run qhelpgenerator on the generated +# .qhp file. + +QHG_LOCATION = + +# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files +# will be generated, which together with the HTML files, form an Eclipse help +# plugin. To install this plugin and make it available under the help contents +# menu in Eclipse, the contents of the directory containing the HTML and XML +# files needs to be copied into the plugins directory of eclipse. The name of +# the directory within the plugins directory should be the same as +# the ECLIPSE_DOC_ID value. After copying Eclipse needs to be restarted before +# the help appears. + +GENERATE_ECLIPSEHELP = NO + +# A unique identifier for the eclipse help plugin. When installing the plugin +# the directory name containing the HTML and XML files should also have +# this name. + +ECLIPSE_DOC_ID = org.doxygen.Project + +# The DISABLE_INDEX tag can be used to turn on/off the condensed index at +# top of each HTML page. The value NO (the default) enables the index and +# the value YES disables it. + +DISABLE_INDEX = NO + +# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values +# (range [0,1..20]) that doxygen will group on one line in the generated HTML +# documentation. Note that a value of 0 will completely suppress the enum +# values from appearing in the overview section. + +ENUM_VALUES_PER_LINE = 4 + +# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index +# structure should be generated to display hierarchical information. +# If the tag value is set to YES, a side panel will be generated +# containing a tree-like index structure (just like the one that +# is generated for HTML Help). For this to work a browser that supports +# JavaScript, DHTML, CSS and frames is required (i.e. any modern browser). +# Windows users are probably better off using the HTML help feature. + +GENERATE_TREEVIEW = NO + +# By enabling USE_INLINE_TREES, doxygen will generate the Groups, Directories, +# and Class Hierarchy pages using a tree view instead of an ordered list. + +USE_INLINE_TREES = NO + +# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be +# used to set the initial width (in pixels) of the frame in which the tree +# is shown. + +TREEVIEW_WIDTH = 250 + +# When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open +# links to external symbols imported via tag files in a separate window. + +EXT_LINKS_IN_WINDOW = NO + +# Use this tag to change the font size of Latex formulas included +# as images in the HTML documentation. The default is 10. Note that +# when you change the font size after a successful doxygen run you need +# to manually remove any form_*.png images from the HTML output directory +# to force them to be regenerated. + +FORMULA_FONTSIZE = 10 + +# Use the FORMULA_TRANPARENT tag to determine whether or not the images +# generated for formulas are transparent PNGs. Transparent PNGs are +# not supported properly for IE 6.0, but are supported on all modern browsers. +# Note that when changing this option you need to delete any form_*.png files +# in the HTML output before the changes have effect. + +FORMULA_TRANSPARENT = YES + +# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax +# (see http://www.mathjax.org) which uses client side Javascript for the +# rendering instead of using prerendered bitmaps. Use this if you do not +# have LaTeX installed or if you want to formulas look prettier in the HTML +# output. When enabled you also need to install MathJax separately and +# configure the path to it using the MATHJAX_RELPATH option. + +USE_MATHJAX = NO + +# When MathJax is enabled you need to specify the location relative to the +# HTML output directory using the MATHJAX_RELPATH option. The destination +# directory should contain the MathJax.js script. For instance, if the mathjax +# directory is located at the same level as the HTML output directory, then +# MATHJAX_RELPATH should be ../mathjax. The default value points to the +# mathjax.org site, so you can quickly see the result without installing +# MathJax, but it is strongly recommended to install a local copy of MathJax +# before deployment. + +MATHJAX_RELPATH = http://www.mathjax.org/mathjax + +# When the SEARCHENGINE tag is enabled doxygen will generate a search box +# for the HTML output. The underlying search engine uses javascript +# and DHTML and should work on any modern browser. Note that when using +# HTML help (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets +# (GENERATE_DOCSET) there is already a search function so this one should +# typically be disabled. For large projects the javascript based search engine +# can be slow, then enabling SERVER_BASED_SEARCH may provide a better solution. + +SEARCHENGINE = YES + +# When the SERVER_BASED_SEARCH tag is enabled the search engine will be +# implemented using a PHP enabled web server instead of at the web client +# using Javascript. Doxygen will generate the search PHP script and index +# file to put on the web server. The advantage of the server +# based approach is that it scales better to large projects and allows +# full text search. The disadvantages are that it is more difficult to setup +# and does not have live searching capabilities. + +SERVER_BASED_SEARCH = NO + +#--------------------------------------------------------------------------- +# configuration options related to the LaTeX output +#--------------------------------------------------------------------------- + +# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will +# generate Latex output. + +GENERATE_LATEX = NO + +# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `latex' will be used as the default path. + +LATEX_OUTPUT = latex + +# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be +# invoked. If left blank `latex' will be used as the default command name. +# Note that when enabling USE_PDFLATEX this option is only used for +# generating bitmaps for formulas in the HTML output, but not in the +# Makefile that is written to the output directory. + +LATEX_CMD_NAME = latex + +# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to +# generate index for LaTeX. If left blank `makeindex' will be used as the +# default command name. + +MAKEINDEX_CMD_NAME = makeindex + +# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact +# LaTeX documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_LATEX = NO + +# The PAPER_TYPE tag can be used to set the paper type that is used +# by the printer. Possible values are: a4, letter, legal and +# executive. If left blank a4wide will be used. + +PAPER_TYPE = a4 + +# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX +# packages that should be included in the LaTeX output. + +EXTRA_PACKAGES = + +# The LATEX_HEADER tag can be used to specify a personal LaTeX header for +# the generated latex document. The header should contain everything until +# the first chapter. If it is left blank doxygen will generate a +# standard header. Notice: only use this tag if you know what you are doing! + +LATEX_HEADER = + +# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for +# the generated latex document. The footer should contain everything after +# the last chapter. If it is left blank doxygen will generate a +# standard footer. Notice: only use this tag if you know what you are doing! + +LATEX_FOOTER = + +# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated +# is prepared for conversion to pdf (using ps2pdf). The pdf file will +# contain links (just like the HTML output) instead of page references +# This makes the output suitable for online browsing using a pdf viewer. + +PDF_HYPERLINKS = YES + +# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of +# plain latex in the generated Makefile. Set this option to YES to get a +# higher quality PDF documentation. + +USE_PDFLATEX = YES + +# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. +# command to the generated LaTeX files. This will instruct LaTeX to keep +# running if errors occur, instead of asking the user for help. +# This option is also used when generating formulas in HTML. + +LATEX_BATCHMODE = NO + +# If LATEX_HIDE_INDICES is set to YES then doxygen will not +# include the index chapters (such as File Index, Compound Index, etc.) +# in the output. + +LATEX_HIDE_INDICES = NO + +# If LATEX_SOURCE_CODE is set to YES then doxygen will include +# source code with syntax highlighting in the LaTeX output. +# Note that which sources are shown also depends on other settings +# such as SOURCE_BROWSER. + +LATEX_SOURCE_CODE = NO + +#--------------------------------------------------------------------------- +# configuration options related to the RTF output +#--------------------------------------------------------------------------- + +# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output +# The RTF output is optimized for Word 97 and may not look very pretty with +# other RTF readers or editors. + +GENERATE_RTF = NO + +# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `rtf' will be used as the default path. + +RTF_OUTPUT = rtf + +# If the COMPACT_RTF tag is set to YES Doxygen generates more compact +# RTF documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_RTF = NO + +# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated +# will contain hyperlink fields. The RTF file will +# contain links (just like the HTML output) instead of page references. +# This makes the output suitable for online browsing using WORD or other +# programs which support those fields. +# Note: wordpad (write) and others do not support links. + +RTF_HYPERLINKS = NO + +# Load stylesheet definitions from file. Syntax is similar to doxygen's +# config file, i.e. a series of assignments. You only have to provide +# replacements, missing definitions are set to their default value. + +RTF_STYLESHEET_FILE = + +# Set optional variables used in the generation of an rtf document. +# Syntax is similar to doxygen's config file. + +RTF_EXTENSIONS_FILE = + +#--------------------------------------------------------------------------- +# configuration options related to the man page output +#--------------------------------------------------------------------------- + +# If the GENERATE_MAN tag is set to YES (the default) Doxygen will +# generate man pages + +GENERATE_MAN = NO + +# The MAN_OUTPUT tag is used to specify where the man pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `man' will be used as the default path. + +MAN_OUTPUT = man + +# The MAN_EXTENSION tag determines the extension that is added to +# the generated man pages (default is the subroutine's section .3) + +MAN_EXTENSION = .3 + +# If the MAN_LINKS tag is set to YES and Doxygen generates man output, +# then it will generate one additional man file for each entity +# documented in the real man page(s). These additional files +# only source the real man page, but without them the man command +# would be unable to find the correct page. The default is NO. + +MAN_LINKS = NO + +#--------------------------------------------------------------------------- +# configuration options related to the XML output +#--------------------------------------------------------------------------- + +# If the GENERATE_XML tag is set to YES Doxygen will +# generate an XML file that captures the structure of +# the code including all documentation. + +GENERATE_XML = NO + +# The XML_OUTPUT tag is used to specify where the XML pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `xml' will be used as the default path. + +XML_OUTPUT = xml + +# The XML_SCHEMA tag can be used to specify an XML schema, +# which can be used by a validating XML parser to check the +# syntax of the XML files. + +XML_SCHEMA = + +# The XML_DTD tag can be used to specify an XML DTD, +# which can be used by a validating XML parser to check the +# syntax of the XML files. + +XML_DTD = + +# If the XML_PROGRAMLISTING tag is set to YES Doxygen will +# dump the program listings (including syntax highlighting +# and cross-referencing information) to the XML output. Note that +# enabling this will significantly increase the size of the XML output. + +XML_PROGRAMLISTING = YES + +#--------------------------------------------------------------------------- +# configuration options for the AutoGen Definitions output +#--------------------------------------------------------------------------- + +# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will +# generate an AutoGen Definitions (see autogen.sf.net) file +# that captures the structure of the code including all +# documentation. Note that this feature is still experimental +# and incomplete at the moment. + +GENERATE_AUTOGEN_DEF = NO + +#--------------------------------------------------------------------------- +# configuration options related to the Perl module output +#--------------------------------------------------------------------------- + +# If the GENERATE_PERLMOD tag is set to YES Doxygen will +# generate a Perl module file that captures the structure of +# the code including all documentation. Note that this +# feature is still experimental and incomplete at the +# moment. + +GENERATE_PERLMOD = NO + +# If the PERLMOD_LATEX tag is set to YES Doxygen will generate +# the necessary Makefile rules, Perl scripts and LaTeX code to be able +# to generate PDF and DVI output from the Perl module output. + +PERLMOD_LATEX = NO + +# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be +# nicely formatted so it can be parsed by a human reader. This is useful +# if you want to understand what is going on. On the other hand, if this +# tag is set to NO the size of the Perl module output will be much smaller +# and Perl will parse it just the same. + +PERLMOD_PRETTY = YES + +# The names of the make variables in the generated doxyrules.make file +# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. +# This is useful so different doxyrules.make files included by the same +# Makefile don't overwrite each other's variables. + +PERLMOD_MAKEVAR_PREFIX = + +#--------------------------------------------------------------------------- +# Configuration options related to the preprocessor +#--------------------------------------------------------------------------- + +# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will +# evaluate all C-preprocessor directives found in the sources and include +# files. + +ENABLE_PREPROCESSING = YES + +# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro +# names in the source code. If set to NO (the default) only conditional +# compilation will be performed. Macro expansion can be done in a controlled +# way by setting EXPAND_ONLY_PREDEF to YES. + +MACRO_EXPANSION = NO + +# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES +# then the macro expansion is limited to the macros specified with the +# PREDEFINED and EXPAND_AS_DEFINED tags. + +EXPAND_ONLY_PREDEF = NO + +# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files +# pointed to by INCLUDE_PATH will be searched when a #include is found. + +SEARCH_INCLUDES = YES + +# The INCLUDE_PATH tag can be used to specify one or more directories that +# contain include files that are not input files but should be processed by +# the preprocessor. + +INCLUDE_PATH = + +# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard +# patterns (like *.h and *.hpp) to filter out the header-files in the +# directories. If left blank, the patterns specified with FILE_PATTERNS will +# be used. + +INCLUDE_FILE_PATTERNS = + +# The PREDEFINED tag can be used to specify one or more macro names that +# are defined before the preprocessor is started (similar to the -D option of +# gcc). The argument of the tag is a list of macros of the form: name +# or name=definition (no spaces). If the definition and the = are +# omitted =1 is assumed. To prevent a macro definition from being +# undefined via #undef or recursively expanded use the := operator +# instead of the = operator. + +PREDEFINED = + +# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then +# this tag can be used to specify a list of macro names that should be expanded. +# The macro definition that is found in the sources will be used. +# Use the PREDEFINED tag if you want to use a different macro definition that +# overrules the definition found in the source code. + +EXPAND_AS_DEFINED = + +# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then +# doxygen's preprocessor will remove all references to function-like macros +# that are alone on a line, have an all uppercase name, and do not end with a +# semicolon, because these will confuse the parser if not removed. + +SKIP_FUNCTION_MACROS = YES + +#--------------------------------------------------------------------------- +# Configuration::additions related to external references +#--------------------------------------------------------------------------- + +# The TAGFILES option can be used to specify one or more tagfiles. +# Optionally an initial location of the external documentation +# can be added for each tagfile. The format of a tag file without +# this location is as follows: +# TAGFILES = file1 file2 ... +# Adding location for the tag files is done as follows: +# TAGFILES = file1=loc1 "file2 = loc2" ... +# where "loc1" and "loc2" can be relative or absolute paths or +# URLs. If a location is present for each tag, the installdox tool +# does not have to be run to correct the links. +# Note that each tag file must have a unique name +# (where the name does NOT include the path) +# If a tag file is not located in the directory in which doxygen +# is run, you must also specify the path to the tagfile here. + +TAGFILES = + +# When a file name is specified after GENERATE_TAGFILE, doxygen will create +# a tag file that is based on the input files it reads. + +GENERATE_TAGFILE = + +# If the ALLEXTERNALS tag is set to YES all external classes will be listed +# in the class index. If set to NO only the inherited external classes +# will be listed. + +ALLEXTERNALS = NO + +# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed +# in the modules index. If set to NO, only the current project's groups will +# be listed. + +EXTERNAL_GROUPS = YES + +# The PERL_PATH should be the absolute path and name of the perl script +# interpreter (i.e. the result of `which perl'). + +PERL_PATH = /usr/bin/perl + +#--------------------------------------------------------------------------- +# Configuration options related to the dot tool +#--------------------------------------------------------------------------- + +# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will +# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base +# or super classes. Setting the tag to NO turns the diagrams off. Note that +# this option also works with HAVE_DOT disabled, but it is recommended to +# install and use dot, since it yields more powerful graphs. + +CLASS_DIAGRAMS = YES + +# You can define message sequence charts within doxygen comments using the \msc +# command. Doxygen will then run the mscgen tool (see +# http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the +# documentation. The MSCGEN_PATH tag allows you to specify the directory where +# the mscgen tool resides. If left empty the tool is assumed to be found in the +# default search path. + +MSCGEN_PATH = + +# If set to YES, the inheritance and collaboration graphs will hide +# inheritance and usage relations if the target is undocumented +# or is not a class. + +HIDE_UNDOC_RELATIONS = YES + +# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is +# available from the path. This tool is part of Graphviz, a graph visualization +# toolkit from AT&T and Lucent Bell Labs. The other options in this section +# have no effect if this option is set to NO (the default) + +HAVE_DOT = NO + +# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is +# allowed to run in parallel. When set to 0 (the default) doxygen will +# base this on the number of processors available in the system. You can set it +# explicitly to a value larger than 0 to get control over the balance +# between CPU load and processing speed. + +DOT_NUM_THREADS = 0 + +# By default doxygen will write a font called Helvetica to the output +# directory and reference it in all dot files that doxygen generates. +# When you want a differently looking font you can specify the font name +# using DOT_FONTNAME. You need to make sure dot is able to find the font, +# which can be done by putting it in a standard location or by setting the +# DOTFONTPATH environment variable or by setting DOT_FONTPATH to the directory +# containing the font. + +DOT_FONTNAME = Helvetica + +# The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs. +# The default size is 10pt. + +DOT_FONTSIZE = 10 + +# By default doxygen will tell dot to use the output directory to look for the +# FreeSans.ttf font (which doxygen will put there itself). If you specify a +# different font using DOT_FONTNAME you can set the path where dot +# can find it using this tag. + +DOT_FONTPATH = + +# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect inheritance relations. Setting this tag to YES will force the +# the CLASS_DIAGRAMS tag to NO. + +CLASS_GRAPH = YES + +# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect implementation dependencies (inheritance, containment, and +# class references variables) of the class with other documented classes. + +COLLABORATION_GRAPH = YES + +# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for groups, showing the direct groups dependencies + +GROUP_GRAPHS = YES + +# If the UML_LOOK tag is set to YES doxygen will generate inheritance and +# collaboration diagrams in a style similar to the OMG's Unified Modeling +# Language. + +UML_LOOK = NO + +# If set to YES, the inheritance and collaboration graphs will show the +# relations between templates and their instances. + +TEMPLATE_RELATIONS = NO + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT +# tags are set to YES then doxygen will generate a graph for each documented +# file showing the direct and indirect include dependencies of the file with +# other documented files. + +INCLUDE_GRAPH = YES + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and +# HAVE_DOT tags are set to YES then doxygen will generate a graph for each +# documented header file showing the documented files that directly or +# indirectly include this file. + +INCLUDED_BY_GRAPH = YES + +# If the CALL_GRAPH and HAVE_DOT options are set to YES then +# doxygen will generate a call dependency graph for every global function +# or class method. Note that enabling this option will significantly increase +# the time of a run. So in most cases it will be better to enable call graphs +# for selected functions only using the \callgraph command. + +CALL_GRAPH = NO + +# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then +# doxygen will generate a caller dependency graph for every global function +# or class method. Note that enabling this option will significantly increase +# the time of a run. So in most cases it will be better to enable caller +# graphs for selected functions only using the \callergraph command. + +CALLER_GRAPH = NO + +# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen +# will generate a graphical hierarchy of all classes instead of a textual one. + +GRAPHICAL_HIERARCHY = YES + +# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES +# then doxygen will show the dependencies a directory has on other directories +# in a graphical way. The dependency relations are determined by the #include +# relations between the files in the directories. + +DIRECTORY_GRAPH = YES + +# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images +# generated by dot. Possible values are svg, png, jpg, or gif. +# If left blank png will be used. + +DOT_IMAGE_FORMAT = png + +# The tag DOT_PATH can be used to specify the path where the dot tool can be +# found. If left blank, it is assumed the dot tool can be found in the path. + +DOT_PATH = + +# The DOTFILE_DIRS tag can be used to specify one or more directories that +# contain dot files that are included in the documentation (see the +# \dotfile command). + +DOTFILE_DIRS = + +# The MSCFILE_DIRS tag can be used to specify one or more directories that +# contain msc files that are included in the documentation (see the +# \mscfile command). + +MSCFILE_DIRS = + +# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of +# nodes that will be shown in the graph. If the number of nodes in a graph +# becomes larger than this value, doxygen will truncate the graph, which is +# visualized by representing a node as a red box. Note that doxygen if the +# number of direct children of the root node in a graph is already larger than +# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note +# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH. + +DOT_GRAPH_MAX_NODES = 50 + +# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the +# graphs generated by dot. A depth value of 3 means that only nodes reachable +# from the root by following a path via at most 3 edges will be shown. Nodes +# that lay further from the root node will be omitted. Note that setting this +# option to 1 or 2 may greatly reduce the computation time needed for large +# code bases. Also note that the size of a graph can be further restricted by +# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction. + +MAX_DOT_GRAPH_DEPTH = 0 + +# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent +# background. This is disabled by default, because dot on Windows does not +# seem to support this out of the box. Warning: Depending on the platform used, +# enabling this option may lead to badly anti-aliased labels on the edges of +# a graph (i.e. they become hard to read). + +DOT_TRANSPARENT = NO + +# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output +# files in one run (i.e. multiple -o and -T options on the command line). This +# makes dot run faster, but since only newer versions of dot (>1.8.10) +# support this, this feature is disabled by default. + +DOT_MULTI_TARGETS = NO + +# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will +# generate a legend page explaining the meaning of the various boxes and +# arrows in the dot generated graphs. + +GENERATE_LEGEND = YES + +# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will +# remove the intermediate dot files that are used to generate +# the various graphs. + +DOT_CLEANUP = YES diff --git a/doc/README b/doc/README new file mode 100644 index 0000000..7477d5d --- /dev/null +++ b/doc/README @@ -0,0 +1,18 @@ +arepacoin 0.4.4 BETA + +Copyright (c) 2013 NovaCoin Developers +Copyright (c) 2011-2012 PPCoin Developers +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 +the OpenSSL Toolkit (http://www.openssl.org/). This product includes +cryptographic software written by Eric Young (eay@cryptsoft.com). + + +Intro +----- +arepacoin is a free open source project derived from Bitcoin, with +the goal of providing a long-term energy-efficient scrypt-based crypto-currency. +Built on the foundation of Bitcoin, PPCoin and NovaCoin, innovations such as proof-of-stake +help further advance the field of crypto-currency. + diff --git a/doc/README_windows.txt b/doc/README_windows.txt new file mode 100644 index 0000000..62e3e19 --- /dev/null +++ b/doc/README_windows.txt @@ -0,0 +1,18 @@ +arepacoin 0.4.4 BETA + +Copyright (c) 2013 NovaCoin Developers +Copyright (c) 2011-2013 PPCoin Developers +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 +the OpenSSL Toolkit (http://www.openssl.org/). This product includes +cryptographic software written by Eric Young (eay@cryptsoft.com). + + +Intro +----- +arepacoin is a free open source project derived from Bitcoin, with +the goal of providing a long-term energy-efficient scrypt-based crypto-currency. +Built on the foundation of Bitcoin, PPCoin and NovaCoin, innovations such as proof-of-stake and scrypt +help further advance the field of crypto-currency. + diff --git a/doc/assets-attribution.txt b/doc/assets-attribution.txt new file mode 100644 index 0000000..a4eb497 --- /dev/null +++ b/doc/assets-attribution.txt @@ -0,0 +1,59 @@ +Code: src/strlcpy.h +Author: Todd C. Miller +License: ISC + +Icon: src/qt/res/icons/clock*.png, src/qt/res/icons/tx*.png, + src/qt/res/src/*.svg +Designer: Wladimir van der Laan +License: MIT + +Icon: src/qt/res/icons/address-book.png, src/qt/res/icons/export.png, + src/qt/res/icons/history.png, src/qt/res/icons/key.png, + src/qt/res/icons/lock_*.png, src/qt/res/icons/overview.png, + src/qt/res/icons/receive.png, src/qt/res/icons/send.png, + src/qt/res/icons/synced.png, src/qt/res/icons/filesave.png +Icon Pack: NUVOLA ICON THEME for KDE 3.x +Designer: David Vignoni (david@icon-king.com) + ICON KING - www.icon-king.com +License: LGPL +Site: http://www.icon-king.com/projects/nuvola/ + +Icon: src/qt/res/icons/connect*.png +Icon Pack: Human-O2 +Designer: schollidesign +License: GNU/GPL +Site: http://findicons.com/icon/93743/blocks_gnome_netstatus_0 + +Icon: src/qt/res/icons/transaction*.png +Designer: md2k7 +Site: https://forum.bitcoin.org/index.php?topic=15276.0 +License: You are free to do with these icons as you wish, including selling, + copying, modifying etc. + +Icon: src/qt/res/icons/configure.png, src/qt/res/icons/quit.png, + src/qt/res/icons/editcopy.png, src/qt/res/icons/editpaste.png, + src/qt/res/icons/add.png, src/qt/res/icons/edit.png, + src/qt/res/icons/remove.png (edited) +Designer: http://www.everaldo.com +Icon Pack: Crystal SVG +License: LGPL + +Icon: src/qt/res/icons/bitcoin.png, src/qt/res/icons/toolbar.png +Designer: Bitboy (optimized for 16x16 by Wladimir van der Laan) +License: Public Domain +Site: http://forum.bitcoin.org/?topic=1756.0 + +Icon: scripts/img/reload.xcf (modified),src/qt/res/movies/update_spinner.mng +Icon Pack: Kids +Designer: Everaldo (Everaldo Coelho) +License: GNU/GPL +Site: http://findicons.com/icon/17102/reload?id=17102 + +Image: src/qt/res/images/splash2.png (Wallet image) +Designer: Crobbo (forum) +Site: https://bitcointalk.org/index.php?topic=32273.0 +License: Public domain + +arepacoin Logo +Designer: Evan +License: Creative Commons Attribution 4.0 International License diff --git a/doc/bitcoin_logo_doxygen.png b/doc/bitcoin_logo_doxygen.png new file mode 100644 index 0000000..5b41b02 Binary files /dev/null and b/doc/bitcoin_logo_doxygen.png differ diff --git a/doc/build-msw.txt b/doc/build-msw.txt new file mode 100644 index 0000000..45a3e72 --- /dev/null +++ b/doc/build-msw.txt @@ -0,0 +1,84 @@ +Copyright (c) 2009-2012 Bitcoin Developers +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 +the OpenSSL Toolkit (http://www.openssl.org/). This product includes +cryptographic software written by Eric Young (eay@cryptsoft.com) and UPnP +software written by Thomas Bernard. + + +See readme-qt.rst for instructions on building arepacoin QT, the +graphical user interface. + +WINDOWS BUILD NOTES +=================== + +Compilers Supported +------------------- +TODO: What works? +Note: releases are cross-compiled using mingw running on Linux. + + +Dependencies +------------ +Libraries you need to download separately and build: + + default path download +OpenSSL \openssl-1.0.1b-mgw http://www.openssl.org/source/ +Berkeley DB \db-4.8.30.NC-mgw http://www.oracle.com/technology/software/products/berkeley-db/index.html +Boost \boost-1.47.0-mgw http://www.boost.org/users/download/ +miniupnpc \miniupnpc-1.6-mgw http://miniupnp.tuxfamily.org/files/ + +Their licenses: +OpenSSL Old BSD license with the problematic advertising requirement +Berkeley DB New BSD license with additional requirement that linked software must be free open source +Boost MIT-like license +miniupnpc New (3-clause) BSD license + +Versions used in this release: +OpenSSL 1.0.1b +Berkeley DB 4.8.30.NC +Boost 1.47.0 +miniupnpc 1.6 + + +OpenSSL +------- +MSYS shell: +un-tar sources with MSYS 'tar xfz' to avoid issue with symlinks (OpenSSL ticket 2377) +change 'MAKE' env. variable from 'C:\MinGW32\bin\mingw32-make.exe' to '/c/MinGW32/bin/mingw32-make.exe' + +cd /c/openssl-1.0.1b-mgw +./config +make + +Berkeley DB +----------- +MSYS shell: +cd /c/db-4.8.30.NC-mgw/build_unix +sh ../dist/configure --enable-mingw --enable-cxx +make + +Boost +----- +DOS prompt: +downloaded boost jam 3.1.18 +cd \boost-1.47.0-mgw +bjam toolset=gcc --build-type=complete stage + +MiniUPnPc +--------- +UPnP support is optional, make with USE_UPNP= to disable it. + +MSYS shell: +cd /c/miniupnpc-1.6-mgw +make -f Makefile.mingw +mkdir miniupnpc +cp *.h miniupnpc/ + +arepacoin +------- +DOS prompt: +cd \arepacoin\src +mingw32-make -f makefile.mingw +strip arepacoind.exe diff --git a/doc/build-osx.txt b/doc/build-osx.txt new file mode 100644 index 0000000..6f41d5d --- /dev/null +++ b/doc/build-osx.txt @@ -0,0 +1,54 @@ +Copyright (c) 2009-2012 Bitcoin Developers +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 the +OpenSSL Toolkit (http://www.openssl.org/). This product includes cryptographic +software written by Eric Young (eay@cryptsoft.com) and UPnP software written by +Thomas Bernard. + + +Mac OS X arepacoind build instructions +Laszlo Hanyecz +Douglas Huff + + +See readme-qt.rst for instructions on building arepacoin QT, the +graphical user interface. + +Tested on 10.5 and 10.6 intel. PPC is not supported because it's big-endian. + +All of the commands should be executed in Terminal.app.. it's in +/Applications/Utilities + +You need to install XCode with all the options checked so that the compiler and +everything is available in /usr not just /Developer I think it comes on the DVD +but you can get the current version from http://developer.apple.com + + +1. Clone the github tree to get the source code: + +git clone git@github.com:rat4/arepacoin.git arepacoin + +2. Download and install MacPorts from http://www.macports.org/ + +2a. (for 10.7 Lion) + Edit /opt/local/etc/macports/macports.conf and uncomment "build_arch i386" + +3. Install dependencies from MacPorts + +sudo port install boost db48 openssl miniupnpc + +Optionally install qrencode (and set USE_QRCODE=1): +sudo port install qrencode + +4. Now you should be able to build arepacoind: + +cd arepacoin/src +make -f makefile.osx + +Run: + ./arepacoind --help # for a list of command-line options. +Run + ./arepacoind -daemon # to start the arepacoin daemon. +Run + ./arepacoind help # When the daemon is running, to get a list of RPC commands diff --git a/doc/build-unix.txt b/doc/build-unix.txt new file mode 100644 index 0000000..d6d360c --- /dev/null +++ b/doc/build-unix.txt @@ -0,0 +1,153 @@ +Copyright (c) 2009-2012 Bitcoin Developers +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 +the OpenSSL Toolkit (http://www.openssl.org/). This product includes +cryptographic software written by Eric Young (eay@cryptsoft.com) and UPnP +software written by Thomas Bernard. + + +UNIX BUILD NOTES +================ + +To Build +-------- + +cd src/ +make -f makefile.unix # Headless arepacoin + +See readme-qt.rst for instructions on building arepacoin QT, +the graphical arepacoin. + +Dependencies +------------ + + Library Purpose Description + ------- ------- ----------- + libssl SSL Support Secure communications + libdb Berkeley DB Blockchain & wallet storage + libboost Boost C++ Library + miniupnpc UPnP Support Optional firewall-jumping support + libqrencode QRCode generation Optional QRCode generation + +Note that libexecinfo should be installed, if you building under *BSD systems. +This library provides backtrace facility. + +miniupnpc may be used for UPnP port mapping. It can be downloaded from +http://miniupnp.tuxfamily.org/files/. UPnP support is compiled in and +turned off by default. Set USE_UPNP to a different value to control this: + USE_UPNP=- No UPnP support - miniupnp not required + USE_UPNP=0 (the default) UPnP support turned off by default at runtime + USE_UPNP=1 UPnP support turned on by default at runtime + +libqrencode may be used for QRCode image generation. It can be downloaded +from http://fukuchi.org/works/qrencode/index.html.en, or installed via +your package manager. Set USE_QRCODE to control this: + USE_QRCODE=0 (the default) No QRCode support - libqrcode not required + USE_QRCODE=1 QRCode support enabled + +Licenses of statically linked libraries: + Berkeley DB New BSD license with additional requirement that linked + software must be free open source + Boost MIT-like license + miniupnpc New (3-clause) BSD license + +Versions used in this release: + GCC 4.9.0 + OpenSSL 1.0.1g + Berkeley DB 5.3.28.NC + Boost 1.55.0 + miniupnpc 1.9.20140401 + +Dependency Build Instructions: Ubuntu & Debian +---------------------------------------------- +sudo apt-get install build-essential +sudo apt-get install libssl-dev +sudo apt-get install libdb++-dev +sudo apt-get install libboost-all-dev +sudo apt-get install libqrencode-dev + +If using Boost 1.37, append -mt to the boost libraries in the makefile. + + +Dependency Build Instructions: Gentoo +------------------------------------- + +emerge -av1 --noreplace boost openssl sys-libs/db + +Take the following steps to build (no UPnP support): + cd ${arepacoin_DIR}/src + make -f makefile.unix USE_UPNP= + strip arepacoind + + +Notes +----- +The release is built with GCC and then "strip arepacoind" to strip the debug +symbols, which reduces the executable size by about 90%. + + +miniupnpc +--------- +tar -xzvf miniupnpc-1.6.tar.gz +cd miniupnpc-1.6 +make +sudo su +make install + + +Berkeley DB +----------- +You need Berkeley DB. If you have to build Berkeley DB yourself: +../dist/configure --enable-cxx +make + + +Boost +----- +If you need to build Boost yourself: +sudo su +./bootstrap.sh +./bjam install + + +Security +-------- +To help make your arepacoin installation more secure by making certain attacks impossible to +exploit even if a vulnerability is found, you can take the following measures: + +* Position Independent Executable + Build position independent code to take advantage of Address Space Layout Randomization + offered by some kernels. An attacker who is able to cause execution of code at an arbitrary + memory location is thwarted if he doesn't know where anything useful is located. + The stack and heap are randomly located by default but this allows the code section to be + randomly located as well. + + On an Amd64 processor where a library was not compiled with -fPIC, this will cause an error + such as: "relocation R_X86_64_32 against `......' can not be used when making a shared object;" + + To build with PIE, use: + make -f makefile.unix ... -e PIE=1 + + To test that you have built PIE executable, install scanelf, part of paxutils, and use: + scanelf -e ./arepacoin + + The output should contain: + TYPE + ET_DYN + +* Non-executable Stack + If the stack is executable then trivial stack based buffer overflow exploits are possible if + vulnerable buffers are found. By default, arepacoin should be built with a non-executable stack + but if one of the libraries it uses asks for an executable stack or someone makes a mistake + and uses a compiler extension which requires an executable stack, it will silently build an + executable without the non-executable stack protection. + + To verify that the stack is non-executable after compiling use: + scanelf -e ./arepacoin + + the output should contain: + STK/REL/PTL + RW- R-- RW- + + The STK RW- means that the stack is readable and writeable but not executable. diff --git a/doc/coding.txt b/doc/coding.txt new file mode 100644 index 0000000..5940985 --- /dev/null +++ b/doc/coding.txt @@ -0,0 +1,99 @@ +Please be consistent with the existing coding style. + +Block style: + +bool Function(char* psz, int n) +{ + // Comment summarising what this section of code does + for (int i = 0; i < n; i++) + { + // When something fails, return early + if (!Something()) + return false; + ... + } + + // Success return is usually at the end + return true; +} + +- ANSI/Allman block style +- 4 space indenting, no tabs +- No extra spaces inside parenthesis; please don't do ( this ) +- No space after function names, one space after if, for and while + +Variable names begin with the type in lowercase, like nSomeVariable. +Please don't put the first word of the variable name in lowercase like +someVariable. + +Common types: +n integer number: short, unsigned short, int, unsigned int, + int64_t, uint64_t, sometimes char if used as a number +d double, float +f flag +hash uint256 +p pointer or array, one p for each level of indirection +psz pointer to null terminated string +str string object +v vector or similar list objects +map map or multimap +set set or multiset +bn CBigNum + +------------------------- +Locking/mutex usage notes + +The code is multi-threaded, and uses mutexes and the +CRITICAL_BLOCK/TRY_CRITICAL_BLOCK macros to protect data structures. + +Deadlocks due to inconsistent lock ordering (thread 1 locks cs_main +and then cs_wallet, while thread 2 locks them in the opposite order: +result, deadlock as each waits for the other to release its lock) are +a problem. Compile with -DDEBUG_LOCKORDER to get lock order +inconsistencies reported in the debug.log file. + +Re-architecting the core code so there are better-defined interfaces +between the various components is a goal, with any necessary locking +done by the components (e.g. see the self-contained CKeyStore class +and its cs_KeyStore lock for example). + +------- +Threads + +StartNode : Starts other threads. + +ThreadGetMyExternalIP : Determines outside-the-firewall IP address, +sends addr message to connected peers when it determines it. + +ThreadIRCSeed : Joins IRC bootstrapping channel, watching for new +peers and advertising this node's IP address. + +ThreadSocketHandler : Sends/Receives data from peers on port 8333. + +ThreadMessageHandler : Higher-level message handling (sending and +receiving). + +ThreadOpenConnections : Initiates new connections to peers. + +ThreadTopUpKeyPool : replenishes the keystore's keypool. + +ThreadCleanWalletPassphrase : re-locks an encrypted wallet after user +has unlocked it for a period of time. + +SendingDialogStartTransfer : used by pay-via-ip-address code (obsolete) + +ThreadDelayedRepaint : repaint the gui + +ThreadFlushWalletDB : Close the wallet.dat file if it hasn't been used +in 500ms. + +ThreadRPCServer : Remote procedure call handler, listens on port 8332 +for connections and services them. + +ThreadBitcoinMiner : Generates bitcoins + +ThreadMapPort : Universal plug-and-play startup/shutdown + +Shutdown : Does an orderly shutdown of everything + +ExitTimeout : Windows-only, sleeps 5 seconds then exits application diff --git a/doc/readme-qt.rst b/doc/readme-qt.rst new file mode 100644 index 0000000..eb877b3 --- /dev/null +++ b/doc/readme-qt.rst @@ -0,0 +1,147 @@ +arepacoin-qt: Qt5 GUI for arepacoin +=============================== + +Build instructions +=================== + +Debian +------- + +First, make sure that the required packages for Qt5 development of your +distribution are installed, for Debian and Ubuntu these are: + +:: + + apt-get install qt5-default qt5-qmake qtbase5-dev-tools qttools5-dev-tools \ + build-essential libboost-dev libboost-system-dev \ + libboost-filesystem-dev libboost-program-options-dev libboost-thread-dev \ + libssl-dev libdb++-dev + +then execute the following: + +:: + + qmake + make + +Alternatively, install Qt Creator and open the `arepacoin-qt.pro` file. + +An executable named `arepacoin-qt` will be built. + + +Windows +-------- + +Windows build instructions: + +- Download the `QT Windows SDK`_ and install it. You don't need the Symbian stuff, just the desktop Qt. + +- Compile openssl, boost and dbcxx. + +- Open the .pro file in QT creator and build as normal (ctrl-B) + +.. _`QT Windows SDK`: http://qt-project.org/downloads + + +Mac OS X +-------- + +- Download and install the `Qt Mac OS X SDK`_. It is recommended to also install Apple's Xcode with UNIX tools. + +- Download and install `MacPorts`_. + +- Execute the following commands in a terminal to get the dependencies: + +:: + + sudo port selfupdate + sudo port install boost db48 miniupnpc + +- Open the .pro file in Qt Creator and build as normal (cmd-B) + +.. _`Qt Mac OS X SDK`: http://qt-project.org/downloads +.. _`MacPorts`: http://www.macports.org/install.php + + +Build configuration options +============================ + +UPNnP port forwarding +--------------------- + +To use UPnP for port forwarding behind a NAT router (recommended, as more connections overall allow for a faster and more stable arepacoin experience), pass the following argument to qmake: + +:: + + qmake "USE_UPNP=1" + +(in **Qt Creator**, you can find the setting for additional qmake arguments under "Projects" -> "Build Settings" -> "Build Steps", then click "Details" next to **qmake**) + +This requires miniupnpc for UPnP port mapping. It can be downloaded from +http://miniupnp.tuxfamily.org/files/. UPnP support is not compiled in by default. + +Set USE_UPNP to a different value to control this: + ++------------+--------------------------------------------------------------------------+ +| USE_UPNP=- | no UPnP support, miniupnpc not required; | ++------------+--------------------------------------------------------------------------+ +| USE_UPNP=0 | (the default) built with UPnP, support turned off by default at runtime; | ++------------+--------------------------------------------------------------------------+ +| USE_UPNP=1 | build with UPnP support turned on by default at runtime. | ++------------+--------------------------------------------------------------------------+ + +Notification support for recent (k)ubuntu versions +--------------------------------------------------- + +To see desktop notifications on (k)ubuntu versions starting from 10.04, enable usage of the +FreeDesktop notification interface through DBUS using the following qmake option: + +:: + + qmake "USE_DBUS=1" + +Generation of QR codes +----------------------- + +libqrencode may be used to generate QRCode images for payment requests. +It can be downloaded from http://fukuchi.org/works/qrencode/index.html.en, or installed via your package manager. Pass the USE_QRCODE +flag to qmake to control this: + ++--------------+--------------------------------------------------------------------------+ +| USE_QRCODE=0 | (the default) No QRCode support - libarcode not required | ++--------------+--------------------------------------------------------------------------+ +| USE_QRCODE=1 | QRCode support enabled | ++--------------+--------------------------------------------------------------------------+ + + +Berkely DB version warning +========================== + +A warning for people using the *static binary* version of arepacoin on a Linux/UNIX-ish system (tl;dr: **Berkely DB databases are not forward compatible**). + +The static binary version of arepacoin is linked against libdb 5.0 (see also `this Debian issue`_). + +Now the nasty thing is that databases from 5.X are not compatible with 4.X. + +If the globally installed development package of Berkely DB installed on your system is 5.X, any source you +build yourself will be linked against that. The first time you run with a 5.X version the database will be upgraded, +and 4.X cannot open the new format. This means that you cannot go back to the old statically linked version without +significant hassle! + +.. _`this Debian issue`: http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=621425 + +Ubuntu 11.10 warning +==================== + +Ubuntu 11.10 has a package called 'qt-at-spi' installed by default. At the time of writing, having that package +installed causes arepacoin-qt to crash intermittently. The issue has been reported as `launchpad bug 857790`_, but +isn't yet fixed. + +Until the bug is fixed, you can remove the qt-at-spi package to work around the problem, though this will presumably +disable screen reader functionality for Qt apps: + +:: + + sudo apt-get remove qt-at-spi + +.. _`launchpad bug 857790`: https://bugs.launchpad.net/ubuntu/+source/qt-at-spi/+bug/857790 diff --git a/doc/release-process.txt b/doc/release-process.txt new file mode 100644 index 0000000..ed23ef3 --- /dev/null +++ b/doc/release-process.txt @@ -0,0 +1,142 @@ +* update translations (ping tcatm on IRC for now) + +* update (commit) version in sources + bitcoin-qt.pro + src/version.h + share/setup.nsi + doc/README* + +* tag version in git + + git tag -a v0.5.1 + +* write release notes. git shortlog helps a lot: + + git shortlog --no-merges v0.5.0.. + +* perform gitian builds + + * From a directory containing the bitcoin source, gitian-builder and gitian.sigs + export SIGNER=(your gitian key, ie bluematt, sipa, etc) + export VERSION=0.5.1 + cd ./gitian-builder + + * Fetch and build inputs: + mkdir -p inputs; cd inputs/ + wget 'http://miniupnp.free.fr/files/download.php?file=miniupnpc-1.6.tar.gz' -O miniupnpc-1.6.tar.gz + wget 'http://www.openssl.org/source/openssl-1.0.1b.tar.gz' + wget 'http://download.oracle.com/berkeley-db/db-4.8.30.NC.tar.gz' + wget 'http://zlib.net/zlib-1.2.6.tar.gz' + wget 'ftp://ftp.simplesystems.org/pub/libpng/png/src/libpng-1.5.9.tar.gz' + wget 'http://fukuchi.org/works/qrencode/qrencode-3.2.0.tar.bz2' + wget 'http://downloads.sourceforge.net/project/boost/boost/1.47.0/boost_1_47_0.tar.bz2' + wget 'http://download.qt.nokia.com/qt/source/qt-everywhere-opensource-src-4.7.4.tar.gz' + cd .. + ./bin/gbuild ../bitcoin/contrib/gitian-descriptors/boost-win32.yml + cp build/out/boost-win32-1.47.0-gitian.zip inputs/ + ./bin/gbuild ../bitcoin/contrib/gitian-descriptors/qt-win32.yml + cp build/out/qt-win32-4.7.4-gitian.zip inputs/ + ./bin/gbuild ../bitcoin/contrib/gitian-descriptors/deps-win32.yml + cp build/out/bitcoin-deps-0.0.3.zip inputs/ + + * Build bitcoind and bitcoin-qt on Linux32, Linux64, and Win32: + ./bin/gbuild --commit bitcoin=v${VERSION} ../bitcoin/contrib/gitian-descriptors/gitian.yml + ./bin/gsign --signer $SIGNER --release ${VERSION} --destination ../gitian.sigs/ ../bitcoin/contrib/gitian-descriptors/gitian.yml + pushd build/out + zip -r bitcoin-${VERSION}-linux-gitian.zip * + mv bitcoin-${VERSION}-linux-gitian.zip ../../ + popd + ./bin/gbuild --commit bitcoin=v${VERSION} ../bitcoin/contrib/gitian-descriptors/gitian-win32.yml + ./bin/gsign --signer $SIGNER --release ${VERSION}-win32 --destination ../gitian.sigs/ ../bitcoin/contrib/gitian-descriptors/gitian-win32.yml + pushd build/out + zip -r bitcoin-${VERSION}-win32-gitian.zip * + mv bitcoin-${VERSION}-win32-gitian.zip ../../ + popd + + Build output expected: + 1. linux 32-bit and 64-bit binaries + source (bitcoin-${VERSION}-linux-gitian.zip) + 2. windows 32-bit binary, installer + source (bitcoin-${VERSION}-win32-gitian.zip) + 3. Gitian signatures (in gitian.sigs/${VERSION}[-win32]/(your gitian key)/ + +* repackage gitian builds for release as stand-alone zip/tar/installer exe + + * Linux .tar.gz: + unzip bitcoin-${VERSION}-linux-gitian.zip -d bitcoin-${VERSION}-linux + tar czvf bitcoin-${VERSION}-linux.tar.gz bitcoin-${VERSION}-linux + rm -rf bitcoin-${VERSION}-linux + + * Windows .zip and setup.exe: + unzip bitcoin-${VERSION}-win32-gitian.zip -d bitcoin-${VERSION}-win32 + mv bitcoin-${VERSION}-win32/bitcoin-*-setup.exe . + zip -r bitcoin-${VERSION}-win32.zip bitcoin-${VERSION}-win32 + rm -rf bitcoin-${VERSION}-win32 + +* perform Mac build + See this blog post for how Gavin set up his build environment to build the OSX + release; note that a patched version of macdeployqt is not needed anymore, as + the required functionality and fixes are implemented directly in macdeployqtplus: + http://gavintech.blogspot.com/2011/11/deploying-bitcoin-qt-on-osx.html + Gavin also had trouble with the macports py27-appscript package; he + ended up installing a version that worked with: /usr/bin/easy_install-2.7 appscript + + qmake RELEASE=1 USE_UPNP=1 USE_QRCODE=1 bitcoin-qt.pro + make + export QTDIR=/opt/local/share/qt4 # needed to find translations/qt_*.qm files + T=$(contrib/qt_translations.py $QTDIR/translations src/qt/locale) + python2.7 contrib/macdeploy/macdeployqtplus Bitcoin-Qt.app -add-qt-tr $T -dmg -fancy contrib/macdeploy/fancy.plist + + Build output expected: + Bitcoin-Qt.dmg + +* upload builds to SourceForge + +* create SHA256SUMS for builds, and PGP-sign it + +* update bitcoin.org version + +* update forum version + +* update wiki download links + +* update wiki changelog: https://en.bitcoin.it/wiki/Changelog + +* Commit your signature to gitian.sigs: + pushd gitian.sigs + git add ${VERSION}/${SIGNER} + git add ${VERSION}-win32/${SIGNER} + git commit -a + git push # Assuming you can push to the gitian.sigs tree + popd + +------------------------------------------------------------------------- + +* After 3 or more people have gitian-built, repackage gitian-signed zips: + + * From a directory containing bitcoin source, gitian.sigs and gitian zips + export VERSION=0.5.1 + mkdir bitcoin-${VERSION}-linux-gitian + pushd bitcoin-${VERSION}-linux-gitian + unzip ../bitcoin-${VERSION}-linux-gitian.zip + mkdir gitian + cp ../bitcoin/contrib/gitian-downloader/*.pgp ./gitian/ + for signer in $(ls ../gitian.sigs/${VERSION}/); do + cp ../gitian.sigs/${VERSION}/${signer}/bitcoin-build.assert ./gitian/${signer}-build.assert + cp ../gitian.sigs/${VERSION}/${signer}/bitcoin-build.assert.sig ./gitian/${signer}-build.assert.sig + done + zip -r bitcoin-${VERSION}-linux-gitian.zip * + cp bitcoin-${VERSION}-linux-gitian.zip ../ + popd + mkdir bitcoin-${VERSION}-win32-gitian + pushd bitcoin-${VERSION}-win32-gitian + unzip ../bitcoin-${VERSION}-win32-gitian.zip + mkdir gitian + cp ../bitcoin/contrib/gitian-downloader/*.pgp ./gitian/ + for signer in $(ls ../gitian.sigs/${VERSION}-win32/); do + cp ../gitian.sigs/${VERSION}-win32/${signer}/bitcoin-build.assert ./gitian/${signer}-build.assert + cp ../gitian.sigs/${VERSION}-win32/${signer}/bitcoin-build.assert.sig ./gitian/${signer}-build.assert.sig + done + zip -r bitcoin-${VERSION}-win32-gitian.zip * + cp bitcoin-${VERSION}-win32-gitian.zip ../ + popd + + * Upload gitian zips to SourceForge diff --git a/doc/translation_process.md b/doc/translation_process.md new file mode 100644 index 0000000..3ddfc0c --- /dev/null +++ b/doc/translation_process.md @@ -0,0 +1,80 @@ +Translations +============ + +The Qt GUI can be easily translated into other languages. Here's how we +handle those translations. + +Files and Folders +----------------- + +### bitcoin-qt.pro + +This file takes care of generating `.qm` files from `.ts` files. It is mostly +automated. + +### src/qt/bitcoin.qrc + +This file must be updated whenever a new translation is added. Please note that +files must end with `.qm`, not `.ts`. + + + locale/bitcoin_en.qm + ... + + +### src/qt/locale/ + +This directory contains all translations. Filenames must adhere to this format: + + bitcoin_xx_YY.ts or bitcoin_xx.ts + +#### Source file + +`src/qt/locale/bitcoin_en.ts` is treated in a special way. It is used as the +source for all other translations. Whenever a string in the code is changed +this file must be updated to reflect those changes. Usually, this can be +accomplished by running `lupdate` (included in the Qt SDK). + +An updated source file should be merged to github and transifex will pick it +up from there. Afterwards the new strings show up as "Remaining" in transifex +and can be translated. + +Syncing with transifex +---------------------- + +We are using http://transifex.net as a frontend for translating the client. + +https://www.transifex.net/projects/p/bitcoin/resource/tx/ + +The "transifex client" (see: http://help.transifex.net/features/client/) +will help with fetching new translations from transifex. Use the following +config to be able to connect with the client. + +### .tx/config + + [main] + host = https://www.transifex.net + + [bitcoin.tx] + file_filter = src/qt/locale/bitcoin_.ts + source_file = src/qt/locale/bitcoin_en.ts + source_lang = en + +### .tx/config (for Windows) + + [main] + host = https://www.transifex.net + + [bitcoin.tx] + file_filter = src\qt\locale\bitcoin_.ts + source_file = src\qt\locale\bitcoin_en.ts + source_lang = en + +It is also possible to directly download new translations one by one from transifex. + +### Fetching new translations + +1. `tx pull -a` +2. update `src/qt/bitcoin.qrc` manually or via + `ls src/qt/locale/*ts|xargs -n1 basename|sed 's/\(bitcoin_\(.*\)\).ts/locale/\1.qm<\/file>/'` +3. `git add` new translations from `src/qt/locale/` diff --git a/share/genbuild.sh b/share/genbuild.sh new file mode 100644 index 0000000..d959877 --- /dev/null +++ b/share/genbuild.sh @@ -0,0 +1,35 @@ +#!/bin/sh + +if [ $# -gt 0 ]; then + FILE="$1" + shift + if [ -f "$FILE" ]; then + INFO="$(head -n 1 "$FILE")" + fi +else + echo "Usage: $0 " + exit 1 +fi + +if [ -e "$(which git)" ]; then + # clean 'dirty' status of touched files that haven't been modified + git diff >/dev/null 2>/dev/null + + # get a string like "v0.6.0-66-g59887e8-dirty" + DESC="$(git describe --dirty 2>/dev/null)" + + # get a string like "2012-04-10 16:27:19 +0200" + TIME="$(git log -n 1 --format="%ci")" +fi + +if [ -n "$DESC" ]; then + NEWINFO="#define BUILD_DESC \"$DESC\"" +else + NEWINFO="// No build information available" +fi + +# only update build.h if necessary +if [ "$INFO" != "$NEWINFO" ]; then + echo "$NEWINFO" >"$FILE" + echo "#define BUILD_DATE \"$TIME\"" >>"$FILE" +fi diff --git a/share/pixmaps/addressbook16.bmp b/share/pixmaps/addressbook16.bmp new file mode 100644 index 0000000..c557691 Binary files /dev/null and b/share/pixmaps/addressbook16.bmp differ diff --git a/share/pixmaps/addressbook16mask.bmp b/share/pixmaps/addressbook16mask.bmp new file mode 100644 index 0000000..d3a478d Binary files /dev/null and b/share/pixmaps/addressbook16mask.bmp differ diff --git a/share/pixmaps/addressbook20.bmp b/share/pixmaps/addressbook20.bmp new file mode 100644 index 0000000..2b33b22 Binary files /dev/null and b/share/pixmaps/addressbook20.bmp differ diff --git a/share/pixmaps/addressbook20mask.bmp b/share/pixmaps/addressbook20mask.bmp new file mode 100644 index 0000000..56ce612 Binary files /dev/null and b/share/pixmaps/addressbook20mask.bmp differ diff --git a/share/pixmaps/bitcoin-bc.ico b/share/pixmaps/bitcoin-bc.ico new file mode 100644 index 0000000..88cc240 Binary files /dev/null and b/share/pixmaps/bitcoin-bc.ico differ diff --git a/share/pixmaps/bitcoin.ico b/share/pixmaps/bitcoin.ico new file mode 100644 index 0000000..6192680 Binary files /dev/null and b/share/pixmaps/bitcoin.ico differ diff --git a/share/pixmaps/bitcoin32.xpm b/share/pixmaps/bitcoin32.xpm new file mode 100644 index 0000000..f538a44 --- /dev/null +++ b/share/pixmaps/bitcoin32.xpm @@ -0,0 +1,232 @@ +/* XPM */ +static const char * bitcoin32_xpm[] = { +/* columns rows colors chars-per-pixel */ +"32 32 194 2", +" c #745305", +". c #785704", +"X c #7C5903", +"o c #75560B", +"O c #77590F", +"+ c #7C5C0B", +"@ c #795B12", +"# c #7F631D", +"$ c #825E07", +"% c #825F0B", +"& c #85610A", +"* c #8C660C", +"= c #8E680E", +"- c #916B0F", +"; c #856515", +": c #8B6714", +"> c #8F6A16", +", c #816218", +"< c #88691C", +"1 c #926D12", +"2 c #936F1C", +"3 c #997417", +"4 c #94721E", +"5 c #9B761C", +"6 c #9F781C", +"7 c #A17B1E", +"8 c #826622", +"9 c #916E20", +"0 c #967425", +"q c #9D7420", +"w c #9C7923", +"e c #997728", +"r c #99792C", +"t c #A37D23", +"y c #A37F2C", +"u c #A68125", +"i c #AB8225", +"p c #A5832B", +"a c #AA852C", +"s c #B28A2C", +"d c #A58233", +"f c #AC8734", +"g c #AE8C33", +"h c #AC8C3C", +"j c #B28C33", +"k c #B98E34", +"l c #B28D3D", +"z c #B59136", +"x c #BC9335", +"c c #B3913E", +"v c #BC933A", +"b c #BF9A3D", +"n c #C19235", +"m c #C2953C", +"M c #C39B3C", +"N c #CA9C3D", +"B c #B59343", +"V c #BE9642", +"C c #B69A44", +"Z c #BD9A45", +"A c #B49649", +"S c #BB9A49", +"D c #BB9F52", +"F c #BFA256", +"G c #C49C43", +"H c #CA9D41", +"J c #C59D4A", +"K c #C99E4D", +"L c #C3A144", +"P c #CDA244", +"I c #CFAA47", +"U c #C3A14D", +"Y c #CDA24A", +"T c #CCAB49", +"R c #D2A644", +"E c #D2A54B", +"W c #D6AA4C", +"Q c #DAAE4E", +"! c #DAB04F", +"~ c #C7A656", +"^ c #CDA452", +"/ c #CFAC52", +"( c #C0A65E", +") c #CEA75A", +"_ c #CCAC59", +"` c #D2AB53", +"' c #DCAF52", +"] c #D6AD5A", +"[ c #D9AE5B", +"{ c #DCB556", +"} c #DFB855", +"| c #D6B25F", +" . c #DCB35C", +".. c #DEBE5E", +"X. c #E2B656", +"o. c #E1B55A", +"O. c #E6BC5D", +"+. c #E9BD5E", +"@. c #C3AA63", +"#. c #CCAD62", +"$. c #D4AF62", +"%. c #CDB565", +"&. c #CEB46D", +"*. c #D7B164", +"=. c #DBB362", +"-. c #D6BD64", +";. c #DDBA64", +":. c #D3B66C", +">. c #DFB86B", +",. c #CEB772", +"<. c #D0B771", +"1. c #D4BA73", +"2. c #D9BE77", +"3. c #D6BE79", +"4. c #D8BF7A", +"5. c #E4BB62", +"6. c #E9BF64", +"7. c #E4BC69", +"8. c #E9BF69", +"9. c #E0BB71", +"0. c #E9C05E", +"q. c #D2C279", +"w. c #DBC27C", +"e. c #E2C667", +"r. c #EDC364", +"t. c #E3C16E", +"y. c #ECC46C", +"u. c #EDCC6C", +"i. c #F1C764", +"p. c #F5CA66", +"a. c #F9CD67", +"s. c #F5CC6A", +"d. c #F9CD6B", +"f. c #FBD36F", +"g. c #EDC572", +"h. c #E5CF77", +"j. c #ECCA74", +"k. c #E0C67E", +"l. c #EFCE78", +"z. c #F6CE72", +"x. c #FBCF71", +"c. c #F4CE79", +"v. c #F4D273", +"b. c #FCD473", +"n. c #F4DC75", +"m. c #FEDA74", +"M. c #F6D77C", +"N. c #FBD47A", +"B. c #F1DA7B", +"V. c #FDDA7C", +"C. c #FEE27D", +"Z. c #DDC683", +"A. c #DFC884", +"S. c #E4CA84", +"D. c #E3CC89", +"F. c #E7D183", +"G. c #EFD280", +"H. c #EFDC82", +"J. c #ECD48D", +"K. c #EFDA8C", +"L. c #F9D783", +"P. c #F2DF83", +"I. c #FCDB83", +"U. c #F5DC8F", +"Y. c #FADD8B", +"T. c #EBD593", +"R. c #EFDA99", +"E. c #F3DD93", +"W. c #F3DF9F", +"Q. c #FFE385", +"!. c #FEE986", +"~. c #FDE48C", +"^. c #FEEC8E", +"/. c #ECE199", +"(. c #F6E591", +"). c #FEE494", +"_. c #FEEB93", +"`. c #FEE69A", +"'. c #FFEB9B", +"]. c #FFF197", +"[. c #FFF39B", +"{. c #FEF99B", +"}. c #F6E2A2", +"|. c #F9E5A5", +" X c #F7E9A5", +".X c #FEECA4", +"XX c #FBE7A8", +"oX c #FDEAAB", +"OX c #F7F2AA", +"+X c #FEF2AC", +"@X c #FDF4B4", +"#X c #FFFABA", +"$X c #FFFEC2", +"%X c None", +/* pixels */ +"%X%X%X%X%X%X%X%X%X%X%X%Xp t 6 5 w t w %X%X%X%X%X%X%X%X%X%X%X%X%X", +"%X%X%X%X%X%X%X%X%Xu u x I X.0.s.u.0.W x 7 4 %X%X%X%X%X%X%X%X%X%X", +"%X%X%X%X%X%X%Xy i I i.a.f.m.m.b.f.s.a.s.i.W 7 > %X%X%X%X%X%X%X%X", +"%X%X%X%X%X%Xt M 0.a.m.m.m.m.f.d.p.p.p.f.d.f.i.b 1 < %X%X%X%X%X%X", +"%X%X%X%X%X7 ! d.f.f.m.f.+.W P R I Q 5.v.V.V.z.f.{ 5 + %X%X%X%X%X", +"%X%X%X%Xu X.f.m.m.f.' H s ~ V y _ Z J o.g.L.L.Q.!.e.5 X %X%X%X%X", +"%X%X%Xu X.b.C.m.+.N m n t }.3.> }.w.V 5.y.y.Y.[.^.^.-.1 + %X%X%X", +"%X%Xt P m.N.m.X.v v v k 6 }.1.: /.4.c 7.N.N.v.!.{.{.^.L & %X%X%X", +"%X%Xg Y.Y.V.+.m k a t t : }.1.% }.1.r | l.B.M.b.!.{.^.n.7 X %X%X", +"%Xp -._.'.Y.' Y n D.}.}.|.oXXX|.oX XT.w.F _ j.v.v._.^.C.T & @ %X", +"%Xa (.'.'.9.[ [ K S.}.oXoXoXoXXXoXoXoXoX XD / s.d.v.!.C.v.3 o %X", +"%XU '.'.Y.[ [ [ [ J f <.oXoX( 2 f S J.oXoXT.j r.s.i.C.C.C.z X %X", +"p e.'.'.F. .=.=.=.=.) 1.oXoX@.f . .F oXoX}.a +.i.i.b.C.m.I X O ", +"u w.'.[.j.5.8.7.7.7.] 2.oXoX@.y W c &.oXoXZ.k r.s.i.s.V.m.} = o ", +"u H.[.{.y.8.y.g.8.g.7.2.oXoXA.@.&.D.oXoXT.e G +.O.O.5.V.m.0.- o ", +"u !.].[.r.8.y.g.g.g.7.4.oXoXoXoXoXoXoXoXoX<.y W X.o.o.m.m.0.- o ", +"u B._._.5.5.8.y.g.c.g.w.oXoX,.h A F <..XoXoX1.k ' ' ' V.N.r.- ", +"u u.Q.~.r.6.z.N.V.I.v.k.oXoX@.B | _ c 1.oXoX}.a ' ' O.I.b.O.= o ", +"u ..Q.Q.v.i.s.c.N.L.l.Z.oXoX@.B t.=.S &.oXoXXXy Y R +.N.b.Q % o ", +"t T C.I.I.6.u.z.z.5.S 1.oXoX@.e B h D |.oXoXS.f Y Y 6.d.d.n X O ", +"%Xs m.V.Q.r.r.z.5.<.}.oXoXoXXXW.}.oXoXoXoXW.h G H R a.p.s.7 %X", +"%X7 O.V.V.v.+.r.` 4.oXoXoXoXoXoXoXoXXXR.<.h v N N o.a.p.Q = %X", +"%Xw x v.v.v.r.+. .Z l d e }.Z.r }.3.d l V G n n R a.s.a.s X O %X", +"%X%X6 { v.l.v.+.O.5.=.^ d }.4.9 }.1.f J G m m G d.d.x.Q = %X%X", +"%X%X%Xs u.v.v.v.r.6.o. .l }.4.9 W.4.l ^ ^ J ) c.N.N.y.7 X O %X%X", +"%X%X%X5 z v.v.M.I.g.;. .J 1.#.B 1.#.) 7.$.S..X'.W.Y.j $ %X%X%X", +"%X%X%X%X5 b N.Y.~.).Y.j.5.$.=.=.$.*.2.J.@X$X#X#XoXC $ %X%X%X%X", +"%X%X%X%X%X3 z U.@X+X`.`.`.(.E.E.E.|.@X@X#X#X#X/.j % %X%X%X%X%X", +"%X%X%X%X%X%Xw a q.OX|.).`._.'.'.XX.X.X+X+X X%.w X o %X%X%X%X%X%X", +"%X%X%X%X%X%X%X%Xw a _ j.~.~.).).`.`.`.F._ t & . # %X%X%X%X%X%X%X", +"%X%X%X%X%X%X%X%X%X%X4 3 t z L U Z z t 1 $ . 8 %X%X%X%X%X%X%X%X%X", +"%X%X%X%X%X%X%X%X%X%X%X%X%X< ; & + + , 8 %X%X%X%X%X%X%X%X%X%X%X%X" +}; diff --git a/share/pixmaps/bitcoin80.xpm b/share/pixmaps/bitcoin80.xpm new file mode 100644 index 0000000..c3c816e --- /dev/null +++ b/share/pixmaps/bitcoin80.xpm @@ -0,0 +1,292 @@ +/* XPM */ +static const char * bitcoin80_xpm[] = { +/* columns rows colors chars-per-pixel */ +"80 80 206 2", +" c #725203", +". c #785706", +"X c #7B5907", +"o c #7C5A09", +"O c #7F5F10", +"+ c #815E0B", +"@ c #85620C", +"# c #89650F", +"$ c #856313", +"% c #896614", +"& c #8D6913", +"* c #886718", +"= c #8D6B1B", +"- c #926D14", +"; c #926E1B", +": c #967116", +"> c #997317", +", c #95711E", +"< c #9B7419", +"1 c #9F781B", +"2 c #A27B1D", +"3 c #8F6F22", +"4 c #926F21", +"5 c #947323", +"6 c #9A7623", +"7 c #9D7925", +"8 c #957628", +"9 c #9A7729", +"0 c #9D7B2B", +"q c #9D7F33", +"w c #A47D23", +"e c #A97F27", +"r c #A37E2B", +"t c #9F8030", +"y c #A78021", +"u c #AC8425", +"i c #A5802D", +"p c #AC842B", +"a c #AF8829", +"s c #B2872C", +"d c #B28B2D", +"f c #A68333", +"g c #AA8633", +"h c #AD8A36", +"j c #A4863A", +"k c #A88638", +"l c #A7893B", +"z c #AC8B3B", +"x c #B28732", +"c c #B48C32", +"v c #B98E34", +"b c #B28D3B", +"n c #B88F3C", +"m c #B69033", +"M c #BD9235", +"N c #B4913D", +"B c #BC943A", +"V c #BE993C", +"C c #C19336", +"Z c #C1953B", +"A c #C49A3C", +"S c #C99C3D", +"D c #CDA13F", +"F c #D0A33F", +"G c #A88B40", +"H c #B08F40", +"J c #AE9142", +"K c #AE944C", +"L c #B49443", +"P c #BB9542", +"I c #B49946", +"U c #BD9846", +"Y c #B3964C", +"T c #BB974A", +"R c #B6994A", +"E c #BF9C4A", +"W c #B69B53", +"Q c #B99D53", +"! c #BCA055", +"~ c #BDA25A", +"^ c #C49742", +"/ c #C49C43", +"( c #CB9E42", +") c #C49D4B", +"_ c #C99E4C", +"` c #C29F52", +"' c #C5A244", +"] c #CDA245", +"[ c #C5A34C", +"{ c #CCA34B", +"} c #CCA94D", +"| c #D2A445", +" . c #D1A54B", +".. c #D5AA4E", +"X. c #DBAF4F", +"o. c #C6A352", +"O. c #CBA554", +"+. c #C5AA57", +"@. c #CEAC54", +"#. c #C4A65A", +"$. c #CDA458", +"%. c #C2A85F", +"&. c #CEAA5B", +"*. c #D0A550", +"=. c #D4AB53", +"-. c #DBAE53", +";. c #D0A75B", +":. c #D4AC5A", +">. c #D9AE5C", +",. c #CEB25E", +"<. c #D4B156", +"1. c #DDB156", +"2. c #D4B25C", +"3. c #DCB35D", +"4. c #D7B85C", +"5. c #DCBA5E", +"6. c #E2B355", +"7. c #E2B65B", +"8. c #E4BA5D", +"9. c #EABD5E", +"0. c #C5AA62", +"q. c #CCAE63", +"w. c #C6AE69", +"e. c #D5AF62", +"r. c #CEB167", +"t. c #CCB36C", +"y. c #D5B162", +"u. c #DCB462", +"i. c #D7B964", +"p. c #DCBC64", +"a. c #D2B66B", +"s. c #DCB669", +"d. c #D7BE69", +"f. c #DFB86A", +"g. c #D0B771", +"h. c #D2BA74", +"j. c #D5BE78", +"k. c #E1B766", +"l. c #E4BB63", +"z. c #E9BE63", +"x. c #E3BB6A", +"c. c #E9BF6A", +"v. c #E1BE72", +"b. c #DDC16B", +"n. c #DAC27E", +"m. c #E4C164", +"M. c #ECC264", +"N. c #E4C36B", +"B. c #EBC36C", +"V. c #E7C96F", +"C. c #EECA6E", +"Z. c #F1C564", +"A. c #F1C76A", +"S. c #F5CB6C", +"D. c #FACE6D", +"F. c #F4D06F", +"G. c #FCD06E", +"H. c #E5C371", +"J. c #EDC573", +"K. c #E4CA73", +"L. c #ECCC74", +"P. c #E7CF7A", +"I. c #EBCD7A", +"U. c #F3CD73", +"Y. c #F8CE71", +"T. c #F3CD7A", +"R. c #EDD076", +"E. c #EDD17B", +"W. c #F4D274", +"Q. c #FBD274", +"!. c #FED977", +"~. c #F3D47B", +"^. c #FDD47A", +"/. c #F5DA7C", +"(. c #FDDA7C", +"). c #FFE07F", +"_. c #DBC481", +"`. c #DFC885", +"'. c #E1CA86", +"]. c #EACC80", +"[. c #E4CD8A", +"{. c #EED383", +"}. c #E7D18F", +"|. c #EAD38C", +" X c #F4D680", +".X c #FDD780", +"XX c #F5DA83", +"oX c #FCDC84", +"OX c #F5DB8A", +"+X c #FADE89", +"@X c #EAD492", +"#X c #EED896", +"$X c #EFDA9A", +"%X c #F1DD9D", +"&X c #FDE283", +"*X c #F6E18D", +"=X c #FEE48D", +"-X c #FFE692", +";X c #FFE894", +":X c #FBE799", +">X c #FFEA98", +",X c #F6E2A3", +".J..X.X.X.X(.W.Z.C.&X;X;X;X;X-X-X-X<.u u < 3X3X3X3X3X3X3X3X3X3X3X", +"3X3X3X3X3X3X3X3Xu u c oX=X=X=X=X=X=X=Xl.Z C M M C C v v v s w = '.2X2X2X5 $ = 2X2X2X}.5 g ) u./.+X+X=X=X=X&XW.Z.F.=X;X;X;X;X-X-X*XV u y @ X 3X3X3X3X3X3X3X3X3X3X", +"3X3X3X3X3X3X3Xu u u N.-X-X-X-X=X=X=XB.Z M C v v s e e e e w > % `.2X2X2X= + % 2X2X2X}.= r L 4.E.OX+X-X=X=X&X).W.M.R.;X;X;X-X-X-X;XR.u u y 3X3X3X3X3X3X3X3X3X3X", +"3X3X3X3X3X3X3Xu u U -X-X-X-X-X-X=XW.^ C C C x e e r 6 5 4 ; = $ `.2X2X2X= O = 2X2X2X}.O = t Q ,.b.P./.*X=X&X&X).F.M.W.;X;X;X;X&X-X&X} u u O 3X3X3X3X3X3X3X3X3X", +"3X3X3X3X3X3Xu u u R.-X-X-X-X-X-X=X=.{ ^ Z C x n 2X2X.>.>.=.=._ n b 2X2X2X2X2X2X2X2X2X2X2X2X2X2X2X2X2X2X2X2X2X2X2X2X2X:XI N +.V./.).).F.F.9.W.;X=X;X-X-X-XR.u u > 3X3X3X3X3X3X3X3X", +"3X3X3X3X3Xu u d =X;X-X-X-X-X-Xx.>.>.>.>.>...^ P 2X2X2X2X2X2X2X2X2X2X2X2X2X2X2X2X2X2X2X2X2X2X2X2X2X2X,Xl N 4.R.!.!.!.G.Z.M.&X;X=X=X-X-X-XB a u 3X3X3X3X3X3X3X", +"3X3X3X3X3Xu u @.;X;X-X;X;X;XXX>.:.>.>.>.>.>._ P ` Y Y W _.2X2X2X2X2X2X@XW W ~ 0.t.'..>.>.>.>.>.>.=._ P z r 4 8 2X2X2X2X2X2X_.. $ , 6 1 3 t ~ 1X2X2X2X2X2X2X2Xt B 5.G.!.!.G.G.M.9.&X;X=X-X-X=X/.u u > 3X3X3X3X3X3X3X", +"3X3X3X3Xu u d =X;X;X=X;X;X=X3.>.>.>.e.>.3.3.>.:.*._ P r 9 2X2X2X2X2X1Xn.@ , c B N m h 8 ~ 2X2X2X2X2X2X2XI h <.F.!.G.G.F.M.9.W.;X=X-X-X=X=Xm u y . 3X3X3X3X3X3X", +"3X3X3X3Xu u ' -X-X>X-X-X-X X>.>.>.>.>.>.>.u.u.u.u.3.$.P f 2X2X2X2X2X2X_.$ i / -.<.8.} h 8 1X2X2X2X2X2X2X! i <.S.G.G.G.G.Z.9.Z.=X-X=X-X&X-X} u u X 3X3X3X3X3X3X", +"3X3X3X3Xu u 4.-X-X-X-X-X-XJ.3.>.>.k.k.k.k.k.u.k.u.u.:.U k 2X2X2X2X2X1X_.% f } 8.Z.F.8.U 8 ,X2X2X2X2X2X2XI g } Z.D.G.D.G.D.Z.9.&X-X=X=X=X-Xm.u u @ 3X3X3X3X3X3X", +"3X3X3X3Xu u K.;X-X;X-X>X-Xk.3.k.k.k.k.k.k.k.k.k.k.u.e.U k 2X2X2X2X2X2X_.% f [ 8.F.M.<.b i 2X2X2X2X2X2X2Xt a X.Z.D.D.D.G.G.Z.9./.=X-X=X=X=XR.u u & 3X3X3X3X3X3X", +"3X3X3X3Xu u E.;X-X;X-X-X=Xl.l.x.c.k.x.k.k.x.x.v.x.x.u.) z 2X2X2X2X2X2X_.$ 7 L <.<.} N 6 h.2X2X2X2X2X2X_.: V 1.S.D.D.G.D.S.M.6.W.-X=X-X=X=X&Xu u > X 3X3X3X3X3X", +"3X3X3Xu a u =X;X;X;X;X;XoX7.z.c.c.c.c.c.c.c.c.c.x.k.u.) z 2X2X2X2X2X2Xn.o = i N h i l n.2X2X2X2X2X2X.o.L r [.2X2X2X9 = 8 2X2X2X}.4 r ^ _ *.*._ ) ) ^ ^ ^ O.oX=X-X-X-X-X-X-X<.u u : . 3X3X3X3X3X3X3X3X3X", +"3X3X3X3X3X3X3X3X3Xy u u i.=X=X=X=X=X-X*X=XW.9.M.A.B.3.5.5.;.U f [.2X2X2Xq 4 8 2X2X2X}.r q _ _ ;.;.*._ _ ` _ e.+X-X-X-X-X-X-X-XR.a u 2 3X3X3X3X3X3X3X3X3X3X", +"3X3X3X3X3X3X3X3X3X3Xu u u K.=X=X=X-X=X=X=X=XXXz.M.8.5.8.u.:.) h }.2X2X2Xj r f 2X2X2X@Xq T _ e.e.u.e.;.$.$.b.-X-X-X=X;X=X;X-X&Xa a u + 3X3X3X3X3X3X3X3X3X3X3X", +"3X3X3X3X3X3X3X3X3X3X3Xu u d ~.=X=X=X=X=X-X=X-X+XC.3.5.7.7.2.@.) q.r.q.q.H H L g.r.w.q.T ` e.k.v.k.k.s.s.{.-X-X;X-X;X;X;X;X*XV u u & . 3X3X3X3X3X3X3X3X3X3X3X", +"3X3X3X3X3X3X3X3X3X3X3X2 u u c XX-X=X=X=X=X-X=X-X-X Xl.7.7.u.2.$.o.[ [ o.O.$.&.&.` ` ` q.s.k.v.k.k.x.{.%X>X>X>X;X>X;X>X>X*XV u u > 3X3X3X3X3X3X3X3X3X3X3X3X", +"3X3X3X3X3X3X3X3X3X3X3X3X2 u u m ~.=X-X-X-X=X-X-X-X-X-X Xc.7.5.u.3.e.y.u.s.f.k.s.e.e.s.s.k.k.k.v. X:X>X>X>X>X>X>X;X>X>X*XV u u < 3X3X3X3X3X3X3X3X3X3X3X3X3X", +"3X3X3X3X3X3X3X3X3X3X3X3X3X2 u u d R.-X=X-X=X-X-X-X-X-X-X-X+XI.v.u.s.l.k.k.x.x.x.s.s.s.s.j.].+X>X>X>X>X>X:X>X>X>X>X>XOXV u u 1 3X3X3X3X3X3X3X3X3X3X3X3X3X3X", +"3X3X3X3X3X3X3X3X3X3X3X3X3X3X2 u u a p.-X-X-X;X;X;X-X-X-X:X-X-X-X-XOX XL.J.J.J.L.I.].OX:X>X-X>X>X-X>X>X>X>X>X>X>X>XK.a a u < 3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X", +"3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X2 u u u @.=X;X;X>X;X-X-X>X-X-X-X-X;X-X-X-X-X-X>X>X-X>X-X>X>X>X>X;X>X>X>X-X>X-X-X:X<.u u u > 3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X", +"3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X1 u u u m n.>X;X>X>X-X-X-X-X>X-X-X-X;X;X;X-X-X-X-X-X>X-X-X>X-X>X>X-X>X>X>X>XK.B u u u & 3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X", +"3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3Xw u u u / {.>X>X-X-X-X-X-X-X-X-X-X-X;X-X-X;X:X-X-X>X-X:X>X;X;X>X;X;X{.[ u u u w + 3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X", +"3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X2 u u u u ) K.-X-X-X-X:X-X-X-X-X-X-X-X-X-X-X-X-X>X-X-X-X-X-X-XE.[ u u u u - . 3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X", +"3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X1 u u u u m 2.E.-X+X:X-X-X-X-X-X-X-X-X-X:X-X-X-X;X-XOXi.B u u u u 1 o 3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X", +"3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X> u u u u u v [ l.I.OX-X-X-X-X-X-X-X-X+XI.f.@.m u u u u u 1 + o 3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X", +"3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X& 2 u u u u u u u d B V V V V B d u u u u u u u y - . o 3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X", +"3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X+ - 1 u u u u u u u a u u u u u u u u 2 - o o 3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X", +"3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3Xo . X # - > 1 2 2 2 1 2 > - # o . o 3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X", +"3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3Xo o . o 3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X", +"3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X", +"3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X", +"3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X", +"3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X" +}; diff --git a/share/pixmaps/check.ico b/share/pixmaps/check.ico new file mode 100644 index 0000000..0c4e6e8 Binary files /dev/null and b/share/pixmaps/check.ico differ diff --git a/share/pixmaps/favicon.ico b/share/pixmaps/favicon.ico new file mode 100644 index 0000000..d249e41 Binary files /dev/null and b/share/pixmaps/favicon.ico differ diff --git a/share/pixmaps/nsis-header.bmp b/share/pixmaps/nsis-header.bmp new file mode 100644 index 0000000..5eb10ae Binary files /dev/null and b/share/pixmaps/nsis-header.bmp differ diff --git a/share/pixmaps/nsis-wizard.bmp b/share/pixmaps/nsis-wizard.bmp new file mode 100644 index 0000000..330de6b Binary files /dev/null and b/share/pixmaps/nsis-wizard.bmp differ diff --git a/share/pixmaps/send16.bmp b/share/pixmaps/send16.bmp new file mode 100644 index 0000000..676b5c4 Binary files /dev/null and b/share/pixmaps/send16.bmp differ diff --git a/share/pixmaps/send16mask.bmp b/share/pixmaps/send16mask.bmp new file mode 100644 index 0000000..06c747f Binary files /dev/null and b/share/pixmaps/send16mask.bmp differ diff --git a/share/pixmaps/send16masknoshadow.bmp b/share/pixmaps/send16masknoshadow.bmp new file mode 100644 index 0000000..faf24e0 Binary files /dev/null and b/share/pixmaps/send16masknoshadow.bmp differ diff --git a/share/pixmaps/send20.bmp b/share/pixmaps/send20.bmp new file mode 100644 index 0000000..2b90422 Binary files /dev/null and b/share/pixmaps/send20.bmp differ diff --git a/share/pixmaps/send20mask.bmp b/share/pixmaps/send20mask.bmp new file mode 100644 index 0000000..f124d0d Binary files /dev/null and b/share/pixmaps/send20mask.bmp differ diff --git a/share/qt/extract_strings_qt.py b/share/qt/extract_strings_qt.py new file mode 100644 index 0000000..771f28a --- /dev/null +++ b/share/qt/extract_strings_qt.py @@ -0,0 +1,70 @@ +#!/usr/bin/python +''' +Extract _("...") strings for translation and convert to Qt4 stringdefs so that +they can be picked up by Qt linguist. +''' +from subprocess import Popen, PIPE +import glob + +OUT_CPP="src/qt/bitcoinstrings.cpp" +EMPTY=['""'] + +def parse_po(text): + """ + Parse 'po' format produced by xgettext. + Return a list of (msgid,msgstr) tuples. + """ + messages = [] + msgid = [] + msgstr = [] + in_msgid = False + in_msgstr = False + + for line in text.split('\n'): + line = line.rstrip('\r') + if line.startswith('msgid '): + if in_msgstr: + messages.append((msgid, msgstr)) + in_msgstr = False + # message start + in_msgid = True + + msgid = [line[6:]] + elif line.startswith('msgstr '): + in_msgid = False + in_msgstr = True + msgstr = [line[7:]] + elif line.startswith('"'): + if in_msgid: + msgid.append(line) + if in_msgstr: + msgstr.append(line) + + if in_msgstr: + messages.append((msgid, msgstr)) + + return messages + +files = glob.glob('src/*.cpp') + glob.glob('src/*.h') + +# xgettext -n --keyword=_ $FILES +child = Popen(['xgettext','--output=-','-n','--keyword=_'] + files, stdout=PIPE) +(out, err) = child.communicate() + +messages = parse_po(out) + +f = open(OUT_CPP, 'w') +f.write("""#include +// Automatically generated by extract_strings.py +#ifdef __GNUC__ +#define UNUSED __attribute__((unused)) +#else +#define UNUSED +#endif +""") +f.write('static const char UNUSED *bitcoin_strings[] = {') +for (msgid, msgstr) in messages: + if msgid != EMPTY: + f.write('QT_TRANSLATE_NOOP("bitcoin-core", %s),\n' % ('\n'.join(msgid))) +f.write('};') +f.close() diff --git a/share/qt/img/reload.xcf b/share/qt/img/reload.xcf new file mode 100644 index 0000000..dc8be62 Binary files /dev/null and b/share/qt/img/reload.xcf differ diff --git a/share/qt/make_spinner.py b/share/qt/make_spinner.py new file mode 100644 index 0000000..136aff3 --- /dev/null +++ b/share/qt/make_spinner.py @@ -0,0 +1,43 @@ +#!/usr/bin/env python +# W.J. van der Laan, 2011 +# Make spinning .mng animation from a .png +# Requires imagemagick 6.7+ +from __future__ import division +from os import path +from PIL import Image +from subprocess import Popen + +SRC='img/reload_scaled.png' +DST='../../src/qt/res/movies/update_spinner.mng' +TMPDIR='/tmp' +TMPNAME='tmp-%03i.png' +NUMFRAMES=35 +FRAMERATE=10.0 +CONVERT='convert' +CLOCKWISE=True +DSIZE=(16,16) + +im_src = Image.open(SRC) + +if CLOCKWISE: + im_src = im_src.transpose(Image.FLIP_LEFT_RIGHT) + +def frame_to_filename(frame): + return path.join(TMPDIR, TMPNAME % frame) + +frame_files = [] +for frame in xrange(NUMFRAMES): + rotation = (frame + 0.5) / NUMFRAMES * 360.0 + if CLOCKWISE: + rotation = -rotation + im_new = im_src.rotate(rotation, Image.BICUBIC) + im_new.thumbnail(DSIZE, Image.ANTIALIAS) + outfile = frame_to_filename(frame) + im_new.save(outfile, 'png') + frame_files.append(outfile) + +p = Popen([CONVERT, "-delay", str(FRAMERATE), "-dispose", "2"] + frame_files + [DST]) +p.communicate() + + + diff --git a/share/qt/make_windows_icon.sh b/share/qt/make_windows_icon.sh new file mode 100644 index 0000000..79da706 --- /dev/null +++ b/share/qt/make_windows_icon.sh @@ -0,0 +1,5 @@ +#!/bin/bash +# create multiresolution windows icon +ICON_DST=../../src/qt/res/icons/arepa.ico + +convert ../../src/qt/res/icons/arepa-16.png ../../src/qt/res/icons/arepa-32.png ../../src/qt/res/icons/arepa-48.png ${ICON_DST} \ No newline at end of file diff --git a/share/setup.nsi b/share/setup.nsi new file mode 100644 index 0000000..4c5a35c --- /dev/null +++ b/share/setup.nsi @@ -0,0 +1,163 @@ +Name NovaCoin + +RequestExecutionLevel highest +SetCompressor /SOLID lzma + +# General Symbol Definitions +!define REGKEY "SOFTWARE\$(^Name)" +!define VERSION 1.0.1.8 +!define COMPANY "NovaCoin project" +!define URL http://www.arepacrypto.org/ + +# MUI Symbol Definitions +!define MUI_ICON "../share/pixmaps/novacoin.ico" +!define MUI_WELCOMEFINISHPAGE_BITMAP "../share/pixmaps/nsis-wizard.bmp" +!define MUI_HEADERIMAGE +!define MUI_HEADERIMAGE_RIGHT +!define MUI_HEADERIMAGE_BITMAP "../share/pixmaps/nsis-header.bmp" +!define MUI_FINISHPAGE_NOAUTOCLOSE +!define MUI_STARTMENUPAGE_REGISTRY_ROOT HKLM +!define MUI_STARTMENUPAGE_REGISTRY_KEY ${REGKEY} +!define MUI_STARTMENUPAGE_REGISTRY_VALUENAME StartMenuGroup +!define MUI_STARTMENUPAGE_DEFAULTFOLDER NovaCoin +#!define MUI_FINISHPAGE_RUN $INSTDIR\novacoin-qt.exe +!define MUI_UNICON "${NSISDIR}\Contrib\Graphics\Icons\modern-uninstall.ico" +!define MUI_UNWELCOMEFINISHPAGE_BITMAP "../share/pixmaps/nsis-wizard.bmp" +!define MUI_UNFINISHPAGE_NOAUTOCLOSE + +# Included files +!include Sections.nsh +!include MUI2.nsh + +# Variables +Var StartMenuGroup + +# Installer pages +!insertmacro MUI_PAGE_WELCOME +!insertmacro MUI_PAGE_DIRECTORY +!insertmacro MUI_PAGE_STARTMENU Application $StartMenuGroup +!insertmacro MUI_PAGE_INSTFILES +!insertmacro MUI_PAGE_FINISH +!insertmacro MUI_UNPAGE_CONFIRM +!insertmacro MUI_UNPAGE_INSTFILES + +# Installer languages +!insertmacro MUI_LANGUAGE English + +# Installer attributes +OutFile novacoin-1.0.1.8-win32-setup.exe +InstallDir $PROGRAMFILES\NovaCoin +CRCCheck on +XPStyle on +BrandingText " " +ShowInstDetails show +VIProductVersion 1.0.1.8 +VIAddVersionKey ProductName NovaCoin +VIAddVersionKey ProductVersion "${VERSION}" +VIAddVersionKey CompanyName "${COMPANY}" +VIAddVersionKey CompanyWebsite "${URL}" +VIAddVersionKey FileVersion "${VERSION}" +VIAddVersionKey FileDescription "" +VIAddVersionKey LegalCopyright "" +InstallDirRegKey HKCU "${REGKEY}" Path +ShowUninstDetails show + +# Installer sections +Section -Main SEC0000 + SetOutPath $INSTDIR + SetOverwrite on + #File ../release/novacoin-qt.exe + File /oname=license.txt ../COPYING + File /oname=readme.txt ../doc/README_windows.txt + SetOutPath $INSTDIR\daemon + File ../src/novacoind.exe + SetOutPath $INSTDIR\src + File /r /x *.exe /x *.o ../src\*.* + SetOutPath $INSTDIR + WriteRegStr HKCU "${REGKEY}\Components" Main 1 + + # Remove old wxwidgets-based-bitcoin executable and locales: + #Delete /REBOOTOK $INSTDIR\novacoin.exe + #RMDir /r /REBOOTOK $INSTDIR\locale +SectionEnd + +Section -post SEC0001 + WriteRegStr HKCU "${REGKEY}" Path $INSTDIR + SetOutPath $INSTDIR + WriteUninstaller $INSTDIR\uninstall.exe + !insertmacro MUI_STARTMENU_WRITE_BEGIN Application + CreateDirectory $SMPROGRAMS\$StartMenuGroup + CreateShortcut "$SMPROGRAMS\$StartMenuGroup\Uninstall NovaCoin.lnk" $INSTDIR\uninstall.exe + !insertmacro MUI_STARTMENU_WRITE_END + WriteRegStr HKCU "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$(^Name)" DisplayName "$(^Name)" + WriteRegStr HKCU "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$(^Name)" DisplayVersion "${VERSION}" + WriteRegStr HKCU "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$(^Name)" Publisher "${COMPANY}" + WriteRegStr HKCU "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$(^Name)" URLInfoAbout "${URL}" + WriteRegStr HKCU "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$(^Name)" DisplayIcon $INSTDIR\uninstall.exe + WriteRegStr HKCU "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$(^Name)" UninstallString $INSTDIR\uninstall.exe + WriteRegDWORD HKCU "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$(^Name)" NoModify 1 + WriteRegDWORD HKCU "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$(^Name)" NoRepair 1 + + # bitcoin: URI handling disabled for 0.6.0 + # WriteRegStr HKCR "bitcoin" "URL Protocol" "" + # WriteRegStr HKCR "bitcoin" "" "URL:Bitcoin" + # WriteRegStr HKCR "bitcoin\DefaultIcon" "" $INSTDIR\bitcoin-qt.exe + # WriteRegStr HKCR "bitcoin\shell\open\command" "" '"$INSTDIR\bitcoin-qt.exe" "$$1"' +SectionEnd + +# Macro for selecting uninstaller sections +!macro SELECT_UNSECTION SECTION_NAME UNSECTION_ID + Push $R0 + ReadRegStr $R0 HKCU "${REGKEY}\Components" "${SECTION_NAME}" + StrCmp $R0 1 0 next${UNSECTION_ID} + !insertmacro SelectSection "${UNSECTION_ID}" + GoTo done${UNSECTION_ID} +next${UNSECTION_ID}: + !insertmacro UnselectSection "${UNSECTION_ID}" +done${UNSECTION_ID}: + Pop $R0 +!macroend + +# Uninstaller sections +Section /o -un.Main UNSEC0000 + #Delete /REBOOTOK $INSTDIR\novacoin-qt.exe + Delete /REBOOTOK $INSTDIR\license.txt + Delete /REBOOTOK $INSTDIR\readme.txt + RMDir /r /REBOOTOK $INSTDIR\daemon + RMDir /r /REBOOTOK $INSTDIR\src + DeleteRegValue HKCU "${REGKEY}\Components" Main +SectionEnd + +Section -un.post UNSEC0001 + DeleteRegKey HKCU "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$(^Name)" + Delete /REBOOTOK "$SMPROGRAMS\$StartMenuGroup\Uninstall NovaCoin.lnk" + #Delete /REBOOTOK "$SMPROGRAMS\$StartMenuGroup\Bitcoin.lnk" + #Delete /REBOOTOK "$SMSTARTUP\Bitcoin.lnk" + Delete /REBOOTOK $INSTDIR\uninstall.exe + Delete /REBOOTOK $INSTDIR\debug.log + Delete /REBOOTOK $INSTDIR\db.log + DeleteRegValue HKCU "${REGKEY}" StartMenuGroup + DeleteRegValue HKCU "${REGKEY}" Path + DeleteRegKey /IfEmpty HKCU "${REGKEY}\Components" + DeleteRegKey /IfEmpty HKCU "${REGKEY}" + DeleteRegKey HKCR "novacoin" + RmDir /REBOOTOK $SMPROGRAMS\$StartMenuGroup + RmDir /REBOOTOK $INSTDIR + Push $R0 + StrCpy $R0 $StartMenuGroup 1 + StrCmp $R0 ">" no_smgroup +no_smgroup: + Pop $R0 +SectionEnd + +# Installer functions +Function .onInit + InitPluginsDir +FunctionEnd + +# Uninstaller functions +Function un.onInit + ReadRegStr $INSTDIR HKCU "${REGKEY}" Path + !insertmacro MUI_STARTMENU_GETFOLDER Application $StartMenuGroup + !insertmacro SELECT_UNSECTION Main ${UNSEC0000} +FunctionEnd diff --git a/share/ui.rc b/share/ui.rc new file mode 100644 index 0000000..c3cece1 --- /dev/null +++ b/share/ui.rc @@ -0,0 +1,15 @@ +bitcoin ICON "pixmaps/bitcoin.ico" + +#include "wx/msw/wx.rc" + +check ICON "pixmaps/check.ico" +send16 BITMAP "pixmaps/send16.bmp" +send16mask BITMAP "pixmaps/send16mask.bmp" +send16masknoshadow BITMAP "pixmaps/send16masknoshadow.bmp" +send20 BITMAP "pixmaps/send20.bmp" +send20mask BITMAP "pixmaps/send20mask.bmp" +addressbook16 BITMAP "pixmaps/addressbook16.bmp" +addressbook16mask BITMAP "pixmaps/addressbook16mask.bmp" +addressbook20 BITMAP "pixmaps/addressbook20.bmp" +addressbook20mask BITMAP "pixmaps/addressbook20mask.bmp" +favicon ICON "pixmaps/favicon.ico" diff --git a/src/addrman.cpp b/src/addrman.cpp new file mode 100644 index 0000000..ae77459 --- /dev/null +++ b/src/addrman.cpp @@ -0,0 +1,527 @@ +// Copyright (c) 2012 Pieter Wuille +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include "addrman.h" + +using namespace std; + +int CAddrInfo::GetTriedBucket(const std::vector &nKey) const +{ + CDataStream ss1(SER_GETHASH, 0); + std::vector vchKey = GetKey(); + ss1 << nKey << vchKey; + uint64_t hash1 = Hash(ss1.begin(), ss1.end()).Get64(); + + CDataStream ss2(SER_GETHASH, 0); + std::vector vchGroupKey = GetGroup(); + ss2 << nKey << vchGroupKey << (hash1 % ADDRMAN_TRIED_BUCKETS_PER_GROUP); + uint64_t hash2 = Hash(ss2.begin(), ss2.end()).Get64(); + return hash2 % ADDRMAN_TRIED_BUCKET_COUNT; +} + +int CAddrInfo::GetNewBucket(const std::vector &nKey, const CNetAddr& src) const +{ + CDataStream ss1(SER_GETHASH, 0); + std::vector vchGroupKey = GetGroup(); + std::vector vchSourceGroupKey = src.GetGroup(); + ss1 << nKey << vchGroupKey << vchSourceGroupKey; + uint64_t hash1 = Hash(ss1.begin(), ss1.end()).Get64(); + + CDataStream ss2(SER_GETHASH, 0); + ss2 << nKey << vchSourceGroupKey << (hash1 % ADDRMAN_NEW_BUCKETS_PER_SOURCE_GROUP); + uint64_t hash2 = Hash(ss2.begin(), ss2.end()).Get64(); + return hash2 % ADDRMAN_NEW_BUCKET_COUNT; +} + +bool CAddrInfo::IsTerrible(int64_t nNow) const +{ + if (nLastTry && nLastTry >= nNow-60) // never remove things tried the last minute + return false; + + if (nTime > nNow + 10*60) // came in a flying DeLorean + return true; + + if (nTime==0 || nNow-nTime > ADDRMAN_HORIZON_DAYS*86400) // not seen in over a month + return true; + + if (nLastSuccess==0 && nAttempts>=ADDRMAN_RETRIES) // tried three times and never a success + return true; + + if (nNow-nLastSuccess > ADDRMAN_MIN_FAIL_DAYS*86400 && nAttempts>=ADDRMAN_MAX_FAILURES) // 10 successive failures in the last week + return true; + + return false; +} + +double CAddrInfo::GetChance(int64_t nNow) const +{ + double fChance = 1.0; + + int64_t nSinceLastSeen = nNow - nTime; + int64_t nSinceLastTry = nNow - nLastTry; + + if (nSinceLastSeen < 0) nSinceLastSeen = 0; + if (nSinceLastTry < 0) nSinceLastTry = 0; + + fChance *= 600.0 / (600.0 + nSinceLastSeen); + + // deprioritize very recent attempts away + if (nSinceLastTry < 60*10) + fChance *= 0.01; + + // deprioritize 50% after each failed attempt + for (int n=0; n::iterator it = mapAddr.find(addr); + if (it == mapAddr.end()) + return NULL; + if (pnId) + *pnId = (*it).second; + std::map::iterator it2 = mapInfo.find((*it).second); + if (it2 != mapInfo.end()) + return &(*it2).second; + return NULL; +} + +CAddrInfo* CAddrMan::Create(const CAddress &addr, const CNetAddr &addrSource, int *pnId) +{ + int nId = nIdCount++; + mapInfo[nId] = CAddrInfo(addr, addrSource); + mapAddr[addr] = nId; + mapInfo[nId].nRandomPos = vRandom.size(); + vRandom.push_back(nId); + if (pnId) + *pnId = nId; + return &mapInfo[nId]; +} + +void CAddrMan::SwapRandom(unsigned int nRndPos1, unsigned int nRndPos2) +{ + if (nRndPos1 == nRndPos2) + return; + + assert(nRndPos1 < vRandom.size() && nRndPos2 < vRandom.size()); + + int nId1 = vRandom[nRndPos1]; + int nId2 = vRandom[nRndPos2]; + + assert(mapInfo.count(nId1) == 1); + assert(mapInfo.count(nId2) == 1); + + mapInfo[nId1].nRandomPos = nRndPos2; + mapInfo[nId2].nRandomPos = nRndPos1; + + vRandom[nRndPos1] = nId2; + vRandom[nRndPos2] = nId1; +} + +int CAddrMan::SelectTried(int nKBucket) +{ + std::vector &vTried = vvTried[nKBucket]; + + // random shuffle the first few elements (using the entire list) + // find the least recently tried among them + int64_t nOldest = -1; + int nOldestPos = -1; + for (unsigned int i = 0; i < ADDRMAN_TRIED_ENTRIES_INSPECT_ON_EVICT && i < vTried.size(); i++) + { + int nPos = GetRandInt(vTried.size() - i) + i; + int nTemp = vTried[nPos]; + vTried[nPos] = vTried[i]; + vTried[i] = nTemp; + assert(nOldest == -1 || mapInfo.count(nTemp) == 1); + if (nOldest == -1 || mapInfo[nTemp].nLastSuccess < mapInfo[nOldest].nLastSuccess) { + nOldest = nTemp; + nOldestPos = nPos; + } + } + + return nOldestPos; +} + +int CAddrMan::ShrinkNew(int nUBucket) +{ + assert(nUBucket >= 0 && (unsigned int)nUBucket < vvNew.size()); + std::set &vNew = vvNew[nUBucket]; + + // first look for deletable items + for (std::set::iterator it = vNew.begin(); it != vNew.end(); it++) + { + assert(mapInfo.count(*it)); + CAddrInfo &info = mapInfo[*it]; + if (info.IsTerrible()) + { + if (--info.nRefCount == 0) + { + SwapRandom(info.nRandomPos, vRandom.size()-1); + vRandom.pop_back(); + mapAddr.erase(info); + mapInfo.erase(*it); + nNew--; + } + vNew.erase(it); + return 0; + } + } + + // otherwise, select four randomly, and pick the oldest of those to replace + int n[4] = {GetRandInt(vNew.size()), GetRandInt(vNew.size()), GetRandInt(vNew.size()), GetRandInt(vNew.size())}; + int nI = 0; + int nOldest = -1; + for (std::set::iterator it = vNew.begin(); it != vNew.end(); it++) + { + if (nI == n[0] || nI == n[1] || nI == n[2] || nI == n[3]) + { + assert(nOldest == -1 || mapInfo.count(*it) == 1); + if (nOldest == -1 || mapInfo[*it].nTime < mapInfo[nOldest].nTime) + nOldest = *it; + } + nI++; + } + assert(mapInfo.count(nOldest) == 1); + CAddrInfo &info = mapInfo[nOldest]; + if (--info.nRefCount == 0) + { + SwapRandom(info.nRandomPos, vRandom.size()-1); + vRandom.pop_back(); + mapAddr.erase(info); + mapInfo.erase(nOldest); + nNew--; + } + vNew.erase(nOldest); + + return 1; +} + +void CAddrMan::MakeTried(CAddrInfo& info, int nId, int nOrigin) +{ + assert(vvNew[nOrigin].count(nId) == 1); + + // remove the entry from all new buckets + for (std::vector >::iterator it = vvNew.begin(); it != vvNew.end(); it++) + { + if ((*it).erase(nId)) + info.nRefCount--; + } + nNew--; + + assert(info.nRefCount == 0); + + // what tried bucket to move the entry to + int nKBucket = info.GetTriedBucket(nKey); + std::vector &vTried = vvTried[nKBucket]; + + // first check whether there is place to just add it + if (vTried.size() < ADDRMAN_TRIED_BUCKET_SIZE) + { + vTried.push_back(nId); + nTried++; + info.fInTried = true; + return; + } + + // otherwise, find an item to evict + int nPos = SelectTried(nKBucket); + + // find which new bucket it belongs to + assert(mapInfo.count(vTried[nPos]) == 1); + int nUBucket = mapInfo[vTried[nPos]].GetNewBucket(nKey); + std::set &vNew = vvNew[nUBucket]; + + // remove the to-be-replaced tried entry from the tried set + CAddrInfo& infoOld = mapInfo[vTried[nPos]]; + infoOld.fInTried = false; + infoOld.nRefCount = 1; + // do not update nTried, as we are going to move something else there immediately + + // check whether there is place in that one, + if (vNew.size() < ADDRMAN_NEW_BUCKET_SIZE) + { + // if so, move it back there + vNew.insert(vTried[nPos]); + } else { + // otherwise, move it to the new bucket nId came from (there is certainly place there) + vvNew[nOrigin].insert(vTried[nPos]); + } + nNew++; + + vTried[nPos] = nId; + // we just overwrote an entry in vTried; no need to update nTried + info.fInTried = true; + return; +} + +void CAddrMan::Good_(const CService &addr, int64_t nTime) +{ +// printf("Good: addr=%s\n", addr.ToString().c_str()); + + int nId; + CAddrInfo *pinfo = Find(addr, &nId); + + // if not found, bail out + if (!pinfo) + return; + + CAddrInfo &info = *pinfo; + + // check whether we are talking about the exact same CService (including same port) + if (info != addr) + return; + + // update info + info.nLastSuccess = nTime; + info.nLastTry = nTime; + info.nTime = nTime; + info.nAttempts = 0; + + // if it is already in the tried set, don't do anything else + if (info.fInTried) + return; + + // find a bucket it is in now + int nRnd = GetRandInt(vvNew.size()); + int nUBucket = -1; + for (unsigned int n = 0; n < vvNew.size(); n++) + { + int nB = (n+nRnd) % vvNew.size(); + std::set &vNew = vvNew[nB]; + if (vNew.count(nId)) + { + nUBucket = nB; + break; + } + } + + // if no bucket is found, something bad happened; + // TODO: maybe re-add the node, but for now, just bail out + if (nUBucket == -1) return; + + printf("Moving %s to tried\n", addr.ToString().c_str()); + + // move nId to the tried tables + MakeTried(info, nId, nUBucket); +} + +bool CAddrMan::Add_(const CAddress &addr, const CNetAddr& source, int64_t nTimePenalty) +{ + if (!addr.IsRoutable()) + return false; + + bool fNew = false; + int nId; + CAddrInfo *pinfo = Find(addr, &nId); + + if (pinfo) + { + // periodically update nTime + bool fCurrentlyOnline = (GetAdjustedTime() - addr.nTime < 24 * 60 * 60); + int64_t nUpdateInterval = (fCurrentlyOnline ? 60 * 60 : 24 * 60 * 60); + if (addr.nTime && (!pinfo->nTime || pinfo->nTime < addr.nTime - nUpdateInterval - nTimePenalty)) + pinfo->nTime = max((int64_t)0, addr.nTime - nTimePenalty); + + // add services + pinfo->nServices |= addr.nServices; + + // do not update if no new information is present + if (!addr.nTime || (pinfo->nTime && addr.nTime <= pinfo->nTime)) + return false; + + // do not update if the entry was already in the "tried" table + if (pinfo->fInTried) + return false; + + // do not update if the max reference count is reached + if (pinfo->nRefCount == ADDRMAN_NEW_BUCKETS_PER_ADDRESS) + return false; + + // stochastic test: previous nRefCount == N: 2^N times harder to increase it + int nFactor = 1; + for (int n=0; nnRefCount; n++) + nFactor *= 2; + if (nFactor > 1 && (GetRandInt(nFactor) != 0)) + return false; + } else { + pinfo = Create(addr, source, &nId); + pinfo->nTime = max((int64_t)0, (int64_t)pinfo->nTime - nTimePenalty); +// printf("Added %s [nTime=%fhr]\n", pinfo->ToString().c_str(), (GetAdjustedTime() - pinfo->nTime) / 3600.0); + nNew++; + fNew = true; + } + + int nUBucket = pinfo->GetNewBucket(nKey, source); + std::set &vNew = vvNew[nUBucket]; + if (!vNew.count(nId)) + { + pinfo->nRefCount++; + if (vNew.size() == ADDRMAN_NEW_BUCKET_SIZE) + ShrinkNew(nUBucket); + vvNew[nUBucket].insert(nId); + } + return fNew; +} + +void CAddrMan::Attempt_(const CService &addr, int64_t nTime) +{ + CAddrInfo *pinfo = Find(addr); + + // if not found, bail out + if (!pinfo) + return; + + CAddrInfo &info = *pinfo; + + // check whether we are talking about the exact same CService (including same port) + if (info != addr) + return; + + // update info + info.nLastTry = nTime; + info.nAttempts++; +} + +CAddress CAddrMan::Select_(int nUnkBias) +{ + if (size() == 0) + return CAddress(); + + double nCorTried = sqrt(nTried) * (100.0 - nUnkBias); + double nCorNew = sqrt(nNew) * nUnkBias; + if ((nCorTried + nCorNew)*GetRandInt(1<<30)/(1<<30) < nCorTried) + { + // use a tried node + double fChanceFactor = 1.0; + while(1) + { + int nKBucket = GetRandInt(vvTried.size()); + std::vector &vTried = vvTried[nKBucket]; + if (vTried.size() == 0) continue; + int nPos = GetRandInt(vTried.size()); + assert(mapInfo.count(vTried[nPos]) == 1); + CAddrInfo &info = mapInfo[vTried[nPos]]; + if (GetRandInt(1<<30) < fChanceFactor*info.GetChance()*(1<<30)) + return info; + fChanceFactor *= 1.2; + } + } else { + // use a new node + double fChanceFactor = 1.0; + while(1) + { + int nUBucket = GetRandInt(vvNew.size()); + std::set &vNew = vvNew[nUBucket]; + if (vNew.size() == 0) continue; + int nPos = GetRandInt(vNew.size()); + std::set::iterator it = vNew.begin(); + while (nPos--) + it++; + assert(mapInfo.count(*it) == 1); + CAddrInfo &info = mapInfo[*it]; + if (GetRandInt(1<<30) < fChanceFactor*info.GetChance()*(1<<30)) + return info; + fChanceFactor *= 1.2; + } + } +} + +#ifdef DEBUG_ADDRMAN +int CAddrMan::Check_() +{ + std::set setTried; + std::map mapNew; + + if (vRandom.size() != nTried + nNew) return -7; + + for (std::map::iterator it = mapInfo.begin(); it != mapInfo.end(); it++) + { + int n = (*it).first; + CAddrInfo &info = (*it).second; + if (info.fInTried) + { + + if (!info.nLastSuccess) return -1; + if (info.nRefCount) return -2; + setTried.insert(n); + } else { + if (info.nRefCount < 0 || info.nRefCount > ADDRMAN_NEW_BUCKETS_PER_ADDRESS) return -3; + if (!info.nRefCount) return -4; + mapNew[n] = info.nRefCount; + } + if (mapAddr[info] != n) return -5; + if (info.nRandomPos<0 || info.nRandomPos>=vRandom.size() || vRandom[info.nRandomPos] != n) return -14; + if (info.nLastTry < 0) return -6; + if (info.nLastSuccess < 0) return -8; + } + + if (setTried.size() != nTried) return -9; + if (mapNew.size() != nNew) return -10; + + for (int n=0; n &vTried = vvTried[n]; + for (std::vector::iterator it = vTried.begin(); it != vTried.end(); it++) + { + if (!setTried.count(*it)) return -11; + setTried.erase(*it); + } + } + + for (int n=0; n &vNew = vvNew[n]; + for (std::set::iterator it = vNew.begin(); it != vNew.end(); it++) + { + if (!mapNew.count(*it)) return -12; + if (--mapNew[*it] == 0) + mapNew.erase(*it); + } + } + + if (setTried.size()) return -13; + if (mapNew.size()) return -15; + + return 0; +} +#endif + +void CAddrMan::GetAddr_(std::vector &vAddr) +{ + int nNodes = ADDRMAN_GETADDR_MAX_PCT*vRandom.size()/100; + if (nNodes > ADDRMAN_GETADDR_MAX) + nNodes = ADDRMAN_GETADDR_MAX; + + // perform a random shuffle over the first nNodes elements of vRandom (selecting from all) + for (int n = 0; n nUpdateInterval) + info.nTime = nTime; +} diff --git a/src/addrman.h b/src/addrman.h new file mode 100644 index 0000000..3afe0aa --- /dev/null +++ b/src/addrman.h @@ -0,0 +1,503 @@ +// Copyright (c) 2012 Pieter Wuille +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. +#ifndef _BITCOIN_ADDRMAN +#define _BITCOIN_ADDRMAN 1 + +#include "netbase.h" +#include "protocol.h" +#include "util.h" +#include "sync.h" + + +#include +#include + +#include + + +/** Extended statistics about a CAddress */ +class CAddrInfo : public CAddress +{ +private: + // where knowledge about this address first came from + CNetAddr source; + + // last successful connection by us + int64_t nLastSuccess; + + // last try whatsoever by us: + // int64_t CAddress::nLastTry + + // connection attempts since last successful attempt + int nAttempts; + + // reference count in new sets (memory only) + int nRefCount; + + // in tried set? (memory only) + bool fInTried; + + // position in vRandom + int nRandomPos; + + friend class CAddrMan; + +public: + + IMPLEMENT_SERIALIZE( + CAddress* pthis = (CAddress*)(this); + READWRITE(*pthis); + READWRITE(source); + READWRITE(nLastSuccess); + READWRITE(nAttempts); + ) + + void Init() + { + nLastSuccess = 0; + nLastTry = 0; + nAttempts = 0; + nRefCount = 0; + fInTried = false; + nRandomPos = -1; + } + + CAddrInfo(const CAddress &addrIn, const CNetAddr &addrSource) : CAddress(addrIn), source(addrSource) + { + Init(); + } + + CAddrInfo() : CAddress(), source() + { + Init(); + } + + // Calculate in which "tried" bucket this entry belongs + int GetTriedBucket(const std::vector &nKey) const; + + // Calculate in which "new" bucket this entry belongs, given a certain source + int GetNewBucket(const std::vector &nKey, const CNetAddr& src) const; + + // Calculate in which "new" bucket this entry belongs, using its default source + int GetNewBucket(const std::vector &nKey) const + { + return GetNewBucket(nKey, source); + } + + // Determine whether the statistics about this entry are bad enough so that it can just be deleted + bool IsTerrible(int64_t nNow = GetAdjustedTime()) const; + + // Calculate the relative chance this entry should be given when selecting nodes to connect to + double GetChance(int64_t nNow = GetAdjustedTime()) const; + +}; + +// Stochastic address manager +// +// Design goals: +// * Only keep a limited number of addresses around, so that addr.dat and memory requirements do not grow without bound. +// * Keep the address tables in-memory, and asynchronously dump the entire to able in addr.dat. +// * Make sure no (localized) attacker can fill the entire table with his nodes/addresses. +// +// To that end: +// * Addresses are organized into buckets. +// * Address that have not yet been tried go into 256 "new" buckets. +// * Based on the address range (/16 for IPv4) of source of the information, 32 buckets are selected at random +// * The actual bucket is chosen from one of these, based on the range the address itself is located. +// * One single address can occur in up to 4 different buckets, to increase selection chances for addresses that +// are seen frequently. The chance for increasing this multiplicity decreases exponentially. +// * When adding a new address to a full bucket, a randomly chosen entry (with a bias favoring less recently seen +// ones) is removed from it first. +// * Addresses of nodes that are known to be accessible go into 64 "tried" buckets. +// * Each address range selects at random 4 of these buckets. +// * The actual bucket is chosen from one of these, based on the full address. +// * When adding a new good address to a full bucket, a randomly chosen entry (with a bias favoring less recently +// tried ones) is evicted from it, back to the "new" buckets. +// * Bucket selection is based on cryptographic hashing, using a randomly-generated 256-bit key, which should not +// be observable by adversaries. +// * Several indexes are kept for high performance. Defining DEBUG_ADDRMAN will introduce frequent (and expensive) +// consistency checks for the entire data structure. + +// total number of buckets for tried addresses +#define ADDRMAN_TRIED_BUCKET_COUNT 64 + +// maximum allowed number of entries in buckets for tried addresses +#define ADDRMAN_TRIED_BUCKET_SIZE 64 + +// total number of buckets for new addresses +#define ADDRMAN_NEW_BUCKET_COUNT 256 + +// maximum allowed number of entries in buckets for new addresses +#define ADDRMAN_NEW_BUCKET_SIZE 64 + +// over how many buckets entries with tried addresses from a single group (/16 for IPv4) are spread +#define ADDRMAN_TRIED_BUCKETS_PER_GROUP 4 + +// over how many buckets entries with new addresses originating from a single group are spread +#define ADDRMAN_NEW_BUCKETS_PER_SOURCE_GROUP 32 + +// in how many buckets for entries with new addresses a single address may occur +#define ADDRMAN_NEW_BUCKETS_PER_ADDRESS 4 + +// how many entries in a bucket with tried addresses are inspected, when selecting one to replace +#define ADDRMAN_TRIED_ENTRIES_INSPECT_ON_EVICT 4 + +// how old addresses can maximally be +#define ADDRMAN_HORIZON_DAYS 30 + +// after how many failed attempts we give up on a new node +#define ADDRMAN_RETRIES 3 + +// how many successive failures are allowed ... +#define ADDRMAN_MAX_FAILURES 10 + +// ... in at least this many days +#define ADDRMAN_MIN_FAIL_DAYS 7 + +// the maximum percentage of nodes to return in a getaddr call +#define ADDRMAN_GETADDR_MAX_PCT 23 + +// the maximum number of nodes to return in a getaddr call +#define ADDRMAN_GETADDR_MAX 2500 + +/** Stochastical (IP) address manager */ +class CAddrMan +{ +private: + // critical section to protect the inner data structures + mutable CCriticalSection cs; + + // secret key to randomize bucket select with + std::vector nKey; + + // last used nId + int nIdCount; + + // table with information about all nIds + std::map mapInfo; + + // find an nId based on its network address + std::map mapAddr; + + // randomly-ordered vector of all nIds + std::vector vRandom; + + // number of "tried" entries + int nTried; + + // list of "tried" buckets + std::vector > vvTried; + + // number of (unique) "new" entries + int nNew; + + // list of "new" buckets + std::vector > vvNew; + +protected: + + // Find an entry. + CAddrInfo* Find(const CNetAddr& addr, int *pnId = NULL); + + // find an entry, creating it if necessary. + // nTime and nServices of found node is updated, if necessary. + CAddrInfo* Create(const CAddress &addr, const CNetAddr &addrSource, int *pnId = NULL); + + // Swap two elements in vRandom. + void SwapRandom(unsigned int nRandomPos1, unsigned int nRandomPos2); + + // Return position in given bucket to replace. + int SelectTried(int nKBucket); + + // Remove an element from a "new" bucket. + // This is the only place where actual deletes occur. + // They are never deleted while in the "tried" table, only possibly evicted back to the "new" table. + int ShrinkNew(int nUBucket); + + // Move an entry from the "new" table(s) to the "tried" table + // @pre vvUnkown[nOrigin].count(nId) != 0 + void MakeTried(CAddrInfo& info, int nId, int nOrigin); + + // Mark an entry "good", possibly moving it from "new" to "tried". + void Good_(const CService &addr, int64_t nTime); + + // Add an entry to the "new" table. + bool Add_(const CAddress &addr, const CNetAddr& source, int64_t nTimePenalty); + + // Mark an entry as attempted to connect. + void Attempt_(const CService &addr, int64_t nTime); + + // Select an address to connect to. + // nUnkBias determines how much to favor new addresses over tried ones (min=0, max=100) + CAddress Select_(int nUnkBias); + +#ifdef DEBUG_ADDRMAN + // Perform consistency check. Returns an error code or zero. + int Check_(); +#endif + + // Select several addresses at once. + void GetAddr_(std::vector &vAddr); + + // Mark an entry as currently-connected-to. + void Connected_(const CService &addr, int64_t nTime); + +public: + + IMPLEMENT_SERIALIZE + (({ + // serialized format: + // * version byte (currently 0) + // * nKey + // * nNew + // * nTried + // * number of "new" buckets + // * all nNew addrinfos in vvNew + // * all nTried addrinfos in vvTried + // * for each bucket: + // * number of elements + // * for each element: index + // + // Notice that vvTried, mapAddr and vVector are never encoded explicitly; + // they are instead reconstructed from the other information. + // + // vvNew is serialized, but only used if ADDRMAN_UNKOWN_BUCKET_COUNT didn't change, + // otherwise it is reconstructed as well. + // + // This format is more complex, but significantly smaller (at most 1.5 MiB), and supports + // changes to the ADDRMAN_ parameters without breaking the on-disk structure. + { + LOCK(cs); + unsigned char nVersion = 0; + READWRITE(nVersion); + READWRITE(nKey); + READWRITE(nNew); + READWRITE(nTried); + + CAddrMan *am = const_cast(this); + if (fWrite) + { + int nUBuckets = ADDRMAN_NEW_BUCKET_COUNT; + READWRITE(nUBuckets); + std::map mapUnkIds; + int nIds = 0; + for (std::map::iterator it = am->mapInfo.begin(); it != am->mapInfo.end(); it++) + { + if (nIds == nNew) break; // this means nNew was wrong, oh ow + mapUnkIds[(*it).first] = nIds; + CAddrInfo &info = (*it).second; + if (info.nRefCount) + { + READWRITE(info); + nIds++; + } + } + nIds = 0; + for (std::map::iterator it = am->mapInfo.begin(); it != am->mapInfo.end(); it++) + { + if (nIds == nTried) break; // this means nTried was wrong, oh ow + CAddrInfo &info = (*it).second; + if (info.fInTried) + { + READWRITE(info); + nIds++; + } + } + for (std::vector >::iterator it = am->vvNew.begin(); it != am->vvNew.end(); it++) + { + const std::set &vNew = (*it); + int nSize = vNew.size(); + READWRITE(nSize); + for (std::set::iterator it2 = vNew.begin(); it2 != vNew.end(); it2++) + { + int nIndex = mapUnkIds[*it2]; + READWRITE(nIndex); + } + } + } else { + int nUBuckets = 0; + READWRITE(nUBuckets); + am->nIdCount = 0; + am->mapInfo.clear(); + am->mapAddr.clear(); + am->vRandom.clear(); + am->vvTried = std::vector >(ADDRMAN_TRIED_BUCKET_COUNT, std::vector(0)); + am->vvNew = std::vector >(ADDRMAN_NEW_BUCKET_COUNT, std::set()); + for (int n = 0; n < am->nNew; n++) + { + CAddrInfo &info = am->mapInfo[n]; + READWRITE(info); + am->mapAddr[info] = n; + info.nRandomPos = vRandom.size(); + am->vRandom.push_back(n); + if (nUBuckets != ADDRMAN_NEW_BUCKET_COUNT) + { + am->vvNew[info.GetNewBucket(am->nKey)].insert(n); + info.nRefCount++; + } + } + am->nIdCount = am->nNew; + int nLost = 0; + for (int n = 0; n < am->nTried; n++) + { + CAddrInfo info; + READWRITE(info); + std::vector &vTried = am->vvTried[info.GetTriedBucket(am->nKey)]; + if (vTried.size() < ADDRMAN_TRIED_BUCKET_SIZE) + { + info.nRandomPos = vRandom.size(); + info.fInTried = true; + am->vRandom.push_back(am->nIdCount); + am->mapInfo[am->nIdCount] = info; + am->mapAddr[info] = am->nIdCount; + vTried.push_back(am->nIdCount); + am->nIdCount++; + } else { + nLost++; + } + } + am->nTried -= nLost; + for (int b = 0; b < nUBuckets; b++) + { + std::set &vNew = am->vvNew[b]; + int nSize = 0; + READWRITE(nSize); + for (int n = 0; n < nSize; n++) + { + int nIndex = 0; + READWRITE(nIndex); + CAddrInfo &info = am->mapInfo[nIndex]; + if (nUBuckets == ADDRMAN_NEW_BUCKET_COUNT && info.nRefCount < ADDRMAN_NEW_BUCKETS_PER_ADDRESS) + { + info.nRefCount++; + vNew.insert(nIndex); + } + } + } + } + } + });) + + CAddrMan() : vRandom(0), vvTried(ADDRMAN_TRIED_BUCKET_COUNT, std::vector(0)), vvNew(ADDRMAN_NEW_BUCKET_COUNT, std::set()) + { + nKey.resize(32); + RAND_bytes(&nKey[0], 32); + + nIdCount = 0; + nTried = 0; + nNew = 0; + } + + // Return the number of (unique) addresses in all tables. + int size() + { + return vRandom.size(); + } + + // Consistency check + void Check() + { +#ifdef DEBUG_ADDRMAN + { + LOCK(cs); + int err; + if ((err=Check_())) + printf("ADDRMAN CONSISTENCY CHECK FAILED!!! err=%i\n", err); + } +#endif + } + + // Add a single address. + bool Add(const CAddress &addr, const CNetAddr& source, int64_t nTimePenalty = 0) + { + bool fRet = false; + { + LOCK(cs); + Check(); + fRet |= Add_(addr, source, nTimePenalty); + Check(); + } + if (fRet) + printf("Added %s from %s: %i tried, %i new\n", addr.ToStringIPPort().c_str(), source.ToString().c_str(), nTried, nNew); + return fRet; + } + + // Add multiple addresses. + bool Add(const std::vector &vAddr, const CNetAddr& source, int64_t nTimePenalty = 0) + { + int nAdd = 0; + { + LOCK(cs); + Check(); + for (std::vector::const_iterator it = vAddr.begin(); it != vAddr.end(); it++) + nAdd += Add_(*it, source, nTimePenalty) ? 1 : 0; + Check(); + } + if (nAdd) + printf("Added %i addresses from %s: %i tried, %i new\n", nAdd, source.ToString().c_str(), nTried, nNew); + return nAdd > 0; + } + + // Mark an entry as accessible. + void Good(const CService &addr, int64_t nTime = GetAdjustedTime()) + { + { + LOCK(cs); + Check(); + Good_(addr, nTime); + Check(); + } + } + + // Mark an entry as connection attempted to. + void Attempt(const CService &addr, int64_t nTime = GetAdjustedTime()) + { + { + LOCK(cs); + Check(); + Attempt_(addr, nTime); + Check(); + } + } + + // Choose an address to connect to. + // nUnkBias determines how much "new" entries are favored over "tried" ones (0-100). + CAddress Select(int nUnkBias = 50) + { + CAddress addrRet; + { + LOCK(cs); + Check(); + addrRet = Select_(nUnkBias); + Check(); + } + return addrRet; + } + + // Return a bunch of addresses, selected at random. + std::vector GetAddr() + { + Check(); + std::vector vAddr; + { + LOCK(cs); + GetAddr_(vAddr); + } + Check(); + return vAddr; + } + + // Mark an entry as currently-connected-to. + void Connected(const CService &addr, int64_t nTime = GetAdjustedTime()) + { + { + LOCK(cs); + Check(); + Connected_(addr, nTime); + Check(); + } + } +}; + +#endif diff --git a/src/alert.cpp b/src/alert.cpp new file mode 100644 index 0000000..8a302d7 --- /dev/null +++ b/src/alert.cpp @@ -0,0 +1,273 @@ +// +// Alert system +// + +#include +#include +#include +#include +#include + +#include "alert.h" +#include "key.h" +#include "net.h" +#include "sync.h" +#include "ui_interface.h" + +using namespace std; + +map mapAlerts; +CCriticalSection cs_mapAlerts; + +static const char* pszMainKey = "04406ec49ddd6e534e377857474e741c679939555e0fe7dc188aefc162527abed63abb153265ef8bbe7e66588872a6128084f7eaa41319449cc25c966b12ae5b98"; + +// TestNet alerts pubKey +static const char* pszTestKey = "044bb67ef0ae541342302448234e8c26149ba64f6d24e48aaff5feca8b90bb73a4ff9c76478b1f1d0d9ef5dac118f723a94ccb677c5a6b468dbf5e8fd21b446489"; + +// TestNet alerts private key +// "308201130201010420b665cff1884e53da26376fd1b433812c9a5a8a4d5221533b15b9629789bb7e42a081a53081a2020101302c06072a8648ce3d0101022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f300604010004010704410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141020101a14403420004c0b9829c26bac70bd116a6323ada9be08ddd8fe22c2c833e26a8c067a0dcb5021b4ac7927e9ebb789e34371266a75d97dfb0c4ca24b00bf56dce28f0c4120c74" + +void CUnsignedAlert::SetNull() +{ + nVersion = 1; + nRelayUntil = 0; + nExpiration = 0; + nID = 0; + nCancel = 0; + setCancel.clear(); + nMinVer = 0; + nMaxVer = 0; + setSubVer.clear(); + nPriority = 0; + + strComment.clear(); + strStatusBar.clear(); + strReserved.clear(); +} + +std::string CUnsignedAlert::ToString() const +{ + std::string strSetCancel; + BOOST_FOREACH(int n, setCancel) + strSetCancel += strprintf("%d ", n); + std::string strSetSubVer; + BOOST_FOREACH(std::string str, setSubVer) + strSetSubVer += "\"" + str + "\" "; + return strprintf( + "CAlert(\n" + " nVersion = %d\n" + " nRelayUntil = %" PRId64"\n" + " nExpiration = %" PRId64"\n" + " nID = %d\n" + " nCancel = %d\n" + " setCancel = %s\n" + " nMinVer = %d\n" + " nMaxVer = %d\n" + " setSubVer = %s\n" + " nPriority = %d\n" + " strComment = \"%s\"\n" + " strStatusBar = \"%s\"\n" + ")\n", + nVersion, + nRelayUntil, + nExpiration, + nID, + nCancel, + strSetCancel.c_str(), + nMinVer, + nMaxVer, + strSetSubVer.c_str(), + nPriority, + strComment.c_str(), + strStatusBar.c_str()); +} + +void CUnsignedAlert::print() const +{ + printf("%s", ToString().c_str()); +} + +void CAlert::SetNull() +{ + CUnsignedAlert::SetNull(); + vchMsg.clear(); + vchSig.clear(); +} + +bool CAlert::IsNull() const +{ + return (nExpiration == 0); +} + +uint256 CAlert::GetHash() const +{ + return Hash(this->vchMsg.begin(), this->vchMsg.end()); +} + +bool CAlert::IsInEffect() const +{ + return (GetAdjustedTime() < nExpiration); +} + +bool CAlert::Cancels(const CAlert& alert) const +{ + if (!IsInEffect()) + return false; // this was a no-op before 31403 + return (alert.nID <= nCancel || setCancel.count(alert.nID)); +} + +bool CAlert::AppliesTo(int nVersion, std::string strSubVerIn) const +{ + // TODO: rework for client-version-embedded-in-strSubVer ? + return (IsInEffect() && + nMinVer <= nVersion && nVersion <= nMaxVer && + (setSubVer.empty() || setSubVer.count(strSubVerIn))); +} + +bool CAlert::AppliesToMe() const +{ + return AppliesTo(PROTOCOL_VERSION, FormatSubVersion(CLIENT_NAME, CLIENT_VERSION, std::vector())); +} + +bool CAlert::RelayTo(CNode* pnode) const +{ + if (!IsInEffect()) + return false; + // returns true if wasn't already contained in the set + if (pnode->setKnown.insert(GetHash()).second) + { + if (AppliesTo(pnode->nVersion, pnode->strSubVer) || + AppliesToMe() || + GetAdjustedTime() < nRelayUntil) + { + pnode->PushMessage("alert", *this); + return true; + } + } + return false; +} + +bool CAlert::CheckSignature() const +{ + CKey key; + if (!key.SetPubKey(ParseHex(fTestNet ? pszTestKey : pszMainKey))) + return error("CAlert::CheckSignature() : SetPubKey failed"); + if (!key.Verify(Hash(vchMsg.begin(), vchMsg.end()), vchSig)) + return error("CAlert::CheckSignature() : verify signature failed"); + + // Now unserialize the data + CDataStream sMsg(vchMsg, SER_NETWORK, PROTOCOL_VERSION); + sMsg >> *(CUnsignedAlert*)this; + return true; +} + +CAlert CAlert::getAlertByHash(const uint256 &hash) +{ + CAlert retval; + { + LOCK(cs_mapAlerts); + map::iterator mi = mapAlerts.find(hash); + if(mi != mapAlerts.end()) + retval = mi->second; + } + return retval; +} + +bool CAlert::ProcessAlert(bool fThread) +{ + if (!CheckSignature()) + return false; + if (!IsInEffect()) + return false; + + // alert.nID=max is reserved for if the alert key is + // compromised. It must have a pre-defined message, + // must never expire, must apply to all versions, + // and must cancel all previous + // alerts or it will be ignored (so an attacker can't + // send an "everything is OK, don't panic" version that + // cannot be overridden): + int maxInt = std::numeric_limits::max(); + if (nID == maxInt) + { + if (!( + nExpiration == maxInt && + nCancel == (maxInt-1) && + nMinVer == 0 && + nMaxVer == maxInt && + setSubVer.empty() && + nPriority == maxInt && + strStatusBar == "URGENT: Alert key compromised, upgrade required" + )) + return false; + } + + { + LOCK(cs_mapAlerts); + // Cancel previous alerts + for (map::iterator mi = mapAlerts.begin(); mi != mapAlerts.end();) + { + const CAlert& alert = (*mi).second; + if (Cancels(alert)) + { + printf("cancelling alert %d\n", alert.nID); + uiInterface.NotifyAlertChanged((*mi).first, CT_DELETED); + mapAlerts.erase(mi++); + } + else if (!alert.IsInEffect()) + { + printf("expiring alert %d\n", alert.nID); + uiInterface.NotifyAlertChanged((*mi).first, CT_DELETED); + mapAlerts.erase(mi++); + } + else + mi++; + } + + // Check if this alert has been cancelled + BOOST_FOREACH(PAIRTYPE(const uint256, CAlert)& item, mapAlerts) + { + const CAlert& alert = item.second; + if (alert.Cancels(*this)) + { + printf("alert already cancelled by %d\n", alert.nID); + return false; + } + } + + // Add to mapAlerts + mapAlerts.insert(make_pair(GetHash(), *this)); + // Notify UI and -alertnotify if it applies to me + if(AppliesToMe()) + { + uiInterface.NotifyAlertChanged(GetHash(), CT_NEW); + std::string strCmd = GetArg("-alertnotify", ""); + if (!strCmd.empty()) + { + // Alert text should be plain ascii coming from a trusted source, but to + // be safe we first strip anything not in safeChars, then add single quotes around + // the whole string before passing it to the shell: + std::string singleQuote("'"); + // safeChars chosen to allow simple messages/URLs/email addresses, but avoid anything + // even possibly remotely dangerous like & or > + std::string safeChars("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890 .,;_/:?@"); + std::string safeStatus; + for (std::string::size_type i = 0; i < strStatusBar.size(); i++) + { + if (safeChars.find(strStatusBar[i]) != std::string::npos) + safeStatus.push_back(strStatusBar[i]); + } + safeStatus = singleQuote+safeStatus+singleQuote; + boost::replace_all(strCmd, "%s", safeStatus); + + if (fThread) + boost::thread t(runCommand, strCmd); // thread runs free + else + runCommand(strCmd); + } + } + } + + printf("accepted alert %d, AppliesToMe()=%d\n", nID, AppliesToMe()); + return true; +} diff --git a/src/alert.h b/src/alert.h new file mode 100644 index 0000000..10fafc3 --- /dev/null +++ b/src/alert.h @@ -0,0 +1,102 @@ +// Copyright (c) 2010 Satoshi Nakamoto +// Copyright (c) 2009-2012 The Bitcoin developers +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifndef _BITCOINALERT_H_ +#define _BITCOINALERT_H_ 1 + +#include +#include + +#include "uint256.h" +#include "util.h" + +class CNode; + +/** Alerts are for notifying old versions if they become too obsolete and + * need to upgrade. The message is displayed in the status bar. + * Alert messages are broadcast as a vector of signed data. Unserializing may + * not read the entire buffer if the alert is for a newer version, but older + * versions can still relay the original data. + */ +class CUnsignedAlert +{ +public: + int nVersion; + int64_t nRelayUntil; // when newer nodes stop relaying to newer nodes + int64_t nExpiration; + int nID; + int nCancel; + std::set setCancel; + int nMinVer; // lowest version inclusive + int nMaxVer; // highest version inclusive + std::set setSubVer; // empty matches all + int nPriority; + + // Actions + std::string strComment; + std::string strStatusBar; + std::string strReserved; + + IMPLEMENT_SERIALIZE + ( + READWRITE(this->nVersion); + nVersion = this->nVersion; + READWRITE(nRelayUntil); + READWRITE(nExpiration); + READWRITE(nID); + READWRITE(nCancel); + READWRITE(setCancel); + READWRITE(nMinVer); + READWRITE(nMaxVer); + READWRITE(setSubVer); + READWRITE(nPriority); + + READWRITE(strComment); + READWRITE(strStatusBar); + READWRITE(strReserved); + ) + + void SetNull(); + + std::string ToString() const; + void print() const; +}; + +/** An alert is a combination of a serialized CUnsignedAlert and a signature. */ +class CAlert : public CUnsignedAlert +{ +public: + std::vector vchMsg; + std::vector vchSig; + + CAlert() + { + SetNull(); + } + + IMPLEMENT_SERIALIZE + ( + READWRITE(vchMsg); + READWRITE(vchSig); + ) + + void SetNull(); + bool IsNull() const; + uint256 GetHash() const; + bool IsInEffect() const; + bool Cancels(const CAlert& alert) const; + bool AppliesTo(int nVersion, std::string strSubVerIn) const; + bool AppliesToMe() const; + bool RelayTo(CNode* pnode) const; + bool CheckSignature() const; + bool ProcessAlert(bool fThread = true); + + /* + * Get copy of (active) alert object by hash. Returns a null alert if it is not found. + */ + static CAlert getAlertByHash(const uint256 &hash); +}; + +#endif diff --git a/src/allocators.h b/src/allocators.h new file mode 100644 index 0000000..eb2aed6 --- /dev/null +++ b/src/allocators.h @@ -0,0 +1,258 @@ +// Copyright (c) 2009-2010 Satoshi Nakamoto +// Copyright (c) 2009-2012 The Bitcoin developers +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. +#ifndef BITCOIN_ALLOCATORS_H +#define BITCOIN_ALLOCATORS_H + +#include +#include +#include +#include +#include // for OPENSSL_cleanse() + +#ifdef WIN32 +#ifdef _WIN32_WINNT +#undef _WIN32_WINNT +#endif +#define _WIN32_WINNT 0x0501 +#define WIN32_LEAN_AND_MEAN 1 +#ifndef NOMINMAX +#define NOMINMAX +#endif +#include +// This is used to attempt to keep keying material out of swap +// Note that VirtualLock does not provide this as a guarantee on Windows, +// but, in practice, memory that has been VirtualLock'd almost never gets written to +// the pagefile except in rare circumstances where memory is extremely low. +#else +#include +#include // for PAGESIZE +#include // for sysconf +#endif + +/** + * Thread-safe class to keep track of locked (ie, non-swappable) memory pages. + * + * Memory locks do not stack, that is, pages which have been locked several times by calls to mlock() + * will be unlocked by a single call to munlock(). This can result in keying material ending up in swap when + * those functions are used naively. This class simulates stacking memory locks by keeping a counter per page. + * + * @note By using a map from each page base address to lock count, this class is optimized for + * small objects that span up to a few pages, mostly smaller than a page. To support large allocations, + * something like an interval tree would be the preferred data structure. + */ +template class LockedPageManagerBase +{ +public: + LockedPageManagerBase(size_t page_size): + page_size(page_size) + { + // Determine bitmask for extracting page from address + assert(!(page_size & (page_size-1))); // size must be power of two + page_mask = ~(page_size - 1); + } + + // For all pages in affected range, increase lock count + void LockRange(void *p, size_t size) + { + boost::mutex::scoped_lock lock(mutex); + if(!size) return; + const size_t base_addr = reinterpret_cast(p); + const size_t start_page = base_addr & page_mask; + const size_t end_page = (base_addr + size - 1) & page_mask; + for(size_t page = start_page; page <= end_page; page += page_size) + { + Histogram::iterator it = histogram.find(page); + if(it == histogram.end()) // Newly locked page + { + locker.Lock(reinterpret_cast(page), page_size); + histogram.insert(std::make_pair(page, 1)); + } + else // Page was already locked; increase counter + { + it->second += 1; + } + } + } + + // For all pages in affected range, decrease lock count + void UnlockRange(void *p, size_t size) + { + boost::mutex::scoped_lock lock(mutex); + if(!size) return; + const size_t base_addr = reinterpret_cast(p); + const size_t start_page = base_addr & page_mask; + const size_t end_page = (base_addr + size - 1) & page_mask; + for(size_t page = start_page; page <= end_page; page += page_size) + { + Histogram::iterator it = histogram.find(page); + assert(it != histogram.end()); // Cannot unlock an area that was not locked + // Decrease counter for page, when it is zero, the page will be unlocked + it->second -= 1; + if(it->second == 0) // Nothing on the page anymore that keeps it locked + { + // Unlock page and remove the count from histogram + locker.Unlock(reinterpret_cast(page), page_size); + histogram.erase(it); + } + } + } + + // Get number of locked pages for diagnostics + int GetLockedPageCount() + { + boost::mutex::scoped_lock lock(mutex); + return histogram.size(); + } + +private: + Locker locker; + boost::mutex mutex; + size_t page_size, page_mask; + // map of page base address to lock count + typedef std::map Histogram; + Histogram histogram; +}; + +/** Determine system page size in bytes */ +static inline size_t GetSystemPageSize() +{ + size_t page_size; +#if defined(WIN32) + SYSTEM_INFO sSysInfo; + GetSystemInfo(&sSysInfo); + page_size = sSysInfo.dwPageSize; +#elif defined(PAGESIZE) // defined in limits.h + page_size = PAGESIZE; +#else // assume some POSIX OS + page_size = sysconf(_SC_PAGESIZE); +#endif + return page_size; +} + +/** + * OS-dependent memory page locking/unlocking. + * Defined as policy class to make stubbing for test possible. + */ +class MemoryPageLocker +{ +public: + /** Lock memory pages. + * addr and len must be a multiple of the system page size + */ + bool Lock(const void *addr, size_t len) + { +#ifdef WIN32 + return VirtualLock(const_cast(addr), len); +#else + return mlock(addr, len) == 0; +#endif + } + /** Unlock memory pages. + * addr and len must be a multiple of the system page size + */ + bool Unlock(const void *addr, size_t len) + { +#ifdef WIN32 + return VirtualUnlock(const_cast(addr), len); +#else + return munlock(addr, len) == 0; +#endif + } +}; + +/** + * Singleton class to keep track of locked (ie, non-swappable) memory pages, for use in + * std::allocator templates. + */ +class LockedPageManager: public LockedPageManagerBase +{ +public: + static LockedPageManager instance; // instantiated in util.cpp +private: + LockedPageManager(): + LockedPageManagerBase(GetSystemPageSize()) + {} +}; + +// +// Allocator that locks its contents from being paged +// out of memory and clears its contents before deletion. +// +template +struct secure_allocator : public std::allocator +{ + // MSVC8 default copy constructor is broken + typedef std::allocator base; + typedef typename base::size_type size_type; + typedef typename base::difference_type difference_type; + typedef typename base::pointer pointer; + typedef typename base::const_pointer const_pointer; + typedef typename base::reference reference; + typedef typename base::const_reference const_reference; + typedef typename base::value_type value_type; + secure_allocator() throw() {} + secure_allocator(const secure_allocator& a) throw() : base(a) {} + template + secure_allocator(const secure_allocator& a) throw() : base(a) {} + ~secure_allocator() throw() {} + template struct rebind + { typedef secure_allocator<_Other> other; }; + + T* allocate(std::size_t n, const void *hint = 0) + { + T *p; + p = std::allocator::allocate(n, hint); + if (p != NULL) + LockedPageManager::instance.LockRange(p, sizeof(T) * n); + return p; + } + + void deallocate(T* p, std::size_t n) + { + if (p != NULL) + { + OPENSSL_cleanse(p, sizeof(T) * n); + LockedPageManager::instance.UnlockRange(p, sizeof(T) * n); + } + std::allocator::deallocate(p, n); + } +}; + + +// +// Allocator that clears its contents before deletion. +// +template +struct zero_after_free_allocator : public std::allocator +{ + // MSVC8 default copy constructor is broken + typedef std::allocator base; + typedef typename base::size_type size_type; + typedef typename base::difference_type difference_type; + typedef typename base::pointer pointer; + typedef typename base::const_pointer const_pointer; + typedef typename base::reference reference; + typedef typename base::const_reference const_reference; + typedef typename base::value_type value_type; + zero_after_free_allocator() throw() {} + zero_after_free_allocator(const zero_after_free_allocator& a) throw() : base(a) {} + template + zero_after_free_allocator(const zero_after_free_allocator& a) throw() : base(a) {} + ~zero_after_free_allocator() throw() {} + template struct rebind + { typedef zero_after_free_allocator<_Other> other; }; + + void deallocate(T* p, std::size_t n) + { + if (p != NULL) + OPENSSL_cleanse(p, sizeof(T) * n); + std::allocator::deallocate(p, n); + } +}; + +// This is exactly like std::string, but with a custom allocator. +typedef std::basic_string, secure_allocator > SecureString; + +#endif diff --git a/src/base58.h b/src/base58.h new file mode 100644 index 0000000..f522db8 --- /dev/null +++ b/src/base58.h @@ -0,0 +1,465 @@ +// Copyright (c) 2009-2010 Satoshi Nakamoto +// Copyright (c) 2009-2012 The Bitcoin Developers +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + + +// +// Why base-58 instead of standard base-64 encoding? +// - Don't want 0OIl characters that look the same in some fonts and +// could be used to create visually identical looking account numbers. +// - A string with non-alphanumeric characters is not as easily accepted as an account number. +// - E-mail usually won't line-break if there's no punctuation to break at. +// - Double-clicking selects the whole number as one word if it's all alphanumeric. +// +#ifndef BITCOIN_BASE58_H +#define BITCOIN_BASE58_H + +#include +#include +#include // for OPENSSL_cleanse() + +#include "key.h" +#include "script.h" + +static const char* pszBase58 = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"; + +// Encode a byte sequence as a base58-encoded string +inline std::string EncodeBase58(const unsigned char* pbegin, const unsigned char* pend) +{ + // Skip & count leading zeroes. + int zeroes = 0; + int length = 0; + while (pbegin != pend && *pbegin == 0) { + pbegin++; + zeroes++; + } + // Allocate enough space in big-endian base58 representation. + int size = (pend - pbegin) * 138 / 100 + 1; // log(256) / log(58), rounded up. + std::vector b58(size); + // Process the bytes. + while (pbegin != pend) { + int carry = *pbegin; + int i = 0; + // Apply "b58 = b58 * 256 + ch". + for (std::vector::reverse_iterator it = b58.rbegin(); (carry != 0 || i < length) && (it != b58.rend()); it++, i++) { + carry += 256 * (*it); + *it = carry % 58; + carry /= 58; + } + + assert(carry == 0); + length = i; + pbegin++; + } + // Skip leading zeroes in base58 result. + std::vector::iterator it = b58.begin() + (size - length); + while (it != b58.end() && *it == 0) + it++; + // Translate the result into a string. + std::string str; + str.reserve(zeroes + (b58.end() - it)); + str.assign(zeroes, '1'); + while (it != b58.end()) + str += pszBase58[*(it++)]; + return str; +} + +// Encode a byte vector as a base58-encoded string +inline std::string EncodeBase58(const std::vector& vch) +{ + return EncodeBase58(vch.data(), vch.data() + vch.size()); +} + +// Decode a base58-encoded string psz into byte vector vchRet +// returns true if decoding is successful +inline bool DecodeBase58(const char* psz, std::vector& vch) +{ + // Skip leading spaces. + while (*psz && isspace(*psz)) + psz++; + // Skip and count leading '1's. + int zeroes = 0; + int length = 0; + while (*psz == '1') { + zeroes++; + psz++; + } + // Allocate enough space in big-endian base256 representation. + int size = strlen(psz) * 733 /1000 + 1; // log(58) / log(256), rounded up. + std::vector b256(size); + // Process the characters. + while (*psz && !isspace(*psz)) { + // Decode base58 character + const char* ch = strchr(pszBase58, *psz); + if (ch == NULL) + return false; + // Apply "b256 = b256 * 58 + ch". + int carry = ch - pszBase58; + int i = 0; + for (std::vector::reverse_iterator it = b256.rbegin(); (carry != 0 || i < length) && (it != b256.rend()); ++it, ++i) { + carry += 58 * (*it); + *it = carry % 256; + carry /= 256; + } + assert(carry == 0); + length = i; + psz++; + } + // Skip trailing spaces. + while (isspace(*psz)) + psz++; + if (*psz != 0) + return false; + // Skip leading zeroes in b256. + std::vector::iterator it = b256.begin() + (size - length); + while (it != b256.end() && *it == 0) + it++; + // Copy result into output vector. + vch.reserve(zeroes + (b256.end() - it)); + vch.assign(zeroes, 0x00); + while (it != b256.end()) + vch.push_back(*(it++)); + return true; +} + +// Decode a base58-encoded string str into byte vector vchRet +// returns true if decoding is successful +inline bool DecodeBase58(const std::string& str, std::vector& vchRet) +{ + return DecodeBase58(str.c_str(), vchRet); +} + + + + +// Encode a byte vector to a base58-encoded string, including checksum +inline std::string EncodeBase58Check(const std::vector& vchIn) +{ + // add 4-byte hash check to the end + std::vector vch(vchIn); + uint256 hash = Hash(vch.begin(), vch.end()); + vch.insert(vch.end(), (unsigned char*)&hash, (unsigned char*)&hash + 4); + return EncodeBase58(vch); +} + +// Decode a base58-encoded string psz that includes a checksum, into byte vector vchRet +// returns true if decoding is successful +inline bool DecodeBase58Check(const char* psz, std::vector& vchRet) +{ + if (!DecodeBase58(psz, vchRet)) + return false; + if (vchRet.size() < 4) + { + vchRet.clear(); + return false; + } + uint256 hash = Hash(vchRet.begin(), vchRet.end()-4); + if (memcmp(&hash, &vchRet.end()[-4], 4) != 0) + { + vchRet.clear(); + return false; + } + vchRet.resize(vchRet.size()-4); + return true; +} + +// Decode a base58-encoded string str that includes a checksum, into byte vector vchRet +// returns true if decoding is successful +inline bool DecodeBase58Check(const std::string& str, std::vector& vchRet) +{ + return DecodeBase58Check(str.c_str(), vchRet); +} + + + + + +/** Base class for all base58-encoded data */ +class CBase58Data +{ +protected: + // the version byte + unsigned char nVersion; + + // the actually encoded data + std::vector vchData; + + CBase58Data() + { + nVersion = 0; + vchData.clear(); + } + + ~CBase58Data() + { + // zero the memory, as it may contain sensitive data + if (!vchData.empty()) + OPENSSL_cleanse(&vchData[0], vchData.size()); + } + + void SetData(int nVersionIn, const void* pdata, size_t nSize) + { + nVersion = nVersionIn; + vchData.resize(nSize); + if (!vchData.empty()) + memcpy(&vchData[0], pdata, nSize); + } + + void SetData(int nVersionIn, const unsigned char *pbegin, const unsigned char *pend) + { + SetData(nVersionIn, (void*)pbegin, pend - pbegin); + } + +public: + bool SetString(const char* psz) + { + std::vector vchTemp; + DecodeBase58Check(psz, vchTemp); + if (vchTemp.empty()) + { + vchData.clear(); + nVersion = 0; + return false; + } + nVersion = vchTemp[0]; + vchData.resize(vchTemp.size() - 1); + if (!vchData.empty()) + memcpy(&vchData[0], &vchTemp[1], vchData.size()); + OPENSSL_cleanse(&vchTemp[0], vchData.size()); + return true; + } + + bool SetString(const std::string& str) + { + return SetString(str.c_str()); + } + + std::string ToString() const + { + std::vector vch(1, nVersion); + vch.insert(vch.end(), vchData.begin(), vchData.end()); + return EncodeBase58Check(vch); + } + + int CompareTo(const CBase58Data& b58) const + { + if (nVersion < b58.nVersion) return -1; + if (nVersion > b58.nVersion) return 1; + if (vchData < b58.vchData) return -1; + if (vchData > b58.vchData) return 1; + return 0; + } + + bool operator==(const CBase58Data& b58) const { return CompareTo(b58) == 0; } + bool operator<=(const CBase58Data& b58) const { return CompareTo(b58) <= 0; } + bool operator>=(const CBase58Data& b58) const { return CompareTo(b58) >= 0; } + bool operator< (const CBase58Data& b58) const { return CompareTo(b58) < 0; } + bool operator> (const CBase58Data& b58) const { return CompareTo(b58) > 0; } +}; + +/** base58-encoded Bitcoin addresses. + * Public-key-hash-addresses have version 0 (or 111 testnet). + * The data vector contains RIPEMD160(SHA256(pubkey)), where pubkey is the serialized public key. + * Script-hash-addresses have version 5 (or 196 testnet). + * The data vector contains RIPEMD160(SHA256(cscript)), where cscript is the serialized redemption script. + */ +class CBitcoinAddress; +class CBitcoinAddressVisitor : public boost::static_visitor +{ +private: + CBitcoinAddress *addr; +public: + CBitcoinAddressVisitor(CBitcoinAddress *addrIn) : addr(addrIn) { } + bool operator()(const CKeyID &id) const; + bool operator()(const CScriptID &id) const; + bool operator()(const CNoDestination &no) const; +}; + +class CBitcoinAddress : public CBase58Data +{ +public: + enum + { + PUBKEY_ADDRESS = 23, // Arepa: address begin with 'A' + SCRIPT_ADDRESS = 85, + PUBKEY_ADDRESS_TEST = 111, + SCRIPT_ADDRESS_TEST = 196, + }; + + bool Set(const CKeyID &id) { + SetData(fTestNet ? PUBKEY_ADDRESS_TEST : PUBKEY_ADDRESS, &id, 20); + return true; + } + + bool Set(const CScriptID &id) { + SetData(fTestNet ? SCRIPT_ADDRESS_TEST : SCRIPT_ADDRESS, &id, 20); + return true; + } + + bool Set(const CTxDestination &dest) + { + return boost::apply_visitor(CBitcoinAddressVisitor(this), dest); + } + + bool IsValid() const + { + unsigned int nExpectedSize = 20; + bool fExpectTestNet = false; + switch(nVersion) + { + case PUBKEY_ADDRESS: + nExpectedSize = 20; // Hash of public key + fExpectTestNet = false; + break; + case SCRIPT_ADDRESS: + nExpectedSize = 20; // Hash of CScript + fExpectTestNet = false; + break; + + case PUBKEY_ADDRESS_TEST: + nExpectedSize = 20; + fExpectTestNet = true; + break; + case SCRIPT_ADDRESS_TEST: + nExpectedSize = 20; + fExpectTestNet = true; + break; + + default: + return false; + } + return fExpectTestNet == fTestNet && vchData.size() == nExpectedSize; + } + + CBitcoinAddress() + { + } + + CBitcoinAddress(const CTxDestination &dest) + { + Set(dest); + } + + CBitcoinAddress(const std::string& strAddress) + { + SetString(strAddress); + } + + CBitcoinAddress(const char* pszAddress) + { + SetString(pszAddress); + } + + CTxDestination Get() const { + if (!IsValid()) + return CNoDestination(); + switch (nVersion) { + case PUBKEY_ADDRESS: + case PUBKEY_ADDRESS_TEST: { + uint160 id; + memcpy(&id, &vchData[0], 20); + return CKeyID(id); + } + case SCRIPT_ADDRESS: + case SCRIPT_ADDRESS_TEST: { + uint160 id; + memcpy(&id, &vchData[0], 20); + return CScriptID(id); + } + } + return CNoDestination(); + } + + bool GetKeyID(CKeyID &keyID) const { + if (!IsValid()) + return false; + switch (nVersion) { + case PUBKEY_ADDRESS: + case PUBKEY_ADDRESS_TEST: { + uint160 id; + memcpy(&id, &vchData[0], 20); + keyID = CKeyID(id); + return true; + } + default: return false; + } + } + + bool IsScript() const { + if (!IsValid()) + return false; + switch (nVersion) { + case SCRIPT_ADDRESS: + case SCRIPT_ADDRESS_TEST: { + return true; + } + default: return false; + } + } +}; + +bool inline CBitcoinAddressVisitor::operator()(const CKeyID &id) const { return addr->Set(id); } +bool inline CBitcoinAddressVisitor::operator()(const CScriptID &id) const { return addr->Set(id); } +bool inline CBitcoinAddressVisitor::operator()(const CNoDestination &id) const { return false; } + +/** A base58-encoded secret key */ +class CBitcoinSecret : public CBase58Data +{ +public: + void SetSecret(const CSecret& vchSecret, bool fCompressed) + { + assert(vchSecret.size() == 32); + SetData(128 + (fTestNet ? CBitcoinAddress::PUBKEY_ADDRESS_TEST : CBitcoinAddress::PUBKEY_ADDRESS), &vchSecret[0], vchSecret.size()); + if (fCompressed) + vchData.push_back(1); + } + + CSecret GetSecret(bool &fCompressedOut) + { + CSecret vchSecret; + vchSecret.resize(32); + memcpy(&vchSecret[0], &vchData[0], 32); + fCompressedOut = vchData.size() == 33; + return vchSecret; + } + + bool IsValid() const + { + bool fExpectTestNet = false; + switch(nVersion) + { + case (128 + CBitcoinAddress::PUBKEY_ADDRESS): + break; + + case (128 + CBitcoinAddress::PUBKEY_ADDRESS_TEST): + fExpectTestNet = true; + break; + + default: + return false; + } + return fExpectTestNet == fTestNet && (vchData.size() == 32 || (vchData.size() == 33 && vchData[32] == 1)); + } + + bool SetString(const char* pszSecret) + { + return CBase58Data::SetString(pszSecret) && IsValid(); + } + + bool SetString(const std::string& strSecret) + { + return SetString(strSecret.c_str()); + } + + CBitcoinSecret(const CSecret& vchSecret, bool fCompressed) + { + SetSecret(vchSecret, fCompressed); + } + + CBitcoinSecret() + { + } +}; + +#endif diff --git a/src/bignum.h b/src/bignum.h new file mode 100644 index 0000000..2352e7b --- /dev/null +++ b/src/bignum.h @@ -0,0 +1,726 @@ +// Copyright (c) 2009-2010 Satoshi Nakamoto +// Copyright (c) 2009-2012 The Bitcoin developers +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifndef BITCOIN_BIGNUM_H +#define BITCOIN_BIGNUM_H + +#include "serialize.h" +#include "uint256.h" +#include "version.h" + +#include + +#include +#include + +#include + +/** Errors thrown by the bignum class */ +class bignum_error : public std::runtime_error +{ +public: + explicit bignum_error(const std::string& str) : std::runtime_error(str) {} +}; + + +/** RAII encapsulated BN_CTX (OpenSSL bignum context) */ +class CAutoBN_CTX +{ +protected: + BN_CTX* pctx; + BN_CTX* operator=(BN_CTX* pnew) { return pctx = pnew; } + +public: + CAutoBN_CTX() + { + pctx = BN_CTX_new(); + if (pctx == NULL) + throw bignum_error("CAutoBN_CTX : BN_CTX_new() returned NULL"); + } + + ~CAutoBN_CTX() + { + if (pctx != NULL) + BN_CTX_free(pctx); + } + + operator BN_CTX*() { return pctx; } + BN_CTX& operator*() { return *pctx; } + BN_CTX** operator&() { return &pctx; } + bool operator!() { return (pctx == NULL); } +}; + + +/** C++ wrapper for BIGNUM (OpenSSL bignum) */ +class CBigNum : public BIGNUM +{ +public: + CBigNum() + { + BN_init(this); + } + + CBigNum(const CBigNum& b) + { + BN_init(this); + if (!BN_copy(this, &b)) + { + BN_clear_free(this); + throw bignum_error("CBigNum::CBigNum(const CBigNum&) : BN_copy failed"); + } + } + + CBigNum& operator=(const CBigNum& b) + { + if (!BN_copy(this, &b)) + throw bignum_error("CBigNum::operator= : BN_copy failed"); + return (*this); + } + + ~CBigNum() + { + BN_clear_free(this); + } + + //CBigNum(char n) is not portable. Use 'signed char' or 'unsigned char'. + CBigNum(signed char n) { BN_init(this); if (n >= 0) setulong(n); else setint64(n); } + CBigNum(short n) { BN_init(this); if (n >= 0) setulong(n); else setint64(n); } + CBigNum(int n) { BN_init(this); if (n >= 0) setulong(n); else setint64(n); } + CBigNum(long n) { BN_init(this); if (n >= 0) setulong(n); else setint64(n); } + CBigNum(long long n) { BN_init(this); setint64(n); } + CBigNum(unsigned char n) { BN_init(this); setulong(n); } + CBigNum(unsigned short n) { BN_init(this); setulong(n); } + CBigNum(unsigned int n) { BN_init(this); setulong(n); } + CBigNum(unsigned long n) { BN_init(this); setulong(n); } + CBigNum(unsigned long long n) { BN_init(this); setuint64(n); } + explicit CBigNum(uint256 n) { BN_init(this); setuint256(n); } + + explicit CBigNum(const std::vector& vch) + { + BN_init(this); + setvch(vch); + } + + /** Generates a cryptographically secure random number between zero and range exclusive + * i.e. 0 < returned number < range + * @param range The upper bound on the number. + * @return + */ + static CBigNum randBignum(const CBigNum& range) { + CBigNum ret; + if(!BN_rand_range(&ret, &range)){ + throw bignum_error("CBigNum:rand element : BN_rand_range failed"); + } + return ret; + } + + /** Generates a cryptographically secure random k-bit number + * @param k The bit length of the number. + * @return + */ + static CBigNum RandKBitBigum(const uint32_t k){ + CBigNum ret; + if(!BN_rand(&ret, k, -1, 0)){ + throw bignum_error("CBigNum:rand element : BN_rand failed"); + } + return ret; + } + + /**Returns the size in bits of the underlying bignum. + * + * @return the size + */ + int bitSize() const{ + return BN_num_bits(this); + } + + + void setulong(unsigned long n) + { + if (!BN_set_word(this, n)) + throw bignum_error("CBigNum conversion from unsigned long : BN_set_word failed"); + } + + unsigned long getulong() const + { + return BN_get_word(this); + } + + unsigned int getuint() const + { + return BN_get_word(this); + } + + int getint() const + { + unsigned long n = BN_get_word(this); + if (!BN_is_negative(this)) + return (n > (unsigned long)std::numeric_limits::max() ? std::numeric_limits::max() : n); + else + return (n > (unsigned long)std::numeric_limits::max() ? std::numeric_limits::min() : -(int)n); + } + + void setint64(int64_t sn) + { + unsigned char pch[sizeof(sn) + 6]; + unsigned char* p = pch + 4; + bool fNegative; + uint64_t n; + + if (sn < (int64_t)0) + { + // Since the minimum signed integer cannot be represented as positive so long as its type is signed, and it's not well-defined what happens if you make it unsigned before negating it, we instead increment the negative integer by 1, convert it, then increment the (now positive) unsigned integer by 1 to compensate + n = -(sn + 1); + ++n; + fNegative = true; + } else { + n = sn; + fNegative = false; + } + + bool fLeadingZeroes = true; + for (int i = 0; i < 8; i++) + { + unsigned char c = (n >> 56) & 0xff; + n <<= 8; + if (fLeadingZeroes) + { + if (c == 0) + continue; + if (c & 0x80) + *p++ = (fNegative ? 0x80 : 0); + else if (fNegative) + c |= 0x80; + fLeadingZeroes = false; + } + *p++ = c; + } + unsigned int nSize = p - (pch + 4); + pch[0] = (nSize >> 24) & 0xff; + pch[1] = (nSize >> 16) & 0xff; + pch[2] = (nSize >> 8) & 0xff; + pch[3] = (nSize) & 0xff; + BN_mpi2bn(pch, p - pch, this); + } + + uint64_t getuint64() + { + unsigned int nSize = BN_bn2mpi(this, NULL); + if (nSize < 4) + return 0; + std::vector vch(nSize); + BN_bn2mpi(this, &vch[0]); + if (vch.size() > 4) + vch[4] &= 0x7f; + uint64_t n = 0; + for (unsigned int i = 0, j = vch.size()-1; i < sizeof(n) && j >= 4; i++, j--) + ((unsigned char*)&n)[i] = vch[j]; + return n; + } + + void setuint64(uint64_t n) + { + unsigned char pch[sizeof(n) + 6]; + unsigned char* p = pch + 4; + bool fLeadingZeroes = true; + for (int i = 0; i < 8; i++) + { + unsigned char c = (n >> 56) & 0xff; + n <<= 8; + if (fLeadingZeroes) + { + if (c == 0) + continue; + if (c & 0x80) + *p++ = 0; + fLeadingZeroes = false; + } + *p++ = c; + } + unsigned int nSize = p - (pch + 4); + pch[0] = (nSize >> 24) & 0xff; + pch[1] = (nSize >> 16) & 0xff; + pch[2] = (nSize >> 8) & 0xff; + pch[3] = (nSize) & 0xff; + BN_mpi2bn(pch, p - pch, this); + } + + void setuint256(uint256 n) + { + unsigned char pch[sizeof(n) + 6]; + unsigned char* p = pch + 4; + bool fLeadingZeroes = true; + unsigned char* pbegin = (unsigned char*)&n; + unsigned char* psrc = pbegin + sizeof(n); + while (psrc != pbegin) + { + unsigned char c = *(--psrc); + if (fLeadingZeroes) + { + if (c == 0) + continue; + if (c & 0x80) + *p++ = 0; + fLeadingZeroes = false; + } + *p++ = c; + } + unsigned int nSize = p - (pch + 4); + pch[0] = (nSize >> 24) & 0xff; + pch[1] = (nSize >> 16) & 0xff; + pch[2] = (nSize >> 8) & 0xff; + pch[3] = (nSize >> 0) & 0xff; + BN_mpi2bn(pch, p - pch, this); + } + + uint256 getuint256() const + { + unsigned int nSize = BN_bn2mpi(this, NULL); + if (nSize < 4) + return 0; + std::vector vch(nSize); + BN_bn2mpi(this, &vch[0]); + if (vch.size() > 4) + vch[4] &= 0x7f; + uint256 n = 0; + for (unsigned int i = 0, j = vch.size()-1; i < sizeof(n) && j >= 4; i++, j--) + ((unsigned char*)&n)[i] = vch[j]; + return n; + } + + + void setvch(const std::vector& vch) + { + std::vector vch2(vch.size() + 4); + unsigned int nSize = vch.size(); + // BIGNUM's byte stream format expects 4 bytes of + // big endian size data info at the front + vch2[0] = (nSize >> 24) & 0xff; + vch2[1] = (nSize >> 16) & 0xff; + vch2[2] = (nSize >> 8) & 0xff; + vch2[3] = (nSize >> 0) & 0xff; + // swap data to big endian + reverse_copy(vch.begin(), vch.end(), vch2.begin() + 4); + BN_mpi2bn(&vch2[0], vch2.size(), this); + } + + std::vector getvch() const + { + unsigned int nSize = BN_bn2mpi(this, NULL); + if (nSize <= 4) + return std::vector(); + std::vector vch(nSize); + BN_bn2mpi(this, &vch[0]); + vch.erase(vch.begin(), vch.begin() + 4); + reverse(vch.begin(), vch.end()); + return vch; + } + + CBigNum& SetCompact(unsigned int nCompact) + { + unsigned int nSize = nCompact >> 24; + std::vector vch(4 + nSize); + vch[3] = nSize; + if (nSize >= 1) vch[4] = (nCompact >> 16) & 0xff; + if (nSize >= 2) vch[5] = (nCompact >> 8) & 0xff; + if (nSize >= 3) vch[6] = (nCompact >> 0) & 0xff; + BN_mpi2bn(&vch[0], vch.size(), this); + return *this; + } + + unsigned int GetCompact() const + { + unsigned int nSize = BN_bn2mpi(this, NULL); + std::vector vch(nSize); + nSize -= 4; + BN_bn2mpi(this, &vch[0]); + unsigned int nCompact = nSize << 24; + if (nSize >= 1) nCompact |= (vch[4] << 16); + if (nSize >= 2) nCompact |= (vch[5] << 8); + if (nSize >= 3) nCompact |= (vch[6] << 0); + return nCompact; + } + + void SetHex(const std::string& str) + { + // skip 0x + const char* psz = str.c_str(); + while (isspace(*psz)) + psz++; + bool fNegative = false; + if (*psz == '-') + { + fNegative = true; + psz++; + } + if (psz[0] == '0' && tolower(psz[1]) == 'x') + psz += 2; + while (isspace(*psz)) + psz++; + + // hex string to bignum + static const signed 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 }; + *this = 0; + while (isxdigit(*psz)) + { + *this <<= 4; + int n = phexdigit[(unsigned char)*psz++]; + *this += n; + } + if (fNegative) + *this = 0 - *this; + } + + std::string ToString(int nBase=10) const + { + CAutoBN_CTX pctx; + CBigNum bnBase = nBase; + CBigNum bn0 = 0; + std::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=PROTOCOL_VERSION) const + { + return ::GetSerializeSize(getvch(), nType, nVersion); + } + + template + void Serialize(Stream& s, int nType=0, int nVersion=PROTOCOL_VERSION) const + { + ::Serialize(s, getvch(), nType, nVersion); + } + + template + void Unserialize(Stream& s, int nType=0, int nVersion=PROTOCOL_VERSION) + { + std::vector vch; + ::Unserialize(s, vch, nType, nVersion); + setvch(vch); + } + + /** + * exponentiation with an int. this^e + * @param e the exponent as an int + * @return + */ + CBigNum pow(const int e) const { + return this->pow(CBigNum(e)); + } + + /** + * exponentiation this^e + * @param e the exponent + * @return + */ + CBigNum pow(const CBigNum& e) const { + CAutoBN_CTX pctx; + CBigNum ret; + if (!BN_exp(&ret, this, &e, pctx)) + throw bignum_error("CBigNum::pow : BN_exp failed"); + return ret; + } + + /** + * modular multiplication: (this * b) mod m + * @param b operand + * @param m modulus + */ + CBigNum mul_mod(const CBigNum& b, const CBigNum& m) const { + CAutoBN_CTX pctx; + CBigNum ret; + if (!BN_mod_mul(&ret, this, &b, &m, pctx)) + throw bignum_error("CBigNum::mul_mod : BN_mod_mul failed"); + + return ret; + } + + /** + * modular exponentiation: this^e mod n + * @param e exponent + * @param m modulus + */ + CBigNum pow_mod(const CBigNum& e, const CBigNum& m) const { + CAutoBN_CTX pctx; + CBigNum ret; + if( e < 0){ + // g^-x = (g^-1)^x + CBigNum inv = this->inverse(m); + CBigNum posE = e * -1; + if (!BN_mod_exp(&ret, &inv, &posE, &m, pctx)) + throw bignum_error("CBigNum::pow_mod: BN_mod_exp failed on negative exponent"); + }else + if (!BN_mod_exp(&ret, this, &e, &m, pctx)) + throw bignum_error("CBigNum::pow_mod : BN_mod_exp failed"); + + return ret; + } + + /** + * Calculates the inverse of this element mod m. + * i.e. i such this*i = 1 mod m + * @param m the modu + * @return the inverse + */ + CBigNum inverse(const CBigNum& m) const { + CAutoBN_CTX pctx; + CBigNum ret; + if (!BN_mod_inverse(&ret, this, &m, pctx)) + throw bignum_error("CBigNum::inverse*= :BN_mod_inverse"); + return ret; + } + + /** + * Generates a random (safe) prime of numBits bits + * @param numBits the number of bits + * @param safe true for a safe prime + * @return the prime + */ + static CBigNum generatePrime(const unsigned int numBits, bool safe = false) { + CBigNum ret; + if(!BN_generate_prime_ex(&ret, numBits, (safe == true), NULL, NULL, NULL)) + throw bignum_error("CBigNum::generatePrime*= :BN_generate_prime_ex"); + return ret; + } + + /** + * Calculates the greatest common divisor (GCD) of two numbers. + * @param m the second element + * @return the GCD + */ + CBigNum gcd( const CBigNum& b) const{ + CAutoBN_CTX pctx; + CBigNum ret; + if (!BN_gcd(&ret, this, &b, pctx)) + throw bignum_error("CBigNum::gcd*= :BN_gcd"); + return ret; + } + + /** + * Miller-Rabin primality test on this element + * @param checks: optional, the number of Miller-Rabin tests to run + * default causes error rate of 2^-80. + * @return true if prime + */ + bool isPrime(const int checks=BN_prime_checks) const { + CAutoBN_CTX pctx; + int ret = BN_is_prime(this, checks, NULL, pctx, NULL); + if(ret < 0){ + throw bignum_error("CBigNum::isPrime :BN_is_prime"); + } + return ret; + } + + bool isOne() const { + return BN_is_one(this); + } + + + bool operator!() const + { + return BN_is_zero(this); + } + + CBigNum& operator+=(const CBigNum& b) + { + if (!BN_add(this, this, &b)) + throw bignum_error("CBigNum::operator+= : BN_add failed"); + return *this; + } + + CBigNum& operator-=(const CBigNum& b) + { + *this = *this - b; + return *this; + } + + CBigNum& operator*=(const CBigNum& b) + { + CAutoBN_CTX pctx; + if (!BN_mul(this, this, &b, pctx)) + throw bignum_error("CBigNum::operator*= : BN_mul failed"); + return *this; + } + + CBigNum& operator/=(const CBigNum& b) + { + *this = *this / b; + return *this; + } + + CBigNum& operator%=(const CBigNum& b) + { + *this = *this % b; + return *this; + } + + CBigNum& operator<<=(unsigned int shift) + { + if (!BN_lshift(this, this, shift)) + throw bignum_error("CBigNum:operator<<= : BN_lshift failed"); + return *this; + } + + CBigNum& operator>>=(unsigned int shift) + { + // Note: BN_rshift segfaults on 64-bit if 2^shift is greater than the number + // if built on ubuntu 9.04 or 9.10, probably depends on version of OpenSSL + CBigNum a = 1; + a <<= shift; + if (BN_cmp(&a, this) > 0) + { + *this = 0; + return *this; + } + + if (!BN_rshift(this, this, shift)) + throw bignum_error("CBigNum:operator>>= : BN_rshift failed"); + return *this; + } + + + CBigNum& operator++() + { + // prefix operator + if (!BN_add(this, this, BN_value_one())) + throw bignum_error("CBigNum::operator++ : BN_add failed"); + return *this; + } + + const CBigNum operator++(int) + { + // postfix operator + const CBigNum ret = *this; + ++(*this); + return ret; + } + + CBigNum& operator--() + { + // prefix operator + CBigNum r; + if (!BN_sub(&r, this, BN_value_one())) + throw bignum_error("CBigNum::operator-- : BN_sub failed"); + *this = r; + return *this; + } + + const CBigNum operator--(int) + { + // postfix operator + const CBigNum ret = *this; + --(*this); + return ret; + } + + + friend inline const CBigNum operator-(const CBigNum& a, const CBigNum& b); + friend inline const CBigNum operator/(const CBigNum& a, const CBigNum& b); + friend inline const CBigNum operator%(const CBigNum& a, const CBigNum& b); + friend inline const CBigNum operator*(const CBigNum& a, const CBigNum& b); + friend inline bool operator<(const CBigNum& a, const CBigNum& b); +}; + + + +inline const CBigNum operator+(const CBigNum& a, const CBigNum& b) +{ + CBigNum r; + if (!BN_add(&r, &a, &b)) + throw bignum_error("CBigNum::operator+ : BN_add failed"); + return r; +} + +inline const CBigNum operator-(const CBigNum& a, const CBigNum& b) +{ + CBigNum r; + if (!BN_sub(&r, &a, &b)) + throw bignum_error("CBigNum::operator- : BN_sub failed"); + return r; +} + +inline const CBigNum operator-(const CBigNum& a) +{ + CBigNum r(a); + BN_set_negative(&r, !BN_is_negative(&r)); + return r; +} + +inline const CBigNum operator*(const CBigNum& a, const CBigNum& b) +{ + CAutoBN_CTX pctx; + CBigNum r; + if (!BN_mul(&r, &a, &b, pctx)) + throw bignum_error("CBigNum::operator* : BN_mul failed"); + return r; +} + +inline const CBigNum operator/(const CBigNum& a, const CBigNum& b) +{ + CAutoBN_CTX pctx; + CBigNum r; + if (!BN_div(&r, NULL, &a, &b, pctx)) + throw bignum_error("CBigNum::operator/ : BN_div failed"); + return r; +} + +inline const CBigNum operator%(const CBigNum& a, const CBigNum& b) +{ + CAutoBN_CTX pctx; + CBigNum r; + if (!BN_nnmod(&r, &a, &b, pctx)) + throw bignum_error("CBigNum::operator% : BN_div failed"); + return r; +} + +inline const CBigNum operator<<(const CBigNum& a, unsigned int shift) +{ + CBigNum r; + if (!BN_lshift(&r, &a, shift)) + throw bignum_error("CBigNum:operator<< : BN_lshift failed"); + return r; +} + +inline const CBigNum operator>>(const CBigNum& a, unsigned int shift) +{ + CBigNum r = a; + r >>= shift; + return r; +} + +inline bool operator==(const CBigNum& a, const CBigNum& b) { return (BN_cmp(&a, &b) == 0); } +inline bool operator!=(const CBigNum& a, const CBigNum& b) { return (BN_cmp(&a, &b) != 0); } +inline bool operator<=(const CBigNum& a, const CBigNum& b) { return (BN_cmp(&a, &b) <= 0); } +inline bool operator>=(const CBigNum& a, const CBigNum& b) { return (BN_cmp(&a, &b) >= 0); } +inline bool operator<(const CBigNum& a, const CBigNum& b) { return (BN_cmp(&a, &b) < 0); } +inline bool operator>(const CBigNum& a, const CBigNum& b) { return (BN_cmp(&a, &b) > 0); } + +inline std::ostream& operator<<(std::ostream &strm, const CBigNum &b) { return strm << b.ToString(10); } + +typedef CBigNum Bignum; + +#endif diff --git a/src/bitcoinrpc.cpp b/src/bitcoinrpc.cpp new file mode 100644 index 0000000..e3d5537 --- /dev/null +++ b/src/bitcoinrpc.cpp @@ -0,0 +1,1331 @@ +// Copyright (c) 2010 Satoshi Nakamoto +// Copyright (c) 2009-2012 The Bitcoin developers +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include "init.h" +#include "util.h" +#include "sync.h" +#include "ui_interface.h" +#include "base58.h" +#include "bitcoinrpc.h" +#include "db.h" + +#undef printf +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define printf OutputDebugStringF + +using namespace std; +using namespace boost; +using namespace boost::asio; +using namespace json_spirit; + +void ThreadRPCServer2(void* parg); + +static std::string strRPCUserColonPass; + +const Object emptyobj; + +void ThreadRPCServer3(void* parg); + +static inline unsigned short GetDefaultRPCPort() +{ + return GetBoolArg("-testnet", false) ? 18586 : 8586; +} + +Object JSONRPCError(int code, const string& message) +{ + Object error; + error.push_back(Pair("code", code)); + error.push_back(Pair("message", message)); + return error; +} + +void RPCTypeCheck(const Array& params, + const list& typesExpected, + bool fAllowNull) +{ + unsigned int i = 0; + BOOST_FOREACH(Value_type t, typesExpected) + { + if (params.size() <= i) + break; + + const Value& v = params[i]; + if (!((v.type() == t) || (fAllowNull && (v.type() == null_type)))) + { + string err = strprintf("Expected type %s, got %s", + Value_type_name[t], Value_type_name[v.type()]); + throw JSONRPCError(RPC_TYPE_ERROR, err); + } + i++; + } +} + +void RPCTypeCheck(const Object& o, + const map& typesExpected, + bool fAllowNull) +{ + BOOST_FOREACH(const PAIRTYPE(string, Value_type)& t, typesExpected) + { + const Value& v = find_value(o, t.first); + if (!fAllowNull && v.type() == null_type) + throw JSONRPCError(RPC_TYPE_ERROR, strprintf("Missing %s", t.first.c_str())); + + if (!((v.type() == t.second) || (fAllowNull && (v.type() == null_type)))) + { + string err = strprintf("Expected type %s for %s, got %s", + Value_type_name[t.second], t.first.c_str(), Value_type_name[v.type()]); + throw JSONRPCError(RPC_TYPE_ERROR, err); + } + } +} + +int64_t AmountFromValue(const Value& value) +{ + double dAmount = value.get_real(); + if (dAmount <= 0.0 || dAmount > MAX_MONEY) + throw JSONRPCError(RPC_TYPE_ERROR, "Invalid amount"); + int64_t nAmount = roundint64(dAmount * COIN); + if (!MoneyRange(nAmount)) + throw JSONRPCError(RPC_TYPE_ERROR, "Invalid amount"); + return nAmount; +} + +Value ValueFromAmount(int64_t amount) +{ + return (double)amount / (double)COIN; +} + + +// +// Utilities: convert hex-encoded Values +// (throws error if not hex). +// +uint256 ParseHashV(const Value& v, string strName) +{ + string strHex; + if (v.type() == str_type) + strHex = v.get_str(); + if (!IsHex(strHex)) // Note: IsHex("") is false + throw JSONRPCError(RPC_INVALID_PARAMETER, strName+" must be hexadecimal string (not '"+strHex+"')"); + uint256 result; + result.SetHex(strHex); + return result; +} + +uint256 ParseHashO(const Object& o, string strKey) +{ + return ParseHashV(find_value(o, strKey), strKey); +} + +vector ParseHexV(const Value& v, string strName) +{ + string strHex; + if (v.type() == str_type) + strHex = v.get_str(); + if (!IsHex(strHex)) + throw JSONRPCError(RPC_INVALID_PARAMETER, strName+" must be hexadecimal string (not '"+strHex+"')"); + return ParseHex(strHex); +} + +vector ParseHexO(const Object& o, string strKey) +{ + return ParseHexV(find_value(o, strKey), strKey); +} + + +/// +/// Note: This interface may still be subject to change. +/// + +string CRPCTable::help(string strCommand) const +{ + string strRet; + set setDone; + for (map::const_iterator mi = mapCommands.begin(); mi != mapCommands.end(); ++mi) + { + const CRPCCommand *pcmd = mi->second; + string strMethod = mi->first; + // We already filter duplicates, but these deprecated screw up the sort order + if (strMethod.find("label") != string::npos) + continue; + if (strCommand != "" && strMethod != strCommand) + continue; + try + { + Array params; + rpcfn_type pfn = pcmd->actor; + if (setDone.insert(pfn).second) + (*pfn)(params, true); + } + catch (std::exception& e) + { + // Help text is returned in an exception + string strHelp = string(e.what()); + if (strCommand == "") + if (strHelp.find('\n') != string::npos) + strHelp = strHelp.substr(0, strHelp.find('\n')); + strRet += strHelp + "\n"; + } + } + if (strRet == "") + strRet = strprintf("help: unknown command: %s\n", strCommand.c_str()); + strRet = strRet.substr(0,strRet.size()-1); + return strRet; +} + +Value help(const Array& params, bool fHelp) +{ + if (fHelp || params.size() > 1) + throw runtime_error( + "help [command]\n" + "List commands, or get help for a command."); + + string strCommand; + if (params.size() > 0) + strCommand = params[0].get_str(); + + return tableRPC.help(strCommand); +} + + +Value stop(const Array& params, bool fHelp) +{ + // Accept the deprecated and ignored 'detach´ boolean argument + if (fHelp || params.size() > 1) + throw runtime_error( + "stop\n" + "Stop arepacoin server."); + // Shutdown will take long enough that the response should get back + StartShutdown(); + return "arepacoin server stopping"; +} + + + +// +// Call Table +// + + +static const CRPCCommand vRPCCommands[] = +{ // name function safemd unlocked + // ------------------------ ----------------------- ------ -------- + { "help", &help, true, true }, + { "stop", &stop, true, true }, + { "getbestblockhash", &getbestblockhash, true, false }, + { "getblockcount", &getblockcount, true, false }, + { "getconnectioncount", &getconnectioncount, true, false }, + { "getpeerinfo", &getpeerinfo, true, false }, + { "addnode", &addnode, true, true }, + { "getnettotals", &getnettotals, true, true }, + { "getdifficulty", &getdifficulty, true, false }, + { "getinfo", &getinfo, true, false }, + { "getsubsidy", &getsubsidy, true, false }, + { "getmininginfo", &getmininginfo, true, false }, + { "getstakinginfo", &getstakinginfo, true, false }, + { "getnewaddress", &getnewaddress, true, false }, + { "getnewpubkey", &getnewpubkey, true, false }, + { "getaccountaddress", &getaccountaddress, true, false }, + { "setaccount", &setaccount, true, false }, + { "getaccount", &getaccount, false, false }, + { "getaddressesbyaccount", &getaddressesbyaccount, true, false }, + { "getaddresses", &getaddresses, true, false }, + { "sendtoaddress", &sendtoaddress, false, false }, + { "getreceivedbyaddress", &getreceivedbyaddress, false, false }, + { "getreceivedbyaccount", &getreceivedbyaccount, false, false }, + { "listreceivedbyaddress", &listreceivedbyaddress, false, false }, + { "listreceivedbyaccount", &listreceivedbyaccount, false, false }, + { "backupwallet", &backupwallet, true, false }, + { "keypoolrefill", &keypoolrefill, true, false }, + { "walletpassphrase", &walletpassphrase, true, false }, + { "walletpassphrasechange", &walletpassphrasechange, false, false }, + { "walletlock", &walletlock, true, false }, + { "encryptwallet", &encryptwallet, false, false }, + { "validateaddress", &validateaddress, true, false }, + { "validatepubkey", &validatepubkey, true, false }, + { "getbalance", &getbalance, false, false }, + { "move", &movecmd, false, false }, + { "sendfrom", &sendfrom, false, false }, + { "sendmany", &sendmany, false, false }, + { "addmultisigaddress", &addmultisigaddress, false, false }, + { "addredeemscript", &addredeemscript, false, false }, + { "getrawmempool", &getrawmempool, true, false }, + { "getblock", &getblock, false, false }, + { "getblockbynumber", &getblockbynumber, false, false }, + { "getblockhash", &getblockhash, false, false }, + { "gettransaction", &gettransaction, false, false }, + { "listtransactions", &listtransactions, false, false }, + { "listaddressgroupings", &listaddressgroupings, false, false }, + { "signmessage", &signmessage, false, false }, + { "verifymessage", &verifymessage, false, false }, + { "getwork", &getwork, true, false }, + { "getworkex", &getworkex, true, false }, + { "listaccounts", &listaccounts, false, false }, + { "settxfee", &settxfee, false, false }, + { "getblocktemplate", &getblocktemplate, true, false }, + { "submitblock", &submitblock, false, false }, + { "listsinceblock", &listsinceblock, false, false }, + { "dumpprivkey", &dumpprivkey, false, false }, + { "dumpwallet", &dumpwallet, true, false }, + { "importwallet", &importwallet, false, false }, + { "importprivkey", &importprivkey, false, false }, + { "listunspent", &listunspent, false, false }, + { "getrawtransaction", &getrawtransaction, false, false }, + { "createrawtransaction", &createrawtransaction, false, false }, + { "decoderawtransaction", &decoderawtransaction, false, false }, + { "decodescript", &decodescript, false, false }, + { "signrawtransaction", &signrawtransaction, false, false }, + { "sendrawtransaction", &sendrawtransaction, false, false }, + { "getcheckpoint", &getcheckpoint, true, false }, + { "reservebalance", &reservebalance, false, true}, + { "checkwallet", &checkwallet, false, true}, + { "repairwallet", &repairwallet, false, true}, + { "resendtx", &resendtx, false, true}, + { "makekeypair", &makekeypair, false, true}, + { "sendalert", &sendalert, false, false}, +}; + +CRPCTable::CRPCTable() +{ + unsigned int vcidx; + for (vcidx = 0; vcidx < (sizeof(vRPCCommands) / sizeof(vRPCCommands[0])); vcidx++) + { + const CRPCCommand *pcmd; + + pcmd = &vRPCCommands[vcidx]; + mapCommands[pcmd->name] = pcmd; + } +} + +const CRPCCommand *CRPCTable::operator[](string name) const +{ + map::const_iterator it = mapCommands.find(name); + if (it == mapCommands.end()) + return NULL; + return (*it).second; +} + +// +// 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, const map& mapRequestHeaders) +{ + ostringstream s; + s << "POST / HTTP/1.1\r\n" + << "User-Agent: arepacoin-json-rpc/" << FormatFullVersion() << "\r\n" + << "Host: 127.0.0.1\r\n" + << "Content-Type: application/json\r\n" + << "Content-Length: " << strMsg.size() << "\r\n" + << "Connection: close\r\n" + << "Accept: application/json\r\n"; + BOOST_FOREACH(const PAIRTYPE(string, string)& item, mapRequestHeaders) + s << item.first << ": " << item.second << "\r\n"; + s << "\r\n" << strMsg; + + return s.str(); +} + +string rfc1123Time() +{ + char buffer[64]; + time_t now; + time(&now); + struct tm* now_gmt = gmtime(&now); + string locale(setlocale(LC_TIME, NULL)); + setlocale(LC_TIME, "C"); // we want POSIX (aka "C") weekday/month strings + strftime(buffer, sizeof(buffer), "%a, %d %b %Y %H:%M:%S +0000", now_gmt); + setlocale(LC_TIME, locale.c_str()); + return string(buffer); +} + +static string HTTPReply(int nStatus, const string& strMsg, bool keepalive) +{ + if (nStatus == HTTP_UNAUTHORIZED) + return strprintf("HTTP/1.0 401 Authorization Required\r\n" + "Date: %s\r\n" + "Server: arepacoin-json-rpc/%s\r\n" + "WWW-Authenticate: Basic realm=\"jsonrpc\"\r\n" + "Content-Type: text/html\r\n" + "Content-Length: 296\r\n" + "\r\n" + "\r\n" + "\r\n" + "\r\n" + "Error\r\n" + "\r\n" + "\r\n" + "

401 Unauthorized.

\r\n" + "\r\n", rfc1123Time().c_str(), FormatFullVersion().c_str()); + const char *cStatus; + if (nStatus == HTTP_OK) cStatus = "OK"; + else if (nStatus == HTTP_BAD_REQUEST) cStatus = "Bad Request"; + else if (nStatus == HTTP_FORBIDDEN) cStatus = "Forbidden"; + else if (nStatus == HTTP_NOT_FOUND) cStatus = "Not Found"; + else if (nStatus == HTTP_INTERNAL_SERVER_ERROR) cStatus = "Internal Server Error"; + else cStatus = ""; + return strprintf( + "HTTP/1.1 %d %s\r\n" + "Date: %s\r\n" + "Connection: %s\r\n" + "Content-Length: %" PRIszu"\r\n" + "Content-Type: application/json\r\n" + "Server: arepacoin-json-rpc/%s\r\n" + "\r\n" + "%s", + nStatus, + cStatus, + rfc1123Time().c_str(), + keepalive ? "keep-alive" : "close", + strMsg.size(), + FormatFullVersion().c_str(), + strMsg.c_str()); +} + +int ReadHTTPStatus(std::basic_istream& stream, int &proto) +{ + string str; + getline(stream, str); + vector vWords; + boost::split(vWords, str, boost::is_any_of(" ")); + if (vWords.size() < 2) + return HTTP_INTERNAL_SERVER_ERROR; + proto = 0; + const char *ver = strstr(str.c_str(), "HTTP/1."); + if (ver != NULL) + proto = atoi(ver+7); + return atoi(vWords[1].c_str()); +} + +int ReadHTTPHeader(std::basic_istream& stream, map& mapHeadersRet) +{ + int nLen = 0; + while (true) + { + string str; + std::getline(stream, str); + if (str.empty() || str == "\r") + break; + string::size_type nColon = str.find(":"); + if (nColon != string::npos) + { + string strHeader = str.substr(0, nColon); + boost::trim(strHeader); + boost::to_lower(strHeader); + string strValue = str.substr(nColon+1); + boost::trim(strValue); + mapHeadersRet[strHeader] = strValue; + if (strHeader == "content-length") + nLen = atoi(strValue.c_str()); + } + } + return nLen; +} + +int ReadHTTP(std::basic_istream& stream, map& mapHeadersRet, string& strMessageRet) +{ + mapHeadersRet.clear(); + strMessageRet = ""; + + // Read status + int nProto = 0; + int nStatus = ReadHTTPStatus(stream, nProto); + + // Read header + int nLen = ReadHTTPHeader(stream, mapHeadersRet); + if (nLen < 0 || nLen > (int)MAX_SIZE) + return HTTP_INTERNAL_SERVER_ERROR; + + // Read message + if (nLen > 0) + { + vector vch(nLen); + stream.read(&vch[0], nLen); + strMessageRet = string(vch.begin(), vch.end()); + } + + string sConHdr = mapHeadersRet["connection"]; + + if ((sConHdr != "close") && (sConHdr != "keep-alive")) + { + if (nProto >= 1) + mapHeadersRet["connection"] = "keep-alive"; + else + mapHeadersRet["connection"] = "close"; + } + + return nStatus; +} + +bool HTTPAuthorized(map& mapHeaders) +{ + string strAuth = mapHeaders["authorization"]; + if (strAuth.substr(0,6) != "Basic ") + return false; + string strUserPass64 = strAuth.substr(6); boost::trim(strUserPass64); + string strUserPass = DecodeBase64(strUserPass64); + return TimingResistantEqual(strUserPass, strRPCUserColonPass); +} + +// +// JSON-RPC protocol. Bitcoin speaks version 1.0 for maximum compatibility, +// but uses JSON-RPC 1.1/2.0 standards for parts of the 1.0 standard that were +// unspecified (HTTP errors and contents of 'error'). +// +// 1.0 spec: http://json-rpc.org/wiki/specification +// 1.2 spec: http://groups.google.com/group/json-rpc/web/json-rpc-over-http +// 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"; +} + +Object JSONRPCReplyObj(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 reply; +} + +string JSONRPCReply(const Value& result, const Value& error, const Value& id) +{ + Object reply = JSONRPCReplyObj(result, error, id); + return write_string(Value(reply), false) + "\n"; +} + +void ErrorReply(std::ostream& stream, const Object& objError, const Value& id) +{ + // Send error reply from json-rpc error object + int nStatus = HTTP_INTERNAL_SERVER_ERROR; + int code = find_value(objError, "code").get_int(); + if (code == RPC_INVALID_REQUEST) nStatus = HTTP_BAD_REQUEST; + else if (code == RPC_METHOD_NOT_FOUND) nStatus = HTTP_NOT_FOUND; + string strReply = JSONRPCReply(Value::null, objError, id); + stream << HTTPReply(nStatus, strReply, false) << std::flush; +} + +bool ClientAllowed(const boost::asio::ip::address& address) +{ + // Make sure that IPv4-compatible and IPv4-mapped IPv6 addresses are treated as IPv4 addresses + if (address.is_v6() + && (address.to_v6().is_v4_compatible() + || address.to_v6().is_v4_mapped())) + return ClientAllowed(address.to_v6().to_v4()); + + if (address == asio::ip::address_v4::loopback() + || address == asio::ip::address_v6::loopback() + || (address.is_v4() + // Check whether IPv4 addresses match 127.0.0.0/8 (loopback subnet) + && (address.to_v4().to_ulong() & 0xff000000) == 0x7f000000)) + return true; + + const string strAddress = address.to_string(); + const vector& vAllow = mapMultiArgs["-rpcallowip"]; + BOOST_FOREACH(string strAllow, vAllow) + if (WildcardMatch(strAddress, strAllow)) + return true; + return false; +} + +// +// IOStream device that speaks SSL but can also speak non-SSL +// +template +class SSLIOStreamDevice : public iostreams::device { +public: + SSLIOStreamDevice(asio::ssl::stream &streamIn, bool fUseSSLIn) : stream(streamIn) + { + fUseSSL = fUseSSLIn; + fNeedHandshake = fUseSSLIn; + } + + void handshake(ssl::stream_base::handshake_type role) + { + if (!fNeedHandshake) return; + fNeedHandshake = false; + stream.handshake(role); + } + std::streamsize read(char* s, std::streamsize n) + { + handshake(ssl::stream_base::server); // HTTPS servers read first + if (fUseSSL) return stream.read_some(asio::buffer(s, n)); + return stream.next_layer().read_some(asio::buffer(s, n)); + } + std::streamsize write(const char* s, std::streamsize n) + { + handshake(ssl::stream_base::client); // HTTPS clients write first + if (fUseSSL) return asio::write(stream, asio::buffer(s, n)); + return asio::write(stream.next_layer(), asio::buffer(s, n)); + } + bool connect(const std::string& server, const std::string& port) + { + ip::tcp::resolver resolver(stream.get_io_service()); + ip::tcp::resolver::query query(server.c_str(), port.c_str()); + ip::tcp::resolver::iterator endpoint_iterator = resolver.resolve(query); + ip::tcp::resolver::iterator end; + boost::system::error_code error = asio::error::host_not_found; + while (error && endpoint_iterator != end) + { + stream.lowest_layer().close(); + stream.lowest_layer().connect(*endpoint_iterator++, error); + } + if (error) + return false; + return true; + } + +private: + bool fNeedHandshake; + bool fUseSSL; + asio::ssl::stream& stream; +}; + +class AcceptedConnection +{ +public: + virtual ~AcceptedConnection() {} + + virtual std::iostream& stream() = 0; + virtual std::string peer_address_to_string() const = 0; + virtual void close() = 0; +}; + +template +class AcceptedConnectionImpl : public AcceptedConnection +{ +public: + AcceptedConnectionImpl( + asio::io_service& io_service, + ssl::context &context, + bool fUseSSL) : + sslStream(io_service, context), + _d(sslStream, fUseSSL), + _stream(_d) + { + } + + virtual std::iostream& stream() + { + return _stream; + } + + virtual std::string peer_address_to_string() const + { + return peer.address().to_string(); + } + + virtual void close() + { + _stream.close(); + } + + typename Protocol::endpoint peer; + asio::ssl::stream sslStream; + +private: + SSLIOStreamDevice _d; + iostreams::stream< SSLIOStreamDevice > _stream; +}; + +void ThreadRPCServer(void* parg) +{ + // Make this thread recognisable as the RPC listener + RenameThread("arepacoin-rpclist"); + + try + { + vnThreadsRunning[THREAD_RPCLISTENER]++; + ThreadRPCServer2(parg); + vnThreadsRunning[THREAD_RPCLISTENER]--; + } + catch (std::exception& e) { + vnThreadsRunning[THREAD_RPCLISTENER]--; + PrintException(&e, "ThreadRPCServer()"); + } catch (...) { + vnThreadsRunning[THREAD_RPCLISTENER]--; + PrintException(NULL, "ThreadRPCServer()"); + } + printf("ThreadRPCServer exited\n"); +} + +// Forward declaration required for RPCListen +template +static void RPCAcceptHandler(boost::shared_ptr< basic_socket_acceptor > acceptor, + ssl::context& context, + bool fUseSSL, + AcceptedConnection* conn, + const boost::system::error_code& error); + +/** + * Sets up I/O resources to accept and handle a new connection. + */ +template +static void RPCListen(boost::shared_ptr< basic_socket_acceptor > acceptor, + ssl::context& context, + const bool fUseSSL) +{ + // Accept connection + AcceptedConnectionImpl* conn = new AcceptedConnectionImpl(acceptor->get_io_service(), context, fUseSSL); + + acceptor->async_accept( + conn->sslStream.lowest_layer(), + conn->peer, + boost::bind(&RPCAcceptHandler, + acceptor, + boost::ref(context), + fUseSSL, + conn, + boost::asio::placeholders::error)); +} + +/** + * Accept and handle incoming connection. + */ +template +static void RPCAcceptHandler(boost::shared_ptr< basic_socket_acceptor > acceptor, + ssl::context& context, + const bool fUseSSL, + AcceptedConnection* conn, + const boost::system::error_code& error) +{ + vnThreadsRunning[THREAD_RPCLISTENER]++; + + // Immediately start accepting new connections, except when we're cancelled or our socket is closed. + if (error != asio::error::operation_aborted + && acceptor->is_open()) + RPCListen(acceptor, context, fUseSSL); + + AcceptedConnectionImpl* tcp_conn = dynamic_cast< AcceptedConnectionImpl* >(conn); + + // TODO: Actually handle errors + if (error) + { + delete conn; + } + + // Restrict callers by IP. It is important to + // do this before starting client thread, to filter out + // certain DoS and misbehaving clients. + else if (tcp_conn + && !ClientAllowed(tcp_conn->peer.address())) + { + // Only send a 403 if we're not using SSL to prevent a DoS during the SSL handshake. + if (!fUseSSL) + conn->stream() << HTTPReply(HTTP_FORBIDDEN, "", false) << std::flush; + delete conn; + } + + // start HTTP client thread + else if (!NewThread(ThreadRPCServer3, conn)) { + printf("Failed to create RPC server client thread\n"); + delete conn; + } + + vnThreadsRunning[THREAD_RPCLISTENER]--; +} + +void ThreadRPCServer2(void* parg) +{ + printf("ThreadRPCServer started\n"); + + strRPCUserColonPass = mapArgs["-rpcuser"] + ":" + mapArgs["-rpcpassword"]; + if ((mapArgs["-rpcpassword"] == "") || + (mapArgs["-rpcuser"] == mapArgs["-rpcpassword"])) + { + unsigned char rand_pwd[32]; + RAND_bytes(rand_pwd, 32); + string strWhatAmI = "To use arepacoind"; + if (mapArgs.count("-server")) + strWhatAmI = strprintf(_("To use the %s option"), "\"-server\""); + else if (mapArgs.count("-daemon")) + strWhatAmI = strprintf(_("To use the %s option"), "\"-daemon\""); + uiInterface.ThreadSafeMessageBox(strprintf( + _("%s, you must set a rpcpassword in the configuration file:\n %s\n" + "It is recommended you use the following random password:\n" + "rpcuser=arepacoinrpc\n" + "rpcpassword=%s\n" + "(you do not need to remember this password)\n" + "The username and password MUST NOT be the same.\n" + "If the file does not exist, create it with owner-readable-only file permissions.\n" + "It is also recommended to set alertnotify so you are notified of problems;\n" + "for example: alertnotify=echo %%s | mail -s \"arepacoin Alert\" admin@foo.com\n"), + strWhatAmI.c_str(), + GetConfigFile().string().c_str(), + EncodeBase58(&rand_pwd[0],&rand_pwd[0]+32).c_str()), + _("Error"), CClientUIInterface::OK | CClientUIInterface::MODAL); + StartShutdown(); + return; + } + + const bool fUseSSL = GetBoolArg("-rpcssl"); + + asio::io_service io_service; + + ssl::context context(ssl::context::sslv23); + if (fUseSSL) + { + context.set_options(ssl::context::no_sslv2); + + filesystem::path pathCertFile(GetArg("-rpcsslcertificatechainfile", "server.cert")); + if (!pathCertFile.is_complete()) pathCertFile = filesystem::path(GetDataDir()) / pathCertFile; + if (filesystem::exists(pathCertFile)) context.use_certificate_chain_file(pathCertFile.string()); + else printf("ThreadRPCServer ERROR: missing server certificate file %s\n", pathCertFile.string().c_str()); + + filesystem::path pathPKFile(GetArg("-rpcsslprivatekeyfile", "server.pem")); + if (!pathPKFile.is_complete()) pathPKFile = filesystem::path(GetDataDir()) / pathPKFile; + if (filesystem::exists(pathPKFile)) context.use_private_key_file(pathPKFile.string(), ssl::context::pem); + else printf("ThreadRPCServer ERROR: missing server private key file %s\n", pathPKFile.string().c_str()); + + string strCiphers = GetArg("-rpcsslciphers", "TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH"); + SSL_CTX_set_cipher_list(context.native_handle(), strCiphers.c_str()); + } + + // Try a dual IPv6/IPv4 socket, falling back to separate IPv4 and IPv6 sockets + const bool loopback = !mapArgs.count("-rpcallowip"); + asio::ip::address bindAddress = loopback ? asio::ip::address_v6::loopback() : asio::ip::address_v6::any(); + ip::tcp::endpoint endpoint(bindAddress, GetArg("-rpcport", GetDefaultRPCPort())); + boost::system::error_code v6_only_error; + boost::shared_ptr acceptor(new ip::tcp::acceptor(io_service)); + + boost::signals2::signal StopRequests; + + bool fListening = false; + std::string strerr; + try + { + acceptor->open(endpoint.protocol()); + acceptor->set_option(boost::asio::ip::tcp::acceptor::reuse_address(true)); + + // Try making the socket dual IPv6/IPv4 (if listening on the "any" address) + acceptor->set_option(boost::asio::ip::v6_only(loopback), v6_only_error); + + acceptor->bind(endpoint); + acceptor->listen(socket_base::max_connections); + + RPCListen(acceptor, context, fUseSSL); + // Cancel outstanding listen-requests for this acceptor when shutting down + StopRequests.connect(signals2::slot( + static_cast(&ip::tcp::acceptor::close), acceptor.get()) + .track(acceptor)); + + fListening = true; + } + catch(boost::system::system_error &e) + { + strerr = strprintf(_("An error occurred while setting up the RPC port %u for listening on IPv6, falling back to IPv4: %s"), endpoint.port(), e.what()); + } + + try { + // If dual IPv6/IPv4 failed (or we're opening loopback interfaces only), open IPv4 separately + if (!fListening || loopback || v6_only_error) + { + bindAddress = loopback ? asio::ip::address_v4::loopback() : asio::ip::address_v4::any(); + endpoint.address(bindAddress); + + acceptor.reset(new ip::tcp::acceptor(io_service)); + acceptor->open(endpoint.protocol()); + acceptor->set_option(boost::asio::ip::tcp::acceptor::reuse_address(true)); + acceptor->bind(endpoint); + acceptor->listen(socket_base::max_connections); + + RPCListen(acceptor, context, fUseSSL); + // Cancel outstanding listen-requests for this acceptor when shutting down + StopRequests.connect(signals2::slot( + static_cast(&ip::tcp::acceptor::close), acceptor.get()) + .track(acceptor)); + + fListening = true; + } + } + catch(boost::system::system_error &e) + { + strerr = strprintf(_("An error occurred while setting up the RPC port %u for listening on IPv4: %s"), endpoint.port(), e.what()); + } + + if (!fListening) { + uiInterface.ThreadSafeMessageBox(strerr, _("Error"), CClientUIInterface::OK | CClientUIInterface::MODAL); + StartShutdown(); + return; + } + + vnThreadsRunning[THREAD_RPCLISTENER]--; + while (!fShutdown) + io_service.run_one(); + vnThreadsRunning[THREAD_RPCLISTENER]++; + StopRequests(); +} + +class JSONRequest +{ +public: + Value id; + string strMethod; + Array params; + + JSONRequest() { id = Value::null; } + void parse(const Value& valRequest); +}; + +void JSONRequest::parse(const Value& valRequest) +{ + // Parse request + if (valRequest.type() != obj_type) + throw JSONRPCError(RPC_INVALID_REQUEST, "Invalid Request object"); + const Object& request = valRequest.get_obj(); + + // Parse id now so errors from here on will have the id + id = find_value(request, "id"); + + // Parse method + Value valMethod = find_value(request, "method"); + if (valMethod.type() == null_type) + throw JSONRPCError(RPC_INVALID_REQUEST, "Missing method"); + if (valMethod.type() != str_type) + throw JSONRPCError(RPC_INVALID_REQUEST, "Method must be a string"); + strMethod = valMethod.get_str(); + if (strMethod != "getwork" && strMethod != "getblocktemplate") + printf("ThreadRPCServer method=%s\n", strMethod.c_str()); + + // Parse params + Value valParams = find_value(request, "params"); + if (valParams.type() == array_type) + params = valParams.get_array(); + else if (valParams.type() == null_type) + params = Array(); + else + throw JSONRPCError(RPC_INVALID_REQUEST, "Params must be an array"); +} + +static Object JSONRPCExecOne(const Value& req) +{ + Object rpc_result; + + JSONRequest jreq; + try { + jreq.parse(req); + + Value result = tableRPC.execute(jreq.strMethod, jreq.params); + rpc_result = JSONRPCReplyObj(result, Value::null, jreq.id); + } + catch (Object& objError) + { + rpc_result = JSONRPCReplyObj(Value::null, objError, jreq.id); + } + catch (std::exception& e) + { + rpc_result = JSONRPCReplyObj(Value::null, + JSONRPCError(RPC_PARSE_ERROR, e.what()), jreq.id); + } + + return rpc_result; +} + +static string JSONRPCExecBatch(const Array& vReq) +{ + Array ret; + for (unsigned int reqIdx = 0; reqIdx < vReq.size(); reqIdx++) + ret.push_back(JSONRPCExecOne(vReq[reqIdx])); + + return write_string(Value(ret), false) + "\n"; +} + +static CCriticalSection cs_THREAD_RPCHANDLER; + +void ThreadRPCServer3(void* parg) +{ + // Make this thread recognisable as the RPC handler + RenameThread("arepacoin-rpchand"); + + { + LOCK(cs_THREAD_RPCHANDLER); + vnThreadsRunning[THREAD_RPCHANDLER]++; + } + AcceptedConnection *conn = (AcceptedConnection *) parg; + + bool fRun = true; + while (true) + { + if (fShutdown || !fRun) + { + conn->close(); + delete conn; + { + LOCK(cs_THREAD_RPCHANDLER); + --vnThreadsRunning[THREAD_RPCHANDLER]; + } + return; + } + map mapHeaders; + string strRequest; + + ReadHTTP(conn->stream(), mapHeaders, strRequest); + + // Check authorization + if (mapHeaders.count("authorization") == 0) + { + conn->stream() << HTTPReply(HTTP_UNAUTHORIZED, "", false) << std::flush; + break; + } + if (!HTTPAuthorized(mapHeaders)) + { + printf("ThreadRPCServer incorrect password attempt from %s\n", conn->peer_address_to_string().c_str()); + /* Deter brute-forcing short passwords. + If this results in a DOS the user really + shouldn't have their RPC port exposed.*/ + if (mapArgs["-rpcpassword"].size() < 20) + MilliSleep(250); + + conn->stream() << HTTPReply(HTTP_UNAUTHORIZED, "", false) << std::flush; + break; + } + if (mapHeaders["connection"] == "close") + fRun = false; + + JSONRequest jreq; + try + { + // Parse request + Value valRequest; + if (!read_string(strRequest, valRequest)) + throw JSONRPCError(RPC_PARSE_ERROR, "Parse error"); + + string strReply; + + // singleton request + if (valRequest.type() == obj_type) { + jreq.parse(valRequest); + + Value result = tableRPC.execute(jreq.strMethod, jreq.params); + + // Send reply + strReply = JSONRPCReply(result, Value::null, jreq.id); + + // array of requests + } else if (valRequest.type() == array_type) + strReply = JSONRPCExecBatch(valRequest.get_array()); + else + throw JSONRPCError(RPC_PARSE_ERROR, "Top-level object parse error"); + + conn->stream() << HTTPReply(HTTP_OK, strReply, fRun) << std::flush; + } + catch (Object& objError) + { + ErrorReply(conn->stream(), objError, jreq.id); + break; + } + catch (std::exception& e) + { + ErrorReply(conn->stream(), JSONRPCError(RPC_PARSE_ERROR, e.what()), jreq.id); + break; + } + } + + delete conn; + { + LOCK(cs_THREAD_RPCHANDLER); + vnThreadsRunning[THREAD_RPCHANDLER]--; + } +} + +json_spirit::Value CRPCTable::execute(const std::string &strMethod, const json_spirit::Array ¶ms) const +{ + // Find method + const CRPCCommand *pcmd = tableRPC[strMethod]; + if (!pcmd) + throw JSONRPCError(RPC_METHOD_NOT_FOUND, "Method not found"); + + // Observe safe mode + string strWarning = GetWarnings("rpc"); + if (strWarning != "" && !GetBoolArg("-disablesafemode") && + !pcmd->okSafeMode) + throw JSONRPCError(RPC_FORBIDDEN_BY_SAFE_MODE, string("Safe mode: ") + strWarning); + + try + { + // Execute + Value result; + { + if (pcmd->unlocked) + result = pcmd->actor(params, false); + else { + LOCK2(cs_main, pwalletMain->cs_wallet); + result = pcmd->actor(params, false); + } + } + return result; + } + catch (std::exception& e) + { + throw JSONRPCError(RPC_MISC_ERROR, e.what()); + } +} + + +Object CallRPC(const string& strMethod, const Array& params) +{ + if (mapArgs["-rpcuser"] == "" && mapArgs["-rpcpassword"] == "") + throw runtime_error(strprintf( + _("You must set rpcpassword= in the configuration file:\n%s\n" + "If the file does not exist, create it with owner-readable-only file permissions."), + GetConfigFile().string().c_str())); + + // Connect to localhost + bool fUseSSL = GetBoolArg("-rpcssl"); + asio::io_service io_service; + ssl::context context(ssl::context::sslv23); + context.set_options(ssl::context::no_sslv2); + asio::ssl::stream sslStream(io_service, context); + SSLIOStreamDevice d(sslStream, fUseSSL); + iostreams::stream< SSLIOStreamDevice > stream(d); + if (!d.connect(GetArg("-rpcconnect", "127.0.0.1"), GetArg("-rpcport", itostr(GetDefaultRPCPort())))) + throw runtime_error("couldn't connect to server"); + + // HTTP basic authentication + string strUserPass64 = EncodeBase64(mapArgs["-rpcuser"] + ":" + mapArgs["-rpcpassword"]); + map mapRequestHeaders; + mapRequestHeaders["Authorization"] = string("Basic ") + strUserPass64; + + // Send request + string strRequest = JSONRPCRequest(strMethod, params, 1); + string strPost = HTTPPost(strRequest, mapRequestHeaders); + stream << strPost << std::flush; + + // Receive reply + map mapHeaders; + string strReply; + int nStatus = ReadHTTP(stream, mapHeaders, strReply); + if (nStatus == HTTP_UNAUTHORIZED) + throw runtime_error("incorrect rpcuser or rpcpassword (authorization failed)"); + else if (nStatus >= 400 && nStatus != HTTP_BAD_REQUEST && nStatus != HTTP_NOT_FOUND && nStatus != HTTP_INTERNAL_SERVER_ERROR) + throw runtime_error(strprintf("server returned HTTP error %d", nStatus)); + else 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"); + + return reply; +} + + + + +template +void ConvertTo(Value& value, bool fAllowNull=false) +{ + if (fAllowNull && value.type() == null_type) + return; + if (value.type() == str_type) + { + // reinterpret string as unquoted json value + Value value2; + string strJSON = value.get_str(); + if (!read_string(strJSON, value2)) + throw runtime_error(string("Error parsing JSON:")+strJSON); + ConvertTo(value2, fAllowNull); + value = value2; + } + else + { + value = value.get_value(); + } +} + +// Convert strings to command-specific RPC representation +Array RPCConvertValues(const std::string &strMethod, const std::vector &strParams) +{ + Array params; + BOOST_FOREACH(const std::string ¶m, strParams) + params.push_back(param); + + int n = params.size(); + + // + // Special case non-string parameter types + // + if (strMethod == "stop" && n > 0) ConvertTo(params[0]); + if (strMethod == "sendtoaddress" && n > 1) ConvertTo(params[1]); + if (strMethod == "settxfee" && n > 0) ConvertTo(params[0]); + if (strMethod == "getreceivedbyaddress" && n > 1) ConvertTo(params[1]); + if (strMethod == "getreceivedbyaccount" && n > 1) ConvertTo(params[1]); + if (strMethod == "listreceivedbyaddress" && n > 0) ConvertTo(params[0]); + if (strMethod == "listreceivedbyaddress" && n > 1) ConvertTo(params[1]); + if (strMethod == "listreceivedbyaccount" && n > 0) ConvertTo(params[0]); + if (strMethod == "listreceivedbyaccount" && n > 1) ConvertTo(params[1]); + if (strMethod == "getbalance" && n > 1) ConvertTo(params[1]); + if (strMethod == "getblock" && n > 1) ConvertTo(params[1]); + if (strMethod == "getblockbynumber" && n > 0) ConvertTo(params[0]); + if (strMethod == "getblockbynumber" && n > 1) ConvertTo(params[1]); + if (strMethod == "getblockhash" && n > 0) ConvertTo(params[0]); + if (strMethod == "move" && n > 2) ConvertTo(params[2]); + if (strMethod == "move" && n > 3) ConvertTo(params[3]); + if (strMethod == "sendfrom" && n > 2) ConvertTo(params[2]); + if (strMethod == "sendfrom" && n > 3) ConvertTo(params[3]); + if (strMethod == "listtransactions" && n > 1) ConvertTo(params[1]); + if (strMethod == "listtransactions" && n > 2) ConvertTo(params[2]); + if (strMethod == "listaccounts" && n > 0) ConvertTo(params[0]); + if (strMethod == "walletpassphrase" && n > 1) ConvertTo(params[1]); + if (strMethod == "walletpassphrase" && n > 2) ConvertTo(params[2]); + if (strMethod == "getblocktemplate" && n > 0) ConvertTo(params[0]); + if (strMethod == "listsinceblock" && n > 1) ConvertTo(params[1]); + + if (strMethod == "sendalert" && n > 2) ConvertTo(params[2]); + if (strMethod == "sendalert" && n > 3) ConvertTo(params[3]); + if (strMethod == "sendalert" && n > 4) ConvertTo(params[4]); + if (strMethod == "sendalert" && n > 5) ConvertTo(params[5]); + if (strMethod == "sendalert" && n > 6) ConvertTo(params[6]); + + if (strMethod == "sendmany" && n > 1) ConvertTo(params[1]); + if (strMethod == "sendmany" && n > 2) ConvertTo(params[2]); + if (strMethod == "reservebalance" && n > 0) ConvertTo(params[0]); + if (strMethod == "reservebalance" && n > 1) ConvertTo(params[1]); + if (strMethod == "addmultisigaddress" && n > 0) ConvertTo(params[0]); + if (strMethod == "addmultisigaddress" && n > 1) ConvertTo(params[1]); + if (strMethod == "listunspent" && n > 0) ConvertTo(params[0]); + if (strMethod == "listunspent" && n > 1) ConvertTo(params[1]); + if (strMethod == "listunspent" && n > 2) ConvertTo(params[2]); + if (strMethod == "getrawtransaction" && n > 1) ConvertTo(params[1]); + if (strMethod == "createrawtransaction" && n > 0) ConvertTo(params[0]); + if (strMethod == "createrawtransaction" && n > 1) ConvertTo(params[1]); + if (strMethod == "signrawtransaction" && n > 1) ConvertTo(params[1], true); + if (strMethod == "signrawtransaction" && n > 2) ConvertTo(params[2], true); + if (strMethod == "keypoolrefill" && n > 0) ConvertTo(params[0]); + + return params; +} + +int CommandLineRPC(int argc, char *argv[]) +{ + string strPrint; + int nRet = 0; + try + { + // Skip switches + while (argc > 1 && IsSwitchChar(argv[1][0])) + { + argc--; + argv++; + } + + // Method + if (argc < 2) + throw runtime_error("too few parameters"); + string strMethod = argv[1]; + + // Parameters default to strings + std::vector strParams(&argv[2], &argv[argc]); + Array params = RPCConvertValues(strMethod, strParams); + + // Execute + Object reply = CallRPC(strMethod, params); + + // Parse reply + const Value& result = find_value(reply, "result"); + const Value& error = find_value(reply, "error"); + + if (error.type() != null_type) + { + // Error + strPrint = "error: " + write_string(error, false); + int code = find_value(error.get_obj(), "code").get_int(); + nRet = abs(code); + } + else + { + // Result + if (result.type() == null_type) + strPrint = ""; + else if (result.type() == str_type) + strPrint = result.get_str(); + else + strPrint = write_string(result, true); + } + } + catch (std::exception& e) + { + strPrint = string("error: ") + e.what(); + nRet = 87; + } + catch (...) + { + PrintException(NULL, "CommandLineRPC()"); + } + + if (strPrint != "") + { + fprintf((nRet == 0 ? stdout : stderr), "%s\n", strPrint.c_str()); + } + return nRet; +} + + + + +#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 + +const CRPCTable tableRPC; diff --git a/src/bitcoinrpc.h b/src/bitcoinrpc.h new file mode 100644 index 0000000..13c2233 --- /dev/null +++ b/src/bitcoinrpc.h @@ -0,0 +1,223 @@ +// Copyright (c) 2010 Satoshi Nakamoto +// Copyright (c) 2009-2012 The Bitcoin developers +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifndef _BITCOINRPC_H_ +#define _BITCOINRPC_H_ 1 + +#include +#include +#include + +class CBlockIndex; + +#include "json/json_spirit_reader_template.h" +#include "json/json_spirit_writer_template.h" +#include "json/json_spirit_utils.h" + +#include "util.h" +#include "checkpoints.h" + +// HTTP status codes +enum HTTPStatusCode +{ + HTTP_OK = 200, + HTTP_BAD_REQUEST = 400, + HTTP_UNAUTHORIZED = 401, + HTTP_FORBIDDEN = 403, + HTTP_NOT_FOUND = 404, + HTTP_INTERNAL_SERVER_ERROR = 500, +}; + +// Bitcoin RPC error codes +enum RPCErrorCode +{ + // Standard JSON-RPC 2.0 errors + RPC_INVALID_REQUEST = -32600, + RPC_METHOD_NOT_FOUND = -32601, + RPC_INVALID_PARAMS = -32602, + RPC_INTERNAL_ERROR = -32603, + RPC_PARSE_ERROR = -32700, + + // General application defined errors + RPC_MISC_ERROR = -1, // std::exception thrown in command handling + RPC_FORBIDDEN_BY_SAFE_MODE = -2, // Server is in safe mode, and command is not allowed in safe mode + RPC_TYPE_ERROR = -3, // Unexpected type was passed as parameter + RPC_INVALID_ADDRESS_OR_KEY = -5, // Invalid address or key + RPC_OUT_OF_MEMORY = -7, // Ran out of memory during operation + RPC_INVALID_PARAMETER = -8, // Invalid, missing or duplicate parameter + RPC_DATABASE_ERROR = -20, // Database error + RPC_DESERIALIZATION_ERROR = -22, // Error parsing or validating structure in raw format + + // P2P client errors + RPC_CLIENT_NOT_CONNECTED = -9, // Bitcoin is not connected + RPC_CLIENT_IN_INITIAL_DOWNLOAD = -10, // Still downloading initial blocks + + // Wallet errors + RPC_WALLET_ERROR = -4, // Unspecified problem with wallet (key not found etc.) + RPC_WALLET_INSUFFICIENT_FUNDS = -6, // Not enough funds in wallet or account + RPC_WALLET_INVALID_ACCOUNT_NAME = -11, // Invalid account name + RPC_WALLET_KEYPOOL_RAN_OUT = -12, // Keypool ran out, call keypoolrefill first + RPC_WALLET_UNLOCK_NEEDED = -13, // Enter the wallet passphrase with walletpassphrase first + RPC_WALLET_PASSPHRASE_INCORRECT = -14, // The wallet passphrase entered was incorrect + RPC_WALLET_WRONG_ENC_STATE = -15, // Command given in wrong wallet encryption state (encrypting an encrypted wallet etc.) + RPC_WALLET_ENCRYPTION_FAILED = -16, // Failed to encrypt the wallet + RPC_WALLET_ALREADY_UNLOCKED = -17, // Wallet is already unlocked +}; + +json_spirit::Object JSONRPCError(int code, const std::string& message); + +void ThreadRPCServer(void* parg); +int CommandLineRPC(int argc, char *argv[]); + +/** Convert parameter values for RPC call from strings to command-specific JSON objects. */ +json_spirit::Array RPCConvertValues(const std::string &strMethod, const std::vector &strParams); + +/* + Type-check arguments; throws JSONRPCError if wrong type given. Does not check that + the right number of arguments are passed, just that any passed are the correct type. + Use like: RPCTypeCheck(params, boost::assign::list_of(str_type)(int_type)(obj_type)); +*/ +void RPCTypeCheck(const json_spirit::Array& params, + const std::list& typesExpected, bool fAllowNull=false); +/* + Check for expected keys/value types in an Object. + Use like: RPCTypeCheck(object, boost::assign::map_list_of("name", str_type)("value", int_type)); +*/ +void RPCTypeCheck(const json_spirit::Object& o, + const std::map& typesExpected, bool fAllowNull=false); + +typedef json_spirit::Value(*rpcfn_type)(const json_spirit::Array& params, bool fHelp); + +class CRPCCommand +{ +public: + std::string name; + rpcfn_type actor; + bool okSafeMode; + bool unlocked; +}; + +/** + * Bitcoin RPC command dispatcher. + */ +class CRPCTable +{ +private: + std::map mapCommands; +public: + CRPCTable(); + const CRPCCommand* operator[](std::string name) const; + std::string help(std::string name) const; + + /** + * Execute a method. + * @param method Method to execute + * @param params Array of arguments (JSON objects) + * @returns Result of the call. + * @throws an exception (json_spirit::Value) when an error happens. + */ + json_spirit::Value execute(const std::string &method, const json_spirit::Array ¶ms) const; +}; + +extern const CRPCTable tableRPC; + +extern int64_t nWalletUnlockTime; +extern int64_t AmountFromValue(const json_spirit::Value& value); +extern json_spirit::Value ValueFromAmount(int64_t amount); +extern double GetDifficulty(const CBlockIndex* blockindex = NULL); + +extern double GetPoWMHashPS(); +extern double GetPoSKernelPS(); + +extern std::string HelpRequiringPassphrase(); +extern void EnsureWalletIsUnlocked(); + +// +// Utilities: convert hex-encoded Values +// (throws error if not hex). +// +extern uint256 ParseHashV(const json_spirit::Value& v, std::string strName); +extern uint256 ParseHashO(const json_spirit::Object& o, std::string strKey); +extern std::vector ParseHexV(const json_spirit::Value& v, std::string strName); +extern std::vector ParseHexO(const json_spirit::Object& o, std::string strKey); + +extern json_spirit::Value getconnectioncount(const json_spirit::Array& params, bool fHelp); // in rpcnet.cpp +extern json_spirit::Value getpeerinfo(const json_spirit::Array& params, bool fHelp); +extern json_spirit::Value addnode(const json_spirit::Array& params, bool fHelp); +extern json_spirit::Value getnettotals(const json_spirit::Array& params, bool fHelp); +extern json_spirit::Value dumpwallet(const json_spirit::Array& params, bool fHelp); +extern json_spirit::Value importwallet(const json_spirit::Array& params, bool fHelp); +extern json_spirit::Value dumpprivkey(const json_spirit::Array& params, bool fHelp); // in rpcdump.cpp +extern json_spirit::Value importprivkey(const json_spirit::Array& params, bool fHelp); + +extern json_spirit::Value sendalert(const json_spirit::Array& params, bool fHelp); + +extern json_spirit::Value getsubsidy(const json_spirit::Array& params, bool fHelp); +extern json_spirit::Value getmininginfo(const json_spirit::Array& params, bool fHelp); +extern json_spirit::Value getstakinginfo(const json_spirit::Array& params, bool fHelp); +extern json_spirit::Value getwork(const json_spirit::Array& params, bool fHelp); +extern json_spirit::Value getworkex(const json_spirit::Array& params, bool fHelp); +extern json_spirit::Value getblocktemplate(const json_spirit::Array& params, bool fHelp); +extern json_spirit::Value submitblock(const json_spirit::Array& params, bool fHelp); + +extern json_spirit::Value getnewaddress(const json_spirit::Array& params, bool fHelp); // in rpcwallet.cpp +extern json_spirit::Value getaccountaddress(const json_spirit::Array& params, bool fHelp); +extern json_spirit::Value setaccount(const json_spirit::Array& params, bool fHelp); +extern json_spirit::Value getaccount(const json_spirit::Array& params, bool fHelp); +extern json_spirit::Value getaddressesbyaccount(const json_spirit::Array& params, bool fHelp); +extern json_spirit::Value getaddresses(const json_spirit::Array& params, bool fHelp); +extern json_spirit::Value sendtoaddress(const json_spirit::Array& params, bool fHelp); +extern json_spirit::Value signmessage(const json_spirit::Array& params, bool fHelp); +extern json_spirit::Value verifymessage(const json_spirit::Array& params, bool fHelp); +extern json_spirit::Value getreceivedbyaddress(const json_spirit::Array& params, bool fHelp); +extern json_spirit::Value getreceivedbyaccount(const json_spirit::Array& params, bool fHelp); +extern json_spirit::Value getbalance(const json_spirit::Array& params, bool fHelp); +extern json_spirit::Value movecmd(const json_spirit::Array& params, bool fHelp); +extern json_spirit::Value sendfrom(const json_spirit::Array& params, bool fHelp); +extern json_spirit::Value sendmany(const json_spirit::Array& params, bool fHelp); +extern json_spirit::Value addmultisigaddress(const json_spirit::Array& params, bool fHelp); +extern json_spirit::Value addredeemscript(const json_spirit::Array& params, bool fHelp); +extern json_spirit::Value listreceivedbyaddress(const json_spirit::Array& params, bool fHelp); +extern json_spirit::Value listreceivedbyaccount(const json_spirit::Array& params, bool fHelp); +extern json_spirit::Value listtransactions(const json_spirit::Array& params, bool fHelp); +extern json_spirit::Value listaddressgroupings(const json_spirit::Array& params, bool fHelp); +extern json_spirit::Value listaccounts(const json_spirit::Array& params, bool fHelp); +extern json_spirit::Value listsinceblock(const json_spirit::Array& params, bool fHelp); +extern json_spirit::Value gettransaction(const json_spirit::Array& params, bool fHelp); +extern json_spirit::Value backupwallet(const json_spirit::Array& params, bool fHelp); +extern json_spirit::Value keypoolrefill(const json_spirit::Array& params, bool fHelp); +extern json_spirit::Value walletpassphrase(const json_spirit::Array& params, bool fHelp); +extern json_spirit::Value walletpassphrasechange(const json_spirit::Array& params, bool fHelp); +extern json_spirit::Value walletlock(const json_spirit::Array& params, bool fHelp); +extern json_spirit::Value encryptwallet(const json_spirit::Array& params, bool fHelp); +extern json_spirit::Value validateaddress(const json_spirit::Array& params, bool fHelp); +extern json_spirit::Value getinfo(const json_spirit::Array& params, bool fHelp); +extern json_spirit::Value reservebalance(const json_spirit::Array& params, bool fHelp); +extern json_spirit::Value checkwallet(const json_spirit::Array& params, bool fHelp); +extern json_spirit::Value repairwallet(const json_spirit::Array& params, bool fHelp); +extern json_spirit::Value resendtx(const json_spirit::Array& params, bool fHelp); +extern json_spirit::Value makekeypair(const json_spirit::Array& params, bool fHelp); +extern json_spirit::Value validatepubkey(const json_spirit::Array& params, bool fHelp); +extern json_spirit::Value getnewpubkey(const json_spirit::Array& params, bool fHelp); + +extern json_spirit::Value getrawtransaction(const json_spirit::Array& params, bool fHelp); // in rcprawtransaction.cpp +extern json_spirit::Value listunspent(const json_spirit::Array& params, bool fHelp); +extern json_spirit::Value createrawtransaction(const json_spirit::Array& params, bool fHelp); +extern json_spirit::Value decoderawtransaction(const json_spirit::Array& params, bool fHelp); +extern json_spirit::Value decodescript(const json_spirit::Array& params, bool fHelp); +extern json_spirit::Value signrawtransaction(const json_spirit::Array& params, bool fHelp); +extern json_spirit::Value sendrawtransaction(const json_spirit::Array& params, bool fHelp); + +extern json_spirit::Value getbestblockhash(const json_spirit::Array& params, bool fHelp); // in rpcblockchain.cpp +extern json_spirit::Value getblockcount(const json_spirit::Array& params, bool fHelp); // in rpcblockchain.cpp +extern json_spirit::Value getdifficulty(const json_spirit::Array& params, bool fHelp); +extern json_spirit::Value settxfee(const json_spirit::Array& params, bool fHelp); +extern json_spirit::Value getrawmempool(const json_spirit::Array& params, bool fHelp); +extern json_spirit::Value getblockhash(const json_spirit::Array& params, bool fHelp); +extern json_spirit::Value getblock(const json_spirit::Array& params, bool fHelp); +extern json_spirit::Value getblockbynumber(const json_spirit::Array& params, bool fHelp); +extern json_spirit::Value getcheckpoint(const json_spirit::Array& params, bool fHelp); + +#endif diff --git a/src/checkpoints.cpp b/src/checkpoints.cpp new file mode 100644 index 0000000..f41a608 --- /dev/null +++ b/src/checkpoints.cpp @@ -0,0 +1,439 @@ +// Copyright (c) 2009-2012 The Bitcoin developers +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include // for 'map_list_of()' +#include + +#include "checkpoints.h" + +#include "txdb.h" +#include "main.h" +#include "uint256.h" + + +static const int nCheckpointSpan = 10; + +namespace Checkpoints +{ + typedef std::map MapCheckpoints; + + // + // What makes a good checkpoint block? + // + Is surrounded by blocks with reasonable timestamps + // (no blocks before with a timestamp after, none after with + // timestamp before) + // + Contains no strange transactions + // + static MapCheckpoints mapCheckpoints = + boost::assign::map_list_of + ( 0, uint256("0x000002cac270a01e29300abaaeb7d412ca00fa7f43f0d547a57b9ff9c85d95e8")) + ( 100, uint256("0x00000c8f8f6fb876b152e184f73f5e3268d539ec0bce3705fac501af0de42031")) + ( 1000, uint256("0x000006bf4aa4a8da4933675be303ade4e361e38eb561d108b9dd9b07e6350f2a")) + ( 10000, uint256("0xbfb0a611b1c045c502c1839bb60ddb8d4828ee35ad524a8a4e44fbde96f9b0fd")) + ( 50000, uint256("0x00000000001fc332b5cdcdea04d168c81c311161c47c0c68f549a7941196e0a2")) + ( 100000, uint256("0xde54b5cc380063f32f90dc1af4f5b7bb0e7226376bc81c50adf804c772478d59")) + ( 150000, uint256("0xdb39ebc6c0653fc0a415cb625feb63b000253f4a9a04530ca5ca6cd5bebfec3d")) + ( 200000, uint256("0x0000000002f9f5cfd7c9ea589583220fa9eb86c22576f73d40d611dc5cd9b2ba")) + ( 250000, uint256("0x62a249523891e824591b0ad11f9fbe9eede6e468b451d6a23c45f1df7d293fec")) + ( 300000, uint256("0x0000000000b7e25fba047eafe4f63b795e09d1123fe4eab726d6d0a6dd5d5b56")) + ( 400000, uint256("0x0000000002ba3bbb771bb96003b05b05e8e390aba69d566fe80e16c82687e1e5")) + ( 500000, uint256("0x0bb0c31492c2822a300283de9efc30b4a0b8330816494df862c6a8f6eedd4295")) + ( 600000, uint256("0x6e3d7789ba9884df704cedffb379bbaa818155de945cabdbb5070d547b356144")) + ( 700000, uint256("0x8b468893fbd92361c54837cf4bbe7d9a52cf3818e324457a19100dd7258347f7")) + ( 800000, uint256("0xeee5f95e742dc7dfb98ddd889e231e4a2390a9ab96541941859ed8f5a0112653")) + ( 900000, uint256("0x0000000002c01bbcf8b54a450f6709e710905326ef3b05a6182ae49150801238")) + (1000000, uint256("0x0000000000b4a5f3a11c52d7495e789ab3dbca8313d54736f803efba81bfb057")) + (1100000, uint256("0x0000000001a6ca32cd6c8fee3dadabcff15b610b4e447af005f8b8687aeb32bf")) + (1200000, uint256("0x91953f74c55fce96e4c37e81a880faf58523960f91275a9a7453dbd9376b16fd")) + ; + + // TestNet has no checkpoints + static MapCheckpoints mapCheckpointsTestnet = + boost::assign::map_list_of + ( 0, hashGenesisBlockTestNet ) + ; + + bool CheckHardened(int nHeight, const uint256& hash) + { + MapCheckpoints& checkpoints = (fTestNet ? mapCheckpointsTestnet : mapCheckpoints); + + MapCheckpoints::const_iterator i = checkpoints.find(nHeight); + if (i == checkpoints.end()) return true; + return hash == i->second; + } + + int GetTotalBlocksEstimate() + { + MapCheckpoints& checkpoints = (fTestNet ? mapCheckpointsTestnet : mapCheckpoints); + + return checkpoints.rbegin()->first; + } + + CBlockIndex* GetLastCheckpoint(const std::map& mapBlockIndex) + { + MapCheckpoints& checkpoints = (fTestNet ? mapCheckpointsTestnet : mapCheckpoints); + + BOOST_REVERSE_FOREACH(const MapCheckpoints::value_type& i, checkpoints) + { + const uint256& hash = i.second; + std::map::const_iterator t = mapBlockIndex.find(hash); + if (t != mapBlockIndex.end()) + return t->second; + } + return NULL; + } + + // ppcoin: synchronized checkpoint (centrally broadcasted) + uint256 hashSyncCheckpoint = 0; + uint256 hashPendingCheckpoint = 0; + CSyncCheckpoint checkpointMessage; + CSyncCheckpoint checkpointMessagePending; + uint256 hashInvalidCheckpoint = 0; + CCriticalSection cs_hashSyncCheckpoint; + + // ppcoin: get last synchronized checkpoint + CBlockIndex* GetLastSyncCheckpoint() + { + LOCK(cs_hashSyncCheckpoint); + if (!mapBlockIndex.count(hashSyncCheckpoint)) + error("GetSyncCheckpoint: block index missing for current sync-checkpoint %s", hashSyncCheckpoint.ToString().c_str()); + else + return mapBlockIndex[hashSyncCheckpoint]; + return NULL; + } + + // ppcoin: only descendant of current sync-checkpoint is allowed + bool ValidateSyncCheckpoint(uint256 hashCheckpoint) + { + if (!mapBlockIndex.count(hashSyncCheckpoint)) + return error("ValidateSyncCheckpoint: block index missing for current sync-checkpoint %s", hashSyncCheckpoint.ToString().c_str()); + if (!mapBlockIndex.count(hashCheckpoint)) + return error("ValidateSyncCheckpoint: block index missing for received sync-checkpoint %s", hashCheckpoint.ToString().c_str()); + + CBlockIndex* pindexSyncCheckpoint = mapBlockIndex[hashSyncCheckpoint]; + CBlockIndex* pindexCheckpointRecv = mapBlockIndex[hashCheckpoint]; + + if (pindexCheckpointRecv->nHeight <= pindexSyncCheckpoint->nHeight) + { + // Received an older checkpoint, trace back from current checkpoint + // to the same height of the received checkpoint to verify + // that current checkpoint should be a descendant block + CBlockIndex* pindex = pindexSyncCheckpoint; + while (pindex->nHeight > pindexCheckpointRecv->nHeight) + if (!(pindex = pindex->pprev)) + return error("ValidateSyncCheckpoint: pprev null - block index structure failure"); + if (pindex->GetBlockHash() != hashCheckpoint) + { + hashInvalidCheckpoint = hashCheckpoint; + return error("ValidateSyncCheckpoint: new sync-checkpoint %s is conflicting with current sync-checkpoint %s", hashCheckpoint.ToString().c_str(), hashSyncCheckpoint.ToString().c_str()); + } + return false; // ignore older checkpoint + } + + // Received checkpoint should be a descendant block of the current + // checkpoint. Trace back to the same height of current checkpoint + // to verify. + CBlockIndex* pindex = pindexCheckpointRecv; + while (pindex->nHeight > pindexSyncCheckpoint->nHeight) + if (!(pindex = pindex->pprev)) + return error("ValidateSyncCheckpoint: pprev2 null - block index structure failure"); + if (pindex->GetBlockHash() != hashSyncCheckpoint) + { + hashInvalidCheckpoint = hashCheckpoint; + return error("ValidateSyncCheckpoint: new sync-checkpoint %s is not a descendant of current sync-checkpoint %s", hashCheckpoint.ToString().c_str(), hashSyncCheckpoint.ToString().c_str()); + } + return true; + } + + bool WriteSyncCheckpoint(const uint256& hashCheckpoint) + { + CTxDB txdb; + txdb.TxnBegin(); + if (!txdb.WriteSyncCheckpoint(hashCheckpoint)) + { + txdb.TxnAbort(); + return error("WriteSyncCheckpoint(): failed to write to db sync checkpoint %s", hashCheckpoint.ToString().c_str()); + } + if (!txdb.TxnCommit()) + return error("WriteSyncCheckpoint(): failed to commit to db sync checkpoint %s", hashCheckpoint.ToString().c_str()); + + Checkpoints::hashSyncCheckpoint = hashCheckpoint; + return true; + } + + bool AcceptPendingSyncCheckpoint() + { + LOCK(cs_hashSyncCheckpoint); + if (hashPendingCheckpoint != 0 && mapBlockIndex.count(hashPendingCheckpoint)) + { + if (!ValidateSyncCheckpoint(hashPendingCheckpoint)) + { + hashPendingCheckpoint = 0; + checkpointMessagePending.SetNull(); + return false; + } + + CTxDB txdb; + CBlockIndex* pindexCheckpoint = mapBlockIndex[hashPendingCheckpoint]; + if (!pindexCheckpoint->IsInMainChain()) + { + CBlock block; + if (!block.ReadFromDisk(pindexCheckpoint)) + return error("AcceptPendingSyncCheckpoint: ReadFromDisk failed for sync checkpoint %s", hashPendingCheckpoint.ToString().c_str()); + if (!block.SetBestChain(txdb, pindexCheckpoint)) + { + hashInvalidCheckpoint = hashPendingCheckpoint; + return error("AcceptPendingSyncCheckpoint: SetBestChain failed for sync checkpoint %s", hashPendingCheckpoint.ToString().c_str()); + } + } + + if (!WriteSyncCheckpoint(hashPendingCheckpoint)) + return error("AcceptPendingSyncCheckpoint(): failed to write sync checkpoint %s", hashPendingCheckpoint.ToString().c_str()); + hashPendingCheckpoint = 0; + checkpointMessage = checkpointMessagePending; + checkpointMessagePending.SetNull(); + printf("AcceptPendingSyncCheckpoint : sync-checkpoint at %s\n", hashSyncCheckpoint.ToString().c_str()); + // relay the checkpoint + if (!checkpointMessage.IsNull()) + { + BOOST_FOREACH(CNode* pnode, vNodes) + checkpointMessage.RelayTo(pnode); + } + return true; + } + return false; + } + + // Automatically select a suitable sync-checkpoint + uint256 AutoSelectSyncCheckpoint() + { + const CBlockIndex *pindex = pindexBest; + // Search backward for a block within max span and maturity window + while (pindex->pprev && (pindex->GetBlockTime() + nCheckpointSpan * nTargetSpacing > pindexBest->GetBlockTime() || pindex->nHeight + nCheckpointSpan > pindexBest->nHeight)) + pindex = pindex->pprev; + return pindex->GetBlockHash(); + } + + // Check against synchronized checkpoint + bool CheckSync(const uint256& hashBlock, const CBlockIndex* pindexPrev) + { + if (fTestNet) return true; // Testnet has no checkpoints + int nHeight = pindexPrev->nHeight + 1; + + LOCK(cs_hashSyncCheckpoint); + // sync-checkpoint should always be accepted block + assert(mapBlockIndex.count(hashSyncCheckpoint)); + const CBlockIndex* pindexSync = mapBlockIndex[hashSyncCheckpoint]; + + if (nHeight > pindexSync->nHeight) + { + // trace back to same height as sync-checkpoint + const CBlockIndex* pindex = pindexPrev; + while (pindex->nHeight > pindexSync->nHeight) + if (!(pindex = pindex->pprev)) + return error("CheckSync: pprev null - block index structure failure"); + if (pindex->nHeight < pindexSync->nHeight || pindex->GetBlockHash() != hashSyncCheckpoint) + return false; // only descendant of sync-checkpoint can pass check + } + if (nHeight == pindexSync->nHeight && hashBlock != hashSyncCheckpoint) + return false; // same height with sync-checkpoint + if (nHeight < pindexSync->nHeight && !mapBlockIndex.count(hashBlock)) + return false; // lower height than sync-checkpoint + return true; + } + + bool WantedByPendingSyncCheckpoint(uint256 hashBlock) + { + LOCK(cs_hashSyncCheckpoint); + if (hashPendingCheckpoint == 0) + return false; + if (hashBlock == hashPendingCheckpoint) + return true; + if (mapOrphanBlocks.count(hashPendingCheckpoint) + && hashBlock == WantedByOrphan(mapOrphanBlocks[hashPendingCheckpoint])) + return true; + return false; + } + + // ppcoin: reset synchronized checkpoint to last hardened checkpoint + bool ResetSyncCheckpoint() + { + LOCK(cs_hashSyncCheckpoint); + const uint256& hash = mapCheckpoints.rbegin()->second; + if (mapBlockIndex.count(hash) && !mapBlockIndex[hash]->IsInMainChain()) + { + // checkpoint block accepted but not yet in main chain + printf("ResetSyncCheckpoint: SetBestChain to hardened checkpoint %s\n", hash.ToString().c_str()); + CTxDB txdb; + CBlock block; + if (!block.ReadFromDisk(mapBlockIndex[hash])) + return error("ResetSyncCheckpoint: ReadFromDisk failed for hardened checkpoint %s", hash.ToString().c_str()); + if (!block.SetBestChain(txdb, mapBlockIndex[hash])) + { + return error("ResetSyncCheckpoint: SetBestChain failed for hardened checkpoint %s", hash.ToString().c_str()); + } + } + else if(!mapBlockIndex.count(hash)) + { + // checkpoint block not yet accepted + hashPendingCheckpoint = hash; + checkpointMessagePending.SetNull(); + printf("ResetSyncCheckpoint: pending for sync-checkpoint %s\n", hashPendingCheckpoint.ToString().c_str()); + } + + BOOST_REVERSE_FOREACH(const MapCheckpoints::value_type& i, mapCheckpoints) + { + const uint256& hash = i.second; + if (mapBlockIndex.count(hash) && mapBlockIndex[hash]->IsInMainChain()) + { + if (!WriteSyncCheckpoint(hash)) + return error("ResetSyncCheckpoint: failed to write sync checkpoint %s", hash.ToString().c_str()); + printf("ResetSyncCheckpoint: sync-checkpoint reset to %s\n", hashSyncCheckpoint.ToString().c_str()); + return true; + } + } + + return false; + } + + void AskForPendingSyncCheckpoint(CNode* pfrom) + { + LOCK(cs_hashSyncCheckpoint); + if (pfrom && hashPendingCheckpoint != 0 && (!mapBlockIndex.count(hashPendingCheckpoint)) && (!mapOrphanBlocks.count(hashPendingCheckpoint))) + pfrom->AskFor(CInv(MSG_BLOCK, hashPendingCheckpoint)); + } + + bool SetCheckpointPrivKey(std::string strPrivKey) + { + // Test signing a sync-checkpoint with genesis block + CSyncCheckpoint checkpoint; + checkpoint.hashCheckpoint = !fTestNet ? hashGenesisBlock : hashGenesisBlockTestNet; + CDataStream sMsg(SER_NETWORK, PROTOCOL_VERSION); + sMsg << (CUnsignedSyncCheckpoint)checkpoint; + checkpoint.vchMsg = std::vector(sMsg.begin(), sMsg.end()); + + std::vector vchPrivKey = ParseHex(strPrivKey); + CKey key; + key.SetPrivKey(CPrivKey(vchPrivKey.begin(), vchPrivKey.end())); // if key is not correct openssl may crash + if (!key.Sign(Hash(checkpoint.vchMsg.begin(), checkpoint.vchMsg.end()), checkpoint.vchSig)) + return false; + + // Test signing successful, proceed + CSyncCheckpoint::strMasterPrivKey = strPrivKey; + return true; + } + + bool SendSyncCheckpoint(uint256 hashCheckpoint) + { + CSyncCheckpoint checkpoint; + checkpoint.hashCheckpoint = hashCheckpoint; + CDataStream sMsg(SER_NETWORK, PROTOCOL_VERSION); + sMsg << (CUnsignedSyncCheckpoint)checkpoint; + checkpoint.vchMsg = std::vector(sMsg.begin(), sMsg.end()); + + if (CSyncCheckpoint::strMasterPrivKey.empty()) + return error("SendSyncCheckpoint: Checkpoint master key unavailable."); + std::vector vchPrivKey = ParseHex(CSyncCheckpoint::strMasterPrivKey); + CKey key; + key.SetPrivKey(CPrivKey(vchPrivKey.begin(), vchPrivKey.end())); // if key is not correct openssl may crash + if (!key.Sign(Hash(checkpoint.vchMsg.begin(), checkpoint.vchMsg.end()), checkpoint.vchSig)) + return error("SendSyncCheckpoint: Unable to sign checkpoint, check private key?"); + + if(!checkpoint.ProcessSyncCheckpoint(NULL)) + { + printf("WARNING: SendSyncCheckpoint: Failed to process checkpoint.\n"); + return false; + } + + // Relay checkpoint + { + LOCK(cs_vNodes); + BOOST_FOREACH(CNode* pnode, vNodes) + checkpoint.RelayTo(pnode); + } + return true; + } + + // Is the sync-checkpoint outside maturity window? + bool IsMatureSyncCheckpoint() + { + LOCK(cs_hashSyncCheckpoint); + // sync-checkpoint should always be accepted block + assert(mapBlockIndex.count(hashSyncCheckpoint)); + const CBlockIndex* pindexSync = mapBlockIndex[hashSyncCheckpoint]; + return (nBestHeight >= pindexSync->nHeight + nCoinbaseMaturity || + pindexSync->GetBlockTime() + nStakeMinAge < GetAdjustedTime()); + } +} + +// ppcoin: sync-checkpoint master key +const std::string CSyncCheckpoint::strMasterPubKey = "04406ec49ddd6e534e377857474e741c679939555e0fe7dc188aefc162527abed63abb153265ef8bbe7e66588872a6128084f7eaa41319449cc25c966b12ae5b98"; + +std::string CSyncCheckpoint::strMasterPrivKey = ""; + +// ppcoin: verify signature of sync-checkpoint message +bool CSyncCheckpoint::CheckSignature() +{ + CKey key; + if (!key.SetPubKey(ParseHex(CSyncCheckpoint::strMasterPubKey))) + return error("CSyncCheckpoint::CheckSignature() : SetPubKey failed"); + if (!key.Verify(Hash(vchMsg.begin(), vchMsg.end()), vchSig)) + return error("CSyncCheckpoint::CheckSignature() : verify signature failed"); + + // Now unserialize the data + CDataStream sMsg(vchMsg, SER_NETWORK, PROTOCOL_VERSION); + sMsg >> *(CUnsignedSyncCheckpoint*)this; + return true; +} + +// ppcoin: process synchronized checkpoint +bool CSyncCheckpoint::ProcessSyncCheckpoint(CNode* pfrom) +{ + if (!CheckSignature()) + return false; + + LOCK(Checkpoints::cs_hashSyncCheckpoint); + if (!mapBlockIndex.count(hashCheckpoint)) + { + // We haven't received the checkpoint chain, keep the checkpoint as pending + Checkpoints::hashPendingCheckpoint = hashCheckpoint; + Checkpoints::checkpointMessagePending = *this; + printf("ProcessSyncCheckpoint: pending for sync-checkpoint %s\n", hashCheckpoint.ToString().c_str()); + // Ask this guy to fill in what we're missing + if (pfrom) + { + pfrom->PushGetBlocks(pindexBest, hashCheckpoint); + // ask directly as well in case rejected earlier by duplicate + // proof-of-stake because getblocks may not get it this time + pfrom->AskFor(CInv(MSG_BLOCK, mapOrphanBlocks.count(hashCheckpoint)? WantedByOrphan(mapOrphanBlocks[hashCheckpoint]) : hashCheckpoint)); + } + return false; + } + + if (!Checkpoints::ValidateSyncCheckpoint(hashCheckpoint)) + return false; + + CTxDB txdb; + CBlockIndex* pindexCheckpoint = mapBlockIndex[hashCheckpoint]; + if (!pindexCheckpoint->IsInMainChain()) + { + // checkpoint chain received but not yet main chain + CBlock block; + if (!block.ReadFromDisk(pindexCheckpoint)) + return error("ProcessSyncCheckpoint: ReadFromDisk failed for sync checkpoint %s", hashCheckpoint.ToString().c_str()); + if (!block.SetBestChain(txdb, pindexCheckpoint)) + { + Checkpoints::hashInvalidCheckpoint = hashCheckpoint; + return error("ProcessSyncCheckpoint: SetBestChain failed for sync checkpoint %s", hashCheckpoint.ToString().c_str()); + } + } + + if (!Checkpoints::WriteSyncCheckpoint(hashCheckpoint)) + return error("ProcessSyncCheckpoint(): failed to write sync checkpoint %s", hashCheckpoint.ToString().c_str()); + Checkpoints::checkpointMessage = *this; + Checkpoints::hashPendingCheckpoint = 0; + Checkpoints::checkpointMessagePending.SetNull(); + printf("ProcessSyncCheckpoint: sync-checkpoint at %s\n", hashCheckpoint.ToString().c_str()); + return true; +} diff --git a/src/checkpoints.h b/src/checkpoints.h new file mode 100644 index 0000000..0bba6cd --- /dev/null +++ b/src/checkpoints.h @@ -0,0 +1,154 @@ +// Copyright (c) 2009-2012 The Bitcoin developers +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. +#ifndef BITCOIN_CHECKPOINT_H +#define BITCOIN_CHECKPOINT_H + +#include +#include "net.h" +#include "util.h" + +#ifdef WIN32 +#undef STRICT +#undef PERMISSIVE +#undef ADVISORY +#endif + +class uint256; +class CBlockIndex; +class CSyncCheckpoint; + +/** Block-chain checkpoints are compiled-in sanity checks. + * They are updated every release or three. + */ +namespace Checkpoints +{ + /** Checkpointing mode */ + enum CPMode + { + // Scrict checkpoints policy, perform conflicts verification and resolve conflicts + STRICT = 0, + // Advisory checkpoints policy, perform conflicts verification but don't try to resolve them + ADVISORY = 1, + // Permissive checkpoints policy, don't perform any checking + PERMISSIVE = 2 + }; + + // Returns true if block passes checkpoint checks + bool CheckHardened(int nHeight, const uint256& hash); + + // Return conservative estimate of total number of blocks, 0 if unknown + int GetTotalBlocksEstimate(); + + // Returns last CBlockIndex* in mapBlockIndex that is a checkpoint + CBlockIndex* GetLastCheckpoint(const std::map& mapBlockIndex); + + extern uint256 hashSyncCheckpoint; + extern CSyncCheckpoint checkpointMessage; + extern uint256 hashInvalidCheckpoint; + extern CCriticalSection cs_hashSyncCheckpoint; + + CBlockIndex* GetLastSyncCheckpoint(); + bool WriteSyncCheckpoint(const uint256& hashCheckpoint); + bool AcceptPendingSyncCheckpoint(); + uint256 AutoSelectSyncCheckpoint(); + bool CheckSync(const uint256& hashBlock, const CBlockIndex* pindexPrev); + bool WantedByPendingSyncCheckpoint(uint256 hashBlock); + bool ResetSyncCheckpoint(); + void AskForPendingSyncCheckpoint(CNode* pfrom); + bool SetCheckpointPrivKey(std::string strPrivKey); + bool SendSyncCheckpoint(uint256 hashCheckpoint); + bool IsMatureSyncCheckpoint(); +} + +// ppcoin: synchronized checkpoint +class CUnsignedSyncCheckpoint +{ +public: + int nVersion; + uint256 hashCheckpoint; // checkpoint block + + IMPLEMENT_SERIALIZE + ( + READWRITE(this->nVersion); + nVersion = this->nVersion; + READWRITE(hashCheckpoint); + ) + + void SetNull() + { + nVersion = 1; + hashCheckpoint = 0; + } + + std::string ToString() const + { + return strprintf( + "CSyncCheckpoint(\n" + " nVersion = %d\n" + " hashCheckpoint = %s\n" + ")\n", + nVersion, + hashCheckpoint.ToString().c_str()); + } + + void print() const + { + printf("%s", ToString().c_str()); + } +}; + +class CSyncCheckpoint : public CUnsignedSyncCheckpoint +{ +public: + static const std::string strMasterPubKey; + static std::string strMasterPrivKey; + + std::vector vchMsg; + std::vector vchSig; + + CSyncCheckpoint() + { + SetNull(); + } + + IMPLEMENT_SERIALIZE + ( + READWRITE(vchMsg); + READWRITE(vchSig); + ) + + void SetNull() + { + CUnsignedSyncCheckpoint::SetNull(); + vchMsg.clear(); + vchSig.clear(); + } + + bool IsNull() const + { + return (hashCheckpoint == 0); + } + + uint256 GetHash() const + { + return SerializeHash(*this); + } + + bool RelayTo(CNode* pnode) const + { + // returns true if wasn't already sent + if (pnode->hashCheckpointKnown != hashCheckpoint) + { + pnode->hashCheckpointKnown = hashCheckpoint; + pnode->PushMessage("checkpoint", *this); + return true; + } + return false; + } + + bool CheckSignature(); + bool ProcessSyncCheckpoint(CNode* pfrom); +}; + +#endif diff --git a/src/clientversion.h b/src/clientversion.h new file mode 100644 index 0000000..a450526 --- /dev/null +++ b/src/clientversion.h @@ -0,0 +1,19 @@ +#ifndef CLIENTVERSION_H +#define CLIENTVERSION_H + +// +// client versioning +// + +// These need to be macros, as version.cpp's and bitcoin-qt.rc's voodoo requires it +#define CLIENT_VERSION_MAJOR 1 +#define CLIENT_VERSION_MINOR 0 +#define CLIENT_VERSION_REVISION 1 +#define CLIENT_VERSION_BUILD 8 + +// Converts the parameter X to a string after macro replacement on X has been performed. +// Don't merge these into one macro! +#define STRINGIZE(X) DO_STRINGIZE(X) +#define DO_STRINGIZE(X) #X + +#endif // CLIENTVERSION_H diff --git a/src/coincontrol.h b/src/coincontrol.h new file mode 100644 index 0000000..236b586 --- /dev/null +++ b/src/coincontrol.h @@ -0,0 +1,57 @@ +#ifndef COINCONTROL_H +#define COINCONTROL_H + +/** Coin Control Features. */ +class CCoinControl +{ +public: + CTxDestination destChange; + + CCoinControl() + { + SetNull(); + } + + void SetNull() + { + destChange = CNoDestination(); + setSelected.clear(); + } + + bool HasSelected() const + { + return (setSelected.size() > 0); + } + + bool IsSelected(const uint256& hash, unsigned int n) const + { + COutPoint outpt(hash, n); + return (setSelected.count(outpt) > 0); + } + + void Select(COutPoint& output) + { + setSelected.insert(output); + } + + void UnSelect(COutPoint& output) + { + setSelected.erase(output); + } + + void UnSelectAll() + { + setSelected.clear(); + } + + void ListSelected(std::vector& vOutpoints) + { + vOutpoints.assign(setSelected.begin(), setSelected.end()); + } + +private: + std::set setSelected; + +}; + +#endif // COINCONTROL_H diff --git a/src/compat.h b/src/compat.h new file mode 100644 index 0000000..d09ec4f --- /dev/null +++ b/src/compat.h @@ -0,0 +1,65 @@ +// Copyright (c) 2009-2010 Satoshi Nakamoto +// Copyright (c) 2009-2012 The Bitcoin developers +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. +#ifndef _BITCOIN_COMPAT_H +#define _BITCOIN_COMPAT_H 1 + +#ifdef WIN32 +#define _WIN32_WINNT 0x0501 +#define WIN32_LEAN_AND_MEAN 1 +#ifndef NOMINMAX +#define NOMINMAX +#endif +#include +#include +#include +#else +#include +#include +#include +#include +#include +#include +#include +#include + +typedef u_int SOCKET; +#endif + + +#ifdef WIN32 +#define MSG_NOSIGNAL 0 +#define MSG_DONTWAIT 0 +typedef int socklen_t; +#else +#include "errno.h" +#define WSAGetLastError() errno +#define WSAEINVAL EINVAL +#define WSAEALREADY EALREADY +#define WSAEWOULDBLOCK EWOULDBLOCK +#define WSAEMSGSIZE EMSGSIZE +#define WSAEINTR EINTR +#define WSAEINPROGRESS EINPROGRESS +#define WSAEADDRINUSE EADDRINUSE +#define WSAENOTSOCK EBADF +#define INVALID_SOCKET (SOCKET)(~0) +#define SOCKET_ERROR -1 +#endif + +inline int myclosesocket(SOCKET& hSocket) +{ + if (hSocket == INVALID_SOCKET) + return WSAENOTSOCK; +#ifdef WIN32 + int ret = closesocket(hSocket); +#else + int ret = close(hSocket); +#endif + hSocket = INVALID_SOCKET; + return ret; +} +#define closesocket(s) myclosesocket(s) + + +#endif diff --git a/src/crypter.cpp b/src/crypter.cpp new file mode 100644 index 0000000..86c2ccc --- /dev/null +++ b/src/crypter.cpp @@ -0,0 +1,135 @@ +// Copyright (c) 2009-2012 The Bitcoin Developers +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include +#include +#include +#include +#ifdef WIN32 +#include +#endif + +#include "crypter.h" +#include "scrypt.h" + +bool CCrypter::SetKeyFromPassphrase(const SecureString& strKeyData, const std::vector& chSalt, const unsigned int nRounds, const unsigned int nDerivationMethod) +{ + if (nRounds < 1 || chSalt.size() != WALLET_CRYPTO_SALT_SIZE) + return false; + + int i = 0; + if (nDerivationMethod == 0) + { + i = EVP_BytesToKey(EVP_aes_256_cbc(), EVP_sha512(), &chSalt[0], + (unsigned char *)&strKeyData[0], strKeyData.size(), nRounds, chKey, chIV); + } + + if (nDerivationMethod == 1) + { + // Passphrase conversion + uint256 scryptHash = scrypt_salted_multiround_hash((const void*)strKeyData.c_str(), strKeyData.size(), &chSalt[0], 8, nRounds); + + i = EVP_BytesToKey(EVP_aes_256_cbc(), EVP_sha512(), &chSalt[0], + (unsigned char *)&scryptHash, sizeof scryptHash, nRounds, chKey, chIV); + OPENSSL_cleanse(&scryptHash, sizeof scryptHash); + } + + + if (i != (int)WALLET_CRYPTO_KEY_SIZE) + { + OPENSSL_cleanse(chKey, sizeof(chKey)); + OPENSSL_cleanse(chIV, sizeof(chIV)); + return false; + } + + fKeySet = true; + return true; +} + +bool CCrypter::SetKey(const CKeyingMaterial& chNewKey, const std::vector& chNewIV) +{ + if (chNewKey.size() != WALLET_CRYPTO_KEY_SIZE || chNewIV.size() != WALLET_CRYPTO_KEY_SIZE) + return false; + + memcpy(&chKey[0], &chNewKey[0], sizeof chKey); + memcpy(&chIV[0], &chNewIV[0], sizeof chIV); + + fKeySet = true; + return true; +} + +bool CCrypter::Encrypt(const CKeyingMaterial& vchPlaintext, std::vector &vchCiphertext) +{ + if (!fKeySet) + return false; + + // max ciphertext len for a n bytes of plaintext is + // n + AES_BLOCK_SIZE - 1 bytes + int nLen = vchPlaintext.size(); + int nCLen = nLen + AES_BLOCK_SIZE, nFLen = 0; + vchCiphertext = std::vector (nCLen); + + EVP_CIPHER_CTX ctx; + + bool fOk = true; + + EVP_CIPHER_CTX_init(&ctx); + if (fOk) fOk = EVP_EncryptInit_ex(&ctx, EVP_aes_256_cbc(), NULL, chKey, chIV); + if (fOk) fOk = EVP_EncryptUpdate(&ctx, &vchCiphertext[0], &nCLen, &vchPlaintext[0], nLen); + if (fOk) fOk = EVP_EncryptFinal_ex(&ctx, (&vchCiphertext[0])+nCLen, &nFLen); + EVP_CIPHER_CTX_cleanup(&ctx); + + if (!fOk) return false; + + vchCiphertext.resize(nCLen + nFLen); + return true; +} + +bool CCrypter::Decrypt(const std::vector& vchCiphertext, CKeyingMaterial& vchPlaintext) +{ + if (!fKeySet) + return false; + + // plaintext will always be equal to or lesser than length of ciphertext + int nLen = vchCiphertext.size(); + int nPLen = nLen, nFLen = 0; + + vchPlaintext = CKeyingMaterial(nPLen); + + EVP_CIPHER_CTX ctx; + + bool fOk = true; + + EVP_CIPHER_CTX_init(&ctx); + if (fOk) fOk = EVP_DecryptInit_ex(&ctx, EVP_aes_256_cbc(), NULL, chKey, chIV); + if (fOk) fOk = EVP_DecryptUpdate(&ctx, &vchPlaintext[0], &nPLen, &vchCiphertext[0], nLen); + if (fOk) fOk = EVP_DecryptFinal_ex(&ctx, (&vchPlaintext[0])+nPLen, &nFLen); + EVP_CIPHER_CTX_cleanup(&ctx); + + if (!fOk) return false; + + vchPlaintext.resize(nPLen + nFLen); + return true; +} + + +bool EncryptSecret(CKeyingMaterial& vMasterKey, const CSecret &vchPlaintext, const uint256& nIV, std::vector &vchCiphertext) +{ + CCrypter cKeyCrypter; + std::vector chIV(WALLET_CRYPTO_KEY_SIZE); + memcpy(&chIV[0], &nIV, WALLET_CRYPTO_KEY_SIZE); + if(!cKeyCrypter.SetKey(vMasterKey, chIV)) + return false; + return cKeyCrypter.Encrypt((CKeyingMaterial)vchPlaintext, vchCiphertext); +} + +bool DecryptSecret(const CKeyingMaterial& vMasterKey, const std::vector& vchCiphertext, const uint256& nIV, CSecret& vchPlaintext) +{ + CCrypter cKeyCrypter; + std::vector chIV(WALLET_CRYPTO_KEY_SIZE); + memcpy(&chIV[0], &nIV, WALLET_CRYPTO_KEY_SIZE); + if(!cKeyCrypter.SetKey(vMasterKey, chIV)) + return false; + return cKeyCrypter.Decrypt(vchCiphertext, *((CKeyingMaterial*)&vchPlaintext)); +} diff --git a/src/crypter.h b/src/crypter.h new file mode 100644 index 0000000..5427d4c --- /dev/null +++ b/src/crypter.h @@ -0,0 +1,127 @@ +// Copyright (c) 2009-2012 The Bitcoin Developers +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. +#ifndef __CRYPTER_H__ +#define __CRYPTER_H__ + +#include "allocators.h" /* for SecureString */ +#include "key.h" +#include "serialize.h" + +const unsigned int WALLET_CRYPTO_KEY_SIZE = 32; +const unsigned int WALLET_CRYPTO_SALT_SIZE = 8; + +/* +Private key encryption is done based on a CMasterKey, +which holds a salt and random encryption key. + +CMasterKeys are encrypted using AES-256-CBC using a key +derived using derivation method nDerivationMethod +(0 == EVP_sha512()) and derivation iterations nDeriveIterations. +vchOtherDerivationParameters is provided for alternative algorithms +which may require more parameters (such as scrypt). + +Wallet Private Keys are then encrypted using AES-256-CBC +with the double-sha256 of the public key as the IV, and the +master key's key as the encryption key (see keystore.[ch]). +*/ + +/** Master key for wallet encryption */ +class CMasterKey +{ +public: + std::vector vchCryptedKey; + std::vector vchSalt; + // 0 = EVP_sha512() + // 1 = scrypt() + unsigned int nDerivationMethod; + unsigned int nDeriveIterations; + // Use this for more parameters to key derivation, + // such as the various parameters to scrypt + std::vector vchOtherDerivationParameters; + + IMPLEMENT_SERIALIZE + ( + READWRITE(vchCryptedKey); + READWRITE(vchSalt); + READWRITE(nDerivationMethod); + READWRITE(nDeriveIterations); + READWRITE(vchOtherDerivationParameters); + ) + CMasterKey() + { + // 25000 rounds is just under 0.1 seconds on a 1.86 GHz Pentium M + // ie slightly lower than the lowest hardware we need bother supporting + nDeriveIterations = 25000; + nDerivationMethod = 1; + vchOtherDerivationParameters = std::vector(0); + } + + CMasterKey(unsigned int nDerivationMethodIndex) + { + switch (nDerivationMethodIndex) + { + case 0: // sha512 + default: + nDeriveIterations = 25000; + nDerivationMethod = 0; + vchOtherDerivationParameters = std::vector(0); + break; + + case 1: // scrypt+sha512 + nDeriveIterations = 10000; + nDerivationMethod = 1; + vchOtherDerivationParameters = std::vector(0); + break; + } + } + +}; + +typedef std::vector > CKeyingMaterial; + +/** Encryption/decryption context with key information */ +class CCrypter +{ +private: + unsigned char chKey[WALLET_CRYPTO_KEY_SIZE]; + unsigned char chIV[WALLET_CRYPTO_KEY_SIZE]; + bool fKeySet; + +public: + bool SetKeyFromPassphrase(const SecureString &strKeyData, const std::vector& chSalt, const unsigned int nRounds, const unsigned int nDerivationMethod); + bool Encrypt(const CKeyingMaterial& vchPlaintext, std::vector &vchCiphertext); + bool Decrypt(const std::vector& vchCiphertext, CKeyingMaterial& vchPlaintext); + bool SetKey(const CKeyingMaterial& chNewKey, const std::vector& chNewIV); + + void CleanKey() + { + OPENSSL_cleanse(chKey, sizeof(chKey)); + OPENSSL_cleanse(chIV, sizeof(chIV)); + fKeySet = false; + } + + CCrypter() + { + fKeySet = false; + + // Try to keep the key data out of swap (and be a bit over-careful to keep the IV that we don't even use out of swap) + // Note that this does nothing about suspend-to-disk (which will put all our key data on disk) + // Note as well that at no point in this program is any attempt made to prevent stealing of keys by reading the memory of the running process. + LockedPageManager::instance.LockRange(&chKey[0], sizeof chKey); + LockedPageManager::instance.LockRange(&chIV[0], sizeof chIV); + } + + ~CCrypter() + { + CleanKey(); + + LockedPageManager::instance.UnlockRange(&chKey[0], sizeof chKey); + LockedPageManager::instance.UnlockRange(&chIV[0], sizeof chIV); + } +}; + +bool EncryptSecret(CKeyingMaterial& vMasterKey, const CSecret &vchPlaintext, const uint256& nIV, std::vector &vchCiphertext); +bool DecryptSecret(const CKeyingMaterial& vMasterKey, const std::vector &vchCiphertext, const uint256& nIV, CSecret &vchPlaintext); + +#endif diff --git a/src/db.cpp b/src/db.cpp new file mode 100644 index 0000000..4bc4212 --- /dev/null +++ b/src/db.cpp @@ -0,0 +1,581 @@ +// Copyright (c) 2009-2010 Satoshi Nakamoto +// Copyright (c) 2009-2012 The Bitcoin developers +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include "db.h" +#include "net.h" +#include "util.h" +#include "main.h" +#include "ui_interface.h" +#include +#include + +#ifndef WIN32 +#include "sys/stat.h" +#endif + +using namespace std; +using namespace boost; + + +unsigned int nWalletDBUpdated; + + + +// +// CDB +// + +CDBEnv bitdb; + +void CDBEnv::EnvShutdown() +{ + if (!fDbEnvInit) + return; + + fDbEnvInit = false; + int ret = dbenv.close(0); + if (ret != 0) + printf("EnvShutdown exception: %s (%d)\n", DbEnv::strerror(ret), ret); + if (!fMockDb) + DbEnv(0).remove(strPath.c_str(), 0); +} + +CDBEnv::CDBEnv() : dbenv(DB_CXX_NO_EXCEPTIONS) +{ + fDbEnvInit = false; + fMockDb = false; +} + +CDBEnv::~CDBEnv() +{ + EnvShutdown(); +} + +void CDBEnv::Close() +{ + EnvShutdown(); +} + +bool CDBEnv::Open(boost::filesystem::path pathEnv_) +{ + if (fDbEnvInit) + return true; + + if (fShutdown) + return false; + + pathEnv = pathEnv_; + filesystem::path pathDataDir = pathEnv; + strPath = pathDataDir.string(); + filesystem::path pathLogDir = pathDataDir / "database"; + filesystem::create_directory(pathLogDir); + filesystem::path pathErrorFile = pathDataDir / "db.log"; + printf("dbenv.open LogDir=%s ErrorFile=%s\n", pathLogDir.string().c_str(), pathErrorFile.string().c_str()); + + unsigned int nEnvFlags = 0; + if (GetBoolArg("-privdb", true)) + nEnvFlags |= DB_PRIVATE; + + int nDbCache = GetArg("-dbcache", 25); + dbenv.set_lg_dir(pathLogDir.string().c_str()); + dbenv.set_cachesize(nDbCache / 1024, (nDbCache % 1024)*1048576, 1); + dbenv.set_lg_bsize(1048576); + dbenv.set_lg_max(10485760); + + // Bugfix: Bump lk_max_locks default to 537000, to safely handle reorgs with up to 5 blocks reversed + // dbenv.set_lk_max_locks(10000); + dbenv.set_lk_max_locks(537000); + + dbenv.set_lk_max_objects(10000); + dbenv.set_errfile(fopen(pathErrorFile.string().c_str(), "a")); /// debug + dbenv.set_flags(DB_AUTO_COMMIT, 1); + dbenv.set_flags(DB_TXN_WRITE_NOSYNC, 1); +#ifdef DB_LOG_AUTO_REMOVE + dbenv.log_set_config(DB_LOG_AUTO_REMOVE, 1); +#endif + int ret = dbenv.open(strPath.c_str(), + DB_CREATE | + DB_INIT_LOCK | + DB_INIT_LOG | + DB_INIT_MPOOL | + DB_INIT_TXN | + DB_THREAD | + DB_RECOVER | + nEnvFlags, + S_IRUSR | S_IWUSR); + if (ret != 0) + return error("CDB() : error %s (%d) opening database environment", DbEnv::strerror(ret), ret); + + fDbEnvInit = true; + fMockDb = false; + + return true; +} + +void CDBEnv::MakeMock() +{ + if (fDbEnvInit) + throw runtime_error("CDBEnv::MakeMock(): already initialized"); + + if (fShutdown) + throw runtime_error("CDBEnv::MakeMock(): during shutdown"); + + printf("CDBEnv::MakeMock()\n"); + + dbenv.set_cachesize(1, 0, 1); + dbenv.set_lg_bsize(10485760*4); + dbenv.set_lg_max(10485760); + dbenv.set_lk_max_locks(10000); + dbenv.set_lk_max_objects(10000); + dbenv.set_flags(DB_AUTO_COMMIT, 1); +#ifdef DB_LOG_IN_MEMORY + dbenv.log_set_config(DB_LOG_IN_MEMORY, 1); +#endif + int ret = dbenv.open(NULL, + DB_CREATE | + DB_INIT_LOCK | + DB_INIT_LOG | + DB_INIT_MPOOL | + DB_INIT_TXN | + DB_THREAD | + DB_PRIVATE, + S_IRUSR | S_IWUSR); + if (ret > 0) + throw runtime_error(strprintf("CDBEnv::MakeMock(): error %d opening database environment", ret)); + + fDbEnvInit = true; + fMockDb = true; +} + +CDBEnv::VerifyResult CDBEnv::Verify(std::string strFile, bool (*recoverFunc)(CDBEnv& dbenv, std::string strFile)) +{ + LOCK(cs_db); + assert(mapFileUseCount.count(strFile) == 0); + + Db db(&dbenv, 0); + int result = db.verify(strFile.c_str(), NULL, NULL, 0); + if (result == 0) + return VERIFY_OK; + else if (recoverFunc == NULL) + return RECOVER_FAIL; + + // Try to recover: + bool fRecovered = (*recoverFunc)(*this, strFile); + return (fRecovered ? RECOVER_OK : RECOVER_FAIL); +} + +bool CDBEnv::Salvage(std::string strFile, bool fAggressive, + std::vector& vResult) +{ + LOCK(cs_db); + assert(mapFileUseCount.count(strFile) == 0); + + u_int32_t flags = DB_SALVAGE; + if (fAggressive) flags |= DB_AGGRESSIVE; + + stringstream strDump; + + Db db(&dbenv, 0); + int result = db.verify(strFile.c_str(), NULL, &strDump, flags); + if (result == DB_VERIFY_BAD) + { + printf("Error: Salvage found errors, all data may not be recoverable.\n"); + if (!fAggressive) + { + printf("Error: Rerun with aggressive mode to ignore errors and continue.\n"); + return false; + } + } + if (result != 0 && result != DB_VERIFY_BAD) + { + printf("ERROR: db salvage failed: %d\n",result); + return false; + } + + // Format of bdb dump is ascii lines: + // header lines... + // HEADER=END + // hexadecimal key + // hexadecimal value + // ... repeated + // DATA=END + + string strLine; + while (!strDump.eof() && strLine != "HEADER=END") + getline(strDump, strLine); // Skip past header + + std::string keyHex, valueHex; + while (!strDump.eof() && keyHex != "DATA=END") + { + getline(strDump, keyHex); + if (keyHex != "DATA_END") + { + getline(strDump, valueHex); + vResult.push_back(make_pair(ParseHex(keyHex),ParseHex(valueHex))); + } + } + + return (result == 0); +} + + +void CDBEnv::CheckpointLSN(std::string strFile) +{ + dbenv.txn_checkpoint(0, 0, 0); + if (fMockDb) + return; + dbenv.lsn_reset(strFile.c_str(), 0); +} + + +CDB::CDB(const char *pszFile, const char* pszMode) : + pdb(NULL), activeTxn(NULL) +{ + int ret; + if (pszFile == NULL) + return; + + fReadOnly = (!strchr(pszMode, '+') && !strchr(pszMode, 'w')); + bool fCreate = strchr(pszMode, 'c'); + unsigned int nFlags = DB_THREAD; + if (fCreate) + nFlags |= DB_CREATE; + + { + LOCK(bitdb.cs_db); + if (!bitdb.Open(GetDataDir())) + throw runtime_error("env open failed"); + + strFile = pszFile; + ++bitdb.mapFileUseCount[strFile]; + pdb = bitdb.mapDb[strFile]; + if (pdb == NULL) + { + pdb = new Db(&bitdb.dbenv, 0); + + bool fMockDb = bitdb.IsMock(); + if (fMockDb) + { + DbMpoolFile*mpf = pdb->get_mpf(); + ret = mpf->set_flags(DB_MPOOL_NOFILE, 1); + if (ret != 0) + throw runtime_error(strprintf("CDB() : failed to configure for no temp file backing for database %s", pszFile)); + } + + ret = pdb->open(NULL, // Txn pointer + fMockDb ? NULL : pszFile, // Filename + "main", // Logical db name + DB_BTREE, // Database type + nFlags, // Flags + 0); + + if (ret != 0) + { + delete pdb; + pdb = NULL; + --bitdb.mapFileUseCount[strFile]; + strFile = ""; + throw runtime_error(strprintf("CDB() : can't open database file %s, error %d", pszFile, ret)); + } + + if (fCreate && !Exists(string("version"))) + { + bool fTmp = fReadOnly; + fReadOnly = false; + WriteVersion(CLIENT_VERSION); + fReadOnly = fTmp; + } + + bitdb.mapDb[strFile] = pdb; + } + } +} + +void CDB::Close() +{ + if (!pdb) + return; + if (activeTxn) + activeTxn->abort(); + activeTxn = NULL; + pdb = NULL; + + // Flush database activity from memory pool to disk log + unsigned int nMinutes = 0; + if (fReadOnly) + nMinutes = 1; + + bitdb.dbenv.txn_checkpoint(nMinutes ? GetArg("-dblogsize", 100)*1024 : 0, nMinutes, 0); + + { + LOCK(bitdb.cs_db); + --bitdb.mapFileUseCount[strFile]; + } +} + +void CDBEnv::CloseDb(const string& strFile) +{ + { + LOCK(cs_db); + if (mapDb[strFile] != NULL) + { + // Close the database handle + Db* pdb = mapDb[strFile]; + pdb->close(0); + delete pdb; + mapDb[strFile] = NULL; + } + } +} + +bool CDBEnv::RemoveDb(const string& strFile) +{ + this->CloseDb(strFile); + + LOCK(cs_db); + int rc = dbenv.dbremove(NULL, strFile.c_str(), NULL, DB_AUTO_COMMIT); + return (rc == 0); +} + +bool CDB::Rewrite(const string& strFile, const char* pszSkip) +{ + while (!fShutdown) + { + { + LOCK(bitdb.cs_db); + if (!bitdb.mapFileUseCount.count(strFile) || bitdb.mapFileUseCount[strFile] == 0) + { + // Flush log data to the dat file + bitdb.CloseDb(strFile); + bitdb.CheckpointLSN(strFile); + bitdb.mapFileUseCount.erase(strFile); + + bool fSuccess = true; + printf("Rewriting %s...\n", strFile.c_str()); + string strFileRes = strFile + ".rewrite"; + { // surround usage of db with extra {} + CDB db(strFile.c_str(), "r"); + Db* pdbCopy = new Db(&bitdb.dbenv, 0); + + int ret = pdbCopy->open(NULL, // Txn pointer + strFileRes.c_str(), // Filename + "main", // Logical db name + DB_BTREE, // Database type + DB_CREATE, // Flags + 0); + if (ret > 0) + { + printf("Cannot create database file %s\n", strFileRes.c_str()); + fSuccess = false; + } + + Dbc* pcursor = db.GetCursor(); + if (pcursor) + while (fSuccess) + { + CDataStream ssKey(SER_DISK, CLIENT_VERSION); + CDataStream ssValue(SER_DISK, CLIENT_VERSION); + int ret = db.ReadAtCursor(pcursor, ssKey, ssValue, DB_NEXT); + if (ret == DB_NOTFOUND) + { + pcursor->close(); + break; + } + else if (ret != 0) + { + pcursor->close(); + fSuccess = false; + break; + } + if (pszSkip && + strncmp(&ssKey[0], pszSkip, std::min(ssKey.size(), strlen(pszSkip))) == 0) + continue; + if (strncmp(&ssKey[0], "\x07version", 8) == 0) + { + // Update version: + ssValue.clear(); + ssValue << CLIENT_VERSION; + } + Dbt datKey(&ssKey[0], ssKey.size()); + Dbt datValue(&ssValue[0], ssValue.size()); + int ret2 = pdbCopy->put(NULL, &datKey, &datValue, DB_NOOVERWRITE); + if (ret2 > 0) + fSuccess = false; + } + if (fSuccess) + { + db.Close(); + bitdb.CloseDb(strFile); + if (pdbCopy->close(0)) + fSuccess = false; + delete pdbCopy; + } + } + if (fSuccess) + { + Db dbA(&bitdb.dbenv, 0); + if (dbA.remove(strFile.c_str(), NULL, 0)) + fSuccess = false; + Db dbB(&bitdb.dbenv, 0); + if (dbB.rename(strFileRes.c_str(), NULL, strFile.c_str(), 0)) + fSuccess = false; + } + if (!fSuccess) + printf("Rewriting of %s FAILED!\n", strFileRes.c_str()); + return fSuccess; + } + } + MilliSleep(100); + } + return false; +} + + +void CDBEnv::Flush(bool fShutdown) +{ + int64_t nStart = GetTimeMillis(); + // Flush log data to the actual data file + // on all files that are not in use + printf("Flush(%s)%s\n", fShutdown ? "true" : "false", fDbEnvInit ? "" : " db not started"); + if (!fDbEnvInit) + return; + { + LOCK(cs_db); + map::iterator mi = mapFileUseCount.begin(); + while (mi != mapFileUseCount.end()) + { + string strFile = (*mi).first; + int nRefCount = (*mi).second; + printf("%s refcount=%d\n", strFile.c_str(), nRefCount); + if (nRefCount == 0) + { + // Move log data to the dat file + CloseDb(strFile); + printf("%s checkpoint\n", strFile.c_str()); + dbenv.txn_checkpoint(0, 0, 0); + printf("%s detach\n", strFile.c_str()); + if (!fMockDb) + dbenv.lsn_reset(strFile.c_str(), 0); + printf("%s closed\n", strFile.c_str()); + mapFileUseCount.erase(mi++); + } + else + mi++; + } + printf("DBFlush(%s)%s ended %15" PRId64"ms\n", fShutdown ? "true" : "false", fDbEnvInit ? "" : " db not started", GetTimeMillis() - nStart); + if (fShutdown) + { + char** listp; + if (mapFileUseCount.empty()) + { + dbenv.log_archive(&listp, DB_ARCH_REMOVE); + Close(); + } + } + } +} + + +// +// CAddrDB +// + + +CAddrDB::CAddrDB() +{ + pathAddr = GetDataDir() / "peers.dat"; +} + +bool CAddrDB::Write(const CAddrMan& addr) +{ + // Generate random temporary filename + unsigned short randv = 0; + RAND_bytes((unsigned char *)&randv, sizeof(randv)); + std::string tmpfn = strprintf("peers.dat.%04x", randv); + + // serialize addresses, checksum data up to that point, then append csum + CDataStream ssPeers(SER_DISK, CLIENT_VERSION); + ssPeers << FLATDATA(pchMessageStart); + ssPeers << addr; + uint256 hash = Hash(ssPeers.begin(), ssPeers.end()); + ssPeers << hash; + + // open temp output file, and associate with CAutoFile + boost::filesystem::path pathTmp = GetDataDir() / tmpfn; + FILE *file = fopen(pathTmp.string().c_str(), "wb"); + CAutoFile fileout = CAutoFile(file, SER_DISK, CLIENT_VERSION); + if (!fileout) + return error("CAddrman::Write() : open failed"); + + // Write and commit header, data + try { + fileout << ssPeers; + } + catch (std::exception &e) { + return error("CAddrman::Write() : I/O error"); + } + FileCommit(fileout); + fileout.fclose(); + + // replace existing peers.dat, if any, with new peers.dat.XXXX + if (!RenameOver(pathTmp, pathAddr)) + return error("CAddrman::Write() : Rename-into-place failed"); + + return true; +} + +bool CAddrDB::Read(CAddrMan& addr) +{ + // open input file, and associate with CAutoFile + FILE *file = fopen(pathAddr.string().c_str(), "rb"); + CAutoFile filein = CAutoFile(file, SER_DISK, CLIENT_VERSION); + if (!filein) + return error("CAddrman::Read() : open failed"); + + // use file size to size memory buffer + int fileSize = boost::filesystem::file_size(pathAddr); + int dataSize = fileSize - sizeof(uint256); + // Don't try to resize to a negative number if file is small + if ( dataSize < 0 ) dataSize = 0; + vector vchData; + vchData.resize(dataSize); + uint256 hashIn; + + // read data and checksum from file + try { + filein.read((char *)&vchData[0], dataSize); + filein >> hashIn; + } + catch (std::exception &e) { + return error("CAddrman::Read() 2 : I/O error or stream data corrupted"); + } + filein.fclose(); + + CDataStream ssPeers(vchData, SER_DISK, CLIENT_VERSION); + + // verify stored checksum matches input data + uint256 hashTmp = Hash(ssPeers.begin(), ssPeers.end()); + if (hashIn != hashTmp) + return error("CAddrman::Read() : checksum mismatch; data corrupted"); + + unsigned char pchMsgTmp[4]; + try { + // de-serialize file header (pchMessageStart magic number) and + ssPeers >> FLATDATA(pchMsgTmp); + + // verify the network matches ours + if (memcmp(pchMsgTmp, pchMessageStart, sizeof(pchMsgTmp))) + return error("CAddrman::Read() : invalid network magic number"); + + // de-serialize address data into one CAddrMan object + ssPeers >> addr; + } + catch (std::exception &e) { + return error("CAddrman::Read() : I/O error or stream data corrupted"); + } + + return true; +} + diff --git a/src/db.h b/src/db.h new file mode 100644 index 0000000..3a2de20 --- /dev/null +++ b/src/db.h @@ -0,0 +1,323 @@ +// Copyright (c) 2009-2010 Satoshi Nakamoto +// Copyright (c) 2009-2012 The Bitcoin developers +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. +#ifndef BITCOIN_DB_H +#define BITCOIN_DB_H + +#include "main.h" + +#include +#include +#include + +#include + +class CAddress; +class CAddrMan; +class CBlockLocator; +class CDiskBlockIndex; +class CDiskTxPos; +class CMasterKey; +class COutPoint; +class CTxIndex; +class CWallet; +class CWalletTx; + +extern unsigned int nWalletDBUpdated; + +void ThreadFlushWalletDB(void* parg); +bool BackupWallet(const CWallet& wallet, const std::string& strDest); + + +class CDBEnv +{ +private: + bool fDbEnvInit; + bool fMockDb; + boost::filesystem::path pathEnv; + std::string strPath; + + void EnvShutdown(); + +public: + mutable CCriticalSection cs_db; + DbEnv dbenv; + std::map mapFileUseCount; + std::map mapDb; + + CDBEnv(); + ~CDBEnv(); + void MakeMock(); + bool IsMock() { return fMockDb; }; + + /* + * Verify that database file strFile is OK. If it is not, + * call the callback to try to recover. + * This must be called BEFORE strFile is opened. + * Returns true if strFile is OK. + */ + enum VerifyResult { VERIFY_OK, RECOVER_OK, RECOVER_FAIL }; + VerifyResult Verify(std::string strFile, bool (*recoverFunc)(CDBEnv& dbenv, std::string strFile)); + /* + * Salvage data from a file that Verify says is bad. + * fAggressive sets the DB_AGGRESSIVE flag (see berkeley DB->verify() method documentation). + * Appends binary key/value pairs to vResult, returns true if successful. + * NOTE: reads the entire database into memory, so cannot be used + * for huge databases. + */ + typedef std::pair, std::vector > KeyValPair; + bool Salvage(std::string strFile, bool fAggressive, std::vector& vResult); + + bool Open(boost::filesystem::path pathEnv_); + void Close(); + void Flush(bool fShutdown); + void CheckpointLSN(std::string strFile); + + void CloseDb(const std::string& strFile); + bool RemoveDb(const std::string& strFile); + + DbTxn *TxnBegin(int flags=DB_TXN_WRITE_NOSYNC) + { + DbTxn* ptxn = NULL; + int ret = dbenv.txn_begin(NULL, &ptxn, flags); + if (!ptxn || ret != 0) + return NULL; + return ptxn; + } +}; + +extern CDBEnv bitdb; + + +/** RAII class that provides access to a Berkeley database */ +class CDB +{ +protected: + Db* pdb; + std::string strFile; + DbTxn *activeTxn; + bool fReadOnly; + + explicit CDB(const char* pszFile, const char* pszMode="r+"); + ~CDB() { Close(); } +public: + void Close(); +private: + CDB(const CDB&); + void operator=(const CDB&); + +protected: + template + bool Read(const K& key, T& value) + { + if (!pdb) + return false; + + // Key + CDataStream ssKey(SER_DISK, CLIENT_VERSION); + ssKey.reserve(1000); + ssKey << key; + Dbt datKey(&ssKey[0], ssKey.size()); + + // Read + Dbt datValue; + datValue.set_flags(DB_DBT_MALLOC); + int ret = pdb->get(activeTxn, &datKey, &datValue, 0); + memset(datKey.get_data(), 0, datKey.get_size()); + if (datValue.get_data() == NULL) + return false; + + // Unserialize value + try { + CDataStream ssValue((char*)datValue.get_data(), (char*)datValue.get_data() + datValue.get_size(), SER_DISK, CLIENT_VERSION); + ssValue >> value; + } + catch (std::exception &e) { + return false; + } + + // Clear and free memory + memset(datValue.get_data(), 0, datValue.get_size()); + free(datValue.get_data()); + return (ret == 0); + } + + template + bool Write(const K& key, const T& value, bool fOverwrite=true) + { + if (!pdb) + return false; + if (fReadOnly) + assert(!"Write called on database in read-only mode"); + + // Key + CDataStream ssKey(SER_DISK, CLIENT_VERSION); + ssKey.reserve(1000); + ssKey << key; + Dbt datKey(&ssKey[0], ssKey.size()); + + // Value + CDataStream ssValue(SER_DISK, CLIENT_VERSION); + ssValue.reserve(10000); + ssValue << value; + Dbt datValue(&ssValue[0], ssValue.size()); + + // Write + int ret = pdb->put(activeTxn, &datKey, &datValue, (fOverwrite ? 0 : DB_NOOVERWRITE)); + + // Clear memory in case it was a private key + memset(datKey.get_data(), 0, datKey.get_size()); + memset(datValue.get_data(), 0, datValue.get_size()); + return (ret == 0); + } + + template + bool Erase(const K& key) + { + if (!pdb) + return false; + if (fReadOnly) + assert(!"Erase called on database in read-only mode"); + + // Key + CDataStream ssKey(SER_DISK, CLIENT_VERSION); + ssKey.reserve(1000); + ssKey << key; + Dbt datKey(&ssKey[0], ssKey.size()); + + // Erase + int ret = pdb->del(activeTxn, &datKey, 0); + + // Clear memory + memset(datKey.get_data(), 0, datKey.get_size()); + return (ret == 0 || ret == DB_NOTFOUND); + } + + template + bool Exists(const K& key) + { + if (!pdb) + return false; + + // Key + CDataStream ssKey(SER_DISK, CLIENT_VERSION); + ssKey.reserve(1000); + ssKey << key; + Dbt datKey(&ssKey[0], ssKey.size()); + + // Exists + int ret = pdb->exists(activeTxn, &datKey, 0); + + // Clear memory + memset(datKey.get_data(), 0, datKey.get_size()); + return (ret == 0); + } + + Dbc* GetCursor() + { + if (!pdb) + return NULL; + Dbc* pcursor = NULL; + int ret = pdb->cursor(NULL, &pcursor, 0); + if (ret != 0) + return NULL; + return pcursor; + } + + int ReadAtCursor(Dbc* pcursor, CDataStream& ssKey, CDataStream& ssValue, unsigned int fFlags=DB_NEXT) + { + // Read at cursor + Dbt datKey; + if (fFlags == DB_SET || fFlags == DB_SET_RANGE || fFlags == DB_GET_BOTH || fFlags == DB_GET_BOTH_RANGE) + { + datKey.set_data(&ssKey[0]); + datKey.set_size(ssKey.size()); + } + Dbt datValue; + if (fFlags == DB_GET_BOTH || fFlags == DB_GET_BOTH_RANGE) + { + datValue.set_data(&ssValue[0]); + datValue.set_size(ssValue.size()); + } + datKey.set_flags(DB_DBT_MALLOC); + datValue.set_flags(DB_DBT_MALLOC); + int ret = pcursor->get(&datKey, &datValue, fFlags); + if (ret != 0) + return ret; + else if (datKey.get_data() == NULL || datValue.get_data() == NULL) + return 99999; + + // Convert to streams + ssKey.SetType(SER_DISK); + ssKey.clear(); + ssKey.write((char*)datKey.get_data(), datKey.get_size()); + ssValue.SetType(SER_DISK); + ssValue.clear(); + ssValue.write((char*)datValue.get_data(), datValue.get_size()); + + // Clear and free memory + memset(datKey.get_data(), 0, datKey.get_size()); + memset(datValue.get_data(), 0, datValue.get_size()); + free(datKey.get_data()); + free(datValue.get_data()); + return 0; + } + +public: + bool TxnBegin() + { + if (!pdb || activeTxn) + return false; + DbTxn* ptxn = bitdb.TxnBegin(); + if (!ptxn) + return false; + activeTxn = ptxn; + return true; + } + + bool TxnCommit() + { + if (!pdb || !activeTxn) + return false; + int ret = activeTxn->commit(0); + activeTxn = NULL; + return (ret == 0); + } + + bool TxnAbort() + { + if (!pdb || !activeTxn) + return false; + int ret = activeTxn->abort(); + activeTxn = NULL; + return (ret == 0); + } + + bool ReadVersion(int& nVersion) + { + nVersion = 0; + return Read(std::string("version"), nVersion); + } + + bool WriteVersion(int nVersion) + { + return Write(std::string("version"), nVersion); + } + + bool static Rewrite(const std::string& strFile, const char* pszSkip = NULL); +}; + + +/** Access to the (IP) address database (peers.dat) */ +class CAddrDB +{ +private: + boost::filesystem::path pathAddr; +public: + CAddrDB(); + bool Write(const CAddrMan& addr); + bool Read(CAddrMan& addr); +}; + +#endif // BITCOIN_DB_H diff --git a/src/init.cpp b/src/init.cpp new file mode 100644 index 0000000..088ce7a --- /dev/null +++ b/src/init.cpp @@ -0,0 +1,929 @@ +// Copyright (c) 2009-2010 Satoshi Nakamoto +// Copyright (c) 2009-2012 The Bitcoin developers +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. +#include "txdb.h" +#include "walletdb.h" +#include "bitcoinrpc.h" +#include "net.h" +#include "init.h" +#include "util.h" +#include "ui_interface.h" +#include "checkpoints.h" +#include "zerocoin/ZeroTest.h" +#include +#include +#include +#include +#include +#include + +#ifndef WIN32 +#include +#endif + + +using namespace std; +using namespace boost; + +CWallet* pwalletMain; +CClientUIInterface uiInterface; +bool fConfChange; +bool fEnforceCanonical; +unsigned int nNodeLifespan; +unsigned int nDerivationMethodIndex; +unsigned int nMinerSleep; +bool fUseFastIndex; +enum Checkpoints::CPMode CheckpointsMode; + +////////////////////////////////////////////////////////////////////////////// +// +// Shutdown +// + +void ExitTimeout(void* parg) +{ +#ifdef WIN32 + MilliSleep(5000); + ExitProcess(0); +#endif +} + +void StartShutdown() +{ +#ifdef QT_GUI + // ensure we leave the Qt main loop for a clean GUI exit (Shutdown() is called in bitcoin.cpp afterwards) + uiInterface.QueueShutdown(); +#else + // Without UI, Shutdown() can simply be started in a new thread + NewThread(Shutdown, NULL); +#endif +} + +void Shutdown(void* parg) +{ + static CCriticalSection cs_Shutdown; + static bool fTaken; + + // Make this thread recognisable as the shutdown thread + RenameThread("arepacoin-shutoff"); + + bool fFirstThread = false; + { + TRY_LOCK(cs_Shutdown, lockShutdown); + if (lockShutdown) + { + fFirstThread = !fTaken; + fTaken = true; + } + } + static bool fExit; + if (fFirstThread) + { + fShutdown = true; + nTransactionsUpdated++; +// CTxDB().Close(); + bitdb.Flush(false); + StopNode(); + bitdb.Flush(true); + boost::filesystem::remove(GetPidFile()); + UnregisterWallet(pwalletMain); + delete pwalletMain; + NewThread(ExitTimeout, NULL); + MilliSleep(50); + printf("arepacoin exited\n\n"); + fExit = true; +#ifndef QT_GUI + // ensure non-UI client gets exited here, but let Bitcoin-Qt reach 'return 0;' in bitcoin.cpp + exit(0); +#endif + } + else + { + while (!fExit) + MilliSleep(500); + MilliSleep(100); + ExitThread(0); + } +} + +void HandleSIGTERM(int) +{ + fRequestShutdown = true; +} + +void HandleSIGHUP(int) +{ + fReopenDebugLog = true; +} + + + + + +////////////////////////////////////////////////////////////////////////////// +// +// Start +// +#if !defined(QT_GUI) +bool AppInit(int argc, char* argv[]) +{ + bool fRet = false; + try + { + // + // Parameters + // + // If Qt is used, parameters/bitcoin.conf are parsed in qt/bitcoin.cpp's main() + ParseParameters(argc, argv); + if (!boost::filesystem::is_directory(GetDataDir(false))) + { + fprintf(stderr, "Error: Specified directory does not exist\n"); + Shutdown(NULL); + } + ReadConfigFile(mapArgs, mapMultiArgs); + + if (mapArgs.count("-?") || mapArgs.count("--help")) + { + // First part of help message is specific to bitcoind / RPC client + std::string strUsage = _("arepacoin version") + " " + FormatFullVersion() + "\n\n" + + _("Usage:") + "\n" + + " arepacoind [options] " + "\n" + + " arepacoind [options] [params] " + _("Send command to -server or arepacoind") + "\n" + + " arepacoind [options] help " + _("List commands") + "\n" + + " arepacoind [options] help " + _("Get help for a command") + "\n"; + + strUsage += "\n" + HelpMessage(); + + fprintf(stdout, "%s", strUsage.c_str()); + return false; + } + + // Command-line RPC + for (int i = 1; i < argc; i++) + if (!IsSwitchChar(argv[i][0]) && !boost::algorithm::istarts_with(argv[i], "arepacoin:")) + fCommandLine = true; + + if (fCommandLine) + { + int ret = CommandLineRPC(argc, argv); + exit(ret); + } + + fRet = AppInit2(); + } + catch (std::exception& e) { + PrintException(&e, "AppInit()"); + } catch (...) { + PrintException(NULL, "AppInit()"); + } + if (!fRet) + Shutdown(NULL); + return fRet; +} + +extern void noui_connect(); +int main(int argc, char* argv[]) +{ + bool fRet = false; + + // Connect bitcoind signal handlers + noui_connect(); + + fRet = AppInit(argc, argv); + + if (fRet && fDaemon) + return 0; + + return 1; +} +#endif + +bool static InitError(const std::string &str) +{ + uiInterface.ThreadSafeMessageBox(str, _("arepacoin"), CClientUIInterface::OK | CClientUIInterface::MODAL); + return false; +} + +bool static InitWarning(const std::string &str) +{ + uiInterface.ThreadSafeMessageBox(str, _("arepacoin"), CClientUIInterface::OK | CClientUIInterface::ICON_EXCLAMATION | CClientUIInterface::MODAL); + return true; +} + + +bool static Bind(const CService &addr, bool fError = true) { + if (IsLimited(addr)) + return false; + std::string strError; + if (!BindListenPort(addr, strError)) { + if (fError) + return InitError(strError); + return false; + } + return true; +} + +// Core-specific options shared between UI and daemon +std::string HelpMessage() +{ + string strUsage = _("Options:") + "\n" + + " -? " + _("This help message") + "\n" + + " -conf= " + _("Specify configuration file (default: arepacoin.conf)") + "\n" + + " -pid= " + _("Specify pid file (default: arepacoind.pid)") + "\n" + + " -datadir= " + _("Specify data directory") + "\n" + + " -wallet= " + _("Specify wallet file (within data directory)") + "\n" + + " -dbcache= " + _("Set database cache size in megabytes (default: 25)") + "\n" + + " -dblogsize= " + _("Set database disk log size in megabytes (default: 100)") + "\n" + + " -timeout= " + _("Specify connection timeout in milliseconds (default: 5000)") + "\n" + + " -proxy= " + _("Connect through socks proxy") + "\n" + + " -socks= " + _("Select the version of socks proxy to use (4-5, default: 5)") + "\n" + + " -tor= " + _("Use proxy to reach tor hidden services (default: same as -proxy)") + "\n" + " -dns " + _("Allow DNS lookups for -addnode, -seednode and -connect") + "\n" + + " -port= " + _("Listen for connections on (default: 8585 or testnet: 18585)") + "\n" + + " -maxconnections= " + _("Maintain at most connections to peers (default: 125)") + "\n" + + " -addnode= " + _("Add a node to connect to and attempt to keep the connection open") + "\n" + + " -connect= " + _("Connect only to the specified node(s)") + "\n" + + " -seednode= " + _("Connect to a node to retrieve peer addresses, and disconnect") + "\n" + + " -externalip= " + _("Specify your own public address") + "\n" + + " -onlynet= " + _("Only connect to nodes in network (IPv4, IPv6 or Tor)") + "\n" + + " -discover " + _("Discover own IP address (default: 1 when listening and no -externalip)") + "\n" + + " -irc " + _("Find peers using internet relay chat (default: 0)") + "\n" + + " -listen " + _("Accept connections from outside (default: 1 if no -proxy or -connect)") + "\n" + + " -bind= " + _("Bind to given address. Use [host]:port notation for IPv6") + "\n" + + " -dnsseed " + _("Find peers using DNS lookup (default: 1)") + "\n" + + " -staking " + _("Stake your coins to support network and gain reward (default: 1)") + "\n" + + " -synctime " + _("Sync time with other nodes. Disable if time on your system is precise e.g. syncing with NTP (default: 1)") + "\n" + + " -cppolicy " + _("Sync checkpoints policy (default: strict)") + "\n" + + " -banscore= " + _("Threshold for disconnecting misbehaving peers (default: 100)") + "\n" + + " -bantime= " + _("Number of seconds to keep misbehaving peers from reconnecting (default: 86400)") + "\n" + + " -maxreceivebuffer= " + _("Maximum per-connection receive buffer, *1000 bytes (default: 5000)") + "\n" + + " -maxsendbuffer= " + _("Maximum per-connection send buffer, *1000 bytes (default: 1000)") + "\n" + +#ifdef USE_UPNP +#if USE_UPNP + " -upnp " + _("Use UPnP to map the listening port (default: 1 when listening)") + "\n" + +#else + " -upnp " + _("Use UPnP to map the listening port (default: 0)") + "\n" + +#endif +#endif + " -paytxfee= " + _("Fee per KB to add to transactions you send") + "\n" + + " -mininput= " + _("When creating transactions, ignore inputs with value less than this (default: 0.01)") + "\n" + +#ifdef QT_GUI + " -server " + _("Accept command line and JSON-RPC commands") + "\n" + +#endif +#if !defined(WIN32) && !defined(QT_GUI) + " -daemon " + _("Run in the background as a daemon and accept commands") + "\n" + +#endif + " -testnet " + _("Use the test network") + "\n" + + " -debug " + _("Output extra debugging information. Implies all other -debug* options") + "\n" + + " -debugnet " + _("Output extra network debugging information") + "\n" + + " -logtimestamps " + _("Prepend debug output with timestamp") + "\n" + + " -shrinkdebugfile " + _("Shrink debug.log file on client startup (default: 1 when no -debug)") + "\n" + + " -printtoconsole " + _("Send trace/debug info to console instead of debug.log file") + "\n" + +#ifdef WIN32 + " -printtodebugger " + _("Send trace/debug info to debugger") + "\n" + +#endif + " -rpcuser= " + _("Username for JSON-RPC connections") + "\n" + + " -rpcpassword= " + _("Password for JSON-RPC connections") + "\n" + + " -rpcport= " + _("Listen for JSON-RPC connections on (default: 8586 or testnet: 18586)") + "\n" + + " -rpcallowip= " + _("Allow JSON-RPC connections from specified IP address") + "\n" + + " -rpcconnect= " + _("Send commands to node running on (default: 127.0.0.1)") + "\n" + + " -blocknotify= " + _("Execute command when the best block changes (%s in cmd is replaced by block hash)") + "\n" + + " -walletnotify= " + _("Execute command when a wallet transaction changes (%s in cmd is replaced by TxID)") + "\n" + + " -confchange " + _("Require a confirmations for change (default: 0)") + "\n" + + " -enforcecanonical " + _("Enforce transaction scripts to use canonical PUSH operators (default: 1)") + "\n" + + " -alertnotify= " + _("Execute command when a relevant alert is received (%s in cmd is replaced by message)") + "\n" + + " -upgradewallet " + _("Upgrade wallet to latest format") + "\n" + + " -keypool= " + _("Set key pool size to (default: 100)") + "\n" + + " -rescan " + _("Rescan the block chain for missing wallet transactions") + "\n" + + " -salvagewallet " + _("Attempt to recover private keys from a corrupt wallet.dat") + "\n" + + " -checkblocks= " + _("How many blocks to check at startup (default: 2500, 0 = all)") + "\n" + + " -checklevel= " + _("How thorough the block verification is (0-6, default: 1)") + "\n" + + " -loadblock= " + _("Imports blocks from external blk000?.dat file") + "\n" + + + "\n" + _("Block creation options:") + "\n" + + " -blockminsize= " + _("Set minimum block size in bytes (default: 0)") + "\n" + + " -blockmaxsize= " + _("Set maximum block size in bytes (default: 250000)") + "\n" + + " -blockprioritysize= " + _("Set maximum size of high-priority/low-fee transactions in bytes (default: 27000)") + "\n" + + + "\n" + _("SSL options: (see the Bitcoin Wiki for SSL setup instructions)") + "\n" + + " -rpcssl " + _("Use OpenSSL (https) for JSON-RPC connections") + "\n" + + " -rpcsslcertificatechainfile= " + _("Server certificate file (default: server.cert)") + "\n" + + " -rpcsslprivatekeyfile= " + _("Server private key (default: server.pem)") + "\n" + + " -rpcsslciphers= " + _("Acceptable ciphers (default: TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH)") + "\n"; + + return strUsage; +} + +/** Sanity checks + * Ensure that Bitcoin is running in a usable environment with all + * necessary library support. + */ +bool InitSanityCheck(void) +{ + if(!ECC_InitSanityCheck()) { + InitError("OpenSSL appears to lack support for elliptic curve cryptography. For more " + "information, visit https://en.bitcoin.it/wiki/OpenSSL_and_EC_Libraries"); + return false; + } + + // TODO: remaining sanity checks, see #4081 + + return true; +} + +/** Initialize bitcoin. + * @pre Parameters should be parsed and config file should be read. + */ +bool AppInit2() +{ + // ********************************************************* Step 1: setup +#ifdef _MSC_VER + // Turn off Microsoft heap dump noise + _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE); + _CrtSetReportFile(_CRT_WARN, CreateFileA("NUL", GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0)); +#endif +#if _MSC_VER >= 1400 + // Disable confusing "helpful" text message on abort, Ctrl-C + _set_abort_behavior(0, _WRITE_ABORT_MSG | _CALL_REPORTFAULT); +#endif +#ifdef WIN32 + // Enable Data Execution Prevention (DEP) + // Minimum supported OS versions: WinXP SP3, WinVista >= SP1, Win Server 2008 + // A failure is non-critical and needs no further attention! +#ifndef PROCESS_DEP_ENABLE +// We define this here, because GCCs winbase.h limits this to _WIN32_WINNT >= 0x0601 (Windows 7), +// which is not correct. Can be removed, when GCCs winbase.h is fixed! +#define PROCESS_DEP_ENABLE 0x00000001 +#endif + typedef BOOL (WINAPI *PSETPROCDEPPOL)(DWORD); + PSETPROCDEPPOL setProcDEPPol = (PSETPROCDEPPOL)GetProcAddress(GetModuleHandleA("Kernel32.dll"), "SetProcessDEPPolicy"); + if (setProcDEPPol != NULL) setProcDEPPol(PROCESS_DEP_ENABLE); +#endif +#ifndef WIN32 + umask(077); + + // Clean shutdown on SIGTERM + struct sigaction sa; + sa.sa_handler = HandleSIGTERM; + sigemptyset(&sa.sa_mask); + sa.sa_flags = 0; + sigaction(SIGTERM, &sa, NULL); + sigaction(SIGINT, &sa, NULL); + + // Reopen debug.log on SIGHUP + struct sigaction sa_hup; + sa_hup.sa_handler = HandleSIGHUP; + sigemptyset(&sa_hup.sa_mask); + sa_hup.sa_flags = 0; + sigaction(SIGHUP, &sa_hup, NULL); +#endif + + // ********************************************************* Step 2: parameter interactions + + nNodeLifespan = GetArg("-addrlifespan", 7); + fUseFastIndex = GetBoolArg("-fastindex", true); + nMinerSleep = GetArg("-minersleep", 500); + + CheckpointsMode = Checkpoints::STRICT; + std::string strCpMode = GetArg("-cppolicy", "strict"); + + if(strCpMode == "strict") + CheckpointsMode = Checkpoints::STRICT; + + if(strCpMode == "advisory") + CheckpointsMode = Checkpoints::ADVISORY; + + if(strCpMode == "permissive") + CheckpointsMode = Checkpoints::PERMISSIVE; + + nDerivationMethodIndex = 0; + + if (mapArgs.count("-bind")) { + // when specifying an explicit binding address, you want to listen on it + // even when -connect or -proxy is specified + SoftSetBoolArg("-listen", true); + } + + if (mapArgs.count("-connect") && mapMultiArgs["-connect"].size() > 0) { + // when only connecting to trusted nodes, do not seed via DNS, or listen by default + SoftSetBoolArg("-dnsseed", false); + SoftSetBoolArg("-listen", false); + } + + if (mapArgs.count("-proxy")) { + // to protect privacy, do not listen by default if a proxy server is specified + SoftSetBoolArg("-listen", false); + } + + if (!GetBoolArg("-listen", true)) { + // do not map ports or try to retrieve public IP when not listening (pointless) + SoftSetBoolArg("-upnp", false); + SoftSetBoolArg("-discover", false); + } + + if (mapArgs.count("-externalip")) { + // if an explicit public IP is specified, do not try to find others + SoftSetBoolArg("-discover", false); + } + + if (GetBoolArg("-salvagewallet")) { + // Rewrite just private keys: rescan to find transactions + SoftSetBoolArg("-rescan", true); + } + + // ********************************************************* Step 3: parameter-to-internal-flags + + fDebug = GetBoolArg("-debug"); + + // -debug implies fDebug* + if (fDebug) + fDebugNet = true; + else + fDebugNet = GetBoolArg("-debugnet"); + +#if !defined(WIN32) && !defined(QT_GUI) + fDaemon = GetBoolArg("-daemon"); +#else + fDaemon = false; +#endif + + if (fDaemon) + fServer = true; + else + fServer = GetBoolArg("-server"); + + /* force fServer when running without GUI */ +#if !defined(QT_GUI) + fServer = true; +#endif + fPrintToConsole = GetBoolArg("-printtoconsole"); + fPrintToDebugger = GetBoolArg("-printtodebugger"); + fLogTimestamps = GetBoolArg("-logtimestamps"); + + if (mapArgs.count("-timeout")) + { + int nNewTimeout = GetArg("-timeout", 5000); + if (nNewTimeout > 0 && nNewTimeout < 600000) + nConnectTimeout = nNewTimeout; + } + + if (mapArgs.count("-paytxfee")) + { + if (!ParseMoney(mapArgs["-paytxfee"], nTransactionFee)) + return InitError(strprintf(_("Invalid amount for -paytxfee=: '%s'"), mapArgs["-paytxfee"].c_str())); + if (nTransactionFee > 0.25 * COIN) + InitWarning(_("Warning: -paytxfee is set very high! This is the transaction fee you will pay if you send a transaction.")); + } + + fConfChange = GetBoolArg("-confchange", false); + fEnforceCanonical = GetBoolArg("-enforcecanonical", true); + + if (mapArgs.count("-mininput")) + { + if (!ParseMoney(mapArgs["-mininput"], nMinimumInputValue)) + return InitError(strprintf(_("Invalid amount for -mininput=: '%s'"), mapArgs["-mininput"].c_str())); + } + + // ********************************************************* Step 4: application initialization: dir lock, daemonize, pidfile, debug log + // Sanity check + if (!InitSanityCheck()) + return InitError(_("Initialization sanity check failed. arepacoin is shutting down.")); + + std::string strDataDir = GetDataDir().string(); + std::string strWalletFileName = GetArg("-wallet", "wallet.dat"); + + // strWalletFileName must be a plain filename without a directory + if (strWalletFileName != boost::filesystem::basename(strWalletFileName) + boost::filesystem::extension(strWalletFileName)) + return InitError(strprintf(_("Wallet %s resides outside data directory %s."), strWalletFileName.c_str(), strDataDir.c_str())); + + // Make sure only a single Bitcoin process is using the data directory. + boost::filesystem::path pathLockFile = GetDataDir() / ".lock"; + FILE* file = fopen(pathLockFile.string().c_str(), "a"); // empty lock file; created if it doesn't exist. + if (file) fclose(file); + static boost::interprocess::file_lock lock(pathLockFile.string().c_str()); + if (!lock.try_lock()) + return InitError(strprintf(_("Cannot obtain a lock on data directory %s. arepacoin is probably already running."), strDataDir.c_str())); + +#if !defined(WIN32) && !defined(QT_GUI) + if (fDaemon) + { + // Daemonize + pid_t pid = fork(); + if (pid < 0) + { + fprintf(stderr, "Error: fork() returned %d errno %d\n", pid, errno); + return false; + } + if (pid > 0) + { + CreatePidFile(GetPidFile(), pid); + return true; + } + + pid_t sid = setsid(); + if (sid < 0) + fprintf(stderr, "Error: setsid() returned %d errno %d\n", sid, errno); + } +#endif + + if (GetBoolArg("-shrinkdebugfile", !fDebug)) + ShrinkDebugFile(); + printf("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"); + printf("arepacoin version %s (%s)\n", FormatFullVersion().c_str(), CLIENT_DATE.c_str()); + printf("Using OpenSSL version %s\n", SSLeay_version(SSLEAY_VERSION)); + if (!fLogTimestamps) + printf("Startup time: %s\n", DateTimeStrFormat("%x %H:%M:%S", GetTime()).c_str()); + printf("Default data directory %s\n", GetDefaultDataDir().string().c_str()); + printf("Used data directory %s\n", strDataDir.c_str()); + std::ostringstream strErrors; + + if (fDaemon) + fprintf(stdout, "arepacoin server starting\n"); + + int64_t nStart; + + // ********************************************************* Step 5: verify database integrity + + uiInterface.InitMessage(_("Verifying database integrity...")); + + if (!bitdb.Open(GetDataDir())) + { + string msg = strprintf(_("Error initializing database environment %s!" + " To recover, BACKUP THAT DIRECTORY, then remove" + " everything from it except for wallet.dat."), strDataDir.c_str()); + return InitError(msg); + } + + if (GetBoolArg("-salvagewallet")) + { + // Recover readable keypairs: + if (!CWalletDB::Recover(bitdb, strWalletFileName, true)) + return false; + } + + if (filesystem::exists(GetDataDir() / strWalletFileName)) + { + CDBEnv::VerifyResult r = bitdb.Verify(strWalletFileName, CWalletDB::Recover); + if (r == CDBEnv::RECOVER_OK) + { + string msg = strprintf(_("Warning: wallet.dat corrupt, data salvaged!" + " Original wallet.dat saved as wallet.{timestamp}.bak in %s; if" + " your balance or transactions are incorrect you should" + " restore from a backup."), strDataDir.c_str()); + uiInterface.ThreadSafeMessageBox(msg, _("arepacoin"), CClientUIInterface::OK | CClientUIInterface::ICON_EXCLAMATION | CClientUIInterface::MODAL); + } + if (r == CDBEnv::RECOVER_FAIL) + return InitError(_("wallet.dat corrupt, salvage failed")); + } + + // ********************************************************* Step 6: network initialization + + int nSocksVersion = GetArg("-socks", 5); + + if (nSocksVersion != 4 && nSocksVersion != 5) + return InitError(strprintf(_("Unknown -socks proxy version requested: %i"), nSocksVersion)); + + if (mapArgs.count("-onlynet")) { + std::set nets; + BOOST_FOREACH(std::string snet, mapMultiArgs["-onlynet"]) { + enum Network net = ParseNetwork(snet); + if (net == NET_UNROUTABLE) + return InitError(strprintf(_("Unknown network specified in -onlynet: '%s'"), snet.c_str())); + nets.insert(net); + } + for (int n = 0; n < NET_MAX; n++) { + enum Network net = (enum Network)n; + if (!nets.count(net)) + SetLimited(net); + } + } + + CService addrProxy; + bool fProxy = false; + if (mapArgs.count("-proxy")) { + addrProxy = CService(mapArgs["-proxy"], 9050); + if (!addrProxy.IsValid()) + return InitError(strprintf(_("Invalid -proxy address: '%s'"), mapArgs["-proxy"].c_str())); + + if (!IsLimited(NET_IPV4)) + SetProxy(NET_IPV4, addrProxy, nSocksVersion); + if (nSocksVersion > 4) { + if (!IsLimited(NET_IPV6)) + SetProxy(NET_IPV6, addrProxy, nSocksVersion); + SetNameProxy(addrProxy, nSocksVersion); + } + fProxy = true; + } + + // -tor can override normal proxy, -notor disables tor entirely + if (!(mapArgs.count("-tor") && mapArgs["-tor"] == "0") && (fProxy || mapArgs.count("-tor"))) { + CService addrOnion; + if (!mapArgs.count("-tor")) + addrOnion = addrProxy; + else + addrOnion = CService(mapArgs["-tor"], 9050); + if (!addrOnion.IsValid()) + return InitError(strprintf(_("Invalid -tor address: '%s'"), mapArgs["-tor"].c_str())); + SetProxy(NET_TOR, addrOnion, 5); + SetReachable(NET_TOR); + } + + // see Step 2: parameter interactions for more information about these + fNoListen = !GetBoolArg("-listen", true); + fDiscover = GetBoolArg("-discover", true); + fNameLookup = GetBoolArg("-dns", true); +#ifdef USE_UPNP + fUseUPnP = GetBoolArg("-upnp", USE_UPNP); +#endif + + bool fBound = false; + if (!fNoListen) + { + std::string strError; + if (mapArgs.count("-bind")) { + BOOST_FOREACH(std::string strBind, mapMultiArgs["-bind"]) { + CService addrBind; + if (!Lookup(strBind.c_str(), addrBind, GetListenPort(), false)) + return InitError(strprintf(_("Cannot resolve -bind address: '%s'"), strBind.c_str())); + fBound |= Bind(addrBind); + } + } else { + struct in_addr inaddr_any; + inaddr_any.s_addr = INADDR_ANY; + if (!IsLimited(NET_IPV6)) + fBound |= Bind(CService(in6addr_any, GetListenPort()), false); + if (!IsLimited(NET_IPV4)) + fBound |= Bind(CService(inaddr_any, GetListenPort()), !fBound); + } + if (!fBound) + return InitError(_("Failed to listen on any port. Use -listen=0 if you want this.")); + } + + if (mapArgs.count("-externalip")) + { + BOOST_FOREACH(string strAddr, mapMultiArgs["-externalip"]) { + CService addrLocal(strAddr, GetListenPort(), fNameLookup); + if (!addrLocal.IsValid()) + return InitError(strprintf(_("Cannot resolve -externalip address: '%s'"), strAddr.c_str())); + AddLocal(CService(strAddr, GetListenPort(), fNameLookup), LOCAL_MANUAL); + } + } + + if (mapArgs.count("-reservebalance")) // ppcoin: reserve balance amount + { + if (!ParseMoney(mapArgs["-reservebalance"], nReserveBalance)) + { + InitError(_("Invalid amount for -reservebalance=")); + return false; + } + } + + if (mapArgs.count("-checkpointkey")) // ppcoin: checkpoint master priv key + { + if (!Checkpoints::SetCheckpointPrivKey(GetArg("-checkpointkey", ""))) + InitError(_("Unable to sign checkpoint, wrong checkpointkey?\n")); + } + + BOOST_FOREACH(string strDest, mapMultiArgs["-seednode"]) + AddOneShot(strDest); + + // ********************************************************* Step 7: load blockchain + + if (!bitdb.Open(GetDataDir())) + { + string msg = strprintf(_("Error initializing database environment %s!" + " To recover, BACKUP THAT DIRECTORY, then remove" + " everything from it except for wallet.dat."), strDataDir.c_str()); + return InitError(msg); + } + + if (GetBoolArg("-loadblockindextest")) + { + CTxDB txdb("r"); + txdb.LoadBlockIndex(); + PrintBlockTree(); + return false; + } + + uiInterface.InitMessage(_("Loading block index...")); + printf("Loading block index...\n"); + nStart = GetTimeMillis(); + if (!LoadBlockIndex()) + return InitError(_("Error loading blkindex.dat")); + + + // as LoadBlockIndex can take several minutes, it's possible the user + // requested to kill bitcoin-qt during the last operation. If so, exit. + // As the program has not fully started yet, Shutdown() is possibly overkill. + if (fRequestShutdown) + { + printf("Shutdown requested. Exiting.\n"); + return false; + } + printf(" block index %15" PRId64"ms\n", GetTimeMillis() - nStart); + + if (GetBoolArg("-printblockindex") || GetBoolArg("-printblocktree")) + { + PrintBlockTree(); + return false; + } + + if (mapArgs.count("-printblock")) + { + string strMatch = mapArgs["-printblock"]; + int nFound = 0; + for (map::iterator mi = mapBlockIndex.begin(); mi != mapBlockIndex.end(); ++mi) + { + uint256 hash = (*mi).first; + if (strncmp(hash.ToString().c_str(), strMatch.c_str(), strMatch.size()) == 0) + { + CBlockIndex* pindex = (*mi).second; + CBlock block; + block.ReadFromDisk(pindex); + block.BuildMerkleTree(); + block.print(); + printf("\n"); + nFound++; + } + } + if (nFound == 0) + printf("No blocks matching %s were found\n", strMatch.c_str()); + return false; + } + + // ********************************************************* Testing Zerocoin + + + if (GetBoolArg("-zerotest", false)) + { + printf("\n=== ZeroCoin tests start ===\n"); + Test_RunAllTests(); + printf("=== ZeroCoin tests end ===\n\n"); + } + + // ********************************************************* Step 8: load wallet + + uiInterface.InitMessage(_("Loading wallet...")); + printf("Loading wallet...\n"); + nStart = GetTimeMillis(); + bool fFirstRun = true; + pwalletMain = new CWallet(strWalletFileName); + DBErrors nLoadWalletRet = pwalletMain->LoadWallet(fFirstRun); + if (nLoadWalletRet != DB_LOAD_OK) + { + if (nLoadWalletRet == DB_CORRUPT) + strErrors << _("Error loading wallet.dat: Wallet corrupted") << "\n"; + else if (nLoadWalletRet == DB_NONCRITICAL_ERROR) + { + string msg(_("Warning: error reading wallet.dat! All keys read correctly, but transaction data" + " or address book entries might be missing or incorrect.")); + uiInterface.ThreadSafeMessageBox(msg, _("arepacoin"), CClientUIInterface::OK | CClientUIInterface::ICON_EXCLAMATION | CClientUIInterface::MODAL); + } + else if (nLoadWalletRet == DB_TOO_NEW) + strErrors << _("Error loading wallet.dat: Wallet requires newer version of arepacoin") << "\n"; + else if (nLoadWalletRet == DB_NEED_REWRITE) + { + strErrors << _("Wallet needed to be rewritten: restart arepacoin to complete") << "\n"; + printf("%s", strErrors.str().c_str()); + return InitError(strErrors.str()); + } + else + strErrors << _("Error loading wallet.dat") << "\n"; + } + + if (GetBoolArg("-upgradewallet", fFirstRun)) + { + int nMaxVersion = GetArg("-upgradewallet", 0); + if (nMaxVersion == 0) // the -upgradewallet without argument case + { + printf("Performing wallet upgrade to %i\n", FEATURE_LATEST); + nMaxVersion = CLIENT_VERSION; + pwalletMain->SetMinVersion(FEATURE_LATEST); // permanently upgrade the wallet immediately + } + else + printf("Allowing wallet upgrade up to %i\n", nMaxVersion); + if (nMaxVersion < pwalletMain->GetVersion()) + strErrors << _("Cannot downgrade wallet") << "\n"; + pwalletMain->SetMaxVersion(nMaxVersion); + } + + if (fFirstRun) + { + // Create new keyUser and set as default key + RandAddSeedPerfmon(); + + CPubKey newDefaultKey; + if (pwalletMain->GetKeyFromPool(newDefaultKey, false)) { + pwalletMain->SetDefaultKey(newDefaultKey); + if (!pwalletMain->SetAddressBookName(pwalletMain->vchDefaultKey.GetID(), "")) + strErrors << _("Cannot write default address") << "\n"; + } + } + + printf("%s", strErrors.str().c_str()); + printf(" wallet %15" PRId64"ms\n", GetTimeMillis() - nStart); + + RegisterWallet(pwalletMain); + + CBlockIndex *pindexRescan = pindexBest; + if (GetBoolArg("-rescan")) + pindexRescan = pindexGenesisBlock; + else + { + CWalletDB walletdb(strWalletFileName); + CBlockLocator locator; + if (walletdb.ReadBestBlock(locator)) + pindexRescan = locator.GetBlockIndex(); + } + if (pindexBest != pindexRescan && pindexBest && pindexRescan && pindexBest->nHeight > pindexRescan->nHeight) + { + uiInterface.InitMessage(_("Rescanning...")); + printf("Rescanning last %i blocks (from block %i)...\n", pindexBest->nHeight - pindexRescan->nHeight, pindexRescan->nHeight); + nStart = GetTimeMillis(); + pwalletMain->ScanForWalletTransactions(pindexRescan, true); + printf(" rescan %15" PRId64"ms\n", GetTimeMillis() - nStart); + } + + // ********************************************************* Step 9: import blocks + + if (mapArgs.count("-loadblock")) + { + uiInterface.InitMessage(_("Importing blockchain data file.")); + + BOOST_FOREACH(string strFile, mapMultiArgs["-loadblock"]) + { + FILE *file = fopen(strFile.c_str(), "rb"); + if (file) + LoadExternalBlockFile(file); + } + exit(0); + } + + filesystem::path pathBootstrap = GetDataDir() / "bootstrap.dat"; + if (filesystem::exists(pathBootstrap)) { + uiInterface.InitMessage(_("Importing bootstrap blockchain data file.")); + + FILE *file = fopen(pathBootstrap.string().c_str(), "rb"); + if (file) { + filesystem::path pathBootstrapOld = GetDataDir() / "bootstrap.dat.old"; + LoadExternalBlockFile(file); + RenameOver(pathBootstrap, pathBootstrapOld); + } + } + + // ********************************************************* Step 10: load peers + + uiInterface.InitMessage(_("Loading addresses...")); + printf("Loading addresses...\n"); + nStart = GetTimeMillis(); + + { + CAddrDB adb; + if (!adb.Read(addrman)) + printf("Invalid or missing peers.dat; recreating\n"); + } + + printf("Loaded %i addresses from peers.dat %" PRId64"ms\n", + addrman.size(), GetTimeMillis() - nStart); + + // ********************************************************* Step 11: start node + + if (!CheckDiskSpace()) + return false; + + RandAddSeedPerfmon(); + + //// debug print + printf("mapBlockIndex.size() = %" PRIszu"\n", mapBlockIndex.size()); + printf("nBestHeight = %d\n", nBestHeight); + printf("setKeyPool.size() = %" PRIszu"\n", pwalletMain->setKeyPool.size()); + printf("mapWallet.size() = %" PRIszu"\n", pwalletMain->mapWallet.size()); + printf("mapAddressBook.size() = %" PRIszu"\n", pwalletMain->mapAddressBook.size()); + + if (!NewThread(StartNode, NULL)) + InitError(_("Error: could not start node")); + + if (fServer) + NewThread(ThreadRPCServer, NULL); + + // ********************************************************* Step 12: finished + + uiInterface.InitMessage(_("Done loading")); + printf("Done loading\n"); + + if (!strErrors.str().empty()) + return InitError(strErrors.str()); + + // Add wallet transactions that aren't already in a block to mapTransactions + pwalletMain->ReacceptWalletTransactions(); + +#if !defined(QT_GUI) + // Loop until process is exit()ed from shutdown() function, + // called from ThreadRPCServer thread when a "stop" command is received. + while (1) + MilliSleep(5000); +#endif + + return true; +} diff --git a/src/init.h b/src/init.h new file mode 100644 index 0000000..7a17622 --- /dev/null +++ b/src/init.h @@ -0,0 +1,16 @@ +// Copyright (c) 2009-2010 Satoshi Nakamoto +// Copyright (c) 2009-2012 The Bitcoin developers +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. +#ifndef BITCOIN_INIT_H +#define BITCOIN_INIT_H + +#include "wallet.h" + +extern CWallet* pwalletMain; +void StartShutdown(); +void Shutdown(void* parg); +bool AppInit2(); +std::string HelpMessage(); + +#endif diff --git a/src/json/LICENSE.txt b/src/json/LICENSE.txt new file mode 100644 index 0000000..797d536 --- /dev/null +++ b/src/json/LICENSE.txt @@ -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. diff --git a/src/json/json_spirit.h b/src/json/json_spirit.h new file mode 100644 index 0000000..ac1879d --- /dev/null +++ b/src/json/json_spirit.h @@ -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 diff --git a/src/json/json_spirit_error_position.h b/src/json/json_spirit_error_position.h new file mode 100644 index 0000000..1720850 --- /dev/null +++ b/src/json/json_spirit_error_position.h @@ -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 + +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 diff --git a/src/json/json_spirit_reader.cpp b/src/json/json_spirit_reader.cpp new file mode 100644 index 0000000..aa4f637 --- /dev/null +++ b/src/json/json_spirit_reader.cpp @@ -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 diff --git a/src/json/json_spirit_reader.h b/src/json/json_spirit_reader.h new file mode 100644 index 0000000..96494a9 --- /dev/null +++ b/src/json/json_spirit_reader.h @@ -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 + +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 diff --git a/src/json/json_spirit_reader_template.h b/src/json/json_spirit_reader_template.h new file mode 100644 index 0000000..46f5892 --- /dev/null +++ b/src/json/json_spirit_reader_template.h @@ -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 +#include +#include + +#if BOOST_VERSION >= 103800 + #include + #include + #include + #include + #include + #define spirit_namespace boost::spirit::classic +#else + #include + #include + #include + #include + #include + #define spirit_namespace boost::spirit +#endif + +namespace json_spirit +{ + const spirit_namespace::int_parser < int64_t > int64_p = spirit_namespace::int_parser < int64_t >(); + const spirit_namespace::uint_parser< uint64_t > uint64_p = spirit_namespace::uint_parser< 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( int64_t i ) + { + add_to_current( i ); + } + + void new_uint64( 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 ¤t_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( int64_t ) > Int_action; + typedef boost::function< void( 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 diff --git a/src/json/json_spirit_stream_reader.h b/src/json/json_spirit_stream_reader.h new file mode 100644 index 0000000..7e59c9a --- /dev/null +++ b/src/json/json_spirit_stream_reader.h @@ -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 diff --git a/src/json/json_spirit_utils.h b/src/json/json_spirit_utils.h new file mode 100644 index 0000000..553e3b9 --- /dev/null +++ b/src/json/json_spirit_utils.h @@ -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 + +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 diff --git a/src/json/json_spirit_value.cpp b/src/json/json_spirit_value.cpp new file mode 100644 index 0000000..44d2f06 --- /dev/null +++ b/src/json/json_spirit_value.cpp @@ -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" diff --git a/src/json/json_spirit_value.h b/src/json/json_spirit_value.h new file mode 100644 index 0000000..13cc892 --- /dev/null +++ b/src/json/json_spirit_value.h @@ -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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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( int64_t value ); + Value_impl( 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; + int64_t get_int64() const; + 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, 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< int64_t >( value ) ) + , is_uint64_( false ) + { + } + + template< class Config > + Value_impl< Config >::Value_impl( int64_t value ) + : type_( int_type ) + , v_( value ) + , is_uint64_( false ) + { + } + + template< class Config > + Value_impl< Config >::Value_impl( uint64_t value ) + : type_( int_type ) + , v_( static_cast< 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; + + ///// Bitcoin: 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 > + int64_t Value_impl< Config >::get_int64() const + { + check_type( int_type ); + + return boost::get< int64_t >( v_ ); + } + + template< class Config > + uint64_t Value_impl< Config >::get_uint64() const + { + check_type( int_type ); + + return static_cast< 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 > + int64_t get_value( const Value& value, Type_to_type< int64_t > ) + { + return value.get_int64(); + } + + template< class Value > + uint64_t get_value( const Value& value, Type_to_type< 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 diff --git a/src/json/json_spirit_writer.cpp b/src/json/json_spirit_writer.cpp new file mode 100644 index 0000000..d24a632 --- /dev/null +++ b/src/json/json_spirit_writer.cpp @@ -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 diff --git a/src/json/json_spirit_writer.h b/src/json/json_spirit_writer.h new file mode 100644 index 0000000..52e1406 --- /dev/null +++ b/src/json/json_spirit_writer.h @@ -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 + +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 diff --git a/src/json/json_spirit_writer_template.h b/src/json/json_spirit_writer_template.h new file mode 100644 index 0000000..6725810 --- /dev/null +++ b/src/json/json_spirit_writer_template.h @@ -0,0 +1,248 @@ +#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 +#include +#include + +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; + + /// Bitcoin: Added std::fixed and changed precision from 16 to 8 + case real_type: os_ << std::showpoint << std::fixed << std::setprecision(8) + << 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 diff --git a/src/kernel.cpp b/src/kernel.cpp new file mode 100644 index 0000000..7dd55ef --- /dev/null +++ b/src/kernel.cpp @@ -0,0 +1,394 @@ +// Copyright (c) 2012-2013 The PPCoin developers +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include + +#include "kernel.h" +#include "txdb.h" + +using namespace std; + +typedef std::map MapModifierCheckpoints; + +// Hard checkpoints of stake modifiers to ensure they are deterministic +static std::map mapStakeModifierCheckpoints = + boost::assign::map_list_of + ( 0, 0xfd11f4e7 ) + ( 1327, 0xcc08815a ) + ( 7658, 0x242480af ) + ( 51273, 0x02ace671 ) + ( 251966, 0x75195b20 ) + ( 748132, 0x1ade5f52 ) + ( 975864, 0xab755b9c ) + ( 1204080, 0x0ad237f7 ) + ; + +// Hard checkpoints of stake modifiers to ensure they are deterministic (testNet) +static std::map mapStakeModifierCheckpointsTestNet = + boost::assign::map_list_of + ( 0, 0xfd11f4e7 ) + ; + +// Get time weight +int64_t GetWeight(int64_t nIntervalBeginning, int64_t nIntervalEnd) +{ + // Kernel hash weight starts from 0 at the min age + // this change increases active coins participating the hash and helps + // to secure the network when proof-of-stake difficulty is low + + return min(nIntervalEnd - nIntervalBeginning - nStakeMinAge, (int64_t)nStakeMaxAge); +} + +// Get the last stake modifier and its generation time from a given block +static bool GetLastStakeModifier(const CBlockIndex* pindex, uint64_t& nStakeModifier, int64_t& nModifierTime) +{ + if (!pindex) + return error("GetLastStakeModifier: null pindex"); + while (pindex && pindex->pprev && !pindex->GeneratedStakeModifier()) + pindex = pindex->pprev; + if (!pindex->GeneratedStakeModifier()) + return error("GetLastStakeModifier: no generation at genesis block"); + nStakeModifier = pindex->nStakeModifier; + nModifierTime = pindex->GetBlockTime(); + return true; +} + +// Get selection interval section (in seconds) +static int64_t GetStakeModifierSelectionIntervalSection(int nSection) +{ + assert (nSection >= 0 && nSection < 64); + return (nModifierInterval * 63 / (63 + ((63 - nSection) * (MODIFIER_INTERVAL_RATIO - 1)))); +} + +// Get stake modifier selection interval (in seconds) +static int64_t GetStakeModifierSelectionInterval() +{ + int64_t nSelectionInterval = 0; + for (int nSection=0; nSection<64; nSection++) + nSelectionInterval += GetStakeModifierSelectionIntervalSection(nSection); + return nSelectionInterval; +} + +// select a block from the candidate blocks in vSortedByTimestamp, excluding +// already selected blocks in vSelectedBlocks, and with timestamp up to +// nSelectionIntervalStop. +static bool SelectBlockFromCandidates(vector >& vSortedByTimestamp, map& mapSelectedBlocks, + int64_t nSelectionIntervalStop, uint64_t nStakeModifierPrev, const CBlockIndex** pindexSelected) +{ + bool fSelected = false; + uint256 hashBest = 0; + *pindexSelected = (const CBlockIndex*) 0; + BOOST_FOREACH(const PAIRTYPE(int64_t, uint256)& item, vSortedByTimestamp) + { + if (!mapBlockIndex.count(item.second)) + return error("SelectBlockFromCandidates: failed to find block index for candidate block %s", item.second.ToString().c_str()); + const CBlockIndex* pindex = mapBlockIndex[item.second]; + if (fSelected && pindex->GetBlockTime() > nSelectionIntervalStop) + break; + if (mapSelectedBlocks.count(pindex->GetBlockHash()) > 0) + continue; + // compute the selection hash by hashing its proof-hash and the + // previous proof-of-stake modifier + CDataStream ss(SER_GETHASH, 0); + ss << pindex->hashProof << nStakeModifierPrev; + uint256 hashSelection = Hash(ss.begin(), ss.end()); + // the selection hash is divided by 2**32 so that proof-of-stake block + // is always favored over proof-of-work block. this is to preserve + // the energy efficiency property + if (pindex->IsProofOfStake()) + hashSelection >>= 32; + if (fSelected && hashSelection < hashBest) + { + hashBest = hashSelection; + *pindexSelected = (const CBlockIndex*) pindex; + } + else if (!fSelected) + { + fSelected = true; + hashBest = hashSelection; + *pindexSelected = (const CBlockIndex*) pindex; + } + } + if (fDebug && GetBoolArg("-printstakemodifier")) + printf("SelectBlockFromCandidates: selection hash=%s\n", hashBest.ToString().c_str()); + return fSelected; +} + +// Stake Modifier (hash modifier of proof-of-stake): +// The purpose of stake modifier is to prevent a txout (coin) owner from +// computing future proof-of-stake generated by this txout at the time +// of transaction confirmation. To meet kernel protocol, the txout +// must hash with a future stake modifier to generate the proof. +// Stake modifier consists of bits each of which is contributed from a +// selected block of a given block group in the past. +// The selection of a block is based on a hash of the block's proof-hash and +// the previous stake modifier. +// Stake modifier is recomputed at a fixed time interval instead of every +// block. This is to make it difficult for an attacker to gain control of +// additional bits in the stake modifier, even after generating a chain of +// blocks. +bool ComputeNextStakeModifier(const CBlockIndex* pindexPrev, uint64_t& nStakeModifier, bool& fGeneratedStakeModifier) +{ + nStakeModifier = 0; + fGeneratedStakeModifier = false; + if (!pindexPrev) + { + fGeneratedStakeModifier = true; + return true; // genesis block's modifier is 0 + } + // First find current stake modifier and its generation block time + // if it's not old enough, return the same stake modifier + int64_t nModifierTime = 0; + if (!GetLastStakeModifier(pindexPrev, nStakeModifier, nModifierTime)) + return error("ComputeNextStakeModifier: unable to get last modifier"); + if (fDebug) + { + printf("ComputeNextStakeModifier: prev modifier=0x%016" PRIx64" time=%s\n", nStakeModifier, DateTimeStrFormat(nModifierTime).c_str()); + } + if (nModifierTime / nModifierInterval >= pindexPrev->GetBlockTime() / nModifierInterval) + return true; + + // Sort candidate blocks by timestamp + vector > vSortedByTimestamp; + vSortedByTimestamp.reserve(64 * nModifierInterval / nTargetSpacing); + int64_t nSelectionInterval = GetStakeModifierSelectionInterval(); + int64_t nSelectionIntervalStart = (pindexPrev->GetBlockTime() / nModifierInterval) * nModifierInterval - nSelectionInterval; + const CBlockIndex* pindex = pindexPrev; + while (pindex && pindex->GetBlockTime() >= nSelectionIntervalStart) + { + vSortedByTimestamp.push_back(make_pair(pindex->GetBlockTime(), pindex->GetBlockHash())); + pindex = pindex->pprev; + } + int nHeightFirstCandidate = pindex ? (pindex->nHeight + 1) : 0; + reverse(vSortedByTimestamp.begin(), vSortedByTimestamp.end()); + sort(vSortedByTimestamp.begin(), vSortedByTimestamp.end()); + + // Select 64 blocks from candidate blocks to generate stake modifier + uint64_t nStakeModifierNew = 0; + int64_t nSelectionIntervalStop = nSelectionIntervalStart; + map mapSelectedBlocks; + for (int nRound=0; nRoundGetStakeEntropyBit()) << nRound); + // add the selected block from candidates to selected list + mapSelectedBlocks.insert(make_pair(pindex->GetBlockHash(), pindex)); + if (fDebug && GetBoolArg("-printstakemodifier")) + printf("ComputeNextStakeModifier: selected round %d stop=%s height=%d bit=%d\n", nRound, DateTimeStrFormat(nSelectionIntervalStop).c_str(), pindex->nHeight, pindex->GetStakeEntropyBit()); + } + + // Print selection map for visualization of the selected blocks + if (fDebug && GetBoolArg("-printstakemodifier")) + { + string strSelectionMap = ""; + // '-' indicates proof-of-work blocks not selected + strSelectionMap.insert(0, pindexPrev->nHeight - nHeightFirstCandidate + 1, '-'); + pindex = pindexPrev; + while (pindex && pindex->nHeight >= nHeightFirstCandidate) + { + // '=' indicates proof-of-stake blocks not selected + if (pindex->IsProofOfStake()) + strSelectionMap.replace(pindex->nHeight - nHeightFirstCandidate, 1, "="); + pindex = pindex->pprev; + } + BOOST_FOREACH(const PAIRTYPE(uint256, const CBlockIndex*)& item, mapSelectedBlocks) + { + // 'S' indicates selected proof-of-stake blocks + // 'W' indicates selected proof-of-work blocks + strSelectionMap.replace(item.second->nHeight - nHeightFirstCandidate, 1, item.second->IsProofOfStake()? "S" : "W"); + } + printf("ComputeNextStakeModifier: selection height [%d, %d] map %s\n", nHeightFirstCandidate, pindexPrev->nHeight, strSelectionMap.c_str()); + } + if (fDebug) + { + printf("ComputeNextStakeModifier: new modifier=0x%016" PRIx64" time=%s\n", nStakeModifierNew, DateTimeStrFormat(pindexPrev->GetBlockTime()).c_str()); + } + + nStakeModifier = nStakeModifierNew; + fGeneratedStakeModifier = true; + return true; +} + +// The stake modifier used to hash for a stake kernel is chosen as the stake +// modifier about a selection interval later than the coin generating the kernel +static bool GetKernelStakeModifier(uint256 hashBlockFrom, uint64_t& nStakeModifier, int& nStakeModifierHeight, int64_t& nStakeModifierTime, bool fPrintProofOfStake) +{ + nStakeModifier = 0; + if (!mapBlockIndex.count(hashBlockFrom)) + return error("GetKernelStakeModifier() : block not indexed"); + const CBlockIndex* pindexFrom = mapBlockIndex[hashBlockFrom]; + nStakeModifierHeight = pindexFrom->nHeight; + nStakeModifierTime = pindexFrom->GetBlockTime(); + int64_t nStakeModifierSelectionInterval = GetStakeModifierSelectionInterval(); + const CBlockIndex* pindex = pindexFrom; + // loop to find the stake modifier later by a selection interval + while (nStakeModifierTime < pindexFrom->GetBlockTime() + nStakeModifierSelectionInterval) + { + if (!pindex->pnext) + { // reached best block; may happen if node is behind on block chain + if (fPrintProofOfStake || (pindex->GetBlockTime() + nStakeMinAge - nStakeModifierSelectionInterval > GetAdjustedTime())) + return error("GetKernelStakeModifier() : reached best block %s at height %d from block %s", + pindex->GetBlockHash().ToString().c_str(), pindex->nHeight, hashBlockFrom.ToString().c_str()); + else + return false; + } + pindex = pindex->pnext; + if (pindex->GeneratedStakeModifier()) + { + nStakeModifierHeight = pindex->nHeight; + nStakeModifierTime = pindex->GetBlockTime(); + } + } + nStakeModifier = pindex->nStakeModifier; + return true; +} + +// ppcoin kernel protocol +// coinstake must meet hash target according to the protocol: +// kernel (input 0) must meet the formula +// hash(nStakeModifier + txPrev.block.nTime + txPrev.offset + txPrev.nTime + txPrev.vout.n + nTime) < bnTarget * nCoinDayWeight +// this ensures that the chance of getting a coinstake is proportional to the +// amount of coin age one owns. +// The reason this hash is chosen is the following: +// nStakeModifier: scrambles computation to make it very difficult to precompute +// future proof-of-stake at the time of the coin's confirmation +// txPrev.block.nTime: prevent nodes from guessing a good timestamp to +// generate transaction for future advantage +// txPrev.offset: offset of txPrev inside block, to reduce the chance of +// nodes generating coinstake at the same time +// txPrev.nTime: reduce the chance of nodes generating coinstake at the same +// time +// txPrev.vout.n: output number of txPrev, to reduce the chance of nodes +// generating coinstake at the same time +// block/tx hash should not be used here as they can be generated in vast +// quantities so as to generate blocks faster, degrading the system back into +// a proof-of-work situation. +// +bool CheckStakeKernelHash(unsigned int nBits, const CBlock& blockFrom, unsigned int nTxPrevOffset, const CTransaction& txPrev, const COutPoint& prevout, unsigned int nTimeTx, uint256& hashProofOfStake, uint256& targetProofOfStake, bool fPrintProofOfStake) +{ + if (nTimeTx < txPrev.nTime) // Transaction timestamp violation + return error("CheckStakeKernelHash() : nTime violation"); + + unsigned int nTimeBlockFrom = blockFrom.GetBlockTime(); + if (nTimeBlockFrom + nStakeMinAge > nTimeTx) // Min age requirement + return error("CheckStakeKernelHash() : min age violation"); + + CBigNum bnTargetPerCoinDay; + bnTargetPerCoinDay.SetCompact(nBits); + int64_t nValueIn = txPrev.vout[prevout.n].nValue; + + uint256 hashBlockFrom = blockFrom.GetHash(); + + CBigNum bnCoinDayWeight = CBigNum(nValueIn) * GetWeight((int64_t)txPrev.nTime, (int64_t)nTimeTx) / COIN / (24 * 60 * 60); + targetProofOfStake = (bnCoinDayWeight * bnTargetPerCoinDay).getuint256(); + + // Calculate hash + CDataStream ss(SER_GETHASH, 0); + uint64_t nStakeModifier = 0; + int nStakeModifierHeight = 0; + int64_t nStakeModifierTime = 0; + + if (!GetKernelStakeModifier(hashBlockFrom, nStakeModifier, nStakeModifierHeight, nStakeModifierTime, fPrintProofOfStake)) + return false; + ss << nStakeModifier; + + ss << nTimeBlockFrom << nTxPrevOffset << txPrev.nTime << prevout.n << nTimeTx; + hashProofOfStake = Hash(ss.begin(), ss.end()); + if (fPrintProofOfStake) + { + printf("CheckStakeKernelHash() : using modifier 0x%016" PRIx64" at height=%d timestamp=%s for block from height=%d timestamp=%s\n", + nStakeModifier, nStakeModifierHeight, + DateTimeStrFormat(nStakeModifierTime).c_str(), + mapBlockIndex[hashBlockFrom]->nHeight, + DateTimeStrFormat(blockFrom.GetBlockTime()).c_str()); + printf("CheckStakeKernelHash() : check modifier=0x%016" PRIx64" nTimeBlockFrom=%u nTxPrevOffset=%u nTimeTxPrev=%u nPrevout=%u nTimeTx=%u hashProof=%s\n", + nStakeModifier, + nTimeBlockFrom, nTxPrevOffset, txPrev.nTime, prevout.n, nTimeTx, + hashProofOfStake.ToString().c_str()); + } + + // Now check if proof-of-stake hash meets target protocol + if (CBigNum(hashProofOfStake) > bnCoinDayWeight * bnTargetPerCoinDay) + return false; + if (fDebug && !fPrintProofOfStake) + { + printf("CheckStakeKernelHash() : using modifier 0x%016" PRIx64" at height=%d timestamp=%s for block from height=%d timestamp=%s\n", + nStakeModifier, nStakeModifierHeight, + DateTimeStrFormat(nStakeModifierTime).c_str(), + mapBlockIndex[hashBlockFrom]->nHeight, + DateTimeStrFormat(blockFrom.GetBlockTime()).c_str()); + printf("CheckStakeKernelHash() : pass modifier=0x%016" PRIx64" nTimeBlockFrom=%u nTxPrevOffset=%u nTimeTxPrev=%u nPrevout=%u nTimeTx=%u hashProof=%s\n", + nStakeModifier, + nTimeBlockFrom, nTxPrevOffset, txPrev.nTime, prevout.n, nTimeTx, + hashProofOfStake.ToString().c_str()); + } + return true; +} + +// Check kernel hash target and coinstake signature +bool CheckProofOfStake(const CTransaction& tx, unsigned int nBits, uint256& hashProofOfStake, uint256& targetProofOfStake) +{ + if (!tx.IsCoinStake()) + return error("CheckProofOfStake() : called on non-coinstake %s", tx.GetHash().ToString().c_str()); + + // Kernel (input 0) must match the stake hash target per coin age (nBits) + const CTxIn& txin = tx.vin[0]; + + // First try finding the previous transaction in database + CTxDB txdb("r"); + CTransaction txPrev; + CTxIndex txindex; + if (!txPrev.ReadFromDisk(txdb, txin.prevout, txindex)) + return tx.DoS(1, error("CheckProofOfStake() : INFO: read txPrev failed")); // previous transaction not in main chain, may occur during initial download + + // Verify signature + if (!VerifySignature(txPrev, tx, 0, 0)) + return tx.DoS(100, error("CheckProofOfStake() : VerifySignature failed on coinstake %s", tx.GetHash().ToString().c_str())); + + // Read block header + CBlock block; + if (!block.ReadFromDisk(txindex.pos.nFile, txindex.pos.nBlockPos, false)) + return fDebug? error("CheckProofOfStake() : read block failed") : false; // unable to read block of previous transaction + + if (!CheckStakeKernelHash(nBits, block, txindex.pos.nTxPos - txindex.pos.nBlockPos, txPrev, txin.prevout, tx.nTime, hashProofOfStake, targetProofOfStake, fDebug)) + return tx.DoS(1, error("CheckProofOfStake() : INFO: check kernel failed on coinstake %s, hashProof=%s", tx.GetHash().ToString().c_str(), hashProofOfStake.ToString().c_str())); // may occur during initial download or if behind on block chain sync + + return true; +} + +// Check whether the coinstake timestamp meets protocol +bool CheckCoinStakeTimestamp(int64_t nTimeBlock, int64_t nTimeTx) +{ + // v0.3 protocol + return (nTimeBlock == nTimeTx); +} + +// Get stake modifier checksum +unsigned int GetStakeModifierChecksum(const CBlockIndex* pindex) +{ + assert (pindex->pprev || pindex->GetBlockHash() == (!fTestNet ? hashGenesisBlock : hashGenesisBlockTestNet)); + // Hash previous checksum with flags, hashProofOfStake and nStakeModifier + CDataStream ss(SER_GETHASH, 0); + if (pindex->pprev) + ss << pindex->pprev->nStakeModifierChecksum; + ss << pindex->nFlags << (pindex->IsProofOfStake() ? pindex->hashProof : 0) << pindex->nStakeModifier; + uint256 hashChecksum = Hash(ss.begin(), ss.end()); + hashChecksum >>= (256 - 32); + return hashChecksum.Get64(); +} + +// Check stake modifier hard checkpoints +bool CheckStakeModifierCheckpoints(int nHeight, unsigned int nStakeModifierChecksum) +{ + MapModifierCheckpoints& checkpoints = (fTestNet ? mapStakeModifierCheckpointsTestNet : mapStakeModifierCheckpoints); + + if (checkpoints.count(nHeight)) + return nStakeModifierChecksum == checkpoints[nHeight]; + return true; +} diff --git a/src/kernel.h b/src/kernel.h new file mode 100644 index 0000000..1a5a23d --- /dev/null +++ b/src/kernel.h @@ -0,0 +1,39 @@ +// Copyright (c) 2012-2013 The PPCoin developers +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. +#ifndef PPCOIN_KERNEL_H +#define PPCOIN_KERNEL_H + +#include "main.h" + +// MODIFIER_INTERVAL: time to elapse before new modifier is computed +extern unsigned int nModifierInterval; + +// MODIFIER_INTERVAL_RATIO: +// ratio of group interval length between the last group and the first group +static const int MODIFIER_INTERVAL_RATIO = 3; + +// Compute the hash modifier for proof-of-stake +bool ComputeNextStakeModifier(const CBlockIndex* pindexPrev, uint64_t& nStakeModifier, bool& fGeneratedStakeModifier); + +// Check whether stake kernel meets hash target +// Sets hashProofOfStake on success return +bool CheckStakeKernelHash(unsigned int nBits, const CBlock& blockFrom, unsigned int nTxPrevOffset, const CTransaction& txPrev, const COutPoint& prevout, unsigned int nTimeTx, uint256& hashProofOfStake, uint256& targetProofOfStake, bool fPrintProofOfStake=false); + +// Check kernel hash target and coinstake signature +// Sets hashProofOfStake on success return +bool CheckProofOfStake(const CTransaction& tx, unsigned int nBits, uint256& hashProofOfStake, uint256& targetProofOfStake); + +// Check whether the coinstake timestamp meets protocol +bool CheckCoinStakeTimestamp(int64_t nTimeBlock, int64_t nTimeTx); + +// Get stake modifier checksum +unsigned int GetStakeModifierChecksum(const CBlockIndex* pindex); + +// Check stake modifier hard checkpoints +bool CheckStakeModifierCheckpoints(int nHeight, unsigned int nStakeModifierChecksum); + +// Get time weight using supplied timestamps +int64_t GetWeight(int64_t nIntervalBeginning, int64_t nIntervalEnd); + +#endif // PPCOIN_KERNEL_H diff --git a/src/key.cpp b/src/key.cpp new file mode 100644 index 0000000..99f39ed --- /dev/null +++ b/src/key.cpp @@ -0,0 +1,472 @@ +// Copyright (c) 2009-2012 The Bitcoin developers +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include + +#include +#include + +#include "key.h" + +// Generate a private key from just the secret parameter +int EC_KEY_regenerate_key(EC_KEY *eckey, BIGNUM *priv_key) +{ + int ok = 0; + BN_CTX *ctx = NULL; + EC_POINT *pub_key = NULL; + + if (!eckey) return 0; + + const EC_GROUP *group = EC_KEY_get0_group(eckey); + + if ((ctx = BN_CTX_new()) == NULL) + goto err; + + pub_key = EC_POINT_new(group); + + if (pub_key == NULL) + goto err; + + if (!EC_POINT_mul(group, pub_key, priv_key, NULL, NULL, ctx)) + goto err; + + EC_KEY_set_private_key(eckey,priv_key); + EC_KEY_set_public_key(eckey,pub_key); + + ok = 1; + +err: + + if (pub_key) + EC_POINT_free(pub_key); + if (ctx != NULL) + BN_CTX_free(ctx); + + return(ok); +} + +// Perform ECDSA key recovery (see SEC1 4.1.6) for curves over (mod p)-fields +// recid selects which key is recovered +// if check is non-zero, additional checks are performed +int ECDSA_SIG_recover_key_GFp(EC_KEY *eckey, ECDSA_SIG *ecsig, const unsigned char *msg, int msglen, int recid, int check) +{ + if (!eckey) return 0; + + int ret = 0; + BN_CTX *ctx = NULL; + + BIGNUM *x = NULL; + BIGNUM *e = NULL; + BIGNUM *order = NULL; + BIGNUM *sor = NULL; + BIGNUM *eor = NULL; + BIGNUM *field = NULL; + EC_POINT *R = NULL; + EC_POINT *O = NULL; + EC_POINT *Q = NULL; + BIGNUM *rr = NULL; + BIGNUM *zero = NULL; + int n = 0; + int i = recid / 2; + + const EC_GROUP *group = EC_KEY_get0_group(eckey); + if ((ctx = BN_CTX_new()) == NULL) { ret = -1; goto err; } + BN_CTX_start(ctx); + order = BN_CTX_get(ctx); + if (!EC_GROUP_get_order(group, order, ctx)) { ret = -2; goto err; } + x = BN_CTX_get(ctx); + if (!BN_copy(x, order)) { ret=-1; goto err; } + if (!BN_mul_word(x, i)) { ret=-1; goto err; } + if (!BN_add(x, x, ecsig->r)) { ret=-1; goto err; } + field = BN_CTX_get(ctx); + if (!EC_GROUP_get_curve_GFp(group, field, NULL, NULL, ctx)) { ret=-2; goto err; } + if (BN_cmp(x, field) >= 0) { ret=0; goto err; } + if ((R = EC_POINT_new(group)) == NULL) { ret = -2; goto err; } + if (!EC_POINT_set_compressed_coordinates_GFp(group, R, x, recid % 2, ctx)) { ret=0; goto err; } + if (check) + { + if ((O = EC_POINT_new(group)) == NULL) { ret = -2; goto err; } + if (!EC_POINT_mul(group, O, NULL, R, order, ctx)) { ret=-2; goto err; } + if (!EC_POINT_is_at_infinity(group, O)) { ret = 0; goto err; } + } + if ((Q = EC_POINT_new(group)) == NULL) { ret = -2; goto err; } + n = EC_GROUP_get_degree(group); + e = BN_CTX_get(ctx); + if (!BN_bin2bn(msg, msglen, e)) { ret=-1; goto err; } + if (8*msglen > n) BN_rshift(e, e, 8-(n & 7)); + zero = BN_CTX_get(ctx); + if (!BN_zero(zero)) { ret=-1; goto err; } + if (!BN_mod_sub(e, zero, e, order, ctx)) { ret=-1; goto err; } + rr = BN_CTX_get(ctx); + if (!BN_mod_inverse(rr, ecsig->r, order, ctx)) { ret=-1; goto err; } + sor = BN_CTX_get(ctx); + if (!BN_mod_mul(sor, ecsig->s, rr, order, ctx)) { ret=-1; goto err; } + eor = BN_CTX_get(ctx); + if (!BN_mod_mul(eor, e, rr, order, ctx)) { ret=-1; goto err; } + if (!EC_POINT_mul(group, Q, eor, R, sor, ctx)) { ret=-2; goto err; } + if (!EC_KEY_set_public_key(eckey, Q)) { ret=-2; goto err; } + + ret = 1; + +err: + if (ctx) { + BN_CTX_end(ctx); + BN_CTX_free(ctx); + } + if (R != NULL) EC_POINT_free(R); + if (O != NULL) EC_POINT_free(O); + if (Q != NULL) EC_POINT_free(Q); + return ret; +} + +void CKey::SetCompressedPubKey() +{ + EC_KEY_set_conv_form(pkey, POINT_CONVERSION_COMPRESSED); + fCompressedPubKey = true; +} + +void CKey::Reset() +{ + fCompressedPubKey = false; + if (pkey != NULL) + EC_KEY_free(pkey); + pkey = EC_KEY_new_by_curve_name(NID_secp256k1); + if (pkey == NULL) + throw key_error("CKey::CKey() : EC_KEY_new_by_curve_name failed"); + fSet = false; +} + +CKey::CKey() +{ + pkey = NULL; + Reset(); +} + +CKey::CKey(const CKey& b) +{ + pkey = EC_KEY_dup(b.pkey); + if (pkey == NULL) + throw key_error("CKey::CKey(const CKey&) : EC_KEY_dup failed"); + fSet = b.fSet; +} + +CKey& CKey::operator=(const CKey& b) +{ + if (!EC_KEY_copy(pkey, b.pkey)) + throw key_error("CKey::operator=(const CKey&) : EC_KEY_copy failed"); + fSet = b.fSet; + return (*this); +} + +CKey::~CKey() +{ + EC_KEY_free(pkey); +} + +bool CKey::IsNull() const +{ + return !fSet; +} + +bool CKey::IsCompressed() const +{ + return fCompressedPubKey; +} + +int CompareBigEndian(const unsigned char *c1, size_t c1len, const unsigned char *c2, size_t c2len) { + while (c1len > c2len) { + if (*c1) + return 1; + c1++; + c1len--; + } + while (c2len > c1len) { + if (*c2) + return -1; + c2++; + c2len--; + } + while (c1len > 0) { + if (*c1 > *c2) + return 1; + if (*c2 > *c1) + return -1; + c1++; + c2++; + c1len--; + } + return 0; +} + +// Order of secp256k1's generator minus 1. +const unsigned char vchMaxModOrder[32] = { + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE, + 0xBA,0xAE,0xDC,0xE6,0xAF,0x48,0xA0,0x3B, + 0xBF,0xD2,0x5E,0x8C,0xD0,0x36,0x41,0x40 +}; + +// Half of the order of secp256k1's generator minus 1. +const unsigned char vchMaxModHalfOrder[32] = { + 0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0x5D,0x57,0x6E,0x73,0x57,0xA4,0x50,0x1D, + 0xDF,0xE9,0x2F,0x46,0x68,0x1B,0x20,0xA0 +}; + +const unsigned char vchZero[0] = {}; + +bool CKey::CheckSignatureElement(const unsigned char *vch, int len, bool half) { + return CompareBigEndian(vch, len, vchZero, 0) > 0 && + CompareBigEndian(vch, len, half ? vchMaxModHalfOrder : vchMaxModOrder, 32) <= 0; +} + +void CKey::MakeNewKey(bool fCompressed) +{ + if (!EC_KEY_generate_key(pkey)) + throw key_error("CKey::MakeNewKey() : EC_KEY_generate_key failed"); + if (fCompressed) + SetCompressedPubKey(); + fSet = true; +} + +bool CKey::SetPrivKey(const CPrivKey& vchPrivKey) +{ + const unsigned char* pbegin = &vchPrivKey[0]; + if (d2i_ECPrivateKey(&pkey, &pbegin, vchPrivKey.size())) + { + // In testing, d2i_ECPrivateKey can return true + // but fill in pkey with a key that fails + // EC_KEY_check_key, so: + if (EC_KEY_check_key(pkey)) + { + fSet = true; + return true; + } + } + // If vchPrivKey data is bad d2i_ECPrivateKey() can + // leave pkey in a state where calling EC_KEY_free() + // crashes. To avoid that, set pkey to NULL and + // leak the memory (a leak is better than a crash) + pkey = NULL; + Reset(); + return false; +} + +bool CKey::SetSecret(const CSecret& vchSecret, bool fCompressed) +{ + EC_KEY_free(pkey); + pkey = EC_KEY_new_by_curve_name(NID_secp256k1); + if (pkey == NULL) + throw key_error("CKey::SetSecret() : EC_KEY_new_by_curve_name failed"); + if (vchSecret.size() != 32) + throw key_error("CKey::SetSecret() : secret must be 32 bytes"); + BIGNUM *bn = BN_bin2bn(&vchSecret[0],32,BN_new()); + if (bn == NULL) + throw key_error("CKey::SetSecret() : BN_bin2bn failed"); + if (!EC_KEY_regenerate_key(pkey,bn)) + { + BN_clear_free(bn); + throw key_error("CKey::SetSecret() : EC_KEY_regenerate_key failed"); + } + BN_clear_free(bn); + fSet = true; + if (fCompressed || fCompressedPubKey) + SetCompressedPubKey(); + return true; +} + +CSecret CKey::GetSecret(bool &fCompressed) const +{ + CSecret vchRet; + vchRet.resize(32); + const BIGNUM *bn = EC_KEY_get0_private_key(pkey); + int nBytes = BN_num_bytes(bn); + if (bn == NULL) + throw key_error("CKey::GetSecret() : EC_KEY_get0_private_key failed"); + int n=BN_bn2bin(bn,&vchRet[32 - nBytes]); + if (n != nBytes) + throw key_error("CKey::GetSecret(): BN_bn2bin failed"); + fCompressed = fCompressedPubKey; + return vchRet; +} + +CPrivKey CKey::GetPrivKey() const +{ + int nSize = i2d_ECPrivateKey(pkey, NULL); + if (!nSize) + throw key_error("CKey::GetPrivKey() : i2d_ECPrivateKey failed"); + CPrivKey vchPrivKey(nSize, 0); + unsigned char* pbegin = &vchPrivKey[0]; + if (i2d_ECPrivateKey(pkey, &pbegin) != nSize) + throw key_error("CKey::GetPrivKey() : i2d_ECPrivateKey returned unexpected size"); + return vchPrivKey; +} + +bool CKey::SetPubKey(const CPubKey& vchPubKey) +{ + const unsigned char* pbegin = &vchPubKey.vchPubKey[0]; + if (o2i_ECPublicKey(&pkey, &pbegin, vchPubKey.vchPubKey.size())) + { + fSet = true; + if (vchPubKey.vchPubKey.size() == 33) + SetCompressedPubKey(); + return true; + } + pkey = NULL; + Reset(); + return false; +} + +CPubKey CKey::GetPubKey() const +{ + int nSize = i2o_ECPublicKey(pkey, NULL); + if (!nSize) + throw key_error("CKey::GetPubKey() : i2o_ECPublicKey failed"); + std::vector vchPubKey(nSize, 0); + unsigned char* pbegin = &vchPubKey[0]; + if (i2o_ECPublicKey(pkey, &pbegin) != nSize) + throw key_error("CKey::GetPubKey() : i2o_ECPublicKey returned unexpected size"); + return CPubKey(vchPubKey); +} + +bool CKey::Sign(uint256 hash, std::vector& vchSig) +{ + vchSig.clear(); + ECDSA_SIG *sig = ECDSA_do_sign((unsigned char*)&hash, sizeof(hash), pkey); + if (sig == NULL) + return false; + BN_CTX *ctx = BN_CTX_new(); + BN_CTX_start(ctx); + const EC_GROUP *group = EC_KEY_get0_group(pkey); + BIGNUM *order = BN_CTX_get(ctx); + BIGNUM *halforder = BN_CTX_get(ctx); + EC_GROUP_get_order(group, order, ctx); + BN_rshift1(halforder, order); + if (BN_cmp(sig->s, halforder) > 0) { + // enforce low S values, by negating the value (modulo the order) if above order/2. + BN_sub(sig->s, order, sig->s); + } + BN_CTX_end(ctx); + BN_CTX_free(ctx); + unsigned int nSize = ECDSA_size(pkey); + vchSig.resize(nSize); // Make sure it is big enough + unsigned char *pos = &vchSig[0]; + nSize = i2d_ECDSA_SIG(sig, &pos); + ECDSA_SIG_free(sig); + vchSig.resize(nSize); // Shrink to fit actual size + return true; +} + +// create a compact signature (65 bytes), which allows reconstructing the used public key +// The format is one header byte, followed by two times 32 bytes for the serialized r and s values. +// The header byte: 0x1B = first key with even y, 0x1C = first key with odd y, +// 0x1D = second key with even y, 0x1E = second key with odd y +bool CKey::SignCompact(uint256 hash, std::vector& vchSig) +{ + bool fOk = false; + ECDSA_SIG *sig = ECDSA_do_sign((unsigned char*)&hash, sizeof(hash), pkey); + if (sig==NULL) + return false; + vchSig.clear(); + vchSig.resize(65,0); + int nBitsR = BN_num_bits(sig->r); + int nBitsS = BN_num_bits(sig->s); + if (nBitsR <= 256 && nBitsS <= 256) + { + int nRecId = -1; + for (int i=0; i<4; i++) + { + CKey keyRec; + keyRec.fSet = true; + if (fCompressedPubKey) + keyRec.SetCompressedPubKey(); + if (ECDSA_SIG_recover_key_GFp(keyRec.pkey, sig, (unsigned char*)&hash, sizeof(hash), i, 1) == 1) + if (keyRec.GetPubKey() == this->GetPubKey()) + { + nRecId = i; + break; + } + } + + if (nRecId == -1) + { + ECDSA_SIG_free(sig); + throw key_error("CKey::SignCompact() : unable to construct recoverable key"); + } + + vchSig[0] = nRecId+27+(fCompressedPubKey ? 4 : 0); + BN_bn2bin(sig->r,&vchSig[33-(nBitsR+7)/8]); + BN_bn2bin(sig->s,&vchSig[65-(nBitsS+7)/8]); + fOk = true; + } + ECDSA_SIG_free(sig); + return fOk; +} + +// reconstruct public key from a compact signature +// This is only slightly more CPU intensive than just verifying it. +// If this function succeeds, the recovered public key is guaranteed to be valid +// (the signature is a valid signature of the given data for that key) +bool CKey::SetCompactSignature(uint256 hash, const std::vector& vchSig) +{ + if (vchSig.size() != 65) + return false; + int nV = vchSig[0]; + if (nV<27 || nV>=35) + return false; + ECDSA_SIG *sig = ECDSA_SIG_new(); + BN_bin2bn(&vchSig[1],32,sig->r); + BN_bin2bn(&vchSig[33],32,sig->s); + + EC_KEY_free(pkey); + pkey = EC_KEY_new_by_curve_name(NID_secp256k1); + if (nV >= 31) + { + SetCompressedPubKey(); + nV -= 4; + } + if (ECDSA_SIG_recover_key_GFp(pkey, sig, (unsigned char*)&hash, sizeof(hash), nV - 27, 0) == 1) + { + fSet = true; + ECDSA_SIG_free(sig); + return true; + } + ECDSA_SIG_free(sig); + return false; +} + +bool CKey::Verify(uint256 hash, const std::vector& vchSig) +{ + // -1 = error, 0 = bad sig, 1 = good + if (ECDSA_verify(0, (unsigned char*)&hash, sizeof(hash), &vchSig[0], vchSig.size(), pkey) != 1) + return false; + + return true; +} + +bool CKey::IsValid() +{ + if (!fSet) + return false; + + if (!EC_KEY_check_key(pkey)) + return false; + + bool fCompr; + CSecret secret = GetSecret(fCompr); + CKey key2; + key2.SetSecret(secret, fCompr); + return GetPubKey() == key2.GetPubKey(); +} + +bool ECC_InitSanityCheck() { + EC_KEY *pkey = EC_KEY_new_by_curve_name(NID_secp256k1); + if(pkey == NULL) + return false; + EC_KEY_free(pkey); + + // TODO Is there more EC functionality that could be missing? + return true; +} diff --git a/src/key.h b/src/key.h new file mode 100644 index 0000000..0a7bbcf --- /dev/null +++ b/src/key.h @@ -0,0 +1,165 @@ +// Copyright (c) 2009-2010 Satoshi Nakamoto +// Copyright (c) 2009-2012 The Bitcoin developers +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. +#ifndef BITCOIN_KEY_H +#define BITCOIN_KEY_H + +#include +#include + +#include "allocators.h" +#include "serialize.h" +#include "uint256.h" +#include "util.h" + +#include // for EC_KEY definition + +// secp160k1 +// const unsigned int PRIVATE_KEY_SIZE = 192; +// const unsigned int PUBLIC_KEY_SIZE = 41; +// const unsigned int SIGNATURE_SIZE = 48; +// +// secp192k1 +// const unsigned int PRIVATE_KEY_SIZE = 222; +// const unsigned int PUBLIC_KEY_SIZE = 49; +// const unsigned int SIGNATURE_SIZE = 57; +// +// secp224k1 +// const unsigned int PRIVATE_KEY_SIZE = 250; +// const unsigned int PUBLIC_KEY_SIZE = 57; +// const unsigned int SIGNATURE_SIZE = 66; +// +// secp256k1: +// const unsigned int PRIVATE_KEY_SIZE = 279; +// const unsigned int PUBLIC_KEY_SIZE = 65; +// const unsigned int SIGNATURE_SIZE = 72; +// +// see www.keylength.com +// script supports up to 75 for single byte push + +class key_error : public std::runtime_error +{ +public: + explicit key_error(const std::string& str) : std::runtime_error(str) {} +}; + +/** A reference to a CKey: the Hash160 of its serialized public key */ +class CKeyID : public uint160 +{ +public: + CKeyID() : uint160(0) { } + CKeyID(const uint160 &in) : uint160(in) { } +}; + +/** A reference to a CScript: the Hash160 of its serialization (see script.h) */ +class CScriptID : public uint160 +{ +public: + CScriptID() : uint160(0) { } + CScriptID(const uint160 &in) : uint160(in) { } +}; + +/** An encapsulated public key. */ +class CPubKey { +private: + std::vector vchPubKey; + friend class CKey; + +public: + CPubKey() { } + CPubKey(const std::vector &vchPubKeyIn) : vchPubKey(vchPubKeyIn) { } + friend bool operator==(const CPubKey &a, const CPubKey &b) { return a.vchPubKey == b.vchPubKey; } + friend bool operator!=(const CPubKey &a, const CPubKey &b) { return a.vchPubKey != b.vchPubKey; } + friend bool operator<(const CPubKey &a, const CPubKey &b) { return a.vchPubKey < b.vchPubKey; } + + IMPLEMENT_SERIALIZE( + READWRITE(vchPubKey); + ) + + CKeyID GetID() const { + return CKeyID(Hash160(vchPubKey)); + } + + uint256 GetHash() const { + return Hash(vchPubKey.begin(), vchPubKey.end()); + } + + bool IsValid() const { + return vchPubKey.size() == 33 || vchPubKey.size() == 65; + } + + bool IsCompressed() const { + return vchPubKey.size() == 33; + } + + std::vector Raw() const { + return vchPubKey; + } +}; + + +// secure_allocator is defined in allocators.h +// CPrivKey is a serialized private key, with all parameters included (279 bytes) +typedef std::vector > CPrivKey; +// CSecret is a serialization of just the secret parameter (32 bytes) +typedef std::vector > CSecret; + +/** An encapsulated OpenSSL Elliptic Curve key (public and/or private) */ +class CKey +{ +protected: + EC_KEY* pkey; + bool fSet; + bool fCompressedPubKey; + + void SetCompressedPubKey(); + +public: + + void Reset(); + + CKey(); + CKey(const CKey& b); + + CKey& operator=(const CKey& b); + + ~CKey(); + + bool IsNull() const; + bool IsCompressed() const; + + void MakeNewKey(bool fCompressed); + bool SetPrivKey(const CPrivKey& vchPrivKey); + bool SetSecret(const CSecret& vchSecret, bool fCompressed = false); + CSecret GetSecret(bool &fCompressed) const; + CPrivKey GetPrivKey() const; + bool SetPubKey(const CPubKey& vchPubKey); + CPubKey GetPubKey() const; + + bool Sign(uint256 hash, std::vector& vchSig); + + // create a compact signature (65 bytes), which allows reconstructing the used public key + // The format is one header byte, followed by two times 32 bytes for the serialized r and s values. + // The header byte: 0x1B = first key with even y, 0x1C = first key with odd y, + // 0x1D = second key with even y, 0x1E = second key with odd y + bool SignCompact(uint256 hash, std::vector& vchSig); + + // reconstruct public key from a compact signature + // This is only slightly more CPU intensive than just verifying it. + // If this function succeeds, the recovered public key is guaranteed to be valid + // (the signature is a valid signature of the given data for that key) + bool SetCompactSignature(uint256 hash, const std::vector& vchSig); + + bool Verify(uint256 hash, const std::vector& vchSig); + + bool IsValid(); + + // Check whether an element of a signature (r or s) is valid. + static bool CheckSignatureElement(const unsigned char *vch, int len, bool half); +}; + +/** Check that required EC support is available at runtime */ +bool ECC_InitSanityCheck(void); + +#endif diff --git a/src/keystore.cpp b/src/keystore.cpp new file mode 100644 index 0000000..967c79a --- /dev/null +++ b/src/keystore.cpp @@ -0,0 +1,224 @@ +// Copyright (c) 2009-2010 Satoshi Nakamoto +// Copyright (c) 2009-2012 The Bitcoin developers +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include "keystore.h" +#include "script.h" + +bool CKeyStore::GetPubKey(const CKeyID &address, CPubKey &vchPubKeyOut) const +{ + CKey key; + if (!GetKey(address, key)) + return false; + vchPubKeyOut = key.GetPubKey(); + return true; +} + +bool CBasicKeyStore::AddKey(const CKey& key) +{ + bool fCompressed = false; + CSecret secret = key.GetSecret(fCompressed); + { + LOCK(cs_KeyStore); + mapKeys[key.GetPubKey().GetID()] = make_pair(secret, fCompressed); + } + return true; +} + +bool CBasicKeyStore::AddCScript(const CScript& redeemScript) +{ + if (redeemScript.size() > MAX_SCRIPT_ELEMENT_SIZE) + return error("CBasicKeyStore::AddCScript() : redeemScripts > %i bytes are invalid", MAX_SCRIPT_ELEMENT_SIZE); + + { + LOCK(cs_KeyStore); + mapScripts[redeemScript.GetID()] = redeemScript; + } + return true; +} + +bool CBasicKeyStore::HaveCScript(const CScriptID& hash) const +{ + bool result; + { + LOCK(cs_KeyStore); + result = (mapScripts.count(hash) > 0); + } + return result; +} + + +bool CBasicKeyStore::GetCScript(const CScriptID &hash, CScript& redeemScriptOut) const +{ + { + LOCK(cs_KeyStore); + ScriptMap::const_iterator mi = mapScripts.find(hash); + if (mi != mapScripts.end()) + { + redeemScriptOut = (*mi).second; + return true; + } + } + return false; +} + +bool CCryptoKeyStore::SetCrypted() +{ + { + LOCK(cs_KeyStore); + if (fUseCrypto) + return true; + if (!mapKeys.empty()) + return false; + fUseCrypto = true; + } + return true; +} + +bool CCryptoKeyStore::Lock() +{ + if (!SetCrypted()) + return false; + + { + LOCK(cs_KeyStore); + vMasterKey.clear(); + } + + NotifyStatusChanged(this); + return true; +} + +bool CCryptoKeyStore::Unlock(const CKeyingMaterial& vMasterKeyIn) +{ + { + LOCK(cs_KeyStore); + if (!SetCrypted()) + return false; + + CryptedKeyMap::const_iterator mi = mapCryptedKeys.begin(); + for (; mi != mapCryptedKeys.end(); ++mi) + { + const CPubKey &vchPubKey = (*mi).second.first; + const std::vector &vchCryptedSecret = (*mi).second.second; + CSecret vchSecret; + if(!DecryptSecret(vMasterKeyIn, vchCryptedSecret, vchPubKey.GetHash(), vchSecret)) + return false; + if (vchSecret.size() != 32) + return false; + CKey key; + key.SetPubKey(vchPubKey); + key.SetSecret(vchSecret); + if (key.GetPubKey() == vchPubKey) + break; + return false; + } + vMasterKey = vMasterKeyIn; + } + NotifyStatusChanged(this); + return true; +} + +bool CCryptoKeyStore::AddKey(const CKey& key) +{ + { + LOCK(cs_KeyStore); + if (!IsCrypted()) + return CBasicKeyStore::AddKey(key); + + if (IsLocked()) + return false; + + std::vector vchCryptedSecret; + CPubKey vchPubKey = key.GetPubKey(); + bool fCompressed; + if (!EncryptSecret(vMasterKey, key.GetSecret(fCompressed), vchPubKey.GetHash(), vchCryptedSecret)) + return false; + + if (!AddCryptedKey(key.GetPubKey(), vchCryptedSecret)) + return false; + } + return true; +} + + +bool CCryptoKeyStore::AddCryptedKey(const CPubKey &vchPubKey, const std::vector &vchCryptedSecret) +{ + { + LOCK(cs_KeyStore); + if (!SetCrypted()) + return false; + + mapCryptedKeys[vchPubKey.GetID()] = make_pair(vchPubKey, vchCryptedSecret); + } + return true; +} + +bool CCryptoKeyStore::GetKey(const CKeyID &address, CKey& keyOut) const +{ + { + LOCK(cs_KeyStore); + if (!IsCrypted()) + return CBasicKeyStore::GetKey(address, keyOut); + + CryptedKeyMap::const_iterator mi = mapCryptedKeys.find(address); + if (mi != mapCryptedKeys.end()) + { + const CPubKey &vchPubKey = (*mi).second.first; + const std::vector &vchCryptedSecret = (*mi).second.second; + CSecret vchSecret; + if (!DecryptSecret(vMasterKey, vchCryptedSecret, vchPubKey.GetHash(), vchSecret)) + return false; + if (vchSecret.size() != 32) + return false; + keyOut.SetPubKey(vchPubKey); + keyOut.SetSecret(vchSecret); + return true; + } + } + return false; +} + +bool CCryptoKeyStore::GetPubKey(const CKeyID &address, CPubKey& vchPubKeyOut) const +{ + { + LOCK(cs_KeyStore); + if (!IsCrypted()) + return CKeyStore::GetPubKey(address, vchPubKeyOut); + + CryptedKeyMap::const_iterator mi = mapCryptedKeys.find(address); + if (mi != mapCryptedKeys.end()) + { + vchPubKeyOut = (*mi).second.first; + return true; + } + } + return false; +} + +bool CCryptoKeyStore::EncryptKeys(CKeyingMaterial& vMasterKeyIn) +{ + { + LOCK(cs_KeyStore); + if (!mapCryptedKeys.empty() || IsCrypted()) + return false; + + fUseCrypto = true; + BOOST_FOREACH(KeyMap::value_type& mKey, mapKeys) + { + CKey key; + if (!key.SetSecret(mKey.second.first, mKey.second.second)) + return false; + const CPubKey vchPubKey = key.GetPubKey(); + std::vector vchCryptedSecret; + bool fCompressed; + if (!EncryptSecret(vMasterKeyIn, key.GetSecret(fCompressed), vchPubKey.GetHash(), vchCryptedSecret)) + return false; + if (!AddCryptedKey(vchPubKey, vchCryptedSecret)) + return false; + } + mapKeys.clear(); + } + return true; +} diff --git a/src/keystore.h b/src/keystore.h new file mode 100644 index 0000000..ab369bb --- /dev/null +++ b/src/keystore.h @@ -0,0 +1,184 @@ +// Copyright (c) 2009-2010 Satoshi Nakamoto +// Copyright (c) 2009-2012 The Bitcoin developers +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. +#ifndef BITCOIN_KEYSTORE_H +#define BITCOIN_KEYSTORE_H + +#include "crypter.h" +#include "sync.h" +#include + +class CScript; + +/** A virtual base class for key stores */ +class CKeyStore +{ +protected: + mutable CCriticalSection cs_KeyStore; + +public: + virtual ~CKeyStore() {} + + // Add a key to the store. + virtual bool AddKey(const CKey& key) =0; + + // Check whether a key corresponding to a given address is present in the store. + virtual bool HaveKey(const CKeyID &address) const =0; + virtual bool GetKey(const CKeyID &address, CKey& keyOut) const =0; + virtual void GetKeys(std::set &setAddress) const =0; + virtual bool GetPubKey(const CKeyID &address, CPubKey& vchPubKeyOut) const; + + // Support for BIP 0013 : see https://en.bitcoin.it/wiki/BIP_0013 + virtual bool AddCScript(const CScript& redeemScript) =0; + virtual bool HaveCScript(const CScriptID &hash) const =0; + virtual bool GetCScript(const CScriptID &hash, CScript& redeemScriptOut) const =0; + + virtual bool GetSecret(const CKeyID &address, CSecret& vchSecret, bool &fCompressed) const + { + CKey key; + if (!GetKey(address, key)) + return false; + vchSecret = key.GetSecret(fCompressed); + return true; + } +}; + +typedef std::map > KeyMap; +typedef std::map ScriptMap; + +/** Basic key store, that keeps keys in an address->secret map */ +class CBasicKeyStore : public CKeyStore +{ +protected: + KeyMap mapKeys; + ScriptMap mapScripts; + +public: + bool AddKey(const CKey& key); + bool HaveKey(const CKeyID &address) const + { + bool result; + { + LOCK(cs_KeyStore); + result = (mapKeys.count(address) > 0); + } + return result; + } + void GetKeys(std::set &setAddress) const + { + setAddress.clear(); + { + LOCK(cs_KeyStore); + KeyMap::const_iterator mi = mapKeys.begin(); + while (mi != mapKeys.end()) + { + setAddress.insert((*mi).first); + mi++; + } + } + } + bool GetKey(const CKeyID &address, CKey &keyOut) const + { + { + LOCK(cs_KeyStore); + KeyMap::const_iterator mi = mapKeys.find(address); + if (mi != mapKeys.end()) + { + keyOut.Reset(); + keyOut.SetSecret((*mi).second.first, (*mi).second.second); + return true; + } + } + return false; + } + virtual bool AddCScript(const CScript& redeemScript); + virtual bool HaveCScript(const CScriptID &hash) const; + virtual bool GetCScript(const CScriptID &hash, CScript& redeemScriptOut) const; +}; + +typedef std::map > > CryptedKeyMap; + +/** Keystore which keeps the private keys encrypted. + * It derives from the basic key store, which is used if no encryption is active. + */ +class CCryptoKeyStore : public CBasicKeyStore +{ +private: + CryptedKeyMap mapCryptedKeys; + + CKeyingMaterial vMasterKey; + + // if fUseCrypto is true, mapKeys must be empty + // if fUseCrypto is false, vMasterKey must be empty + bool fUseCrypto; + +protected: + bool SetCrypted(); + + // will encrypt previously unencrypted keys + bool EncryptKeys(CKeyingMaterial& vMasterKeyIn); + + bool Unlock(const CKeyingMaterial& vMasterKeyIn); + +public: + CCryptoKeyStore() : fUseCrypto(false) + { + } + + bool IsCrypted() const + { + return fUseCrypto; + } + + bool IsLocked() const + { + if (!IsCrypted()) + return false; + bool result; + { + LOCK(cs_KeyStore); + result = vMasterKey.empty(); + } + return result; + } + + bool Lock(); + + virtual bool AddCryptedKey(const CPubKey &vchPubKey, const std::vector &vchCryptedSecret); + bool AddKey(const CKey& key); + bool HaveKey(const CKeyID &address) const + { + { + LOCK(cs_KeyStore); + if (!IsCrypted()) + return CBasicKeyStore::HaveKey(address); + return mapCryptedKeys.count(address) > 0; + } + return false; + } + bool GetKey(const CKeyID &address, CKey& keyOut) const; + bool GetPubKey(const CKeyID &address, CPubKey& vchPubKeyOut) const; + void GetKeys(std::set &setAddress) const + { + if (!IsCrypted()) + { + CBasicKeyStore::GetKeys(setAddress); + return; + } + setAddress.clear(); + CryptedKeyMap::const_iterator mi = mapCryptedKeys.begin(); + while (mi != mapCryptedKeys.end()) + { + setAddress.insert((*mi).first); + mi++; + } + } + + /* Wallet status (encrypted, locked) changed. + * Note: Called without locks held. + */ + boost::signals2::signal NotifyStatusChanged; +}; + +#endif diff --git a/src/leveldb/.gitignore b/src/leveldb/.gitignore new file mode 100644 index 0000000..71d87a4 --- /dev/null +++ b/src/leveldb/.gitignore @@ -0,0 +1,13 @@ +build_config.mk +*.a +*.o +*.dylib* +*.so +*.so.* +*_test +db_bench +leveldbutil +Release +Debug +Benchmark +vs2010.* diff --git a/src/leveldb/AUTHORS b/src/leveldb/AUTHORS new file mode 100644 index 0000000..2439d7a --- /dev/null +++ b/src/leveldb/AUTHORS @@ -0,0 +1,12 @@ +# Names should be added to this file like so: +# Name or Organization + +Google Inc. + +# Initial version authors: +Jeffrey Dean +Sanjay Ghemawat + +# Partial list of contributors: +Kevin Regan +Johan Bilien diff --git a/src/leveldb/LICENSE b/src/leveldb/LICENSE new file mode 100644 index 0000000..8e80208 --- /dev/null +++ b/src/leveldb/LICENSE @@ -0,0 +1,27 @@ +Copyright (c) 2011 The LevelDB Authors. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/src/leveldb/Makefile b/src/leveldb/Makefile new file mode 100644 index 0000000..f8903b6 --- /dev/null +++ b/src/leveldb/Makefile @@ -0,0 +1,215 @@ +# Copyright (c) 2011 The LevelDB Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. See the AUTHORS file for names of contributors. + +#----------------------------------------------- +# Uncomment exactly one of the lines labelled (A), (B), and (C) below +# to switch between compilation modes. + +OPT ?= -O2 -DNDEBUG # (A) Production use (optimized mode) +# OPT ?= -g2 # (B) Debug mode, w/ full line-level debugging symbols +# OPT ?= -O2 -g2 -DNDEBUG # (C) Profiling mode: opt, but w/debugging symbols +#----------------------------------------------- + +# detect what platform we're building on +$(shell CC="$(CC)" CXX="$(CXX)" TARGET_OS="$(TARGET_OS)" \ + ./build_detect_platform build_config.mk ./) +# this file is generated by the previous line to set build flags and sources +include build_config.mk + +CFLAGS += -I. -I./include $(PLATFORM_CCFLAGS) $(OPT) +CXXFLAGS += -I. -I./include $(PLATFORM_CXXFLAGS) $(OPT) + +LDFLAGS += $(PLATFORM_LDFLAGS) +LIBS += $(PLATFORM_LIBS) + +LIBOBJECTS = $(SOURCES:.cc=.o) +MEMENVOBJECTS = $(MEMENV_SOURCES:.cc=.o) + +TESTUTIL = ./util/testutil.o +TESTHARNESS = ./util/testharness.o $(TESTUTIL) + +TESTS = \ + arena_test \ + autocompact_test \ + bloom_test \ + c_test \ + cache_test \ + coding_test \ + corruption_test \ + crc32c_test \ + db_test \ + dbformat_test \ + env_test \ + filename_test \ + filter_block_test \ + issue178_test \ + issue200_test \ + log_test \ + memenv_test \ + skiplist_test \ + table_test \ + version_edit_test \ + version_set_test \ + write_batch_test + +PROGRAMS = db_bench leveldbutil $(TESTS) +BENCHMARKS = db_bench_sqlite3 db_bench_tree_db + +LIBRARY = libleveldb.a +MEMENVLIBRARY = libmemenv.a + +default: all + +# Should we build shared libraries? +ifneq ($(PLATFORM_SHARED_EXT),) + +ifneq ($(PLATFORM_SHARED_VERSIONED),true) +SHARED1 = libleveldb.$(PLATFORM_SHARED_EXT) +SHARED2 = $(SHARED1) +SHARED3 = $(SHARED1) +SHARED = $(SHARED1) +else +# Update db.h if you change these. +SHARED_MAJOR = 1 +SHARED_MINOR = 17 +SHARED1 = libleveldb.$(PLATFORM_SHARED_EXT) +SHARED2 = $(SHARED1).$(SHARED_MAJOR) +SHARED3 = $(SHARED1).$(SHARED_MAJOR).$(SHARED_MINOR) +SHARED = $(SHARED1) $(SHARED2) $(SHARED3) +$(SHARED1): $(SHARED3) + ln -fs $(SHARED3) $(SHARED1) +$(SHARED2): $(SHARED3) + ln -fs $(SHARED3) $(SHARED2) +endif + +$(SHARED3): + $(CXX) $(LDFLAGS) $(PLATFORM_SHARED_LDFLAGS)$(SHARED2) $(CXXFLAGS) $(PLATFORM_SHARED_CFLAGS) $(SOURCES) -o $(SHARED3) $(LIBS) + +endif # PLATFORM_SHARED_EXT + +all: $(SHARED) $(LIBRARY) + +check: all $(PROGRAMS) $(TESTS) + for t in $(TESTS); do echo "***** Running $$t"; ./$$t || exit 1; done + +clean: + -rm -f $(PROGRAMS) $(BENCHMARKS) $(LIBRARY) $(SHARED) $(MEMENVLIBRARY) */*.o */*/*.o ios-x86/*/*.o ios-arm/*/*.o build_config.mk + -rm -rf ios-x86/* ios-arm/* + +$(LIBRARY): $(LIBOBJECTS) + rm -f $@ + $(AR) -rs $@ $(LIBOBJECTS) + +db_bench: db/db_bench.o $(LIBOBJECTS) $(TESTUTIL) + $(CXX) $(LDFLAGS) db/db_bench.o $(LIBOBJECTS) $(TESTUTIL) -o $@ $(LIBS) + +db_bench_sqlite3: doc/bench/db_bench_sqlite3.o $(LIBOBJECTS) $(TESTUTIL) + $(CXX) $(LDFLAGS) doc/bench/db_bench_sqlite3.o $(LIBOBJECTS) $(TESTUTIL) -o $@ -lsqlite3 $(LIBS) + +db_bench_tree_db: doc/bench/db_bench_tree_db.o $(LIBOBJECTS) $(TESTUTIL) + $(CXX) $(LDFLAGS) doc/bench/db_bench_tree_db.o $(LIBOBJECTS) $(TESTUTIL) -o $@ -lkyotocabinet $(LIBS) + +leveldbutil: db/leveldb_main.o $(LIBOBJECTS) + $(CXX) $(LDFLAGS) db/leveldb_main.o $(LIBOBJECTS) -o $@ $(LIBS) + +arena_test: util/arena_test.o $(LIBOBJECTS) $(TESTHARNESS) + $(CXX) $(LDFLAGS) util/arena_test.o $(LIBOBJECTS) $(TESTHARNESS) -o $@ $(LIBS) + +autocompact_test: db/autocompact_test.o $(LIBOBJECTS) $(TESTHARNESS) + $(CXX) $(LDFLAGS) db/autocompact_test.o $(LIBOBJECTS) $(TESTHARNESS) -o $@ $(LIBS) + +bloom_test: util/bloom_test.o $(LIBOBJECTS) $(TESTHARNESS) + $(CXX) $(LDFLAGS) util/bloom_test.o $(LIBOBJECTS) $(TESTHARNESS) -o $@ $(LIBS) + +c_test: db/c_test.o $(LIBOBJECTS) $(TESTHARNESS) + $(CXX) $(LDFLAGS) db/c_test.o $(LIBOBJECTS) $(TESTHARNESS) -o $@ $(LIBS) + +cache_test: util/cache_test.o $(LIBOBJECTS) $(TESTHARNESS) + $(CXX) $(LDFLAGS) util/cache_test.o $(LIBOBJECTS) $(TESTHARNESS) -o $@ $(LIBS) + +coding_test: util/coding_test.o $(LIBOBJECTS) $(TESTHARNESS) + $(CXX) $(LDFLAGS) util/coding_test.o $(LIBOBJECTS) $(TESTHARNESS) -o $@ $(LIBS) + +corruption_test: db/corruption_test.o $(LIBOBJECTS) $(TESTHARNESS) + $(CXX) $(LDFLAGS) db/corruption_test.o $(LIBOBJECTS) $(TESTHARNESS) -o $@ $(LIBS) + +crc32c_test: util/crc32c_test.o $(LIBOBJECTS) $(TESTHARNESS) + $(CXX) $(LDFLAGS) util/crc32c_test.o $(LIBOBJECTS) $(TESTHARNESS) -o $@ $(LIBS) + +db_test: db/db_test.o $(LIBOBJECTS) $(TESTHARNESS) + $(CXX) $(LDFLAGS) db/db_test.o $(LIBOBJECTS) $(TESTHARNESS) -o $@ $(LIBS) + +dbformat_test: db/dbformat_test.o $(LIBOBJECTS) $(TESTHARNESS) + $(CXX) $(LDFLAGS) db/dbformat_test.o $(LIBOBJECTS) $(TESTHARNESS) -o $@ $(LIBS) + +env_test: util/env_test.o $(LIBOBJECTS) $(TESTHARNESS) + $(CXX) $(LDFLAGS) util/env_test.o $(LIBOBJECTS) $(TESTHARNESS) -o $@ $(LIBS) + +filename_test: db/filename_test.o $(LIBOBJECTS) $(TESTHARNESS) + $(CXX) $(LDFLAGS) db/filename_test.o $(LIBOBJECTS) $(TESTHARNESS) -o $@ $(LIBS) + +filter_block_test: table/filter_block_test.o $(LIBOBJECTS) $(TESTHARNESS) + $(CXX) $(LDFLAGS) table/filter_block_test.o $(LIBOBJECTS) $(TESTHARNESS) -o $@ $(LIBS) + +issue178_test: issues/issue178_test.o $(LIBOBJECTS) $(TESTHARNESS) + $(CXX) $(LDFLAGS) issues/issue178_test.o $(LIBOBJECTS) $(TESTHARNESS) -o $@ $(LIBS) + +issue200_test: issues/issue200_test.o $(LIBOBJECTS) $(TESTHARNESS) + $(CXX) $(LDFLAGS) issues/issue200_test.o $(LIBOBJECTS) $(TESTHARNESS) -o $@ $(LIBS) + +log_test: db/log_test.o $(LIBOBJECTS) $(TESTHARNESS) + $(CXX) $(LDFLAGS) db/log_test.o $(LIBOBJECTS) $(TESTHARNESS) -o $@ $(LIBS) + +table_test: table/table_test.o $(LIBOBJECTS) $(TESTHARNESS) + $(CXX) $(LDFLAGS) table/table_test.o $(LIBOBJECTS) $(TESTHARNESS) -o $@ $(LIBS) + +skiplist_test: db/skiplist_test.o $(LIBOBJECTS) $(TESTHARNESS) + $(CXX) $(LDFLAGS) db/skiplist_test.o $(LIBOBJECTS) $(TESTHARNESS) -o $@ $(LIBS) + +version_edit_test: db/version_edit_test.o $(LIBOBJECTS) $(TESTHARNESS) + $(CXX) $(LDFLAGS) db/version_edit_test.o $(LIBOBJECTS) $(TESTHARNESS) -o $@ $(LIBS) + +version_set_test: db/version_set_test.o $(LIBOBJECTS) $(TESTHARNESS) + $(CXX) $(LDFLAGS) db/version_set_test.o $(LIBOBJECTS) $(TESTHARNESS) -o $@ $(LIBS) + +write_batch_test: db/write_batch_test.o $(LIBOBJECTS) $(TESTHARNESS) + $(CXX) $(LDFLAGS) db/write_batch_test.o $(LIBOBJECTS) $(TESTHARNESS) -o $@ $(LIBS) + +$(MEMENVLIBRARY) : $(MEMENVOBJECTS) + rm -f $@ + $(AR) -rs $@ $(MEMENVOBJECTS) + +memenv_test : helpers/memenv/memenv_test.o $(MEMENVLIBRARY) $(LIBRARY) $(TESTHARNESS) + $(CXX) $(LDFLAGS) helpers/memenv/memenv_test.o $(MEMENVLIBRARY) $(LIBRARY) $(TESTHARNESS) -o $@ $(LIBS) + +ifeq ($(PLATFORM), IOS) +# For iOS, create universal object files to be used on both the simulator and +# a device. +PLATFORMSROOT=/Applications/Xcode.app/Contents/Developer/Platforms +SIMULATORROOT=$(PLATFORMSROOT)/iPhoneSimulator.platform/Developer +DEVICEROOT=$(PLATFORMSROOT)/iPhoneOS.platform/Developer +IOSVERSION=$(shell defaults read $(PLATFORMSROOT)/iPhoneOS.platform/version CFBundleShortVersionString) +IOSARCH=-arch armv6 -arch armv7 -arch armv7s -arch arm64 + +.cc.o: + mkdir -p ios-x86/$(dir $@) + $(CXX) $(CXXFLAGS) -isysroot $(SIMULATORROOT)/SDKs/iPhoneSimulator$(IOSVERSION).sdk -arch i686 -arch x86_64 -c $< -o ios-x86/$@ + mkdir -p ios-arm/$(dir $@) + xcrun -sdk iphoneos $(CXX) $(CXXFLAGS) -isysroot $(DEVICEROOT)/SDKs/iPhoneOS$(IOSVERSION).sdk $(IOSARCH) -c $< -o ios-arm/$@ + lipo ios-x86/$@ ios-arm/$@ -create -output $@ + +.c.o: + mkdir -p ios-x86/$(dir $@) + $(CC) $(CFLAGS) -isysroot $(SIMULATORROOT)/SDKs/iPhoneSimulator$(IOSVERSION).sdk -arch i686 -arch x86_64 -c $< -o ios-x86/$@ + mkdir -p ios-arm/$(dir $@) + xcrun -sdk iphoneos $(CC) $(CFLAGS) -isysroot $(DEVICEROOT)/SDKs/iPhoneOS$(IOSVERSION).sdk $(IOSARCH) -c $< -o ios-arm/$@ + lipo ios-x86/$@ ios-arm/$@ -create -output $@ + +else +.cc.o: + $(CXX) $(CXXFLAGS) -c $< -o $@ + +.c.o: + $(CC) $(CFLAGS) -c $< -o $@ +endif diff --git a/src/leveldb/NEWS b/src/leveldb/NEWS new file mode 100644 index 0000000..3fd9924 --- /dev/null +++ b/src/leveldb/NEWS @@ -0,0 +1,17 @@ +Release 1.2 2011-05-16 +---------------------- + +Fixes for larger databases (tested up to one billion 100-byte entries, +i.e., ~100GB). + +(1) Place hard limit on number of level-0 files. This fixes errors +of the form "too many open files". + +(2) Fixed memtable management. Before the fix, a heavy write burst +could cause unbounded memory usage. + +A fix for a logging bug where the reader would incorrectly complain +about corruption. + +Allow public access to WriteBatch contents so that users can easily +wrap a DB. diff --git a/src/leveldb/README b/src/leveldb/README new file mode 100644 index 0000000..3618ade --- /dev/null +++ b/src/leveldb/README @@ -0,0 +1,51 @@ +leveldb: A key-value store +Authors: Sanjay Ghemawat (sanjay@google.com) and Jeff Dean (jeff@google.com) + +The code under this directory implements a system for maintaining a +persistent key/value store. + +See doc/index.html for more explanation. +See doc/impl.html for a brief overview of the implementation. + +The public interface is in include/*.h. Callers should not include or +rely on the details of any other header files in this package. Those +internal APIs may be changed without warning. + +Guide to header files: + +include/db.h + Main interface to the DB: Start here + +include/options.h + Control over the behavior of an entire database, and also + control over the behavior of individual reads and writes. + +include/comparator.h + Abstraction for user-specified comparison function. If you want + just bytewise comparison of keys, you can use the default comparator, + but clients can write their own comparator implementations if they + want custom ordering (e.g. to handle different character + encodings, etc.) + +include/iterator.h + Interface for iterating over data. You can get an iterator + from a DB object. + +include/write_batch.h + Interface for atomically applying multiple updates to a database. + +include/slice.h + A simple module for maintaining a pointer and a length into some + other byte array. + +include/status.h + Status is returned from many of the public interfaces and is used + to report success and various kinds of errors. + +include/env.h + Abstraction of the OS environment. A posix implementation of + this interface is in util/env_posix.cc + +include/table.h +include/table_builder.h + Lower-level modules that most clients probably won't use directly diff --git a/src/leveldb/TODO b/src/leveldb/TODO new file mode 100644 index 0000000..e603c07 --- /dev/null +++ b/src/leveldb/TODO @@ -0,0 +1,14 @@ +ss +- Stats + +db +- Maybe implement DB::BulkDeleteForRange(start_key, end_key) + that would blow away files whose ranges are entirely contained + within [start_key..end_key]? For Chrome, deletion of obsolete + object stores, etc. can be done in the background anyway, so + probably not that important. +- There have been requests for MultiGet. + +After a range is completely deleted, what gets rid of the +corresponding files if we do no future changes to that range. Make +the conditions for triggering compactions fire in more situations? diff --git a/src/leveldb/WINDOWS.md b/src/leveldb/WINDOWS.md new file mode 100644 index 0000000..5b76c24 --- /dev/null +++ b/src/leveldb/WINDOWS.md @@ -0,0 +1,39 @@ +# Building LevelDB On Windows + +## Prereqs + +Install the [Windows Software Development Kit version 7.1](http://www.microsoft.com/downloads/dlx/en-us/listdetailsview.aspx?FamilyID=6b6c21d2-2006-4afa-9702-529fa782d63b). + +Download and extract the [Snappy source distribution](http://snappy.googlecode.com/files/snappy-1.0.5.tar.gz) + +1. Open the "Windows SDK 7.1 Command Prompt" : + Start Menu -> "Microsoft Windows SDK v7.1" > "Windows SDK 7.1 Command Prompt" +2. Change the directory to the leveldb project + +## Building the Static lib + +* 32 bit Version + + setenv /x86 + msbuild.exe /p:Configuration=Release /p:Platform=Win32 /p:Snappy=..\snappy-1.0.5 + +* 64 bit Version + + setenv /x64 + msbuild.exe /p:Configuration=Release /p:Platform=x64 /p:Snappy=..\snappy-1.0.5 + + +## Building and Running the Benchmark app + +* 32 bit Version + + setenv /x86 + msbuild.exe /p:Configuration=Benchmark /p:Platform=Win32 /p:Snappy=..\snappy-1.0.5 + Benchmark\leveldb.exe + +* 64 bit Version + + setenv /x64 + msbuild.exe /p:Configuration=Benchmark /p:Platform=x64 /p:Snappy=..\snappy-1.0.5 + x64\Benchmark\leveldb.exe + diff --git a/src/leveldb/build_detect_platform b/src/leveldb/build_detect_platform new file mode 100755 index 0000000..85b1ce0 --- /dev/null +++ b/src/leveldb/build_detect_platform @@ -0,0 +1,224 @@ +#!/bin/sh +# +# Detects OS we're compiling on and outputs a file specified by the first +# argument, which in turn gets read while processing Makefile. +# +# The output will set the following variables: +# CC C Compiler path +# CXX C++ Compiler path +# PLATFORM_LDFLAGS Linker flags +# PLATFORM_LIBS Libraries flags +# PLATFORM_SHARED_EXT Extension for shared libraries +# PLATFORM_SHARED_LDFLAGS Flags for building shared library +# This flag is embedded just before the name +# of the shared library without intervening spaces +# PLATFORM_SHARED_CFLAGS Flags for compiling objects for shared library +# PLATFORM_CCFLAGS C compiler flags +# PLATFORM_CXXFLAGS C++ compiler flags. Will contain: +# PLATFORM_SHARED_VERSIONED Set to 'true' if platform supports versioned +# shared libraries, empty otherwise. +# +# The PLATFORM_CCFLAGS and PLATFORM_CXXFLAGS might include the following: +# +# -DLEVELDB_CSTDATOMIC_PRESENT if is present +# -DLEVELDB_PLATFORM_POSIX for Posix-based platforms +# -DSNAPPY if the Snappy library is present +# + +OUTPUT=$1 +PREFIX=$2 +if test -z "$OUTPUT" || test -z "$PREFIX"; then + echo "usage: $0 " >&2 + exit 1 +fi + +# Delete existing output, if it exists +rm -f $OUTPUT +touch $OUTPUT + +if test -z "$CC"; then + CC=cc +fi + +if test -z "$CXX"; then + CXX=g++ +fi + +if test -z "$TMPDIR"; then + TMPDIR=/tmp +fi + +# Detect OS +if test -z "$TARGET_OS"; then + TARGET_OS=`uname -s` +fi + +COMMON_FLAGS= +CROSS_COMPILE= +PLATFORM_CCFLAGS= +PLATFORM_CXXFLAGS= +PLATFORM_LDFLAGS= +PLATFORM_LIBS= +PLATFORM_SHARED_EXT="so" +PLATFORM_SHARED_LDFLAGS="-shared -Wl,-soname -Wl," +PLATFORM_SHARED_CFLAGS="-fPIC" +PLATFORM_SHARED_VERSIONED=true + +MEMCMP_FLAG= +if [ "$CXX" = "g++" ]; then + # Use libc's memcmp instead of GCC's memcmp. This results in ~40% + # performance improvement on readrandom under gcc 4.4.3 on Linux/x86. + MEMCMP_FLAG="-fno-builtin-memcmp" +fi + +case "$TARGET_OS" in + Darwin) + PLATFORM=OS_MACOSX + COMMON_FLAGS="$MEMCMP_FLAG -DOS_MACOSX" + PLATFORM_SHARED_EXT=dylib + [ -z "$INSTALL_PATH" ] && INSTALL_PATH=`pwd` + PLATFORM_SHARED_LDFLAGS="-dynamiclib -install_name $INSTALL_PATH/" + PORT_FILE=port/port_posix.cc + ;; + Linux) + PLATFORM=OS_LINUX + COMMON_FLAGS="$MEMCMP_FLAG -pthread -DOS_LINUX" + PLATFORM_LDFLAGS="-pthread" + PORT_FILE=port/port_posix.cc + ;; + SunOS) + PLATFORM=OS_SOLARIS + COMMON_FLAGS="$MEMCMP_FLAG -D_REENTRANT -DOS_SOLARIS" + PLATFORM_LIBS="-lpthread -lrt" + PORT_FILE=port/port_posix.cc + ;; + FreeBSD) + PLATFORM=OS_FREEBSD + COMMON_FLAGS="$MEMCMP_FLAG -D_REENTRANT -DOS_FREEBSD" + PLATFORM_LIBS="-lpthread" + PORT_FILE=port/port_posix.cc + ;; + GNU/kFreeBSD) + PLATFORM=OS_KFREEBSD + COMMON_FLAGS="$MEMCMP_FLAG -D_REENTRANT -DOS_KFREEBSD" + PLATFORM_LIBS="-lpthread" + PORT_FILE=port/port_posix.cc + ;; + NetBSD) + PLATFORM=OS_NETBSD + COMMON_FLAGS="$MEMCMP_FLAG -D_REENTRANT -DOS_NETBSD" + PLATFORM_LIBS="-lpthread -lgcc_s" + PORT_FILE=port/port_posix.cc + ;; + OpenBSD) + PLATFORM=OS_OPENBSD + COMMON_FLAGS="$MEMCMP_FLAG -D_REENTRANT -DOS_OPENBSD" + PLATFORM_LDFLAGS="-pthread" + PORT_FILE=port/port_posix.cc + ;; + DragonFly) + PLATFORM=OS_DRAGONFLYBSD + COMMON_FLAGS="$MEMCMP_FLAG -D_REENTRANT -DOS_DRAGONFLYBSD" + PLATFORM_LIBS="-lpthread" + PORT_FILE=port/port_posix.cc + ;; + OS_ANDROID_CROSSCOMPILE) + PLATFORM=OS_ANDROID + COMMON_FLAGS="$MEMCMP_FLAG -D_REENTRANT -DOS_ANDROID -DLEVELDB_PLATFORM_POSIX" + PLATFORM_LDFLAGS="" # All pthread features are in the Android C library + PORT_FILE=port/port_posix.cc + CROSS_COMPILE=true + ;; + HP-UX) + PLATFORM=OS_HPUX + COMMON_FLAGS="$MEMCMP_FLAG -D_REENTRANT -DOS_HPUX" + PLATFORM_LDFLAGS="-pthread" + PORT_FILE=port/port_posix.cc + # man ld: +h internal_name + PLATFORM_SHARED_LDFLAGS="-shared -Wl,+h -Wl," + ;; + IOS) + PLATFORM=IOS + COMMON_FLAGS="$MEMCMP_FLAG -DOS_MACOSX" + [ -z "$INSTALL_PATH" ] && INSTALL_PATH=`pwd` + PORT_FILE=port/port_posix.cc + PLATFORM_SHARED_EXT= + PLATFORM_SHARED_LDFLAGS= + PLATFORM_SHARED_CFLAGS= + PLATFORM_SHARED_VERSIONED= + ;; + OS_WINDOWS_CROSSCOMPILE | NATIVE_WINDOWS) + PLATFORM=OS_WINDOWS + COMMON_FLAGS="-fno-builtin-memcmp -D_REENTRANT -DOS_WINDOWS -DLEVELDB_PLATFORM_WINDOWS -DWINVER=0x0500 -D__USE_MINGW_ANSI_STDIO=1" + PLATFORM_SOURCES="util/env_win.cc" + PLATFORM_LIBS="-lshlwapi" + PORT_FILE=port/port_win.cc + CROSS_COMPILE=true + ;; + *) + echo "Unknown platform!" >&2 + exit 1 +esac + +# We want to make a list of all cc files within util, db, table, and helpers +# except for the test and benchmark files. By default, find will output a list +# of all files matching either rule, so we need to append -print to make the +# prune take effect. +DIRS="$PREFIX/db $PREFIX/util $PREFIX/table" + +set -f # temporarily disable globbing so that our patterns aren't expanded +PRUNE_TEST="-name *test*.cc -prune" +PRUNE_BENCH="-name *_bench.cc -prune" +PRUNE_TOOL="-name leveldb_main.cc -prune" +PORTABLE_FILES=`find $DIRS $PRUNE_TEST -o $PRUNE_BENCH -o $PRUNE_TOOL -o -name '*.cc' -print | sort | sed "s,^$PREFIX/,," | tr "\n" " "` + +set +f # re-enable globbing + +# The sources consist of the portable files, plus the platform-specific port +# file. +echo "SOURCES=$PORTABLE_FILES $PORT_FILE" >> $OUTPUT +echo "MEMENV_SOURCES=helpers/memenv/memenv.cc" >> $OUTPUT + +if [ "$CROSS_COMPILE" = "true" ]; then + # Cross-compiling; do not try any compilation tests. + true +else + CXXOUTPUT="${TMPDIR}/leveldb_build_detect_platform-cxx.$$" + + # If -std=c++0x works, use . Otherwise use port_posix.h. + $CXX $CXXFLAGS -std=c++0x -x c++ - -o $CXXOUTPUT 2>/dev/null < + int main() {} +EOF + if [ "$?" = 0 ]; then + COMMON_FLAGS="$COMMON_FLAGS -DLEVELDB_PLATFORM_POSIX -DLEVELDB_CSTDATOMIC_PRESENT" + PLATFORM_CXXFLAGS="-std=c++0x" + else + COMMON_FLAGS="$COMMON_FLAGS -DLEVELDB_PLATFORM_POSIX" + fi + + # Test whether tcmalloc is available + $CXX $CXXFLAGS -x c++ - -o $CXXOUTPUT -ltcmalloc 2>/dev/null </dev/null +fi + +PLATFORM_CCFLAGS="$PLATFORM_CCFLAGS $COMMON_FLAGS" +PLATFORM_CXXFLAGS="$PLATFORM_CXXFLAGS $COMMON_FLAGS" + +echo "CC=$CC" >> $OUTPUT +echo "CXX=$CXX" >> $OUTPUT +echo "PLATFORM=$PLATFORM" >> $OUTPUT +echo "PLATFORM_LDFLAGS=$PLATFORM_LDFLAGS" >> $OUTPUT +echo "PLATFORM_LIBS=$PLATFORM_LIBS" >> $OUTPUT +echo "PLATFORM_CCFLAGS=$PLATFORM_CCFLAGS" >> $OUTPUT +echo "PLATFORM_CXXFLAGS=$PLATFORM_CXXFLAGS" >> $OUTPUT +echo "PLATFORM_SHARED_CFLAGS=$PLATFORM_SHARED_CFLAGS" >> $OUTPUT +echo "PLATFORM_SHARED_EXT=$PLATFORM_SHARED_EXT" >> $OUTPUT +echo "PLATFORM_SHARED_LDFLAGS=$PLATFORM_SHARED_LDFLAGS" >> $OUTPUT +echo "PLATFORM_SHARED_VERSIONED=$PLATFORM_SHARED_VERSIONED" >> $OUTPUT diff --git a/src/leveldb/db/autocompact_test.cc b/src/leveldb/db/autocompact_test.cc new file mode 100644 index 0000000..d20a236 --- /dev/null +++ b/src/leveldb/db/autocompact_test.cc @@ -0,0 +1,118 @@ +// Copyright (c) 2013 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "leveldb/db.h" +#include "db/db_impl.h" +#include "leveldb/cache.h" +#include "util/testharness.h" +#include "util/testutil.h" + +namespace leveldb { + +class AutoCompactTest { + public: + std::string dbname_; + Cache* tiny_cache_; + Options options_; + DB* db_; + + AutoCompactTest() { + dbname_ = test::TmpDir() + "/autocompact_test"; + tiny_cache_ = NewLRUCache(100); + options_.block_cache = tiny_cache_; + DestroyDB(dbname_, options_); + options_.create_if_missing = true; + options_.compression = kNoCompression; + ASSERT_OK(DB::Open(options_, dbname_, &db_)); + } + + ~AutoCompactTest() { + delete db_; + DestroyDB(dbname_, Options()); + delete tiny_cache_; + } + + std::string Key(int i) { + char buf[100]; + snprintf(buf, sizeof(buf), "key%06d", i); + return std::string(buf); + } + + uint64_t Size(const Slice& start, const Slice& limit) { + Range r(start, limit); + uint64_t size; + db_->GetApproximateSizes(&r, 1, &size); + return size; + } + + void DoReads(int n); +}; + +static const int kValueSize = 200 * 1024; +static const int kTotalSize = 100 * 1024 * 1024; +static const int kCount = kTotalSize / kValueSize; + +// Read through the first n keys repeatedly and check that they get +// compacted (verified by checking the size of the key space). +void AutoCompactTest::DoReads(int n) { + std::string value(kValueSize, 'x'); + DBImpl* dbi = reinterpret_cast(db_); + + // Fill database + for (int i = 0; i < kCount; i++) { + ASSERT_OK(db_->Put(WriteOptions(), Key(i), value)); + } + ASSERT_OK(dbi->TEST_CompactMemTable()); + + // Delete everything + for (int i = 0; i < kCount; i++) { + ASSERT_OK(db_->Delete(WriteOptions(), Key(i))); + } + ASSERT_OK(dbi->TEST_CompactMemTable()); + + // Get initial measurement of the space we will be reading. + const int64_t initial_size = Size(Key(0), Key(n)); + const int64_t initial_other_size = Size(Key(n), Key(kCount)); + + // Read until size drops significantly. + std::string limit_key = Key(n); + for (int read = 0; true; read++) { + ASSERT_LT(read, 100) << "Taking too long to compact"; + Iterator* iter = db_->NewIterator(ReadOptions()); + for (iter->SeekToFirst(); + iter->Valid() && iter->key().ToString() < limit_key; + iter->Next()) { + // Drop data + } + delete iter; + // Wait a little bit to allow any triggered compactions to complete. + Env::Default()->SleepForMicroseconds(1000000); + uint64_t size = Size(Key(0), Key(n)); + fprintf(stderr, "iter %3d => %7.3f MB [other %7.3f MB]\n", + read+1, size/1048576.0, Size(Key(n), Key(kCount))/1048576.0); + if (size <= initial_size/10) { + break; + } + } + + // Verify that the size of the key space not touched by the reads + // is pretty much unchanged. + const int64_t final_other_size = Size(Key(n), Key(kCount)); + ASSERT_LE(final_other_size, initial_other_size + 1048576); + ASSERT_GE(final_other_size, initial_other_size/5 - 1048576); +} + +TEST(AutoCompactTest, ReadAll) { + DoReads(kCount); +} + +TEST(AutoCompactTest, ReadHalf) { + DoReads(kCount/2); +} + +} // namespace leveldb + +int main(int argc, char** argv) { + return leveldb::test::RunAllTests(); +} diff --git a/src/leveldb/db/builder.cc b/src/leveldb/db/builder.cc new file mode 100644 index 0000000..f419882 --- /dev/null +++ b/src/leveldb/db/builder.cc @@ -0,0 +1,88 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "db/builder.h" + +#include "db/filename.h" +#include "db/dbformat.h" +#include "db/table_cache.h" +#include "db/version_edit.h" +#include "leveldb/db.h" +#include "leveldb/env.h" +#include "leveldb/iterator.h" + +namespace leveldb { + +Status BuildTable(const std::string& dbname, + Env* env, + const Options& options, + TableCache* table_cache, + Iterator* iter, + FileMetaData* meta) { + Status s; + meta->file_size = 0; + iter->SeekToFirst(); + + std::string fname = TableFileName(dbname, meta->number); + if (iter->Valid()) { + WritableFile* file; + s = env->NewWritableFile(fname, &file); + if (!s.ok()) { + return s; + } + + TableBuilder* builder = new TableBuilder(options, file); + meta->smallest.DecodeFrom(iter->key()); + for (; iter->Valid(); iter->Next()) { + Slice key = iter->key(); + meta->largest.DecodeFrom(key); + builder->Add(key, iter->value()); + } + + // Finish and check for builder errors + if (s.ok()) { + s = builder->Finish(); + if (s.ok()) { + meta->file_size = builder->FileSize(); + assert(meta->file_size > 0); + } + } else { + builder->Abandon(); + } + delete builder; + + // Finish and check for file errors + if (s.ok()) { + s = file->Sync(); + } + if (s.ok()) { + s = file->Close(); + } + delete file; + file = NULL; + + if (s.ok()) { + // Verify that the table is usable + Iterator* it = table_cache->NewIterator(ReadOptions(), + meta->number, + meta->file_size); + s = it->status(); + delete it; + } + } + + // Check for input iterator errors + if (!iter->status().ok()) { + s = iter->status(); + } + + if (s.ok() && meta->file_size > 0) { + // Keep it + } else { + env->DeleteFile(fname); + } + return s; +} + +} // namespace leveldb diff --git a/src/leveldb/db/builder.h b/src/leveldb/db/builder.h new file mode 100644 index 0000000..62431fc --- /dev/null +++ b/src/leveldb/db/builder.h @@ -0,0 +1,34 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#ifndef STORAGE_LEVELDB_DB_BUILDER_H_ +#define STORAGE_LEVELDB_DB_BUILDER_H_ + +#include "leveldb/status.h" + +namespace leveldb { + +struct Options; +struct FileMetaData; + +class Env; +class Iterator; +class TableCache; +class VersionEdit; + +// Build a Table file from the contents of *iter. The generated file +// will be named according to meta->number. On success, the rest of +// *meta will be filled with metadata about the generated table. +// If no data is present in *iter, meta->file_size will be set to +// zero, and no Table file will be produced. +extern Status BuildTable(const std::string& dbname, + Env* env, + const Options& options, + TableCache* table_cache, + Iterator* iter, + FileMetaData* meta); + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_DB_BUILDER_H_ diff --git a/src/leveldb/db/c.cc b/src/leveldb/db/c.cc new file mode 100644 index 0000000..08ff0ad --- /dev/null +++ b/src/leveldb/db/c.cc @@ -0,0 +1,595 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "leveldb/c.h" + +#include +#include +#include "leveldb/cache.h" +#include "leveldb/comparator.h" +#include "leveldb/db.h" +#include "leveldb/env.h" +#include "leveldb/filter_policy.h" +#include "leveldb/iterator.h" +#include "leveldb/options.h" +#include "leveldb/status.h" +#include "leveldb/write_batch.h" + +using leveldb::Cache; +using leveldb::Comparator; +using leveldb::CompressionType; +using leveldb::DB; +using leveldb::Env; +using leveldb::FileLock; +using leveldb::FilterPolicy; +using leveldb::Iterator; +using leveldb::kMajorVersion; +using leveldb::kMinorVersion; +using leveldb::Logger; +using leveldb::NewBloomFilterPolicy; +using leveldb::NewLRUCache; +using leveldb::Options; +using leveldb::RandomAccessFile; +using leveldb::Range; +using leveldb::ReadOptions; +using leveldb::SequentialFile; +using leveldb::Slice; +using leveldb::Snapshot; +using leveldb::Status; +using leveldb::WritableFile; +using leveldb::WriteBatch; +using leveldb::WriteOptions; + +extern "C" { + +struct leveldb_t { DB* rep; }; +struct leveldb_iterator_t { Iterator* rep; }; +struct leveldb_writebatch_t { WriteBatch rep; }; +struct leveldb_snapshot_t { const Snapshot* rep; }; +struct leveldb_readoptions_t { ReadOptions rep; }; +struct leveldb_writeoptions_t { WriteOptions rep; }; +struct leveldb_options_t { Options rep; }; +struct leveldb_cache_t { Cache* rep; }; +struct leveldb_seqfile_t { SequentialFile* rep; }; +struct leveldb_randomfile_t { RandomAccessFile* rep; }; +struct leveldb_writablefile_t { WritableFile* rep; }; +struct leveldb_logger_t { Logger* rep; }; +struct leveldb_filelock_t { FileLock* rep; }; + +struct leveldb_comparator_t : public Comparator { + void* state_; + void (*destructor_)(void*); + int (*compare_)( + void*, + const char* a, size_t alen, + const char* b, size_t blen); + const char* (*name_)(void*); + + virtual ~leveldb_comparator_t() { + (*destructor_)(state_); + } + + virtual int Compare(const Slice& a, const Slice& b) const { + return (*compare_)(state_, a.data(), a.size(), b.data(), b.size()); + } + + virtual const char* Name() const { + return (*name_)(state_); + } + + // No-ops since the C binding does not support key shortening methods. + virtual void FindShortestSeparator(std::string*, const Slice&) const { } + virtual void FindShortSuccessor(std::string* key) const { } +}; + +struct leveldb_filterpolicy_t : public FilterPolicy { + void* state_; + void (*destructor_)(void*); + const char* (*name_)(void*); + char* (*create_)( + void*, + const char* const* key_array, const size_t* key_length_array, + int num_keys, + size_t* filter_length); + unsigned char (*key_match_)( + void*, + const char* key, size_t length, + const char* filter, size_t filter_length); + + virtual ~leveldb_filterpolicy_t() { + (*destructor_)(state_); + } + + virtual const char* Name() const { + return (*name_)(state_); + } + + virtual void CreateFilter(const Slice* keys, int n, std::string* dst) const { + std::vector key_pointers(n); + std::vector key_sizes(n); + for (int i = 0; i < n; i++) { + key_pointers[i] = keys[i].data(); + key_sizes[i] = keys[i].size(); + } + size_t len; + char* filter = (*create_)(state_, &key_pointers[0], &key_sizes[0], n, &len); + dst->append(filter, len); + free(filter); + } + + virtual bool KeyMayMatch(const Slice& key, const Slice& filter) const { + return (*key_match_)(state_, key.data(), key.size(), + filter.data(), filter.size()); + } +}; + +struct leveldb_env_t { + Env* rep; + bool is_default; +}; + +static bool SaveError(char** errptr, const Status& s) { + assert(errptr != NULL); + if (s.ok()) { + return false; + } else if (*errptr == NULL) { + *errptr = strdup(s.ToString().c_str()); + } else { + // TODO(sanjay): Merge with existing error? + free(*errptr); + *errptr = strdup(s.ToString().c_str()); + } + return true; +} + +static char* CopyString(const std::string& str) { + char* result = reinterpret_cast(malloc(sizeof(char) * str.size())); + memcpy(result, str.data(), sizeof(char) * str.size()); + return result; +} + +leveldb_t* leveldb_open( + const leveldb_options_t* options, + const char* name, + char** errptr) { + DB* db; + if (SaveError(errptr, DB::Open(options->rep, std::string(name), &db))) { + return NULL; + } + leveldb_t* result = new leveldb_t; + result->rep = db; + return result; +} + +void leveldb_close(leveldb_t* db) { + delete db->rep; + delete db; +} + +void leveldb_put( + leveldb_t* db, + const leveldb_writeoptions_t* options, + const char* key, size_t keylen, + const char* val, size_t vallen, + char** errptr) { + SaveError(errptr, + db->rep->Put(options->rep, Slice(key, keylen), Slice(val, vallen))); +} + +void leveldb_delete( + leveldb_t* db, + const leveldb_writeoptions_t* options, + const char* key, size_t keylen, + char** errptr) { + SaveError(errptr, db->rep->Delete(options->rep, Slice(key, keylen))); +} + + +void leveldb_write( + leveldb_t* db, + const leveldb_writeoptions_t* options, + leveldb_writebatch_t* batch, + char** errptr) { + SaveError(errptr, db->rep->Write(options->rep, &batch->rep)); +} + +char* leveldb_get( + leveldb_t* db, + const leveldb_readoptions_t* options, + const char* key, size_t keylen, + size_t* vallen, + char** errptr) { + char* result = NULL; + std::string tmp; + Status s = db->rep->Get(options->rep, Slice(key, keylen), &tmp); + if (s.ok()) { + *vallen = tmp.size(); + result = CopyString(tmp); + } else { + *vallen = 0; + if (!s.IsNotFound()) { + SaveError(errptr, s); + } + } + return result; +} + +leveldb_iterator_t* leveldb_create_iterator( + leveldb_t* db, + const leveldb_readoptions_t* options) { + leveldb_iterator_t* result = new leveldb_iterator_t; + result->rep = db->rep->NewIterator(options->rep); + return result; +} + +const leveldb_snapshot_t* leveldb_create_snapshot( + leveldb_t* db) { + leveldb_snapshot_t* result = new leveldb_snapshot_t; + result->rep = db->rep->GetSnapshot(); + return result; +} + +void leveldb_release_snapshot( + leveldb_t* db, + const leveldb_snapshot_t* snapshot) { + db->rep->ReleaseSnapshot(snapshot->rep); + delete snapshot; +} + +char* leveldb_property_value( + leveldb_t* db, + const char* propname) { + std::string tmp; + if (db->rep->GetProperty(Slice(propname), &tmp)) { + // We use strdup() since we expect human readable output. + return strdup(tmp.c_str()); + } else { + return NULL; + } +} + +void leveldb_approximate_sizes( + leveldb_t* db, + int num_ranges, + const char* const* range_start_key, const size_t* range_start_key_len, + const char* const* range_limit_key, const size_t* range_limit_key_len, + uint64_t* sizes) { + Range* ranges = new Range[num_ranges]; + for (int i = 0; i < num_ranges; i++) { + ranges[i].start = Slice(range_start_key[i], range_start_key_len[i]); + ranges[i].limit = Slice(range_limit_key[i], range_limit_key_len[i]); + } + db->rep->GetApproximateSizes(ranges, num_ranges, sizes); + delete[] ranges; +} + +void leveldb_compact_range( + leveldb_t* db, + const char* start_key, size_t start_key_len, + const char* limit_key, size_t limit_key_len) { + Slice a, b; + db->rep->CompactRange( + // Pass NULL Slice if corresponding "const char*" is NULL + (start_key ? (a = Slice(start_key, start_key_len), &a) : NULL), + (limit_key ? (b = Slice(limit_key, limit_key_len), &b) : NULL)); +} + +void leveldb_destroy_db( + const leveldb_options_t* options, + const char* name, + char** errptr) { + SaveError(errptr, DestroyDB(name, options->rep)); +} + +void leveldb_repair_db( + const leveldb_options_t* options, + const char* name, + char** errptr) { + SaveError(errptr, RepairDB(name, options->rep)); +} + +void leveldb_iter_destroy(leveldb_iterator_t* iter) { + delete iter->rep; + delete iter; +} + +unsigned char leveldb_iter_valid(const leveldb_iterator_t* iter) { + return iter->rep->Valid(); +} + +void leveldb_iter_seek_to_first(leveldb_iterator_t* iter) { + iter->rep->SeekToFirst(); +} + +void leveldb_iter_seek_to_last(leveldb_iterator_t* iter) { + iter->rep->SeekToLast(); +} + +void leveldb_iter_seek(leveldb_iterator_t* iter, const char* k, size_t klen) { + iter->rep->Seek(Slice(k, klen)); +} + +void leveldb_iter_next(leveldb_iterator_t* iter) { + iter->rep->Next(); +} + +void leveldb_iter_prev(leveldb_iterator_t* iter) { + iter->rep->Prev(); +} + +const char* leveldb_iter_key(const leveldb_iterator_t* iter, size_t* klen) { + Slice s = iter->rep->key(); + *klen = s.size(); + return s.data(); +} + +const char* leveldb_iter_value(const leveldb_iterator_t* iter, size_t* vlen) { + Slice s = iter->rep->value(); + *vlen = s.size(); + return s.data(); +} + +void leveldb_iter_get_error(const leveldb_iterator_t* iter, char** errptr) { + SaveError(errptr, iter->rep->status()); +} + +leveldb_writebatch_t* leveldb_writebatch_create() { + return new leveldb_writebatch_t; +} + +void leveldb_writebatch_destroy(leveldb_writebatch_t* b) { + delete b; +} + +void leveldb_writebatch_clear(leveldb_writebatch_t* b) { + b->rep.Clear(); +} + +void leveldb_writebatch_put( + leveldb_writebatch_t* b, + const char* key, size_t klen, + const char* val, size_t vlen) { + b->rep.Put(Slice(key, klen), Slice(val, vlen)); +} + +void leveldb_writebatch_delete( + leveldb_writebatch_t* b, + const char* key, size_t klen) { + b->rep.Delete(Slice(key, klen)); +} + +void leveldb_writebatch_iterate( + leveldb_writebatch_t* b, + void* state, + void (*put)(void*, const char* k, size_t klen, const char* v, size_t vlen), + void (*deleted)(void*, const char* k, size_t klen)) { + class H : public WriteBatch::Handler { + public: + void* state_; + void (*put_)(void*, const char* k, size_t klen, const char* v, size_t vlen); + void (*deleted_)(void*, const char* k, size_t klen); + virtual void Put(const Slice& key, const Slice& value) { + (*put_)(state_, key.data(), key.size(), value.data(), value.size()); + } + virtual void Delete(const Slice& key) { + (*deleted_)(state_, key.data(), key.size()); + } + }; + H handler; + handler.state_ = state; + handler.put_ = put; + handler.deleted_ = deleted; + b->rep.Iterate(&handler); +} + +leveldb_options_t* leveldb_options_create() { + return new leveldb_options_t; +} + +void leveldb_options_destroy(leveldb_options_t* options) { + delete options; +} + +void leveldb_options_set_comparator( + leveldb_options_t* opt, + leveldb_comparator_t* cmp) { + opt->rep.comparator = cmp; +} + +void leveldb_options_set_filter_policy( + leveldb_options_t* opt, + leveldb_filterpolicy_t* policy) { + opt->rep.filter_policy = policy; +} + +void leveldb_options_set_create_if_missing( + leveldb_options_t* opt, unsigned char v) { + opt->rep.create_if_missing = v; +} + +void leveldb_options_set_error_if_exists( + leveldb_options_t* opt, unsigned char v) { + opt->rep.error_if_exists = v; +} + +void leveldb_options_set_paranoid_checks( + leveldb_options_t* opt, unsigned char v) { + opt->rep.paranoid_checks = v; +} + +void leveldb_options_set_env(leveldb_options_t* opt, leveldb_env_t* env) { + opt->rep.env = (env ? env->rep : NULL); +} + +void leveldb_options_set_info_log(leveldb_options_t* opt, leveldb_logger_t* l) { + opt->rep.info_log = (l ? l->rep : NULL); +} + +void leveldb_options_set_write_buffer_size(leveldb_options_t* opt, size_t s) { + opt->rep.write_buffer_size = s; +} + +void leveldb_options_set_max_open_files(leveldb_options_t* opt, int n) { + opt->rep.max_open_files = n; +} + +void leveldb_options_set_cache(leveldb_options_t* opt, leveldb_cache_t* c) { + opt->rep.block_cache = c->rep; +} + +void leveldb_options_set_block_size(leveldb_options_t* opt, size_t s) { + opt->rep.block_size = s; +} + +void leveldb_options_set_block_restart_interval(leveldb_options_t* opt, int n) { + opt->rep.block_restart_interval = n; +} + +void leveldb_options_set_compression(leveldb_options_t* opt, int t) { + opt->rep.compression = static_cast(t); +} + +leveldb_comparator_t* leveldb_comparator_create( + void* state, + void (*destructor)(void*), + int (*compare)( + void*, + const char* a, size_t alen, + const char* b, size_t blen), + const char* (*name)(void*)) { + leveldb_comparator_t* result = new leveldb_comparator_t; + result->state_ = state; + result->destructor_ = destructor; + result->compare_ = compare; + result->name_ = name; + return result; +} + +void leveldb_comparator_destroy(leveldb_comparator_t* cmp) { + delete cmp; +} + +leveldb_filterpolicy_t* leveldb_filterpolicy_create( + void* state, + void (*destructor)(void*), + char* (*create_filter)( + void*, + const char* const* key_array, const size_t* key_length_array, + int num_keys, + size_t* filter_length), + unsigned char (*key_may_match)( + void*, + const char* key, size_t length, + const char* filter, size_t filter_length), + const char* (*name)(void*)) { + leveldb_filterpolicy_t* result = new leveldb_filterpolicy_t; + result->state_ = state; + result->destructor_ = destructor; + result->create_ = create_filter; + result->key_match_ = key_may_match; + result->name_ = name; + return result; +} + +void leveldb_filterpolicy_destroy(leveldb_filterpolicy_t* filter) { + delete filter; +} + +leveldb_filterpolicy_t* leveldb_filterpolicy_create_bloom(int bits_per_key) { + // Make a leveldb_filterpolicy_t, but override all of its methods so + // they delegate to a NewBloomFilterPolicy() instead of user + // supplied C functions. + struct Wrapper : public leveldb_filterpolicy_t { + const FilterPolicy* rep_; + ~Wrapper() { delete rep_; } + const char* Name() const { return rep_->Name(); } + void CreateFilter(const Slice* keys, int n, std::string* dst) const { + return rep_->CreateFilter(keys, n, dst); + } + bool KeyMayMatch(const Slice& key, const Slice& filter) const { + return rep_->KeyMayMatch(key, filter); + } + static void DoNothing(void*) { } + }; + Wrapper* wrapper = new Wrapper; + wrapper->rep_ = NewBloomFilterPolicy(bits_per_key); + wrapper->state_ = NULL; + wrapper->destructor_ = &Wrapper::DoNothing; + return wrapper; +} + +leveldb_readoptions_t* leveldb_readoptions_create() { + return new leveldb_readoptions_t; +} + +void leveldb_readoptions_destroy(leveldb_readoptions_t* opt) { + delete opt; +} + +void leveldb_readoptions_set_verify_checksums( + leveldb_readoptions_t* opt, + unsigned char v) { + opt->rep.verify_checksums = v; +} + +void leveldb_readoptions_set_fill_cache( + leveldb_readoptions_t* opt, unsigned char v) { + opt->rep.fill_cache = v; +} + +void leveldb_readoptions_set_snapshot( + leveldb_readoptions_t* opt, + const leveldb_snapshot_t* snap) { + opt->rep.snapshot = (snap ? snap->rep : NULL); +} + +leveldb_writeoptions_t* leveldb_writeoptions_create() { + return new leveldb_writeoptions_t; +} + +void leveldb_writeoptions_destroy(leveldb_writeoptions_t* opt) { + delete opt; +} + +void leveldb_writeoptions_set_sync( + leveldb_writeoptions_t* opt, unsigned char v) { + opt->rep.sync = v; +} + +leveldb_cache_t* leveldb_cache_create_lru(size_t capacity) { + leveldb_cache_t* c = new leveldb_cache_t; + c->rep = NewLRUCache(capacity); + return c; +} + +void leveldb_cache_destroy(leveldb_cache_t* cache) { + delete cache->rep; + delete cache; +} + +leveldb_env_t* leveldb_create_default_env() { + leveldb_env_t* result = new leveldb_env_t; + result->rep = Env::Default(); + result->is_default = true; + return result; +} + +void leveldb_env_destroy(leveldb_env_t* env) { + if (!env->is_default) delete env->rep; + delete env; +} + +void leveldb_free(void* ptr) { + free(ptr); +} + +int leveldb_major_version() { + return kMajorVersion; +} + +int leveldb_minor_version() { + return kMinorVersion; +} + +} // end extern "C" diff --git a/src/leveldb/db/c_test.c b/src/leveldb/db/c_test.c new file mode 100644 index 0000000..7cd5ee0 --- /dev/null +++ b/src/leveldb/db/c_test.c @@ -0,0 +1,390 @@ +/* Copyright (c) 2011 The LevelDB Authors. All rights reserved. + Use of this source code is governed by a BSD-style license that can be + found in the LICENSE file. See the AUTHORS file for names of contributors. */ + +#include "leveldb/c.h" + +#include +#include +#include +#include +#include +#include + +const char* phase = ""; +static char dbname[200]; + +static void StartPhase(const char* name) { + fprintf(stderr, "=== Test %s\n", name); + phase = name; +} + +static const char* GetTempDir(void) { + const char* ret = getenv("TEST_TMPDIR"); + if (ret == NULL || ret[0] == '\0') + ret = "/tmp"; + return ret; +} + +#define CheckNoError(err) \ + if ((err) != NULL) { \ + fprintf(stderr, "%s:%d: %s: %s\n", __FILE__, __LINE__, phase, (err)); \ + abort(); \ + } + +#define CheckCondition(cond) \ + if (!(cond)) { \ + fprintf(stderr, "%s:%d: %s: %s\n", __FILE__, __LINE__, phase, #cond); \ + abort(); \ + } + +static void CheckEqual(const char* expected, const char* v, size_t n) { + if (expected == NULL && v == NULL) { + // ok + } else if (expected != NULL && v != NULL && n == strlen(expected) && + memcmp(expected, v, n) == 0) { + // ok + return; + } else { + fprintf(stderr, "%s: expected '%s', got '%s'\n", + phase, + (expected ? expected : "(null)"), + (v ? v : "(null")); + abort(); + } +} + +static void Free(char** ptr) { + if (*ptr) { + free(*ptr); + *ptr = NULL; + } +} + +static void CheckGet( + leveldb_t* db, + const leveldb_readoptions_t* options, + const char* key, + const char* expected) { + char* err = NULL; + size_t val_len; + char* val; + val = leveldb_get(db, options, key, strlen(key), &val_len, &err); + CheckNoError(err); + CheckEqual(expected, val, val_len); + Free(&val); +} + +static void CheckIter(leveldb_iterator_t* iter, + const char* key, const char* val) { + size_t len; + const char* str; + str = leveldb_iter_key(iter, &len); + CheckEqual(key, str, len); + str = leveldb_iter_value(iter, &len); + CheckEqual(val, str, len); +} + +// Callback from leveldb_writebatch_iterate() +static void CheckPut(void* ptr, + const char* k, size_t klen, + const char* v, size_t vlen) { + int* state = (int*) ptr; + CheckCondition(*state < 2); + switch (*state) { + case 0: + CheckEqual("bar", k, klen); + CheckEqual("b", v, vlen); + break; + case 1: + CheckEqual("box", k, klen); + CheckEqual("c", v, vlen); + break; + } + (*state)++; +} + +// Callback from leveldb_writebatch_iterate() +static void CheckDel(void* ptr, const char* k, size_t klen) { + int* state = (int*) ptr; + CheckCondition(*state == 2); + CheckEqual("bar", k, klen); + (*state)++; +} + +static void CmpDestroy(void* arg) { } + +static int CmpCompare(void* arg, const char* a, size_t alen, + const char* b, size_t blen) { + int n = (alen < blen) ? alen : blen; + int r = memcmp(a, b, n); + if (r == 0) { + if (alen < blen) r = -1; + else if (alen > blen) r = +1; + } + return r; +} + +static const char* CmpName(void* arg) { + return "foo"; +} + +// Custom filter policy +static unsigned char fake_filter_result = 1; +static void FilterDestroy(void* arg) { } +static const char* FilterName(void* arg) { + return "TestFilter"; +} +static char* FilterCreate( + void* arg, + const char* const* key_array, const size_t* key_length_array, + int num_keys, + size_t* filter_length) { + *filter_length = 4; + char* result = malloc(4); + memcpy(result, "fake", 4); + return result; +} +unsigned char FilterKeyMatch( + void* arg, + const char* key, size_t length, + const char* filter, size_t filter_length) { + CheckCondition(filter_length == 4); + CheckCondition(memcmp(filter, "fake", 4) == 0); + return fake_filter_result; +} + +int main(int argc, char** argv) { + leveldb_t* db; + leveldb_comparator_t* cmp; + leveldb_cache_t* cache; + leveldb_env_t* env; + leveldb_options_t* options; + leveldb_readoptions_t* roptions; + leveldb_writeoptions_t* woptions; + char* err = NULL; + int run = -1; + + CheckCondition(leveldb_major_version() >= 1); + CheckCondition(leveldb_minor_version() >= 1); + + snprintf(dbname, sizeof(dbname), + "%s/leveldb_c_test-%d", + GetTempDir(), + ((int) geteuid())); + + StartPhase("create_objects"); + cmp = leveldb_comparator_create(NULL, CmpDestroy, CmpCompare, CmpName); + env = leveldb_create_default_env(); + cache = leveldb_cache_create_lru(100000); + + options = leveldb_options_create(); + leveldb_options_set_comparator(options, cmp); + leveldb_options_set_error_if_exists(options, 1); + leveldb_options_set_cache(options, cache); + leveldb_options_set_env(options, env); + leveldb_options_set_info_log(options, NULL); + leveldb_options_set_write_buffer_size(options, 100000); + leveldb_options_set_paranoid_checks(options, 1); + leveldb_options_set_max_open_files(options, 10); + leveldb_options_set_block_size(options, 1024); + leveldb_options_set_block_restart_interval(options, 8); + leveldb_options_set_compression(options, leveldb_no_compression); + + roptions = leveldb_readoptions_create(); + leveldb_readoptions_set_verify_checksums(roptions, 1); + leveldb_readoptions_set_fill_cache(roptions, 0); + + woptions = leveldb_writeoptions_create(); + leveldb_writeoptions_set_sync(woptions, 1); + + StartPhase("destroy"); + leveldb_destroy_db(options, dbname, &err); + Free(&err); + + StartPhase("open_error"); + db = leveldb_open(options, dbname, &err); + CheckCondition(err != NULL); + Free(&err); + + StartPhase("leveldb_free"); + db = leveldb_open(options, dbname, &err); + CheckCondition(err != NULL); + leveldb_free(err); + err = NULL; + + StartPhase("open"); + leveldb_options_set_create_if_missing(options, 1); + db = leveldb_open(options, dbname, &err); + CheckNoError(err); + CheckGet(db, roptions, "foo", NULL); + + StartPhase("put"); + leveldb_put(db, woptions, "foo", 3, "hello", 5, &err); + CheckNoError(err); + CheckGet(db, roptions, "foo", "hello"); + + StartPhase("compactall"); + leveldb_compact_range(db, NULL, 0, NULL, 0); + CheckGet(db, roptions, "foo", "hello"); + + StartPhase("compactrange"); + leveldb_compact_range(db, "a", 1, "z", 1); + CheckGet(db, roptions, "foo", "hello"); + + StartPhase("writebatch"); + { + leveldb_writebatch_t* wb = leveldb_writebatch_create(); + leveldb_writebatch_put(wb, "foo", 3, "a", 1); + leveldb_writebatch_clear(wb); + leveldb_writebatch_put(wb, "bar", 3, "b", 1); + leveldb_writebatch_put(wb, "box", 3, "c", 1); + leveldb_writebatch_delete(wb, "bar", 3); + leveldb_write(db, woptions, wb, &err); + CheckNoError(err); + CheckGet(db, roptions, "foo", "hello"); + CheckGet(db, roptions, "bar", NULL); + CheckGet(db, roptions, "box", "c"); + int pos = 0; + leveldb_writebatch_iterate(wb, &pos, CheckPut, CheckDel); + CheckCondition(pos == 3); + leveldb_writebatch_destroy(wb); + } + + StartPhase("iter"); + { + leveldb_iterator_t* iter = leveldb_create_iterator(db, roptions); + CheckCondition(!leveldb_iter_valid(iter)); + leveldb_iter_seek_to_first(iter); + CheckCondition(leveldb_iter_valid(iter)); + CheckIter(iter, "box", "c"); + leveldb_iter_next(iter); + CheckIter(iter, "foo", "hello"); + leveldb_iter_prev(iter); + CheckIter(iter, "box", "c"); + leveldb_iter_prev(iter); + CheckCondition(!leveldb_iter_valid(iter)); + leveldb_iter_seek_to_last(iter); + CheckIter(iter, "foo", "hello"); + leveldb_iter_seek(iter, "b", 1); + CheckIter(iter, "box", "c"); + leveldb_iter_get_error(iter, &err); + CheckNoError(err); + leveldb_iter_destroy(iter); + } + + StartPhase("approximate_sizes"); + { + int i; + int n = 20000; + char keybuf[100]; + char valbuf[100]; + uint64_t sizes[2]; + const char* start[2] = { "a", "k00000000000000010000" }; + size_t start_len[2] = { 1, 21 }; + const char* limit[2] = { "k00000000000000010000", "z" }; + size_t limit_len[2] = { 21, 1 }; + leveldb_writeoptions_set_sync(woptions, 0); + for (i = 0; i < n; i++) { + snprintf(keybuf, sizeof(keybuf), "k%020d", i); + snprintf(valbuf, sizeof(valbuf), "v%020d", i); + leveldb_put(db, woptions, keybuf, strlen(keybuf), valbuf, strlen(valbuf), + &err); + CheckNoError(err); + } + leveldb_approximate_sizes(db, 2, start, start_len, limit, limit_len, sizes); + CheckCondition(sizes[0] > 0); + CheckCondition(sizes[1] > 0); + } + + StartPhase("property"); + { + char* prop = leveldb_property_value(db, "nosuchprop"); + CheckCondition(prop == NULL); + prop = leveldb_property_value(db, "leveldb.stats"); + CheckCondition(prop != NULL); + Free(&prop); + } + + StartPhase("snapshot"); + { + const leveldb_snapshot_t* snap; + snap = leveldb_create_snapshot(db); + leveldb_delete(db, woptions, "foo", 3, &err); + CheckNoError(err); + leveldb_readoptions_set_snapshot(roptions, snap); + CheckGet(db, roptions, "foo", "hello"); + leveldb_readoptions_set_snapshot(roptions, NULL); + CheckGet(db, roptions, "foo", NULL); + leveldb_release_snapshot(db, snap); + } + + StartPhase("repair"); + { + leveldb_close(db); + leveldb_options_set_create_if_missing(options, 0); + leveldb_options_set_error_if_exists(options, 0); + leveldb_repair_db(options, dbname, &err); + CheckNoError(err); + db = leveldb_open(options, dbname, &err); + CheckNoError(err); + CheckGet(db, roptions, "foo", NULL); + CheckGet(db, roptions, "bar", NULL); + CheckGet(db, roptions, "box", "c"); + leveldb_options_set_create_if_missing(options, 1); + leveldb_options_set_error_if_exists(options, 1); + } + + StartPhase("filter"); + for (run = 0; run < 2; run++) { + // First run uses custom filter, second run uses bloom filter + CheckNoError(err); + leveldb_filterpolicy_t* policy; + if (run == 0) { + policy = leveldb_filterpolicy_create( + NULL, FilterDestroy, FilterCreate, FilterKeyMatch, FilterName); + } else { + policy = leveldb_filterpolicy_create_bloom(10); + } + + // Create new database + leveldb_close(db); + leveldb_destroy_db(options, dbname, &err); + leveldb_options_set_filter_policy(options, policy); + db = leveldb_open(options, dbname, &err); + CheckNoError(err); + leveldb_put(db, woptions, "foo", 3, "foovalue", 8, &err); + CheckNoError(err); + leveldb_put(db, woptions, "bar", 3, "barvalue", 8, &err); + CheckNoError(err); + leveldb_compact_range(db, NULL, 0, NULL, 0); + + fake_filter_result = 1; + CheckGet(db, roptions, "foo", "foovalue"); + CheckGet(db, roptions, "bar", "barvalue"); + if (phase == 0) { + // Must not find value when custom filter returns false + fake_filter_result = 0; + CheckGet(db, roptions, "foo", NULL); + CheckGet(db, roptions, "bar", NULL); + fake_filter_result = 1; + + CheckGet(db, roptions, "foo", "foovalue"); + CheckGet(db, roptions, "bar", "barvalue"); + } + leveldb_options_set_filter_policy(options, NULL); + leveldb_filterpolicy_destroy(policy); + } + + StartPhase("cleanup"); + leveldb_close(db); + leveldb_options_destroy(options); + leveldb_readoptions_destroy(roptions); + leveldb_writeoptions_destroy(woptions); + leveldb_cache_destroy(cache); + leveldb_comparator_destroy(cmp); + leveldb_env_destroy(env); + + fprintf(stderr, "PASS\n"); + return 0; +} diff --git a/src/leveldb/db/corruption_test.cc b/src/leveldb/db/corruption_test.cc new file mode 100644 index 0000000..96afc68 --- /dev/null +++ b/src/leveldb/db/corruption_test.cc @@ -0,0 +1,374 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "leveldb/db.h" + +#include +#include +#include +#include +#include "leveldb/cache.h" +#include "leveldb/env.h" +#include "leveldb/table.h" +#include "leveldb/write_batch.h" +#include "db/db_impl.h" +#include "db/filename.h" +#include "db/log_format.h" +#include "db/version_set.h" +#include "util/logging.h" +#include "util/testharness.h" +#include "util/testutil.h" + +namespace leveldb { + +static const int kValueSize = 1000; + +class CorruptionTest { + public: + test::ErrorEnv env_; + std::string dbname_; + Cache* tiny_cache_; + Options options_; + DB* db_; + + CorruptionTest() { + tiny_cache_ = NewLRUCache(100); + options_.env = &env_; + options_.block_cache = tiny_cache_; + dbname_ = test::TmpDir() + "/db_test"; + DestroyDB(dbname_, options_); + + db_ = NULL; + options_.create_if_missing = true; + Reopen(); + options_.create_if_missing = false; + } + + ~CorruptionTest() { + delete db_; + DestroyDB(dbname_, Options()); + delete tiny_cache_; + } + + Status TryReopen() { + delete db_; + db_ = NULL; + return DB::Open(options_, dbname_, &db_); + } + + void Reopen() { + ASSERT_OK(TryReopen()); + } + + void RepairDB() { + delete db_; + db_ = NULL; + ASSERT_OK(::leveldb::RepairDB(dbname_, options_)); + } + + void Build(int n) { + std::string key_space, value_space; + WriteBatch batch; + for (int i = 0; i < n; i++) { + //if ((i % 100) == 0) fprintf(stderr, "@ %d of %d\n", i, n); + Slice key = Key(i, &key_space); + batch.Clear(); + batch.Put(key, Value(i, &value_space)); + WriteOptions options; + // Corrupt() doesn't work without this sync on windows; stat reports 0 for + // the file size. + if (i == n - 1) { + options.sync = true; + } + ASSERT_OK(db_->Write(options, &batch)); + } + } + + void Check(int min_expected, int max_expected) { + int next_expected = 0; + int missed = 0; + int bad_keys = 0; + int bad_values = 0; + int correct = 0; + std::string value_space; + Iterator* iter = db_->NewIterator(ReadOptions()); + for (iter->SeekToFirst(); iter->Valid(); iter->Next()) { + uint64_t key; + Slice in(iter->key()); + if (in == "" || in == "~") { + // Ignore boundary keys. + continue; + } + if (!ConsumeDecimalNumber(&in, &key) || + !in.empty() || + key < next_expected) { + bad_keys++; + continue; + } + missed += (key - next_expected); + next_expected = key + 1; + if (iter->value() != Value(key, &value_space)) { + bad_values++; + } else { + correct++; + } + } + delete iter; + + fprintf(stderr, + "expected=%d..%d; got=%d; bad_keys=%d; bad_values=%d; missed=%d\n", + min_expected, max_expected, correct, bad_keys, bad_values, missed); + ASSERT_LE(min_expected, correct); + ASSERT_GE(max_expected, correct); + } + + void Corrupt(FileType filetype, int offset, int bytes_to_corrupt) { + // Pick file to corrupt + std::vector filenames; + ASSERT_OK(env_.GetChildren(dbname_, &filenames)); + uint64_t number; + FileType type; + std::string fname; + int picked_number = -1; + for (size_t i = 0; i < filenames.size(); i++) { + if (ParseFileName(filenames[i], &number, &type) && + type == filetype && + int(number) > picked_number) { // Pick latest file + fname = dbname_ + "/" + filenames[i]; + picked_number = number; + } + } + ASSERT_TRUE(!fname.empty()) << filetype; + + struct stat sbuf; + if (stat(fname.c_str(), &sbuf) != 0) { + const char* msg = strerror(errno); + ASSERT_TRUE(false) << fname << ": " << msg; + } + + if (offset < 0) { + // Relative to end of file; make it absolute + if (-offset > sbuf.st_size) { + offset = 0; + } else { + offset = sbuf.st_size + offset; + } + } + if (offset > sbuf.st_size) { + offset = sbuf.st_size; + } + if (offset + bytes_to_corrupt > sbuf.st_size) { + bytes_to_corrupt = sbuf.st_size - offset; + } + + // Do it + std::string contents; + Status s = ReadFileToString(Env::Default(), fname, &contents); + ASSERT_TRUE(s.ok()) << s.ToString(); + for (int i = 0; i < bytes_to_corrupt; i++) { + contents[i + offset] ^= 0x80; + } + s = WriteStringToFile(Env::Default(), contents, fname); + ASSERT_TRUE(s.ok()) << s.ToString(); + } + + int Property(const std::string& name) { + std::string property; + int result; + if (db_->GetProperty(name, &property) && + sscanf(property.c_str(), "%d", &result) == 1) { + return result; + } else { + return -1; + } + } + + // Return the ith key + Slice Key(int i, std::string* storage) { + char buf[100]; + snprintf(buf, sizeof(buf), "%016d", i); + storage->assign(buf, strlen(buf)); + return Slice(*storage); + } + + // Return the value to associate with the specified key + Slice Value(int k, std::string* storage) { + Random r(k); + return test::RandomString(&r, kValueSize, storage); + } +}; + +TEST(CorruptionTest, Recovery) { + Build(100); + Check(100, 100); + Corrupt(kLogFile, 19, 1); // WriteBatch tag for first record + Corrupt(kLogFile, log::kBlockSize + 1000, 1); // Somewhere in second block + Reopen(); + + // The 64 records in the first two log blocks are completely lost. + Check(36, 36); +} + +TEST(CorruptionTest, RecoverWriteError) { + env_.writable_file_error_ = true; + Status s = TryReopen(); + ASSERT_TRUE(!s.ok()); +} + +TEST(CorruptionTest, NewFileErrorDuringWrite) { + // Do enough writing to force minor compaction + env_.writable_file_error_ = true; + const int num = 3 + (Options().write_buffer_size / kValueSize); + std::string value_storage; + Status s; + for (int i = 0; s.ok() && i < num; i++) { + WriteBatch batch; + batch.Put("a", Value(100, &value_storage)); + s = db_->Write(WriteOptions(), &batch); + } + ASSERT_TRUE(!s.ok()); + ASSERT_GE(env_.num_writable_file_errors_, 1); + env_.writable_file_error_ = false; + Reopen(); +} + +TEST(CorruptionTest, TableFile) { + Build(100); + DBImpl* dbi = reinterpret_cast(db_); + dbi->TEST_CompactMemTable(); + dbi->TEST_CompactRange(0, NULL, NULL); + dbi->TEST_CompactRange(1, NULL, NULL); + + Corrupt(kTableFile, 100, 1); + Check(90, 99); +} + +TEST(CorruptionTest, TableFileRepair) { + options_.block_size = 2 * kValueSize; // Limit scope of corruption + options_.paranoid_checks = true; + Reopen(); + Build(100); + DBImpl* dbi = reinterpret_cast(db_); + dbi->TEST_CompactMemTable(); + dbi->TEST_CompactRange(0, NULL, NULL); + dbi->TEST_CompactRange(1, NULL, NULL); + + Corrupt(kTableFile, 100, 1); + RepairDB(); + Reopen(); + Check(95, 99); +} + +TEST(CorruptionTest, TableFileIndexData) { + Build(10000); // Enough to build multiple Tables + DBImpl* dbi = reinterpret_cast(db_); + dbi->TEST_CompactMemTable(); + + Corrupt(kTableFile, -2000, 500); + Reopen(); + Check(5000, 9999); +} + +TEST(CorruptionTest, MissingDescriptor) { + Build(1000); + RepairDB(); + Reopen(); + Check(1000, 1000); +} + +TEST(CorruptionTest, SequenceNumberRecovery) { + ASSERT_OK(db_->Put(WriteOptions(), "foo", "v1")); + ASSERT_OK(db_->Put(WriteOptions(), "foo", "v2")); + ASSERT_OK(db_->Put(WriteOptions(), "foo", "v3")); + ASSERT_OK(db_->Put(WriteOptions(), "foo", "v4")); + ASSERT_OK(db_->Put(WriteOptions(), "foo", "v5")); + RepairDB(); + Reopen(); + std::string v; + ASSERT_OK(db_->Get(ReadOptions(), "foo", &v)); + ASSERT_EQ("v5", v); + // Write something. If sequence number was not recovered properly, + // it will be hidden by an earlier write. + ASSERT_OK(db_->Put(WriteOptions(), "foo", "v6")); + ASSERT_OK(db_->Get(ReadOptions(), "foo", &v)); + ASSERT_EQ("v6", v); + Reopen(); + ASSERT_OK(db_->Get(ReadOptions(), "foo", &v)); + ASSERT_EQ("v6", v); +} + +TEST(CorruptionTest, CorruptedDescriptor) { + ASSERT_OK(db_->Put(WriteOptions(), "foo", "hello")); + DBImpl* dbi = reinterpret_cast(db_); + dbi->TEST_CompactMemTable(); + dbi->TEST_CompactRange(0, NULL, NULL); + + Corrupt(kDescriptorFile, 0, 1000); + Status s = TryReopen(); + ASSERT_TRUE(!s.ok()); + + RepairDB(); + Reopen(); + std::string v; + ASSERT_OK(db_->Get(ReadOptions(), "foo", &v)); + ASSERT_EQ("hello", v); +} + +TEST(CorruptionTest, CompactionInputError) { + Build(10); + DBImpl* dbi = reinterpret_cast(db_); + dbi->TEST_CompactMemTable(); + const int last = config::kMaxMemCompactLevel; + ASSERT_EQ(1, Property("leveldb.num-files-at-level" + NumberToString(last))); + + Corrupt(kTableFile, 100, 1); + Check(5, 9); + + // Force compactions by writing lots of values + Build(10000); + Check(10000, 10000); +} + +TEST(CorruptionTest, CompactionInputErrorParanoid) { + options_.paranoid_checks = true; + options_.write_buffer_size = 512 << 10; + Reopen(); + DBImpl* dbi = reinterpret_cast(db_); + + // Make multiple inputs so we need to compact. + for (int i = 0; i < 2; i++) { + Build(10); + dbi->TEST_CompactMemTable(); + Corrupt(kTableFile, 100, 1); + env_.SleepForMicroseconds(100000); + } + dbi->CompactRange(NULL, NULL); + + // Write must fail because of corrupted table + std::string tmp1, tmp2; + Status s = db_->Put(WriteOptions(), Key(5, &tmp1), Value(5, &tmp2)); + ASSERT_TRUE(!s.ok()) << "write did not fail in corrupted paranoid db"; +} + +TEST(CorruptionTest, UnrelatedKeys) { + Build(10); + DBImpl* dbi = reinterpret_cast(db_); + dbi->TEST_CompactMemTable(); + Corrupt(kTableFile, 100, 1); + + std::string tmp1, tmp2; + ASSERT_OK(db_->Put(WriteOptions(), Key(1000, &tmp1), Value(1000, &tmp2))); + std::string v; + ASSERT_OK(db_->Get(ReadOptions(), Key(1000, &tmp1), &v)); + ASSERT_EQ(Value(1000, &tmp2).ToString(), v); + dbi->TEST_CompactMemTable(); + ASSERT_OK(db_->Get(ReadOptions(), Key(1000, &tmp1), &v)); + ASSERT_EQ(Value(1000, &tmp2).ToString(), v); +} + +} // namespace leveldb + +int main(int argc, char** argv) { + return leveldb::test::RunAllTests(); +} diff --git a/src/leveldb/db/db_bench.cc b/src/leveldb/db/db_bench.cc new file mode 100644 index 0000000..fc46d89 --- /dev/null +++ b/src/leveldb/db/db_bench.cc @@ -0,0 +1,979 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include +#include +#include +#include "db/db_impl.h" +#include "db/version_set.h" +#include "leveldb/cache.h" +#include "leveldb/db.h" +#include "leveldb/env.h" +#include "leveldb/write_batch.h" +#include "port/port.h" +#include "util/crc32c.h" +#include "util/histogram.h" +#include "util/mutexlock.h" +#include "util/random.h" +#include "util/testutil.h" + +// Comma-separated list of operations to run in the specified order +// Actual benchmarks: +// fillseq -- write N values in sequential key order in async mode +// fillrandom -- write N values in random key order in async mode +// overwrite -- overwrite N values in random key order in async mode +// fillsync -- write N/100 values in random key order in sync mode +// fill100K -- write N/1000 100K values in random order in async mode +// deleteseq -- delete N keys in sequential order +// deleterandom -- delete N keys in random order +// readseq -- read N times sequentially +// readreverse -- read N times in reverse order +// readrandom -- read N times in random order +// readmissing -- read N missing keys in random order +// readhot -- read N times in random order from 1% section of DB +// seekrandom -- N random seeks +// crc32c -- repeated crc32c of 4K of data +// acquireload -- load N*1000 times +// Meta operations: +// compact -- Compact the entire DB +// stats -- Print DB stats +// sstables -- Print sstable info +// heapprofile -- Dump a heap profile (if supported by this port) +static const char* FLAGS_benchmarks = + "fillseq," + "fillsync," + "fillrandom," + "overwrite," + "readrandom," + "readrandom," // Extra run to allow previous compactions to quiesce + "readseq," + "readreverse," + "compact," + "readrandom," + "readseq," + "readreverse," + "fill100K," + "crc32c," + "snappycomp," + "snappyuncomp," + "acquireload," + ; + +// Number of key/values to place in database +static int FLAGS_num = 1000000; + +// Number of read operations to do. If negative, do FLAGS_num reads. +static int FLAGS_reads = -1; + +// Number of concurrent threads to run. +static int FLAGS_threads = 1; + +// Size of each value +static int FLAGS_value_size = 100; + +// Arrange to generate values that shrink to this fraction of +// their original size after compression +static double FLAGS_compression_ratio = 0.5; + +// Print histogram of operation timings +static bool FLAGS_histogram = false; + +// Number of bytes to buffer in memtable before compacting +// (initialized to default value by "main") +static int FLAGS_write_buffer_size = 0; + +// Number of bytes to use as a cache of uncompressed data. +// Negative means use default settings. +static int FLAGS_cache_size = -1; + +// Maximum number of files to keep open at the same time (use default if == 0) +static int FLAGS_open_files = 0; + +// Bloom filter bits per key. +// Negative means use default settings. +static int FLAGS_bloom_bits = -1; + +// If true, do not destroy the existing database. If you set this +// flag and also specify a benchmark that wants a fresh database, that +// benchmark will fail. +static bool FLAGS_use_existing_db = false; + +// Use the db with the following name. +static const char* FLAGS_db = NULL; + +namespace leveldb { + +namespace { + +// Helper for quickly generating random data. +class RandomGenerator { + private: + std::string data_; + int pos_; + + public: + RandomGenerator() { + // We use a limited amount of data over and over again and ensure + // that it is larger than the compression window (32KB), and also + // large enough to serve all typical value sizes we want to write. + Random rnd(301); + std::string piece; + while (data_.size() < 1048576) { + // Add a short fragment that is as compressible as specified + // by FLAGS_compression_ratio. + test::CompressibleString(&rnd, FLAGS_compression_ratio, 100, &piece); + data_.append(piece); + } + pos_ = 0; + } + + Slice Generate(size_t len) { + if (pos_ + len > data_.size()) { + pos_ = 0; + assert(len < data_.size()); + } + pos_ += len; + return Slice(data_.data() + pos_ - len, len); + } +}; + +static Slice TrimSpace(Slice s) { + size_t start = 0; + while (start < s.size() && isspace(s[start])) { + start++; + } + size_t limit = s.size(); + while (limit > start && isspace(s[limit-1])) { + limit--; + } + return Slice(s.data() + start, limit - start); +} + +static void AppendWithSpace(std::string* str, Slice msg) { + if (msg.empty()) return; + if (!str->empty()) { + str->push_back(' '); + } + str->append(msg.data(), msg.size()); +} + +class Stats { + private: + double start_; + double finish_; + double seconds_; + int done_; + int next_report_; + int64_t bytes_; + double last_op_finish_; + Histogram hist_; + std::string message_; + + public: + Stats() { Start(); } + + void Start() { + next_report_ = 100; + last_op_finish_ = start_; + hist_.Clear(); + done_ = 0; + bytes_ = 0; + seconds_ = 0; + start_ = Env::Default()->NowMicros(); + finish_ = start_; + message_.clear(); + } + + void Merge(const Stats& other) { + hist_.Merge(other.hist_); + done_ += other.done_; + bytes_ += other.bytes_; + seconds_ += other.seconds_; + if (other.start_ < start_) start_ = other.start_; + if (other.finish_ > finish_) finish_ = other.finish_; + + // Just keep the messages from one thread + if (message_.empty()) message_ = other.message_; + } + + void Stop() { + finish_ = Env::Default()->NowMicros(); + seconds_ = (finish_ - start_) * 1e-6; + } + + void AddMessage(Slice msg) { + AppendWithSpace(&message_, msg); + } + + void FinishedSingleOp() { + if (FLAGS_histogram) { + double now = Env::Default()->NowMicros(); + double micros = now - last_op_finish_; + hist_.Add(micros); + if (micros > 20000) { + fprintf(stderr, "long op: %.1f micros%30s\r", micros, ""); + fflush(stderr); + } + last_op_finish_ = now; + } + + done_++; + if (done_ >= next_report_) { + if (next_report_ < 1000) next_report_ += 100; + else if (next_report_ < 5000) next_report_ += 500; + else if (next_report_ < 10000) next_report_ += 1000; + else if (next_report_ < 50000) next_report_ += 5000; + else if (next_report_ < 100000) next_report_ += 10000; + else if (next_report_ < 500000) next_report_ += 50000; + else next_report_ += 100000; + fprintf(stderr, "... finished %d ops%30s\r", done_, ""); + fflush(stderr); + } + } + + void AddBytes(int64_t n) { + bytes_ += n; + } + + void Report(const Slice& name) { + // Pretend at least one op was done in case we are running a benchmark + // that does not call FinishedSingleOp(). + if (done_ < 1) done_ = 1; + + std::string extra; + if (bytes_ > 0) { + // Rate is computed on actual elapsed time, not the sum of per-thread + // elapsed times. + double elapsed = (finish_ - start_) * 1e-6; + char rate[100]; + snprintf(rate, sizeof(rate), "%6.1f MB/s", + (bytes_ / 1048576.0) / elapsed); + extra = rate; + } + AppendWithSpace(&extra, message_); + + fprintf(stdout, "%-12s : %11.3f micros/op;%s%s\n", + name.ToString().c_str(), + seconds_ * 1e6 / done_, + (extra.empty() ? "" : " "), + extra.c_str()); + if (FLAGS_histogram) { + fprintf(stdout, "Microseconds per op:\n%s\n", hist_.ToString().c_str()); + } + fflush(stdout); + } +}; + +// State shared by all concurrent executions of the same benchmark. +struct SharedState { + port::Mutex mu; + port::CondVar cv; + int total; + + // Each thread goes through the following states: + // (1) initializing + // (2) waiting for others to be initialized + // (3) running + // (4) done + + int num_initialized; + int num_done; + bool start; + + SharedState() : cv(&mu) { } +}; + +// Per-thread state for concurrent executions of the same benchmark. +struct ThreadState { + int tid; // 0..n-1 when running in n threads + Random rand; // Has different seeds for different threads + Stats stats; + SharedState* shared; + + ThreadState(int index) + : tid(index), + rand(1000 + index) { + } +}; + +} // namespace + +class Benchmark { + private: + Cache* cache_; + const FilterPolicy* filter_policy_; + DB* db_; + int num_; + int value_size_; + int entries_per_batch_; + WriteOptions write_options_; + int reads_; + int heap_counter_; + + void PrintHeader() { + const int kKeySize = 16; + PrintEnvironment(); + fprintf(stdout, "Keys: %d bytes each\n", kKeySize); + fprintf(stdout, "Values: %d bytes each (%d bytes after compression)\n", + FLAGS_value_size, + static_cast(FLAGS_value_size * FLAGS_compression_ratio + 0.5)); + fprintf(stdout, "Entries: %d\n", num_); + fprintf(stdout, "RawSize: %.1f MB (estimated)\n", + ((static_cast(kKeySize + FLAGS_value_size) * num_) + / 1048576.0)); + fprintf(stdout, "FileSize: %.1f MB (estimated)\n", + (((kKeySize + FLAGS_value_size * FLAGS_compression_ratio) * num_) + / 1048576.0)); + PrintWarnings(); + fprintf(stdout, "------------------------------------------------\n"); + } + + void PrintWarnings() { +#if defined(__GNUC__) && !defined(__OPTIMIZE__) + fprintf(stdout, + "WARNING: Optimization is disabled: benchmarks unnecessarily slow\n" + ); +#endif +#ifndef NDEBUG + fprintf(stdout, + "WARNING: Assertions are enabled; benchmarks unnecessarily slow\n"); +#endif + + // See if snappy is working by attempting to compress a compressible string + const char text[] = "yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy"; + std::string compressed; + if (!port::Snappy_Compress(text, sizeof(text), &compressed)) { + fprintf(stdout, "WARNING: Snappy compression is not enabled\n"); + } else if (compressed.size() >= sizeof(text)) { + fprintf(stdout, "WARNING: Snappy compression is not effective\n"); + } + } + + void PrintEnvironment() { + fprintf(stderr, "LevelDB: version %d.%d\n", + kMajorVersion, kMinorVersion); + +#if defined(__linux) + time_t now = time(NULL); + fprintf(stderr, "Date: %s", ctime(&now)); // ctime() adds newline + + FILE* cpuinfo = fopen("/proc/cpuinfo", "r"); + if (cpuinfo != NULL) { + char line[1000]; + int num_cpus = 0; + std::string cpu_type; + std::string cache_size; + while (fgets(line, sizeof(line), cpuinfo) != NULL) { + const char* sep = strchr(line, ':'); + if (sep == NULL) { + continue; + } + Slice key = TrimSpace(Slice(line, sep - 1 - line)); + Slice val = TrimSpace(Slice(sep + 1)); + if (key == "model name") { + ++num_cpus; + cpu_type = val.ToString(); + } else if (key == "cache size") { + cache_size = val.ToString(); + } + } + fclose(cpuinfo); + fprintf(stderr, "CPU: %d * %s\n", num_cpus, cpu_type.c_str()); + fprintf(stderr, "CPUCache: %s\n", cache_size.c_str()); + } +#endif + } + + public: + Benchmark() + : cache_(FLAGS_cache_size >= 0 ? NewLRUCache(FLAGS_cache_size) : NULL), + filter_policy_(FLAGS_bloom_bits >= 0 + ? NewBloomFilterPolicy(FLAGS_bloom_bits) + : NULL), + db_(NULL), + num_(FLAGS_num), + value_size_(FLAGS_value_size), + entries_per_batch_(1), + reads_(FLAGS_reads < 0 ? FLAGS_num : FLAGS_reads), + heap_counter_(0) { + std::vector files; + Env::Default()->GetChildren(FLAGS_db, &files); + for (size_t i = 0; i < files.size(); i++) { + if (Slice(files[i]).starts_with("heap-")) { + Env::Default()->DeleteFile(std::string(FLAGS_db) + "/" + files[i]); + } + } + if (!FLAGS_use_existing_db) { + DestroyDB(FLAGS_db, Options()); + } + } + + ~Benchmark() { + delete db_; + delete cache_; + delete filter_policy_; + } + + void Run() { + PrintHeader(); + Open(); + + const char* benchmarks = FLAGS_benchmarks; + while (benchmarks != NULL) { + const char* sep = strchr(benchmarks, ','); + Slice name; + if (sep == NULL) { + name = benchmarks; + benchmarks = NULL; + } else { + name = Slice(benchmarks, sep - benchmarks); + benchmarks = sep + 1; + } + + // Reset parameters that may be overriddden bwlow + num_ = FLAGS_num; + reads_ = (FLAGS_reads < 0 ? FLAGS_num : FLAGS_reads); + value_size_ = FLAGS_value_size; + entries_per_batch_ = 1; + write_options_ = WriteOptions(); + + void (Benchmark::*method)(ThreadState*) = NULL; + bool fresh_db = false; + int num_threads = FLAGS_threads; + + if (name == Slice("fillseq")) { + fresh_db = true; + method = &Benchmark::WriteSeq; + } else if (name == Slice("fillbatch")) { + fresh_db = true; + entries_per_batch_ = 1000; + method = &Benchmark::WriteSeq; + } else if (name == Slice("fillrandom")) { + fresh_db = true; + method = &Benchmark::WriteRandom; + } else if (name == Slice("overwrite")) { + fresh_db = false; + method = &Benchmark::WriteRandom; + } else if (name == Slice("fillsync")) { + fresh_db = true; + num_ /= 1000; + write_options_.sync = true; + method = &Benchmark::WriteRandom; + } else if (name == Slice("fill100K")) { + fresh_db = true; + num_ /= 1000; + value_size_ = 100 * 1000; + method = &Benchmark::WriteRandom; + } else if (name == Slice("readseq")) { + method = &Benchmark::ReadSequential; + } else if (name == Slice("readreverse")) { + method = &Benchmark::ReadReverse; + } else if (name == Slice("readrandom")) { + method = &Benchmark::ReadRandom; + } else if (name == Slice("readmissing")) { + method = &Benchmark::ReadMissing; + } else if (name == Slice("seekrandom")) { + method = &Benchmark::SeekRandom; + } else if (name == Slice("readhot")) { + method = &Benchmark::ReadHot; + } else if (name == Slice("readrandomsmall")) { + reads_ /= 1000; + method = &Benchmark::ReadRandom; + } else if (name == Slice("deleteseq")) { + method = &Benchmark::DeleteSeq; + } else if (name == Slice("deleterandom")) { + method = &Benchmark::DeleteRandom; + } else if (name == Slice("readwhilewriting")) { + num_threads++; // Add extra thread for writing + method = &Benchmark::ReadWhileWriting; + } else if (name == Slice("compact")) { + method = &Benchmark::Compact; + } else if (name == Slice("crc32c")) { + method = &Benchmark::Crc32c; + } else if (name == Slice("acquireload")) { + method = &Benchmark::AcquireLoad; + } else if (name == Slice("snappycomp")) { + method = &Benchmark::SnappyCompress; + } else if (name == Slice("snappyuncomp")) { + method = &Benchmark::SnappyUncompress; + } else if (name == Slice("heapprofile")) { + HeapProfile(); + } else if (name == Slice("stats")) { + PrintStats("leveldb.stats"); + } else if (name == Slice("sstables")) { + PrintStats("leveldb.sstables"); + } else { + if (name != Slice()) { // No error message for empty name + fprintf(stderr, "unknown benchmark '%s'\n", name.ToString().c_str()); + } + } + + if (fresh_db) { + if (FLAGS_use_existing_db) { + fprintf(stdout, "%-12s : skipped (--use_existing_db is true)\n", + name.ToString().c_str()); + method = NULL; + } else { + delete db_; + db_ = NULL; + DestroyDB(FLAGS_db, Options()); + Open(); + } + } + + if (method != NULL) { + RunBenchmark(num_threads, name, method); + } + } + } + + private: + struct ThreadArg { + Benchmark* bm; + SharedState* shared; + ThreadState* thread; + void (Benchmark::*method)(ThreadState*); + }; + + static void ThreadBody(void* v) { + ThreadArg* arg = reinterpret_cast(v); + SharedState* shared = arg->shared; + ThreadState* thread = arg->thread; + { + MutexLock l(&shared->mu); + shared->num_initialized++; + if (shared->num_initialized >= shared->total) { + shared->cv.SignalAll(); + } + while (!shared->start) { + shared->cv.Wait(); + } + } + + thread->stats.Start(); + (arg->bm->*(arg->method))(thread); + thread->stats.Stop(); + + { + MutexLock l(&shared->mu); + shared->num_done++; + if (shared->num_done >= shared->total) { + shared->cv.SignalAll(); + } + } + } + + void RunBenchmark(int n, Slice name, + void (Benchmark::*method)(ThreadState*)) { + SharedState shared; + shared.total = n; + shared.num_initialized = 0; + shared.num_done = 0; + shared.start = false; + + ThreadArg* arg = new ThreadArg[n]; + for (int i = 0; i < n; i++) { + arg[i].bm = this; + arg[i].method = method; + arg[i].shared = &shared; + arg[i].thread = new ThreadState(i); + arg[i].thread->shared = &shared; + Env::Default()->StartThread(ThreadBody, &arg[i]); + } + + shared.mu.Lock(); + while (shared.num_initialized < n) { + shared.cv.Wait(); + } + + shared.start = true; + shared.cv.SignalAll(); + while (shared.num_done < n) { + shared.cv.Wait(); + } + shared.mu.Unlock(); + + for (int i = 1; i < n; i++) { + arg[0].thread->stats.Merge(arg[i].thread->stats); + } + arg[0].thread->stats.Report(name); + + for (int i = 0; i < n; i++) { + delete arg[i].thread; + } + delete[] arg; + } + + void Crc32c(ThreadState* thread) { + // Checksum about 500MB of data total + const int size = 4096; + const char* label = "(4K per op)"; + std::string data(size, 'x'); + int64_t bytes = 0; + uint32_t crc = 0; + while (bytes < 500 * 1048576) { + crc = crc32c::Value(data.data(), size); + thread->stats.FinishedSingleOp(); + bytes += size; + } + // Print so result is not dead + fprintf(stderr, "... crc=0x%x\r", static_cast(crc)); + + thread->stats.AddBytes(bytes); + thread->stats.AddMessage(label); + } + + void AcquireLoad(ThreadState* thread) { + int dummy; + port::AtomicPointer ap(&dummy); + int count = 0; + void *ptr = NULL; + thread->stats.AddMessage("(each op is 1000 loads)"); + while (count < 100000) { + for (int i = 0; i < 1000; i++) { + ptr = ap.Acquire_Load(); + } + count++; + thread->stats.FinishedSingleOp(); + } + if (ptr == NULL) exit(1); // Disable unused variable warning. + } + + void SnappyCompress(ThreadState* thread) { + RandomGenerator gen; + Slice input = gen.Generate(Options().block_size); + int64_t bytes = 0; + int64_t produced = 0; + bool ok = true; + std::string compressed; + while (ok && bytes < 1024 * 1048576) { // Compress 1G + ok = port::Snappy_Compress(input.data(), input.size(), &compressed); + produced += compressed.size(); + bytes += input.size(); + thread->stats.FinishedSingleOp(); + } + + if (!ok) { + thread->stats.AddMessage("(snappy failure)"); + } else { + char buf[100]; + snprintf(buf, sizeof(buf), "(output: %.1f%%)", + (produced * 100.0) / bytes); + thread->stats.AddMessage(buf); + thread->stats.AddBytes(bytes); + } + } + + void SnappyUncompress(ThreadState* thread) { + RandomGenerator gen; + Slice input = gen.Generate(Options().block_size); + std::string compressed; + bool ok = port::Snappy_Compress(input.data(), input.size(), &compressed); + int64_t bytes = 0; + char* uncompressed = new char[input.size()]; + while (ok && bytes < 1024 * 1048576) { // Compress 1G + ok = port::Snappy_Uncompress(compressed.data(), compressed.size(), + uncompressed); + bytes += input.size(); + thread->stats.FinishedSingleOp(); + } + delete[] uncompressed; + + if (!ok) { + thread->stats.AddMessage("(snappy failure)"); + } else { + thread->stats.AddBytes(bytes); + } + } + + void Open() { + assert(db_ == NULL); + Options options; + options.create_if_missing = !FLAGS_use_existing_db; + options.block_cache = cache_; + options.write_buffer_size = FLAGS_write_buffer_size; + options.max_open_files = FLAGS_open_files; + options.filter_policy = filter_policy_; + Status s = DB::Open(options, FLAGS_db, &db_); + if (!s.ok()) { + fprintf(stderr, "open error: %s\n", s.ToString().c_str()); + exit(1); + } + } + + void WriteSeq(ThreadState* thread) { + DoWrite(thread, true); + } + + void WriteRandom(ThreadState* thread) { + DoWrite(thread, false); + } + + void DoWrite(ThreadState* thread, bool seq) { + if (num_ != FLAGS_num) { + char msg[100]; + snprintf(msg, sizeof(msg), "(%d ops)", num_); + thread->stats.AddMessage(msg); + } + + RandomGenerator gen; + WriteBatch batch; + Status s; + int64_t bytes = 0; + for (int i = 0; i < num_; i += entries_per_batch_) { + batch.Clear(); + for (int j = 0; j < entries_per_batch_; j++) { + const int k = seq ? i+j : (thread->rand.Next() % FLAGS_num); + char key[100]; + snprintf(key, sizeof(key), "%016d", k); + batch.Put(key, gen.Generate(value_size_)); + bytes += value_size_ + strlen(key); + thread->stats.FinishedSingleOp(); + } + s = db_->Write(write_options_, &batch); + if (!s.ok()) { + fprintf(stderr, "put error: %s\n", s.ToString().c_str()); + exit(1); + } + } + thread->stats.AddBytes(bytes); + } + + void ReadSequential(ThreadState* thread) { + Iterator* iter = db_->NewIterator(ReadOptions()); + int i = 0; + int64_t bytes = 0; + for (iter->SeekToFirst(); i < reads_ && iter->Valid(); iter->Next()) { + bytes += iter->key().size() + iter->value().size(); + thread->stats.FinishedSingleOp(); + ++i; + } + delete iter; + thread->stats.AddBytes(bytes); + } + + void ReadReverse(ThreadState* thread) { + Iterator* iter = db_->NewIterator(ReadOptions()); + int i = 0; + int64_t bytes = 0; + for (iter->SeekToLast(); i < reads_ && iter->Valid(); iter->Prev()) { + bytes += iter->key().size() + iter->value().size(); + thread->stats.FinishedSingleOp(); + ++i; + } + delete iter; + thread->stats.AddBytes(bytes); + } + + void ReadRandom(ThreadState* thread) { + ReadOptions options; + std::string value; + int found = 0; + for (int i = 0; i < reads_; i++) { + char key[100]; + const int k = thread->rand.Next() % FLAGS_num; + snprintf(key, sizeof(key), "%016d", k); + if (db_->Get(options, key, &value).ok()) { + found++; + } + thread->stats.FinishedSingleOp(); + } + char msg[100]; + snprintf(msg, sizeof(msg), "(%d of %d found)", found, num_); + thread->stats.AddMessage(msg); + } + + void ReadMissing(ThreadState* thread) { + ReadOptions options; + std::string value; + for (int i = 0; i < reads_; i++) { + char key[100]; + const int k = thread->rand.Next() % FLAGS_num; + snprintf(key, sizeof(key), "%016d.", k); + db_->Get(options, key, &value); + thread->stats.FinishedSingleOp(); + } + } + + void ReadHot(ThreadState* thread) { + ReadOptions options; + std::string value; + const int range = (FLAGS_num + 99) / 100; + for (int i = 0; i < reads_; i++) { + char key[100]; + const int k = thread->rand.Next() % range; + snprintf(key, sizeof(key), "%016d", k); + db_->Get(options, key, &value); + thread->stats.FinishedSingleOp(); + } + } + + void SeekRandom(ThreadState* thread) { + ReadOptions options; + std::string value; + int found = 0; + for (int i = 0; i < reads_; i++) { + Iterator* iter = db_->NewIterator(options); + char key[100]; + const int k = thread->rand.Next() % FLAGS_num; + snprintf(key, sizeof(key), "%016d", k); + iter->Seek(key); + if (iter->Valid() && iter->key() == key) found++; + delete iter; + thread->stats.FinishedSingleOp(); + } + char msg[100]; + snprintf(msg, sizeof(msg), "(%d of %d found)", found, num_); + thread->stats.AddMessage(msg); + } + + void DoDelete(ThreadState* thread, bool seq) { + RandomGenerator gen; + WriteBatch batch; + Status s; + for (int i = 0; i < num_; i += entries_per_batch_) { + batch.Clear(); + for (int j = 0; j < entries_per_batch_; j++) { + const int k = seq ? i+j : (thread->rand.Next() % FLAGS_num); + char key[100]; + snprintf(key, sizeof(key), "%016d", k); + batch.Delete(key); + thread->stats.FinishedSingleOp(); + } + s = db_->Write(write_options_, &batch); + if (!s.ok()) { + fprintf(stderr, "del error: %s\n", s.ToString().c_str()); + exit(1); + } + } + } + + void DeleteSeq(ThreadState* thread) { + DoDelete(thread, true); + } + + void DeleteRandom(ThreadState* thread) { + DoDelete(thread, false); + } + + void ReadWhileWriting(ThreadState* thread) { + if (thread->tid > 0) { + ReadRandom(thread); + } else { + // Special thread that keeps writing until other threads are done. + RandomGenerator gen; + while (true) { + { + MutexLock l(&thread->shared->mu); + if (thread->shared->num_done + 1 >= thread->shared->num_initialized) { + // Other threads have finished + break; + } + } + + const int k = thread->rand.Next() % FLAGS_num; + char key[100]; + snprintf(key, sizeof(key), "%016d", k); + Status s = db_->Put(write_options_, key, gen.Generate(value_size_)); + if (!s.ok()) { + fprintf(stderr, "put error: %s\n", s.ToString().c_str()); + exit(1); + } + } + + // Do not count any of the preceding work/delay in stats. + thread->stats.Start(); + } + } + + void Compact(ThreadState* thread) { + db_->CompactRange(NULL, NULL); + } + + void PrintStats(const char* key) { + std::string stats; + if (!db_->GetProperty(key, &stats)) { + stats = "(failed)"; + } + fprintf(stdout, "\n%s\n", stats.c_str()); + } + + static void WriteToFile(void* arg, const char* buf, int n) { + reinterpret_cast(arg)->Append(Slice(buf, n)); + } + + void HeapProfile() { + char fname[100]; + snprintf(fname, sizeof(fname), "%s/heap-%04d", FLAGS_db, ++heap_counter_); + WritableFile* file; + Status s = Env::Default()->NewWritableFile(fname, &file); + if (!s.ok()) { + fprintf(stderr, "%s\n", s.ToString().c_str()); + return; + } + bool ok = port::GetHeapProfile(WriteToFile, file); + delete file; + if (!ok) { + fprintf(stderr, "heap profiling not supported\n"); + Env::Default()->DeleteFile(fname); + } + } +}; + +} // namespace leveldb + +int main(int argc, char** argv) { + FLAGS_write_buffer_size = leveldb::Options().write_buffer_size; + FLAGS_open_files = leveldb::Options().max_open_files; + std::string default_db_path; + + for (int i = 1; i < argc; i++) { + double d; + int n; + char junk; + if (leveldb::Slice(argv[i]).starts_with("--benchmarks=")) { + FLAGS_benchmarks = argv[i] + strlen("--benchmarks="); + } else if (sscanf(argv[i], "--compression_ratio=%lf%c", &d, &junk) == 1) { + FLAGS_compression_ratio = d; + } else if (sscanf(argv[i], "--histogram=%d%c", &n, &junk) == 1 && + (n == 0 || n == 1)) { + FLAGS_histogram = n; + } else if (sscanf(argv[i], "--use_existing_db=%d%c", &n, &junk) == 1 && + (n == 0 || n == 1)) { + FLAGS_use_existing_db = n; + } else if (sscanf(argv[i], "--num=%d%c", &n, &junk) == 1) { + FLAGS_num = n; + } else if (sscanf(argv[i], "--reads=%d%c", &n, &junk) == 1) { + FLAGS_reads = n; + } else if (sscanf(argv[i], "--threads=%d%c", &n, &junk) == 1) { + FLAGS_threads = n; + } else if (sscanf(argv[i], "--value_size=%d%c", &n, &junk) == 1) { + FLAGS_value_size = n; + } else if (sscanf(argv[i], "--write_buffer_size=%d%c", &n, &junk) == 1) { + FLAGS_write_buffer_size = n; + } else if (sscanf(argv[i], "--cache_size=%d%c", &n, &junk) == 1) { + FLAGS_cache_size = n; + } else if (sscanf(argv[i], "--bloom_bits=%d%c", &n, &junk) == 1) { + FLAGS_bloom_bits = n; + } else if (sscanf(argv[i], "--open_files=%d%c", &n, &junk) == 1) { + FLAGS_open_files = n; + } else if (strncmp(argv[i], "--db=", 5) == 0) { + FLAGS_db = argv[i] + 5; + } else { + fprintf(stderr, "Invalid flag '%s'\n", argv[i]); + exit(1); + } + } + + // Choose a location for the test database if none given with --db= + if (FLAGS_db == NULL) { + leveldb::Env::Default()->GetTestDirectory(&default_db_path); + default_db_path += "/dbbench"; + FLAGS_db = default_db_path.c_str(); + } + + leveldb::Benchmark benchmark; + benchmark.Run(); + return 0; +} diff --git a/src/leveldb/db/db_impl.cc b/src/leveldb/db/db_impl.cc new file mode 100644 index 0000000..faf5e7d --- /dev/null +++ b/src/leveldb/db/db_impl.cc @@ -0,0 +1,1513 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "db/db_impl.h" + +#include +#include +#include +#include +#include +#include +#include "db/builder.h" +#include "db/db_iter.h" +#include "db/dbformat.h" +#include "db/filename.h" +#include "db/log_reader.h" +#include "db/log_writer.h" +#include "db/memtable.h" +#include "db/table_cache.h" +#include "db/version_set.h" +#include "db/write_batch_internal.h" +#include "leveldb/db.h" +#include "leveldb/env.h" +#include "leveldb/status.h" +#include "leveldb/table.h" +#include "leveldb/table_builder.h" +#include "port/port.h" +#include "table/block.h" +#include "table/merger.h" +#include "table/two_level_iterator.h" +#include "util/coding.h" +#include "util/logging.h" +#include "util/mutexlock.h" + +namespace leveldb { + +const int kNumNonTableCacheFiles = 10; + +// Information kept for every waiting writer +struct DBImpl::Writer { + Status status; + WriteBatch* batch; + bool sync; + bool done; + port::CondVar cv; + + explicit Writer(port::Mutex* mu) : cv(mu) { } +}; + +struct DBImpl::CompactionState { + Compaction* const compaction; + + // Sequence numbers < smallest_snapshot are not significant since we + // will never have to service a snapshot below smallest_snapshot. + // Therefore if we have seen a sequence number S <= smallest_snapshot, + // we can drop all entries for the same key with sequence numbers < S. + SequenceNumber smallest_snapshot; + + // Files produced by compaction + struct Output { + uint64_t number; + uint64_t file_size; + InternalKey smallest, largest; + }; + std::vector outputs; + + // State kept for output being generated + WritableFile* outfile; + TableBuilder* builder; + + uint64_t total_bytes; + + Output* current_output() { return &outputs[outputs.size()-1]; } + + explicit CompactionState(Compaction* c) + : compaction(c), + outfile(NULL), + builder(NULL), + total_bytes(0) { + } +}; + +// Fix user-supplied options to be reasonable +template +static void ClipToRange(T* ptr, V minvalue, V maxvalue) { + if (static_cast(*ptr) > maxvalue) *ptr = maxvalue; + if (static_cast(*ptr) < minvalue) *ptr = minvalue; +} +Options SanitizeOptions(const std::string& dbname, + const InternalKeyComparator* icmp, + const InternalFilterPolicy* ipolicy, + const Options& src) { + Options result = src; + result.comparator = icmp; + result.filter_policy = (src.filter_policy != NULL) ? ipolicy : NULL; + ClipToRange(&result.max_open_files, 64 + kNumNonTableCacheFiles, 50000); + ClipToRange(&result.write_buffer_size, 64<<10, 1<<30); + ClipToRange(&result.block_size, 1<<10, 4<<20); + if (result.info_log == NULL) { + // Open a log file in the same directory as the db + src.env->CreateDir(dbname); // In case it does not exist + src.env->RenameFile(InfoLogFileName(dbname), OldInfoLogFileName(dbname)); + Status s = src.env->NewLogger(InfoLogFileName(dbname), &result.info_log); + if (!s.ok()) { + // No place suitable for logging + result.info_log = NULL; + } + } + if (result.block_cache == NULL) { + result.block_cache = NewLRUCache(8 << 20); + } + return result; +} + +DBImpl::DBImpl(const Options& raw_options, const std::string& dbname) + : env_(raw_options.env), + internal_comparator_(raw_options.comparator), + internal_filter_policy_(raw_options.filter_policy), + options_(SanitizeOptions(dbname, &internal_comparator_, + &internal_filter_policy_, raw_options)), + owns_info_log_(options_.info_log != raw_options.info_log), + owns_cache_(options_.block_cache != raw_options.block_cache), + dbname_(dbname), + db_lock_(NULL), + shutting_down_(NULL), + bg_cv_(&mutex_), + mem_(new MemTable(internal_comparator_)), + imm_(NULL), + logfile_(NULL), + logfile_number_(0), + log_(NULL), + seed_(0), + tmp_batch_(new WriteBatch), + bg_compaction_scheduled_(false), + manual_compaction_(NULL) { + mem_->Ref(); + has_imm_.Release_Store(NULL); + + // Reserve ten files or so for other uses and give the rest to TableCache. + const int table_cache_size = options_.max_open_files - kNumNonTableCacheFiles; + table_cache_ = new TableCache(dbname_, &options_, table_cache_size); + + versions_ = new VersionSet(dbname_, &options_, table_cache_, + &internal_comparator_); +} + +DBImpl::~DBImpl() { + // Wait for background work to finish + mutex_.Lock(); + shutting_down_.Release_Store(this); // Any non-NULL value is ok + while (bg_compaction_scheduled_) { + bg_cv_.Wait(); + } + mutex_.Unlock(); + + if (db_lock_ != NULL) { + env_->UnlockFile(db_lock_); + } + + delete versions_; + if (mem_ != NULL) mem_->Unref(); + if (imm_ != NULL) imm_->Unref(); + delete tmp_batch_; + delete log_; + delete logfile_; + delete table_cache_; + + if (owns_info_log_) { + delete options_.info_log; + } + if (owns_cache_) { + delete options_.block_cache; + } +} + +Status DBImpl::NewDB() { + VersionEdit new_db; + new_db.SetComparatorName(user_comparator()->Name()); + new_db.SetLogNumber(0); + new_db.SetNextFile(2); + new_db.SetLastSequence(0); + + const std::string manifest = DescriptorFileName(dbname_, 1); + WritableFile* file; + Status s = env_->NewWritableFile(manifest, &file); + if (!s.ok()) { + return s; + } + { + log::Writer log(file); + std::string record; + new_db.EncodeTo(&record); + s = log.AddRecord(record); + if (s.ok()) { + s = file->Close(); + } + } + delete file; + if (s.ok()) { + // Make "CURRENT" file that points to the new manifest file. + s = SetCurrentFile(env_, dbname_, 1); + } else { + env_->DeleteFile(manifest); + } + return s; +} + +void DBImpl::MaybeIgnoreError(Status* s) const { + if (s->ok() || options_.paranoid_checks) { + // No change needed + } else { + Log(options_.info_log, "Ignoring error %s", s->ToString().c_str()); + *s = Status::OK(); + } +} + +void DBImpl::DeleteObsoleteFiles() { + if (!bg_error_.ok()) { + // After a background error, we don't know whether a new version may + // or may not have been committed, so we cannot safely garbage collect. + return; + } + + // Make a set of all of the live files + std::set live = pending_outputs_; + versions_->AddLiveFiles(&live); + + std::vector filenames; + env_->GetChildren(dbname_, &filenames); // Ignoring errors on purpose + uint64_t number; + FileType type; + for (size_t i = 0; i < filenames.size(); i++) { + if (ParseFileName(filenames[i], &number, &type)) { + bool keep = true; + switch (type) { + case kLogFile: + keep = ((number >= versions_->LogNumber()) || + (number == versions_->PrevLogNumber())); + break; + case kDescriptorFile: + // Keep my manifest file, and any newer incarnations' + // (in case there is a race that allows other incarnations) + keep = (number >= versions_->ManifestFileNumber()); + break; + case kTableFile: + keep = (live.find(number) != live.end()); + break; + case kTempFile: + // Any temp files that are currently being written to must + // be recorded in pending_outputs_, which is inserted into "live" + keep = (live.find(number) != live.end()); + break; + case kCurrentFile: + case kDBLockFile: + case kInfoLogFile: + keep = true; + break; + } + + if (!keep) { + if (type == kTableFile) { + table_cache_->Evict(number); + } + Log(options_.info_log, "Delete type=%d #%lld\n", + int(type), + static_cast(number)); + env_->DeleteFile(dbname_ + "/" + filenames[i]); + } + } + } +} + +Status DBImpl::Recover(VersionEdit* edit) { + mutex_.AssertHeld(); + + // Ignore error from CreateDir since the creation of the DB is + // committed only when the descriptor is created, and this directory + // may already exist from a previous failed creation attempt. + env_->CreateDir(dbname_); + assert(db_lock_ == NULL); + Status s = env_->LockFile(LockFileName(dbname_), &db_lock_); + if (!s.ok()) { + return s; + } + + if (!env_->FileExists(CurrentFileName(dbname_))) { + if (options_.create_if_missing) { + s = NewDB(); + if (!s.ok()) { + return s; + } + } else { + return Status::InvalidArgument( + dbname_, "does not exist (create_if_missing is false)"); + } + } else { + if (options_.error_if_exists) { + return Status::InvalidArgument( + dbname_, "exists (error_if_exists is true)"); + } + } + + s = versions_->Recover(); + if (s.ok()) { + SequenceNumber max_sequence(0); + + // Recover from all newer log files than the ones named in the + // descriptor (new log files may have been added by the previous + // incarnation without registering them in the descriptor). + // + // Note that PrevLogNumber() is no longer used, but we pay + // attention to it in case we are recovering a database + // produced by an older version of leveldb. + const uint64_t min_log = versions_->LogNumber(); + const uint64_t prev_log = versions_->PrevLogNumber(); + std::vector filenames; + s = env_->GetChildren(dbname_, &filenames); + if (!s.ok()) { + return s; + } + std::set expected; + versions_->AddLiveFiles(&expected); + uint64_t number; + FileType type; + std::vector logs; + for (size_t i = 0; i < filenames.size(); i++) { + if (ParseFileName(filenames[i], &number, &type)) { + expected.erase(number); + if (type == kLogFile && ((number >= min_log) || (number == prev_log))) + logs.push_back(number); + } + } + if (!expected.empty()) { + char buf[50]; + snprintf(buf, sizeof(buf), "%d missing files; e.g.", + static_cast(expected.size())); + return Status::Corruption(buf, TableFileName(dbname_, *(expected.begin()))); + } + + // Recover in the order in which the logs were generated + std::sort(logs.begin(), logs.end()); + for (size_t i = 0; i < logs.size(); i++) { + s = RecoverLogFile(logs[i], edit, &max_sequence); + + // The previous incarnation may not have written any MANIFEST + // records after allocating this log number. So we manually + // update the file number allocation counter in VersionSet. + versions_->MarkFileNumberUsed(logs[i]); + } + + if (s.ok()) { + if (versions_->LastSequence() < max_sequence) { + versions_->SetLastSequence(max_sequence); + } + } + } + + return s; +} + +Status DBImpl::RecoverLogFile(uint64_t log_number, + VersionEdit* edit, + SequenceNumber* max_sequence) { + struct LogReporter : public log::Reader::Reporter { + Env* env; + Logger* info_log; + const char* fname; + Status* status; // NULL if options_.paranoid_checks==false + virtual void Corruption(size_t bytes, const Status& s) { + Log(info_log, "%s%s: dropping %d bytes; %s", + (this->status == NULL ? "(ignoring error) " : ""), + fname, static_cast(bytes), s.ToString().c_str()); + if (this->status != NULL && this->status->ok()) *this->status = s; + } + }; + + mutex_.AssertHeld(); + + // Open the log file + std::string fname = LogFileName(dbname_, log_number); + SequentialFile* file; + Status status = env_->NewSequentialFile(fname, &file); + if (!status.ok()) { + MaybeIgnoreError(&status); + return status; + } + + // Create the log reader. + LogReporter reporter; + reporter.env = env_; + reporter.info_log = options_.info_log; + reporter.fname = fname.c_str(); + reporter.status = (options_.paranoid_checks ? &status : NULL); + // We intentially make log::Reader do checksumming even if + // paranoid_checks==false so that corruptions cause entire commits + // to be skipped instead of propagating bad information (like overly + // large sequence numbers). + log::Reader reader(file, &reporter, true/*checksum*/, + 0/*initial_offset*/); + Log(options_.info_log, "Recovering log #%llu", + (unsigned long long) log_number); + + // Read all the records and add to a memtable + std::string scratch; + Slice record; + WriteBatch batch; + MemTable* mem = NULL; + while (reader.ReadRecord(&record, &scratch) && + status.ok()) { + if (record.size() < 12) { + reporter.Corruption( + record.size(), Status::Corruption("log record too small")); + continue; + } + WriteBatchInternal::SetContents(&batch, record); + + if (mem == NULL) { + mem = new MemTable(internal_comparator_); + mem->Ref(); + } + status = WriteBatchInternal::InsertInto(&batch, mem); + MaybeIgnoreError(&status); + if (!status.ok()) { + break; + } + const SequenceNumber last_seq = + WriteBatchInternal::Sequence(&batch) + + WriteBatchInternal::Count(&batch) - 1; + if (last_seq > *max_sequence) { + *max_sequence = last_seq; + } + + if (mem->ApproximateMemoryUsage() > options_.write_buffer_size) { + status = WriteLevel0Table(mem, edit, NULL); + if (!status.ok()) { + // Reflect errors immediately so that conditions like full + // file-systems cause the DB::Open() to fail. + break; + } + mem->Unref(); + mem = NULL; + } + } + + if (status.ok() && mem != NULL) { + status = WriteLevel0Table(mem, edit, NULL); + // Reflect errors immediately so that conditions like full + // file-systems cause the DB::Open() to fail. + } + + if (mem != NULL) mem->Unref(); + delete file; + return status; +} + +Status DBImpl::WriteLevel0Table(MemTable* mem, VersionEdit* edit, + Version* base) { + mutex_.AssertHeld(); + const uint64_t start_micros = env_->NowMicros(); + FileMetaData meta; + meta.number = versions_->NewFileNumber(); + pending_outputs_.insert(meta.number); + Iterator* iter = mem->NewIterator(); + Log(options_.info_log, "Level-0 table #%llu: started", + (unsigned long long) meta.number); + + Status s; + { + mutex_.Unlock(); + s = BuildTable(dbname_, env_, options_, table_cache_, iter, &meta); + mutex_.Lock(); + } + + Log(options_.info_log, "Level-0 table #%llu: %lld bytes %s", + (unsigned long long) meta.number, + (unsigned long long) meta.file_size, + s.ToString().c_str()); + delete iter; + pending_outputs_.erase(meta.number); + + + // Note that if file_size is zero, the file has been deleted and + // should not be added to the manifest. + int level = 0; + if (s.ok() && meta.file_size > 0) { + const Slice min_user_key = meta.smallest.user_key(); + const Slice max_user_key = meta.largest.user_key(); + if (base != NULL) { + level = base->PickLevelForMemTableOutput(min_user_key, max_user_key); + } + edit->AddFile(level, meta.number, meta.file_size, + meta.smallest, meta.largest); + } + + CompactionStats stats; + stats.micros = env_->NowMicros() - start_micros; + stats.bytes_written = meta.file_size; + stats_[level].Add(stats); + return s; +} + +void DBImpl::CompactMemTable() { + mutex_.AssertHeld(); + assert(imm_ != NULL); + + // Save the contents of the memtable as a new Table + VersionEdit edit; + Version* base = versions_->current(); + base->Ref(); + Status s = WriteLevel0Table(imm_, &edit, base); + base->Unref(); + + if (s.ok() && shutting_down_.Acquire_Load()) { + s = Status::IOError("Deleting DB during memtable compaction"); + } + + // Replace immutable memtable with the generated Table + if (s.ok()) { + edit.SetPrevLogNumber(0); + edit.SetLogNumber(logfile_number_); // Earlier logs no longer needed + s = versions_->LogAndApply(&edit, &mutex_); + } + + if (s.ok()) { + // Commit to the new state + imm_->Unref(); + imm_ = NULL; + has_imm_.Release_Store(NULL); + DeleteObsoleteFiles(); + } else { + RecordBackgroundError(s); + } +} + +void DBImpl::CompactRange(const Slice* begin, const Slice* end) { + int max_level_with_files = 1; + { + MutexLock l(&mutex_); + Version* base = versions_->current(); + for (int level = 1; level < config::kNumLevels; level++) { + if (base->OverlapInLevel(level, begin, end)) { + max_level_with_files = level; + } + } + } + TEST_CompactMemTable(); // TODO(sanjay): Skip if memtable does not overlap + for (int level = 0; level < max_level_with_files; level++) { + TEST_CompactRange(level, begin, end); + } +} + +void DBImpl::TEST_CompactRange(int level, const Slice* begin,const Slice* end) { + assert(level >= 0); + assert(level + 1 < config::kNumLevels); + + InternalKey begin_storage, end_storage; + + ManualCompaction manual; + manual.level = level; + manual.done = false; + if (begin == NULL) { + manual.begin = NULL; + } else { + begin_storage = InternalKey(*begin, kMaxSequenceNumber, kValueTypeForSeek); + manual.begin = &begin_storage; + } + if (end == NULL) { + manual.end = NULL; + } else { + end_storage = InternalKey(*end, 0, static_cast(0)); + manual.end = &end_storage; + } + + MutexLock l(&mutex_); + while (!manual.done && !shutting_down_.Acquire_Load() && bg_error_.ok()) { + if (manual_compaction_ == NULL) { // Idle + manual_compaction_ = &manual; + MaybeScheduleCompaction(); + } else { // Running either my compaction or another compaction. + bg_cv_.Wait(); + } + } + if (manual_compaction_ == &manual) { + // Cancel my manual compaction since we aborted early for some reason. + manual_compaction_ = NULL; + } +} + +Status DBImpl::TEST_CompactMemTable() { + // NULL batch means just wait for earlier writes to be done + Status s = Write(WriteOptions(), NULL); + if (s.ok()) { + // Wait until the compaction completes + MutexLock l(&mutex_); + while (imm_ != NULL && bg_error_.ok()) { + bg_cv_.Wait(); + } + if (imm_ != NULL) { + s = bg_error_; + } + } + return s; +} + +void DBImpl::RecordBackgroundError(const Status& s) { + mutex_.AssertHeld(); + if (bg_error_.ok()) { + bg_error_ = s; + bg_cv_.SignalAll(); + } +} + +void DBImpl::MaybeScheduleCompaction() { + mutex_.AssertHeld(); + if (bg_compaction_scheduled_) { + // Already scheduled + } else if (shutting_down_.Acquire_Load()) { + // DB is being deleted; no more background compactions + } else if (!bg_error_.ok()) { + // Already got an error; no more changes + } else if (imm_ == NULL && + manual_compaction_ == NULL && + !versions_->NeedsCompaction()) { + // No work to be done + } else { + bg_compaction_scheduled_ = true; + env_->Schedule(&DBImpl::BGWork, this); + } +} + +void DBImpl::BGWork(void* db) { + reinterpret_cast(db)->BackgroundCall(); +} + +void DBImpl::BackgroundCall() { + MutexLock l(&mutex_); + assert(bg_compaction_scheduled_); + if (shutting_down_.Acquire_Load()) { + // No more background work when shutting down. + } else if (!bg_error_.ok()) { + // No more background work after a background error. + } else { + BackgroundCompaction(); + } + + bg_compaction_scheduled_ = false; + + // Previous compaction may have produced too many files in a level, + // so reschedule another compaction if needed. + MaybeScheduleCompaction(); + bg_cv_.SignalAll(); +} + +void DBImpl::BackgroundCompaction() { + mutex_.AssertHeld(); + + if (imm_ != NULL) { + CompactMemTable(); + return; + } + + Compaction* c; + bool is_manual = (manual_compaction_ != NULL); + InternalKey manual_end; + if (is_manual) { + ManualCompaction* m = manual_compaction_; + c = versions_->CompactRange(m->level, m->begin, m->end); + m->done = (c == NULL); + if (c != NULL) { + manual_end = c->input(0, c->num_input_files(0) - 1)->largest; + } + Log(options_.info_log, + "Manual compaction at level-%d from %s .. %s; will stop at %s\n", + m->level, + (m->begin ? m->begin->DebugString().c_str() : "(begin)"), + (m->end ? m->end->DebugString().c_str() : "(end)"), + (m->done ? "(end)" : manual_end.DebugString().c_str())); + } else { + c = versions_->PickCompaction(); + } + + Status status; + if (c == NULL) { + // Nothing to do + } else if (!is_manual && c->IsTrivialMove()) { + // Move file to next level + assert(c->num_input_files(0) == 1); + FileMetaData* f = c->input(0, 0); + c->edit()->DeleteFile(c->level(), f->number); + c->edit()->AddFile(c->level() + 1, f->number, f->file_size, + f->smallest, f->largest); + status = versions_->LogAndApply(c->edit(), &mutex_); + if (!status.ok()) { + RecordBackgroundError(status); + } + VersionSet::LevelSummaryStorage tmp; + Log(options_.info_log, "Moved #%lld to level-%d %lld bytes %s: %s\n", + static_cast(f->number), + c->level() + 1, + static_cast(f->file_size), + status.ToString().c_str(), + versions_->LevelSummary(&tmp)); + } else { + CompactionState* compact = new CompactionState(c); + status = DoCompactionWork(compact); + if (!status.ok()) { + RecordBackgroundError(status); + } + CleanupCompaction(compact); + c->ReleaseInputs(); + DeleteObsoleteFiles(); + } + delete c; + + if (status.ok()) { + // Done + } else if (shutting_down_.Acquire_Load()) { + // Ignore compaction errors found during shutting down + } else { + Log(options_.info_log, + "Compaction error: %s", status.ToString().c_str()); + } + + if (is_manual) { + ManualCompaction* m = manual_compaction_; + if (!status.ok()) { + m->done = true; + } + if (!m->done) { + // We only compacted part of the requested range. Update *m + // to the range that is left to be compacted. + m->tmp_storage = manual_end; + m->begin = &m->tmp_storage; + } + manual_compaction_ = NULL; + } +} + +void DBImpl::CleanupCompaction(CompactionState* compact) { + mutex_.AssertHeld(); + if (compact->builder != NULL) { + // May happen if we get a shutdown call in the middle of compaction + compact->builder->Abandon(); + delete compact->builder; + } else { + assert(compact->outfile == NULL); + } + delete compact->outfile; + for (size_t i = 0; i < compact->outputs.size(); i++) { + const CompactionState::Output& out = compact->outputs[i]; + pending_outputs_.erase(out.number); + } + delete compact; +} + +Status DBImpl::OpenCompactionOutputFile(CompactionState* compact) { + assert(compact != NULL); + assert(compact->builder == NULL); + uint64_t file_number; + { + mutex_.Lock(); + file_number = versions_->NewFileNumber(); + pending_outputs_.insert(file_number); + CompactionState::Output out; + out.number = file_number; + out.smallest.Clear(); + out.largest.Clear(); + compact->outputs.push_back(out); + mutex_.Unlock(); + } + + // Make the output file + std::string fname = TableFileName(dbname_, file_number); + Status s = env_->NewWritableFile(fname, &compact->outfile); + if (s.ok()) { + compact->builder = new TableBuilder(options_, compact->outfile); + } + return s; +} + +Status DBImpl::FinishCompactionOutputFile(CompactionState* compact, + Iterator* input) { + assert(compact != NULL); + assert(compact->outfile != NULL); + assert(compact->builder != NULL); + + const uint64_t output_number = compact->current_output()->number; + assert(output_number != 0); + + // Check for iterator errors + Status s = input->status(); + const uint64_t current_entries = compact->builder->NumEntries(); + if (s.ok()) { + s = compact->builder->Finish(); + } else { + compact->builder->Abandon(); + } + const uint64_t current_bytes = compact->builder->FileSize(); + compact->current_output()->file_size = current_bytes; + compact->total_bytes += current_bytes; + delete compact->builder; + compact->builder = NULL; + + // Finish and check for file errors + if (s.ok()) { + s = compact->outfile->Sync(); + } + if (s.ok()) { + s = compact->outfile->Close(); + } + delete compact->outfile; + compact->outfile = NULL; + + if (s.ok() && current_entries > 0) { + // Verify that the table is usable + Iterator* iter = table_cache_->NewIterator(ReadOptions(), + output_number, + current_bytes); + s = iter->status(); + delete iter; + if (s.ok()) { + Log(options_.info_log, + "Generated table #%llu: %lld keys, %lld bytes", + (unsigned long long) output_number, + (unsigned long long) current_entries, + (unsigned long long) current_bytes); + } + } + return s; +} + + +Status DBImpl::InstallCompactionResults(CompactionState* compact) { + mutex_.AssertHeld(); + Log(options_.info_log, "Compacted %d@%d + %d@%d files => %lld bytes", + compact->compaction->num_input_files(0), + compact->compaction->level(), + compact->compaction->num_input_files(1), + compact->compaction->level() + 1, + static_cast(compact->total_bytes)); + + // Add compaction outputs + compact->compaction->AddInputDeletions(compact->compaction->edit()); + const int level = compact->compaction->level(); + for (size_t i = 0; i < compact->outputs.size(); i++) { + const CompactionState::Output& out = compact->outputs[i]; + compact->compaction->edit()->AddFile( + level + 1, + out.number, out.file_size, out.smallest, out.largest); + } + return versions_->LogAndApply(compact->compaction->edit(), &mutex_); +} + +Status DBImpl::DoCompactionWork(CompactionState* compact) { + const uint64_t start_micros = env_->NowMicros(); + int64_t imm_micros = 0; // Micros spent doing imm_ compactions + + Log(options_.info_log, "Compacting %d@%d + %d@%d files", + compact->compaction->num_input_files(0), + compact->compaction->level(), + compact->compaction->num_input_files(1), + compact->compaction->level() + 1); + + assert(versions_->NumLevelFiles(compact->compaction->level()) > 0); + assert(compact->builder == NULL); + assert(compact->outfile == NULL); + if (snapshots_.empty()) { + compact->smallest_snapshot = versions_->LastSequence(); + } else { + compact->smallest_snapshot = snapshots_.oldest()->number_; + } + + // Release mutex while we're actually doing the compaction work + mutex_.Unlock(); + + Iterator* input = versions_->MakeInputIterator(compact->compaction); + input->SeekToFirst(); + Status status; + ParsedInternalKey ikey; + std::string current_user_key; + bool has_current_user_key = false; + SequenceNumber last_sequence_for_key = kMaxSequenceNumber; + for (; input->Valid() && !shutting_down_.Acquire_Load(); ) { + // Prioritize immutable compaction work + if (has_imm_.NoBarrier_Load() != NULL) { + const uint64_t imm_start = env_->NowMicros(); + mutex_.Lock(); + if (imm_ != NULL) { + CompactMemTable(); + bg_cv_.SignalAll(); // Wakeup MakeRoomForWrite() if necessary + } + mutex_.Unlock(); + imm_micros += (env_->NowMicros() - imm_start); + } + + Slice key = input->key(); + if (compact->compaction->ShouldStopBefore(key) && + compact->builder != NULL) { + status = FinishCompactionOutputFile(compact, input); + if (!status.ok()) { + break; + } + } + + // Handle key/value, add to state, etc. + bool drop = false; + if (!ParseInternalKey(key, &ikey)) { + // Do not hide error keys + current_user_key.clear(); + has_current_user_key = false; + last_sequence_for_key = kMaxSequenceNumber; + } else { + if (!has_current_user_key || + user_comparator()->Compare(ikey.user_key, + Slice(current_user_key)) != 0) { + // First occurrence of this user key + current_user_key.assign(ikey.user_key.data(), ikey.user_key.size()); + has_current_user_key = true; + last_sequence_for_key = kMaxSequenceNumber; + } + + if (last_sequence_for_key <= compact->smallest_snapshot) { + // Hidden by an newer entry for same user key + drop = true; // (A) + } else if (ikey.type == kTypeDeletion && + ikey.sequence <= compact->smallest_snapshot && + compact->compaction->IsBaseLevelForKey(ikey.user_key)) { + // For this user key: + // (1) there is no data in higher levels + // (2) data in lower levels will have larger sequence numbers + // (3) data in layers that are being compacted here and have + // smaller sequence numbers will be dropped in the next + // few iterations of this loop (by rule (A) above). + // Therefore this deletion marker is obsolete and can be dropped. + drop = true; + } + + last_sequence_for_key = ikey.sequence; + } +#if 0 + Log(options_.info_log, + " Compact: %s, seq %d, type: %d %d, drop: %d, is_base: %d, " + "%d smallest_snapshot: %d", + ikey.user_key.ToString().c_str(), + (int)ikey.sequence, ikey.type, kTypeValue, drop, + compact->compaction->IsBaseLevelForKey(ikey.user_key), + (int)last_sequence_for_key, (int)compact->smallest_snapshot); +#endif + + if (!drop) { + // Open output file if necessary + if (compact->builder == NULL) { + status = OpenCompactionOutputFile(compact); + if (!status.ok()) { + break; + } + } + if (compact->builder->NumEntries() == 0) { + compact->current_output()->smallest.DecodeFrom(key); + } + compact->current_output()->largest.DecodeFrom(key); + compact->builder->Add(key, input->value()); + + // Close output file if it is big enough + if (compact->builder->FileSize() >= + compact->compaction->MaxOutputFileSize()) { + status = FinishCompactionOutputFile(compact, input); + if (!status.ok()) { + break; + } + } + } + + input->Next(); + } + + if (status.ok() && shutting_down_.Acquire_Load()) { + status = Status::IOError("Deleting DB during compaction"); + } + if (status.ok() && compact->builder != NULL) { + status = FinishCompactionOutputFile(compact, input); + } + if (status.ok()) { + status = input->status(); + } + delete input; + input = NULL; + + CompactionStats stats; + stats.micros = env_->NowMicros() - start_micros - imm_micros; + for (int which = 0; which < 2; which++) { + for (int i = 0; i < compact->compaction->num_input_files(which); i++) { + stats.bytes_read += compact->compaction->input(which, i)->file_size; + } + } + for (size_t i = 0; i < compact->outputs.size(); i++) { + stats.bytes_written += compact->outputs[i].file_size; + } + + mutex_.Lock(); + stats_[compact->compaction->level() + 1].Add(stats); + + if (status.ok()) { + status = InstallCompactionResults(compact); + } + if (!status.ok()) { + RecordBackgroundError(status); + } + VersionSet::LevelSummaryStorage tmp; + Log(options_.info_log, + "compacted to: %s", versions_->LevelSummary(&tmp)); + return status; +} + +namespace { +struct IterState { + port::Mutex* mu; + Version* version; + MemTable* mem; + MemTable* imm; +}; + +static void CleanupIteratorState(void* arg1, void* arg2) { + IterState* state = reinterpret_cast(arg1); + state->mu->Lock(); + state->mem->Unref(); + if (state->imm != NULL) state->imm->Unref(); + state->version->Unref(); + state->mu->Unlock(); + delete state; +} +} // namespace + +Iterator* DBImpl::NewInternalIterator(const ReadOptions& options, + SequenceNumber* latest_snapshot, + uint32_t* seed) { + IterState* cleanup = new IterState; + mutex_.Lock(); + *latest_snapshot = versions_->LastSequence(); + + // Collect together all needed child iterators + std::vector list; + list.push_back(mem_->NewIterator()); + mem_->Ref(); + if (imm_ != NULL) { + list.push_back(imm_->NewIterator()); + imm_->Ref(); + } + versions_->current()->AddIterators(options, &list); + Iterator* internal_iter = + NewMergingIterator(&internal_comparator_, &list[0], list.size()); + versions_->current()->Ref(); + + cleanup->mu = &mutex_; + cleanup->mem = mem_; + cleanup->imm = imm_; + cleanup->version = versions_->current(); + internal_iter->RegisterCleanup(CleanupIteratorState, cleanup, NULL); + + *seed = ++seed_; + mutex_.Unlock(); + return internal_iter; +} + +Iterator* DBImpl::TEST_NewInternalIterator() { + SequenceNumber ignored; + uint32_t ignored_seed; + return NewInternalIterator(ReadOptions(), &ignored, &ignored_seed); +} + +int64_t DBImpl::TEST_MaxNextLevelOverlappingBytes() { + MutexLock l(&mutex_); + return versions_->MaxNextLevelOverlappingBytes(); +} + +Status DBImpl::Get(const ReadOptions& options, + const Slice& key, + std::string* value) { + Status s; + MutexLock l(&mutex_); + SequenceNumber snapshot; + if (options.snapshot != NULL) { + snapshot = reinterpret_cast(options.snapshot)->number_; + } else { + snapshot = versions_->LastSequence(); + } + + MemTable* mem = mem_; + MemTable* imm = imm_; + Version* current = versions_->current(); + mem->Ref(); + if (imm != NULL) imm->Ref(); + current->Ref(); + + bool have_stat_update = false; + Version::GetStats stats; + + // Unlock while reading from files and memtables + { + mutex_.Unlock(); + // First look in the memtable, then in the immutable memtable (if any). + LookupKey lkey(key, snapshot); + if (mem->Get(lkey, value, &s)) { + // Done + } else if (imm != NULL && imm->Get(lkey, value, &s)) { + // Done + } else { + s = current->Get(options, lkey, value, &stats); + have_stat_update = true; + } + mutex_.Lock(); + } + + if (have_stat_update && current->UpdateStats(stats)) { + MaybeScheduleCompaction(); + } + mem->Unref(); + if (imm != NULL) imm->Unref(); + current->Unref(); + return s; +} + +Iterator* DBImpl::NewIterator(const ReadOptions& options) { + SequenceNumber latest_snapshot; + uint32_t seed; + Iterator* iter = NewInternalIterator(options, &latest_snapshot, &seed); + return NewDBIterator( + this, user_comparator(), iter, + (options.snapshot != NULL + ? reinterpret_cast(options.snapshot)->number_ + : latest_snapshot), + seed); +} + +void DBImpl::RecordReadSample(Slice key) { + MutexLock l(&mutex_); + if (versions_->current()->RecordReadSample(key)) { + MaybeScheduleCompaction(); + } +} + +const Snapshot* DBImpl::GetSnapshot() { + MutexLock l(&mutex_); + return snapshots_.New(versions_->LastSequence()); +} + +void DBImpl::ReleaseSnapshot(const Snapshot* s) { + MutexLock l(&mutex_); + snapshots_.Delete(reinterpret_cast(s)); +} + +// Convenience methods +Status DBImpl::Put(const WriteOptions& o, const Slice& key, const Slice& val) { + return DB::Put(o, key, val); +} + +Status DBImpl::Delete(const WriteOptions& options, const Slice& key) { + return DB::Delete(options, key); +} + +Status DBImpl::Write(const WriteOptions& options, WriteBatch* my_batch) { + Writer w(&mutex_); + w.batch = my_batch; + w.sync = options.sync; + w.done = false; + + MutexLock l(&mutex_); + writers_.push_back(&w); + while (!w.done && &w != writers_.front()) { + w.cv.Wait(); + } + if (w.done) { + return w.status; + } + + // May temporarily unlock and wait. + Status status = MakeRoomForWrite(my_batch == NULL); + uint64_t last_sequence = versions_->LastSequence(); + Writer* last_writer = &w; + if (status.ok() && my_batch != NULL) { // NULL batch is for compactions + WriteBatch* updates = BuildBatchGroup(&last_writer); + WriteBatchInternal::SetSequence(updates, last_sequence + 1); + last_sequence += WriteBatchInternal::Count(updates); + + // Add to log and apply to memtable. We can release the lock + // during this phase since &w is currently responsible for logging + // and protects against concurrent loggers and concurrent writes + // into mem_. + { + mutex_.Unlock(); + status = log_->AddRecord(WriteBatchInternal::Contents(updates)); + bool sync_error = false; + if (status.ok() && options.sync) { + status = logfile_->Sync(); + if (!status.ok()) { + sync_error = true; + } + } + if (status.ok()) { + status = WriteBatchInternal::InsertInto(updates, mem_); + } + mutex_.Lock(); + if (sync_error) { + // The state of the log file is indeterminate: the log record we + // just added may or may not show up when the DB is re-opened. + // So we force the DB into a mode where all future writes fail. + RecordBackgroundError(status); + } + } + if (updates == tmp_batch_) tmp_batch_->Clear(); + + versions_->SetLastSequence(last_sequence); + } + + while (true) { + Writer* ready = writers_.front(); + writers_.pop_front(); + if (ready != &w) { + ready->status = status; + ready->done = true; + ready->cv.Signal(); + } + if (ready == last_writer) break; + } + + // Notify new head of write queue + if (!writers_.empty()) { + writers_.front()->cv.Signal(); + } + + return status; +} + +// REQUIRES: Writer list must be non-empty +// REQUIRES: First writer must have a non-NULL batch +WriteBatch* DBImpl::BuildBatchGroup(Writer** last_writer) { + assert(!writers_.empty()); + Writer* first = writers_.front(); + WriteBatch* result = first->batch; + assert(result != NULL); + + size_t size = WriteBatchInternal::ByteSize(first->batch); + + // Allow the group to grow up to a maximum size, but if the + // original write is small, limit the growth so we do not slow + // down the small write too much. + size_t max_size = 1 << 20; + if (size <= (128<<10)) { + max_size = size + (128<<10); + } + + *last_writer = first; + std::deque::iterator iter = writers_.begin(); + ++iter; // Advance past "first" + for (; iter != writers_.end(); ++iter) { + Writer* w = *iter; + if (w->sync && !first->sync) { + // Do not include a sync write into a batch handled by a non-sync write. + break; + } + + if (w->batch != NULL) { + size += WriteBatchInternal::ByteSize(w->batch); + if (size > max_size) { + // Do not make batch too big + break; + } + + // Append to *reuslt + if (result == first->batch) { + // Switch to temporary batch instead of disturbing caller's batch + result = tmp_batch_; + assert(WriteBatchInternal::Count(result) == 0); + WriteBatchInternal::Append(result, first->batch); + } + WriteBatchInternal::Append(result, w->batch); + } + *last_writer = w; + } + return result; +} + +// REQUIRES: mutex_ is held +// REQUIRES: this thread is currently at the front of the writer queue +Status DBImpl::MakeRoomForWrite(bool force) { + mutex_.AssertHeld(); + assert(!writers_.empty()); + bool allow_delay = !force; + Status s; + while (true) { + if (!bg_error_.ok()) { + // Yield previous error + s = bg_error_; + break; + } else if ( + allow_delay && + versions_->NumLevelFiles(0) >= config::kL0_SlowdownWritesTrigger) { + // We are getting close to hitting a hard limit on the number of + // L0 files. Rather than delaying a single write by several + // seconds when we hit the hard limit, start delaying each + // individual write by 1ms to reduce latency variance. Also, + // this delay hands over some CPU to the compaction thread in + // case it is sharing the same core as the writer. + mutex_.Unlock(); + env_->SleepForMicroseconds(1000); + allow_delay = false; // Do not delay a single write more than once + mutex_.Lock(); + } else if (!force && + (mem_->ApproximateMemoryUsage() <= options_.write_buffer_size)) { + // There is room in current memtable + break; + } else if (imm_ != NULL) { + // We have filled up the current memtable, but the previous + // one is still being compacted, so we wait. + Log(options_.info_log, "Current memtable full; waiting...\n"); + bg_cv_.Wait(); + } else if (versions_->NumLevelFiles(0) >= config::kL0_StopWritesTrigger) { + // There are too many level-0 files. + Log(options_.info_log, "Too many L0 files; waiting...\n"); + bg_cv_.Wait(); + } else { + // Attempt to switch to a new memtable and trigger compaction of old + assert(versions_->PrevLogNumber() == 0); + uint64_t new_log_number = versions_->NewFileNumber(); + WritableFile* lfile = NULL; + s = env_->NewWritableFile(LogFileName(dbname_, new_log_number), &lfile); + if (!s.ok()) { + // Avoid chewing through file number space in a tight loop. + versions_->ReuseFileNumber(new_log_number); + break; + } + delete log_; + delete logfile_; + logfile_ = lfile; + logfile_number_ = new_log_number; + log_ = new log::Writer(lfile); + imm_ = mem_; + has_imm_.Release_Store(imm_); + mem_ = new MemTable(internal_comparator_); + mem_->Ref(); + force = false; // Do not force another compaction if have room + MaybeScheduleCompaction(); + } + } + return s; +} + +bool DBImpl::GetProperty(const Slice& property, std::string* value) { + value->clear(); + + MutexLock l(&mutex_); + Slice in = property; + Slice prefix("leveldb."); + if (!in.starts_with(prefix)) return false; + in.remove_prefix(prefix.size()); + + if (in.starts_with("num-files-at-level")) { + in.remove_prefix(strlen("num-files-at-level")); + uint64_t level; + bool ok = ConsumeDecimalNumber(&in, &level) && in.empty(); + if (!ok || level >= config::kNumLevels) { + return false; + } else { + char buf[100]; + snprintf(buf, sizeof(buf), "%d", + versions_->NumLevelFiles(static_cast(level))); + *value = buf; + return true; + } + } else if (in == "stats") { + char buf[200]; + snprintf(buf, sizeof(buf), + " Compactions\n" + "Level Files Size(MB) Time(sec) Read(MB) Write(MB)\n" + "--------------------------------------------------\n" + ); + value->append(buf); + for (int level = 0; level < config::kNumLevels; level++) { + int files = versions_->NumLevelFiles(level); + if (stats_[level].micros > 0 || files > 0) { + snprintf( + buf, sizeof(buf), + "%3d %8d %8.0f %9.0f %8.0f %9.0f\n", + level, + files, + versions_->NumLevelBytes(level) / 1048576.0, + stats_[level].micros / 1e6, + stats_[level].bytes_read / 1048576.0, + stats_[level].bytes_written / 1048576.0); + value->append(buf); + } + } + return true; + } else if (in == "sstables") { + *value = versions_->current()->DebugString(); + return true; + } + + return false; +} + +void DBImpl::GetApproximateSizes( + const Range* range, int n, + uint64_t* sizes) { + // TODO(opt): better implementation + Version* v; + { + MutexLock l(&mutex_); + versions_->current()->Ref(); + v = versions_->current(); + } + + for (int i = 0; i < n; i++) { + // Convert user_key into a corresponding internal key. + InternalKey k1(range[i].start, kMaxSequenceNumber, kValueTypeForSeek); + InternalKey k2(range[i].limit, kMaxSequenceNumber, kValueTypeForSeek); + uint64_t start = versions_->ApproximateOffsetOf(v, k1); + uint64_t limit = versions_->ApproximateOffsetOf(v, k2); + sizes[i] = (limit >= start ? limit - start : 0); + } + + { + MutexLock l(&mutex_); + v->Unref(); + } +} + +// Default implementations of convenience methods that subclasses of DB +// can call if they wish +Status DB::Put(const WriteOptions& opt, const Slice& key, const Slice& value) { + WriteBatch batch; + batch.Put(key, value); + return Write(opt, &batch); +} + +Status DB::Delete(const WriteOptions& opt, const Slice& key) { + WriteBatch batch; + batch.Delete(key); + return Write(opt, &batch); +} + +DB::~DB() { } + +Status DB::Open(const Options& options, const std::string& dbname, + DB** dbptr) { + *dbptr = NULL; + + DBImpl* impl = new DBImpl(options, dbname); + impl->mutex_.Lock(); + VersionEdit edit; + Status s = impl->Recover(&edit); // Handles create_if_missing, error_if_exists + if (s.ok()) { + uint64_t new_log_number = impl->versions_->NewFileNumber(); + WritableFile* lfile; + s = options.env->NewWritableFile(LogFileName(dbname, new_log_number), + &lfile); + if (s.ok()) { + edit.SetLogNumber(new_log_number); + impl->logfile_ = lfile; + impl->logfile_number_ = new_log_number; + impl->log_ = new log::Writer(lfile); + s = impl->versions_->LogAndApply(&edit, &impl->mutex_); + } + if (s.ok()) { + impl->DeleteObsoleteFiles(); + impl->MaybeScheduleCompaction(); + } + } + impl->mutex_.Unlock(); + if (s.ok()) { + *dbptr = impl; + } else { + delete impl; + } + return s; +} + +Snapshot::~Snapshot() { +} + +Status DestroyDB(const std::string& dbname, const Options& options) { + Env* env = options.env; + std::vector filenames; + // Ignore error in case directory does not exist + env->GetChildren(dbname, &filenames); + if (filenames.empty()) { + return Status::OK(); + } + + FileLock* lock; + const std::string lockname = LockFileName(dbname); + Status result = env->LockFile(lockname, &lock); + if (result.ok()) { + uint64_t number; + FileType type; + for (size_t i = 0; i < filenames.size(); i++) { + if (ParseFileName(filenames[i], &number, &type) && + type != kDBLockFile) { // Lock file will be deleted at end + Status del = env->DeleteFile(dbname + "/" + filenames[i]); + if (result.ok() && !del.ok()) { + result = del; + } + } + } + env->UnlockFile(lock); // Ignore error since state is already gone + env->DeleteFile(lockname); + env->DeleteDir(dbname); // Ignore error in case dir contains other files + } + return result; +} + +} // namespace leveldb diff --git a/src/leveldb/db/db_impl.h b/src/leveldb/db/db_impl.h new file mode 100644 index 0000000..cfc9981 --- /dev/null +++ b/src/leveldb/db/db_impl.h @@ -0,0 +1,211 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#ifndef STORAGE_LEVELDB_DB_DB_IMPL_H_ +#define STORAGE_LEVELDB_DB_DB_IMPL_H_ + +#include +#include +#include "db/dbformat.h" +#include "db/log_writer.h" +#include "db/snapshot.h" +#include "leveldb/db.h" +#include "leveldb/env.h" +#include "port/port.h" +#include "port/thread_annotations.h" + +namespace leveldb { + +class MemTable; +class TableCache; +class Version; +class VersionEdit; +class VersionSet; + +class DBImpl : public DB { + public: + DBImpl(const Options& options, const std::string& dbname); + virtual ~DBImpl(); + + // Implementations of the DB interface + virtual Status Put(const WriteOptions&, const Slice& key, const Slice& value); + virtual Status Delete(const WriteOptions&, const Slice& key); + virtual Status Write(const WriteOptions& options, WriteBatch* updates); + virtual Status Get(const ReadOptions& options, + const Slice& key, + std::string* value); + virtual Iterator* NewIterator(const ReadOptions&); + virtual const Snapshot* GetSnapshot(); + virtual void ReleaseSnapshot(const Snapshot* snapshot); + virtual bool GetProperty(const Slice& property, std::string* value); + virtual void GetApproximateSizes(const Range* range, int n, uint64_t* sizes); + virtual void CompactRange(const Slice* begin, const Slice* end); + + // Extra methods (for testing) that are not in the public DB interface + + // Compact any files in the named level that overlap [*begin,*end] + void TEST_CompactRange(int level, const Slice* begin, const Slice* end); + + // Force current memtable contents to be compacted. + Status TEST_CompactMemTable(); + + // Return an internal iterator over the current state of the database. + // The keys of this iterator are internal keys (see format.h). + // The returned iterator should be deleted when no longer needed. + Iterator* TEST_NewInternalIterator(); + + // Return the maximum overlapping data (in bytes) at next level for any + // file at a level >= 1. + int64_t TEST_MaxNextLevelOverlappingBytes(); + + // Record a sample of bytes read at the specified internal key. + // Samples are taken approximately once every config::kReadBytesPeriod + // bytes. + void RecordReadSample(Slice key); + + private: + friend class DB; + struct CompactionState; + struct Writer; + + Iterator* NewInternalIterator(const ReadOptions&, + SequenceNumber* latest_snapshot, + uint32_t* seed); + + Status NewDB(); + + // Recover the descriptor from persistent storage. May do a significant + // amount of work to recover recently logged updates. Any changes to + // be made to the descriptor are added to *edit. + Status Recover(VersionEdit* edit) EXCLUSIVE_LOCKS_REQUIRED(mutex_); + + void MaybeIgnoreError(Status* s) const; + + // Delete any unneeded files and stale in-memory entries. + void DeleteObsoleteFiles(); + + // Compact the in-memory write buffer to disk. Switches to a new + // log-file/memtable and writes a new descriptor iff successful. + // Errors are recorded in bg_error_. + void CompactMemTable() EXCLUSIVE_LOCKS_REQUIRED(mutex_); + + Status RecoverLogFile(uint64_t log_number, + VersionEdit* edit, + SequenceNumber* max_sequence) + EXCLUSIVE_LOCKS_REQUIRED(mutex_); + + Status WriteLevel0Table(MemTable* mem, VersionEdit* edit, Version* base) + EXCLUSIVE_LOCKS_REQUIRED(mutex_); + + Status MakeRoomForWrite(bool force /* compact even if there is room? */) + EXCLUSIVE_LOCKS_REQUIRED(mutex_); + WriteBatch* BuildBatchGroup(Writer** last_writer); + + void RecordBackgroundError(const Status& s); + + void MaybeScheduleCompaction() EXCLUSIVE_LOCKS_REQUIRED(mutex_); + static void BGWork(void* db); + void BackgroundCall(); + void BackgroundCompaction() EXCLUSIVE_LOCKS_REQUIRED(mutex_); + void CleanupCompaction(CompactionState* compact) + EXCLUSIVE_LOCKS_REQUIRED(mutex_); + Status DoCompactionWork(CompactionState* compact) + EXCLUSIVE_LOCKS_REQUIRED(mutex_); + + Status OpenCompactionOutputFile(CompactionState* compact); + Status FinishCompactionOutputFile(CompactionState* compact, Iterator* input); + Status InstallCompactionResults(CompactionState* compact) + EXCLUSIVE_LOCKS_REQUIRED(mutex_); + + // Constant after construction + Env* const env_; + const InternalKeyComparator internal_comparator_; + const InternalFilterPolicy internal_filter_policy_; + const Options options_; // options_.comparator == &internal_comparator_ + bool owns_info_log_; + bool owns_cache_; + const std::string dbname_; + + // table_cache_ provides its own synchronization + TableCache* table_cache_; + + // Lock over the persistent DB state. Non-NULL iff successfully acquired. + FileLock* db_lock_; + + // State below is protected by mutex_ + port::Mutex mutex_; + port::AtomicPointer shutting_down_; + port::CondVar bg_cv_; // Signalled when background work finishes + MemTable* mem_; + MemTable* imm_; // Memtable being compacted + port::AtomicPointer has_imm_; // So bg thread can detect non-NULL imm_ + WritableFile* logfile_; + uint64_t logfile_number_; + log::Writer* log_; + uint32_t seed_; // For sampling. + + // Queue of writers. + std::deque writers_; + WriteBatch* tmp_batch_; + + SnapshotList snapshots_; + + // Set of table files to protect from deletion because they are + // part of ongoing compactions. + std::set pending_outputs_; + + // Has a background compaction been scheduled or is running? + bool bg_compaction_scheduled_; + + // Information for a manual compaction + struct ManualCompaction { + int level; + bool done; + const InternalKey* begin; // NULL means beginning of key range + const InternalKey* end; // NULL means end of key range + InternalKey tmp_storage; // Used to keep track of compaction progress + }; + ManualCompaction* manual_compaction_; + + VersionSet* versions_; + + // Have we encountered a background error in paranoid mode? + Status bg_error_; + + // Per level compaction stats. stats_[level] stores the stats for + // compactions that produced data for the specified "level". + struct CompactionStats { + int64_t micros; + int64_t bytes_read; + int64_t bytes_written; + + CompactionStats() : micros(0), bytes_read(0), bytes_written(0) { } + + void Add(const CompactionStats& c) { + this->micros += c.micros; + this->bytes_read += c.bytes_read; + this->bytes_written += c.bytes_written; + } + }; + CompactionStats stats_[config::kNumLevels]; + + // No copying allowed + DBImpl(const DBImpl&); + void operator=(const DBImpl&); + + const Comparator* user_comparator() const { + return internal_comparator_.user_comparator(); + } +}; + +// Sanitize db options. The caller should delete result.info_log if +// it is not equal to src.info_log. +extern Options SanitizeOptions(const std::string& db, + const InternalKeyComparator* icmp, + const InternalFilterPolicy* ipolicy, + const Options& src); + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_DB_DB_IMPL_H_ diff --git a/src/leveldb/db/db_iter.cc b/src/leveldb/db/db_iter.cc new file mode 100644 index 0000000..3b2035e --- /dev/null +++ b/src/leveldb/db/db_iter.cc @@ -0,0 +1,317 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "db/db_iter.h" + +#include "db/filename.h" +#include "db/db_impl.h" +#include "db/dbformat.h" +#include "leveldb/env.h" +#include "leveldb/iterator.h" +#include "port/port.h" +#include "util/logging.h" +#include "util/mutexlock.h" +#include "util/random.h" + +namespace leveldb { + +#if 0 +static void DumpInternalIter(Iterator* iter) { + for (iter->SeekToFirst(); iter->Valid(); iter->Next()) { + ParsedInternalKey k; + if (!ParseInternalKey(iter->key(), &k)) { + fprintf(stderr, "Corrupt '%s'\n", EscapeString(iter->key()).c_str()); + } else { + fprintf(stderr, "@ '%s'\n", k.DebugString().c_str()); + } + } +} +#endif + +namespace { + +// Memtables and sstables that make the DB representation contain +// (userkey,seq,type) => uservalue entries. DBIter +// combines multiple entries for the same userkey found in the DB +// representation into a single entry while accounting for sequence +// numbers, deletion markers, overwrites, etc. +class DBIter: public Iterator { + public: + // Which direction is the iterator currently moving? + // (1) When moving forward, the internal iterator is positioned at + // the exact entry that yields this->key(), this->value() + // (2) When moving backwards, the internal iterator is positioned + // just before all entries whose user key == this->key(). + enum Direction { + kForward, + kReverse + }; + + DBIter(DBImpl* db, const Comparator* cmp, Iterator* iter, SequenceNumber s, + uint32_t seed) + : db_(db), + user_comparator_(cmp), + iter_(iter), + sequence_(s), + direction_(kForward), + valid_(false), + rnd_(seed), + bytes_counter_(RandomPeriod()) { + } + virtual ~DBIter() { + delete iter_; + } + virtual bool Valid() const { return valid_; } + virtual Slice key() const { + assert(valid_); + return (direction_ == kForward) ? ExtractUserKey(iter_->key()) : saved_key_; + } + virtual Slice value() const { + assert(valid_); + return (direction_ == kForward) ? iter_->value() : saved_value_; + } + virtual Status status() const { + if (status_.ok()) { + return iter_->status(); + } else { + return status_; + } + } + + virtual void Next(); + virtual void Prev(); + virtual void Seek(const Slice& target); + virtual void SeekToFirst(); + virtual void SeekToLast(); + + private: + void FindNextUserEntry(bool skipping, std::string* skip); + void FindPrevUserEntry(); + bool ParseKey(ParsedInternalKey* key); + + inline void SaveKey(const Slice& k, std::string* dst) { + dst->assign(k.data(), k.size()); + } + + inline void ClearSavedValue() { + if (saved_value_.capacity() > 1048576) { + std::string empty; + swap(empty, saved_value_); + } else { + saved_value_.clear(); + } + } + + // Pick next gap with average value of config::kReadBytesPeriod. + ssize_t RandomPeriod() { + return rnd_.Uniform(2*config::kReadBytesPeriod); + } + + DBImpl* db_; + const Comparator* const user_comparator_; + Iterator* const iter_; + SequenceNumber const sequence_; + + Status status_; + std::string saved_key_; // == current key when direction_==kReverse + std::string saved_value_; // == current raw value when direction_==kReverse + Direction direction_; + bool valid_; + + Random rnd_; + ssize_t bytes_counter_; + + // No copying allowed + DBIter(const DBIter&); + void operator=(const DBIter&); +}; + +inline bool DBIter::ParseKey(ParsedInternalKey* ikey) { + Slice k = iter_->key(); + ssize_t n = k.size() + iter_->value().size(); + bytes_counter_ -= n; + while (bytes_counter_ < 0) { + bytes_counter_ += RandomPeriod(); + db_->RecordReadSample(k); + } + if (!ParseInternalKey(k, ikey)) { + status_ = Status::Corruption("corrupted internal key in DBIter"); + return false; + } else { + return true; + } +} + +void DBIter::Next() { + assert(valid_); + + if (direction_ == kReverse) { // Switch directions? + direction_ = kForward; + // iter_ is pointing just before the entries for this->key(), + // so advance into the range of entries for this->key() and then + // use the normal skipping code below. + if (!iter_->Valid()) { + iter_->SeekToFirst(); + } else { + iter_->Next(); + } + if (!iter_->Valid()) { + valid_ = false; + saved_key_.clear(); + return; + } + // saved_key_ already contains the key to skip past. + } else { + // Store in saved_key_ the current key so we skip it below. + SaveKey(ExtractUserKey(iter_->key()), &saved_key_); + } + + FindNextUserEntry(true, &saved_key_); +} + +void DBIter::FindNextUserEntry(bool skipping, std::string* skip) { + // Loop until we hit an acceptable entry to yield + assert(iter_->Valid()); + assert(direction_ == kForward); + do { + ParsedInternalKey ikey; + if (ParseKey(&ikey) && ikey.sequence <= sequence_) { + switch (ikey.type) { + case kTypeDeletion: + // Arrange to skip all upcoming entries for this key since + // they are hidden by this deletion. + SaveKey(ikey.user_key, skip); + skipping = true; + break; + case kTypeValue: + if (skipping && + user_comparator_->Compare(ikey.user_key, *skip) <= 0) { + // Entry hidden + } else { + valid_ = true; + saved_key_.clear(); + return; + } + break; + } + } + iter_->Next(); + } while (iter_->Valid()); + saved_key_.clear(); + valid_ = false; +} + +void DBIter::Prev() { + assert(valid_); + + if (direction_ == kForward) { // Switch directions? + // iter_ is pointing at the current entry. Scan backwards until + // the key changes so we can use the normal reverse scanning code. + assert(iter_->Valid()); // Otherwise valid_ would have been false + SaveKey(ExtractUserKey(iter_->key()), &saved_key_); + while (true) { + iter_->Prev(); + if (!iter_->Valid()) { + valid_ = false; + saved_key_.clear(); + ClearSavedValue(); + return; + } + if (user_comparator_->Compare(ExtractUserKey(iter_->key()), + saved_key_) < 0) { + break; + } + } + direction_ = kReverse; + } + + FindPrevUserEntry(); +} + +void DBIter::FindPrevUserEntry() { + assert(direction_ == kReverse); + + ValueType value_type = kTypeDeletion; + if (iter_->Valid()) { + do { + ParsedInternalKey ikey; + if (ParseKey(&ikey) && ikey.sequence <= sequence_) { + if ((value_type != kTypeDeletion) && + user_comparator_->Compare(ikey.user_key, saved_key_) < 0) { + // We encountered a non-deleted value in entries for previous keys, + break; + } + value_type = ikey.type; + if (value_type == kTypeDeletion) { + saved_key_.clear(); + ClearSavedValue(); + } else { + Slice raw_value = iter_->value(); + if (saved_value_.capacity() > raw_value.size() + 1048576) { + std::string empty; + swap(empty, saved_value_); + } + SaveKey(ExtractUserKey(iter_->key()), &saved_key_); + saved_value_.assign(raw_value.data(), raw_value.size()); + } + } + iter_->Prev(); + } while (iter_->Valid()); + } + + if (value_type == kTypeDeletion) { + // End + valid_ = false; + saved_key_.clear(); + ClearSavedValue(); + direction_ = kForward; + } else { + valid_ = true; + } +} + +void DBIter::Seek(const Slice& target) { + direction_ = kForward; + ClearSavedValue(); + saved_key_.clear(); + AppendInternalKey( + &saved_key_, ParsedInternalKey(target, sequence_, kValueTypeForSeek)); + iter_->Seek(saved_key_); + if (iter_->Valid()) { + FindNextUserEntry(false, &saved_key_ /* temporary storage */); + } else { + valid_ = false; + } +} + +void DBIter::SeekToFirst() { + direction_ = kForward; + ClearSavedValue(); + iter_->SeekToFirst(); + if (iter_->Valid()) { + FindNextUserEntry(false, &saved_key_ /* temporary storage */); + } else { + valid_ = false; + } +} + +void DBIter::SeekToLast() { + direction_ = kReverse; + ClearSavedValue(); + iter_->SeekToLast(); + FindPrevUserEntry(); +} + +} // anonymous namespace + +Iterator* NewDBIterator( + DBImpl* db, + const Comparator* user_key_comparator, + Iterator* internal_iter, + SequenceNumber sequence, + uint32_t seed) { + return new DBIter(db, user_key_comparator, internal_iter, sequence, seed); +} + +} // namespace leveldb diff --git a/src/leveldb/db/db_iter.h b/src/leveldb/db/db_iter.h new file mode 100644 index 0000000..04927e9 --- /dev/null +++ b/src/leveldb/db/db_iter.h @@ -0,0 +1,28 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#ifndef STORAGE_LEVELDB_DB_DB_ITER_H_ +#define STORAGE_LEVELDB_DB_DB_ITER_H_ + +#include +#include "leveldb/db.h" +#include "db/dbformat.h" + +namespace leveldb { + +class DBImpl; + +// Return a new iterator that converts internal keys (yielded by +// "*internal_iter") that were live at the specified "sequence" number +// into appropriate user keys. +extern Iterator* NewDBIterator( + DBImpl* db, + const Comparator* user_key_comparator, + Iterator* internal_iter, + SequenceNumber sequence, + uint32_t seed); + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_DB_DB_ITER_H_ diff --git a/src/leveldb/db/db_test.cc b/src/leveldb/db/db_test.cc new file mode 100644 index 0000000..280b01c --- /dev/null +++ b/src/leveldb/db/db_test.cc @@ -0,0 +1,2128 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "leveldb/db.h" +#include "leveldb/filter_policy.h" +#include "db/db_impl.h" +#include "db/filename.h" +#include "db/version_set.h" +#include "db/write_batch_internal.h" +#include "leveldb/cache.h" +#include "leveldb/env.h" +#include "leveldb/table.h" +#include "util/hash.h" +#include "util/logging.h" +#include "util/mutexlock.h" +#include "util/testharness.h" +#include "util/testutil.h" + +namespace leveldb { + +static std::string RandomString(Random* rnd, int len) { + std::string r; + test::RandomString(rnd, len, &r); + return r; +} + +namespace { +class AtomicCounter { + private: + port::Mutex mu_; + int count_; + public: + AtomicCounter() : count_(0) { } + void Increment() { + IncrementBy(1); + } + void IncrementBy(int count) { + MutexLock l(&mu_); + count_ += count; + } + int Read() { + MutexLock l(&mu_); + return count_; + } + void Reset() { + MutexLock l(&mu_); + count_ = 0; + } +}; + +void DelayMilliseconds(int millis) { + Env::Default()->SleepForMicroseconds(millis * 1000); +} +} + +// Special Env used to delay background operations +class SpecialEnv : public EnvWrapper { + public: + // sstable/log Sync() calls are blocked while this pointer is non-NULL. + port::AtomicPointer delay_data_sync_; + + // sstable/log Sync() calls return an error. + port::AtomicPointer data_sync_error_; + + // Simulate no-space errors while this pointer is non-NULL. + port::AtomicPointer no_space_; + + // Simulate non-writable file system while this pointer is non-NULL + port::AtomicPointer non_writable_; + + // Force sync of manifest files to fail while this pointer is non-NULL + port::AtomicPointer manifest_sync_error_; + + // Force write to manifest files to fail while this pointer is non-NULL + port::AtomicPointer manifest_write_error_; + + bool count_random_reads_; + AtomicCounter random_read_counter_; + + explicit SpecialEnv(Env* base) : EnvWrapper(base) { + delay_data_sync_.Release_Store(NULL); + data_sync_error_.Release_Store(NULL); + no_space_.Release_Store(NULL); + non_writable_.Release_Store(NULL); + count_random_reads_ = false; + manifest_sync_error_.Release_Store(NULL); + manifest_write_error_.Release_Store(NULL); + } + + Status NewWritableFile(const std::string& f, WritableFile** r) { + class DataFile : public WritableFile { + private: + SpecialEnv* env_; + WritableFile* base_; + + public: + DataFile(SpecialEnv* env, WritableFile* base) + : env_(env), + base_(base) { + } + ~DataFile() { delete base_; } + Status Append(const Slice& data) { + if (env_->no_space_.Acquire_Load() != NULL) { + // Drop writes on the floor + return Status::OK(); + } else { + return base_->Append(data); + } + } + Status Close() { return base_->Close(); } + Status Flush() { return base_->Flush(); } + Status Sync() { + if (env_->data_sync_error_.Acquire_Load() != NULL) { + return Status::IOError("simulated data sync error"); + } + while (env_->delay_data_sync_.Acquire_Load() != NULL) { + DelayMilliseconds(100); + } + return base_->Sync(); + } + }; + class ManifestFile : public WritableFile { + private: + SpecialEnv* env_; + WritableFile* base_; + public: + ManifestFile(SpecialEnv* env, WritableFile* b) : env_(env), base_(b) { } + ~ManifestFile() { delete base_; } + Status Append(const Slice& data) { + if (env_->manifest_write_error_.Acquire_Load() != NULL) { + return Status::IOError("simulated writer error"); + } else { + return base_->Append(data); + } + } + Status Close() { return base_->Close(); } + Status Flush() { return base_->Flush(); } + Status Sync() { + if (env_->manifest_sync_error_.Acquire_Load() != NULL) { + return Status::IOError("simulated sync error"); + } else { + return base_->Sync(); + } + } + }; + + if (non_writable_.Acquire_Load() != NULL) { + return Status::IOError("simulated write error"); + } + + Status s = target()->NewWritableFile(f, r); + if (s.ok()) { + if (strstr(f.c_str(), ".ldb") != NULL || + strstr(f.c_str(), ".log") != NULL) { + *r = new DataFile(this, *r); + } else if (strstr(f.c_str(), "MANIFEST") != NULL) { + *r = new ManifestFile(this, *r); + } + } + return s; + } + + Status NewRandomAccessFile(const std::string& f, RandomAccessFile** r) { + class CountingFile : public RandomAccessFile { + private: + RandomAccessFile* target_; + AtomicCounter* counter_; + public: + CountingFile(RandomAccessFile* target, AtomicCounter* counter) + : target_(target), counter_(counter) { + } + virtual ~CountingFile() { delete target_; } + virtual Status Read(uint64_t offset, size_t n, Slice* result, + char* scratch) const { + counter_->Increment(); + return target_->Read(offset, n, result, scratch); + } + }; + + Status s = target()->NewRandomAccessFile(f, r); + if (s.ok() && count_random_reads_) { + *r = new CountingFile(*r, &random_read_counter_); + } + return s; + } +}; + +class DBTest { + private: + const FilterPolicy* filter_policy_; + + // Sequence of option configurations to try + enum OptionConfig { + kDefault, + kFilter, + kUncompressed, + kEnd + }; + int option_config_; + + public: + std::string dbname_; + SpecialEnv* env_; + DB* db_; + + Options last_options_; + + DBTest() : option_config_(kDefault), + env_(new SpecialEnv(Env::Default())) { + filter_policy_ = NewBloomFilterPolicy(10); + dbname_ = test::TmpDir() + "/db_test"; + DestroyDB(dbname_, Options()); + db_ = NULL; + Reopen(); + } + + ~DBTest() { + delete db_; + DestroyDB(dbname_, Options()); + delete env_; + delete filter_policy_; + } + + // Switch to a fresh database with the next option configuration to + // test. Return false if there are no more configurations to test. + bool ChangeOptions() { + option_config_++; + if (option_config_ >= kEnd) { + return false; + } else { + DestroyAndReopen(); + return true; + } + } + + // Return the current option configuration. + Options CurrentOptions() { + Options options; + switch (option_config_) { + case kFilter: + options.filter_policy = filter_policy_; + break; + case kUncompressed: + options.compression = kNoCompression; + break; + default: + break; + } + return options; + } + + DBImpl* dbfull() { + return reinterpret_cast(db_); + } + + void Reopen(Options* options = NULL) { + ASSERT_OK(TryReopen(options)); + } + + void Close() { + delete db_; + db_ = NULL; + } + + void DestroyAndReopen(Options* options = NULL) { + delete db_; + db_ = NULL; + DestroyDB(dbname_, Options()); + ASSERT_OK(TryReopen(options)); + } + + Status TryReopen(Options* options) { + delete db_; + db_ = NULL; + Options opts; + if (options != NULL) { + opts = *options; + } else { + opts = CurrentOptions(); + opts.create_if_missing = true; + } + last_options_ = opts; + + return DB::Open(opts, dbname_, &db_); + } + + Status Put(const std::string& k, const std::string& v) { + return db_->Put(WriteOptions(), k, v); + } + + Status Delete(const std::string& k) { + return db_->Delete(WriteOptions(), k); + } + + std::string Get(const std::string& k, const Snapshot* snapshot = NULL) { + ReadOptions options; + options.snapshot = snapshot; + std::string result; + Status s = db_->Get(options, k, &result); + if (s.IsNotFound()) { + result = "NOT_FOUND"; + } else if (!s.ok()) { + result = s.ToString(); + } + return result; + } + + // Return a string that contains all key,value pairs in order, + // formatted like "(k1->v1)(k2->v2)". + std::string Contents() { + std::vector forward; + std::string result; + Iterator* iter = db_->NewIterator(ReadOptions()); + for (iter->SeekToFirst(); iter->Valid(); iter->Next()) { + std::string s = IterStatus(iter); + result.push_back('('); + result.append(s); + result.push_back(')'); + forward.push_back(s); + } + + // Check reverse iteration results are the reverse of forward results + size_t matched = 0; + for (iter->SeekToLast(); iter->Valid(); iter->Prev()) { + ASSERT_LT(matched, forward.size()); + ASSERT_EQ(IterStatus(iter), forward[forward.size() - matched - 1]); + matched++; + } + ASSERT_EQ(matched, forward.size()); + + delete iter; + return result; + } + + std::string AllEntriesFor(const Slice& user_key) { + Iterator* iter = dbfull()->TEST_NewInternalIterator(); + InternalKey target(user_key, kMaxSequenceNumber, kTypeValue); + iter->Seek(target.Encode()); + std::string result; + if (!iter->status().ok()) { + result = iter->status().ToString(); + } else { + result = "[ "; + bool first = true; + while (iter->Valid()) { + ParsedInternalKey ikey; + if (!ParseInternalKey(iter->key(), &ikey)) { + result += "CORRUPTED"; + } else { + if (last_options_.comparator->Compare(ikey.user_key, user_key) != 0) { + break; + } + if (!first) { + result += ", "; + } + first = false; + switch (ikey.type) { + case kTypeValue: + result += iter->value().ToString(); + break; + case kTypeDeletion: + result += "DEL"; + break; + } + } + iter->Next(); + } + if (!first) { + result += " "; + } + result += "]"; + } + delete iter; + return result; + } + + int NumTableFilesAtLevel(int level) { + std::string property; + ASSERT_TRUE( + db_->GetProperty("leveldb.num-files-at-level" + NumberToString(level), + &property)); + return atoi(property.c_str()); + } + + int TotalTableFiles() { + int result = 0; + for (int level = 0; level < config::kNumLevels; level++) { + result += NumTableFilesAtLevel(level); + } + return result; + } + + // Return spread of files per level + std::string FilesPerLevel() { + std::string result; + int last_non_zero_offset = 0; + for (int level = 0; level < config::kNumLevels; level++) { + int f = NumTableFilesAtLevel(level); + char buf[100]; + snprintf(buf, sizeof(buf), "%s%d", (level ? "," : ""), f); + result += buf; + if (f > 0) { + last_non_zero_offset = result.size(); + } + } + result.resize(last_non_zero_offset); + return result; + } + + int CountFiles() { + std::vector files; + env_->GetChildren(dbname_, &files); + return static_cast(files.size()); + } + + uint64_t Size(const Slice& start, const Slice& limit) { + Range r(start, limit); + uint64_t size; + db_->GetApproximateSizes(&r, 1, &size); + return size; + } + + void Compact(const Slice& start, const Slice& limit) { + db_->CompactRange(&start, &limit); + } + + // Do n memtable compactions, each of which produces an sstable + // covering the range [small,large]. + void MakeTables(int n, const std::string& small, const std::string& large) { + for (int i = 0; i < n; i++) { + Put(small, "begin"); + Put(large, "end"); + dbfull()->TEST_CompactMemTable(); + } + } + + // Prevent pushing of new sstables into deeper levels by adding + // tables that cover a specified range to all levels. + void FillLevels(const std::string& smallest, const std::string& largest) { + MakeTables(config::kNumLevels, smallest, largest); + } + + void DumpFileCounts(const char* label) { + fprintf(stderr, "---\n%s:\n", label); + fprintf(stderr, "maxoverlap: %lld\n", + static_cast( + dbfull()->TEST_MaxNextLevelOverlappingBytes())); + for (int level = 0; level < config::kNumLevels; level++) { + int num = NumTableFilesAtLevel(level); + if (num > 0) { + fprintf(stderr, " level %3d : %d files\n", level, num); + } + } + } + + std::string DumpSSTableList() { + std::string property; + db_->GetProperty("leveldb.sstables", &property); + return property; + } + + std::string IterStatus(Iterator* iter) { + std::string result; + if (iter->Valid()) { + result = iter->key().ToString() + "->" + iter->value().ToString(); + } else { + result = "(invalid)"; + } + return result; + } + + bool DeleteAnSSTFile() { + std::vector filenames; + ASSERT_OK(env_->GetChildren(dbname_, &filenames)); + uint64_t number; + FileType type; + for (size_t i = 0; i < filenames.size(); i++) { + if (ParseFileName(filenames[i], &number, &type) && type == kTableFile) { + ASSERT_OK(env_->DeleteFile(TableFileName(dbname_, number))); + return true; + } + } + return false; + } + + // Returns number of files renamed. + int RenameLDBToSST() { + std::vector filenames; + ASSERT_OK(env_->GetChildren(dbname_, &filenames)); + uint64_t number; + FileType type; + int files_renamed = 0; + for (size_t i = 0; i < filenames.size(); i++) { + if (ParseFileName(filenames[i], &number, &type) && type == kTableFile) { + const std::string from = TableFileName(dbname_, number); + const std::string to = SSTTableFileName(dbname_, number); + ASSERT_OK(env_->RenameFile(from, to)); + files_renamed++; + } + } + return files_renamed; + } +}; + +TEST(DBTest, Empty) { + do { + ASSERT_TRUE(db_ != NULL); + ASSERT_EQ("NOT_FOUND", Get("foo")); + } while (ChangeOptions()); +} + +TEST(DBTest, ReadWrite) { + do { + ASSERT_OK(Put("foo", "v1")); + ASSERT_EQ("v1", Get("foo")); + ASSERT_OK(Put("bar", "v2")); + ASSERT_OK(Put("foo", "v3")); + ASSERT_EQ("v3", Get("foo")); + ASSERT_EQ("v2", Get("bar")); + } while (ChangeOptions()); +} + +TEST(DBTest, PutDeleteGet) { + do { + ASSERT_OK(db_->Put(WriteOptions(), "foo", "v1")); + ASSERT_EQ("v1", Get("foo")); + ASSERT_OK(db_->Put(WriteOptions(), "foo", "v2")); + ASSERT_EQ("v2", Get("foo")); + ASSERT_OK(db_->Delete(WriteOptions(), "foo")); + ASSERT_EQ("NOT_FOUND", Get("foo")); + } while (ChangeOptions()); +} + +TEST(DBTest, GetFromImmutableLayer) { + do { + Options options = CurrentOptions(); + options.env = env_; + options.write_buffer_size = 100000; // Small write buffer + Reopen(&options); + + ASSERT_OK(Put("foo", "v1")); + ASSERT_EQ("v1", Get("foo")); + + env_->delay_data_sync_.Release_Store(env_); // Block sync calls + Put("k1", std::string(100000, 'x')); // Fill memtable + Put("k2", std::string(100000, 'y')); // Trigger compaction + ASSERT_EQ("v1", Get("foo")); + env_->delay_data_sync_.Release_Store(NULL); // Release sync calls + } while (ChangeOptions()); +} + +TEST(DBTest, GetFromVersions) { + do { + ASSERT_OK(Put("foo", "v1")); + dbfull()->TEST_CompactMemTable(); + ASSERT_EQ("v1", Get("foo")); + } while (ChangeOptions()); +} + +TEST(DBTest, GetSnapshot) { + do { + // Try with both a short key and a long key + for (int i = 0; i < 2; i++) { + std::string key = (i == 0) ? std::string("foo") : std::string(200, 'x'); + ASSERT_OK(Put(key, "v1")); + const Snapshot* s1 = db_->GetSnapshot(); + ASSERT_OK(Put(key, "v2")); + ASSERT_EQ("v2", Get(key)); + ASSERT_EQ("v1", Get(key, s1)); + dbfull()->TEST_CompactMemTable(); + ASSERT_EQ("v2", Get(key)); + ASSERT_EQ("v1", Get(key, s1)); + db_->ReleaseSnapshot(s1); + } + } while (ChangeOptions()); +} + +TEST(DBTest, GetLevel0Ordering) { + do { + // Check that we process level-0 files in correct order. The code + // below generates two level-0 files where the earlier one comes + // before the later one in the level-0 file list since the earlier + // one has a smaller "smallest" key. + ASSERT_OK(Put("bar", "b")); + ASSERT_OK(Put("foo", "v1")); + dbfull()->TEST_CompactMemTable(); + ASSERT_OK(Put("foo", "v2")); + dbfull()->TEST_CompactMemTable(); + ASSERT_EQ("v2", Get("foo")); + } while (ChangeOptions()); +} + +TEST(DBTest, GetOrderedByLevels) { + do { + ASSERT_OK(Put("foo", "v1")); + Compact("a", "z"); + ASSERT_EQ("v1", Get("foo")); + ASSERT_OK(Put("foo", "v2")); + ASSERT_EQ("v2", Get("foo")); + dbfull()->TEST_CompactMemTable(); + ASSERT_EQ("v2", Get("foo")); + } while (ChangeOptions()); +} + +TEST(DBTest, GetPicksCorrectFile) { + do { + // Arrange to have multiple files in a non-level-0 level. + ASSERT_OK(Put("a", "va")); + Compact("a", "b"); + ASSERT_OK(Put("x", "vx")); + Compact("x", "y"); + ASSERT_OK(Put("f", "vf")); + Compact("f", "g"); + ASSERT_EQ("va", Get("a")); + ASSERT_EQ("vf", Get("f")); + ASSERT_EQ("vx", Get("x")); + } while (ChangeOptions()); +} + +TEST(DBTest, GetEncountersEmptyLevel) { + do { + // Arrange for the following to happen: + // * sstable A in level 0 + // * nothing in level 1 + // * sstable B in level 2 + // Then do enough Get() calls to arrange for an automatic compaction + // of sstable A. A bug would cause the compaction to be marked as + // occuring at level 1 (instead of the correct level 0). + + // Step 1: First place sstables in levels 0 and 2 + int compaction_count = 0; + while (NumTableFilesAtLevel(0) == 0 || + NumTableFilesAtLevel(2) == 0) { + ASSERT_LE(compaction_count, 100) << "could not fill levels 0 and 2"; + compaction_count++; + Put("a", "begin"); + Put("z", "end"); + dbfull()->TEST_CompactMemTable(); + } + + // Step 2: clear level 1 if necessary. + dbfull()->TEST_CompactRange(1, NULL, NULL); + ASSERT_EQ(NumTableFilesAtLevel(0), 1); + ASSERT_EQ(NumTableFilesAtLevel(1), 0); + ASSERT_EQ(NumTableFilesAtLevel(2), 1); + + // Step 3: read a bunch of times + for (int i = 0; i < 1000; i++) { + ASSERT_EQ("NOT_FOUND", Get("missing")); + } + + // Step 4: Wait for compaction to finish + DelayMilliseconds(1000); + + ASSERT_EQ(NumTableFilesAtLevel(0), 0); + } while (ChangeOptions()); +} + +TEST(DBTest, IterEmpty) { + Iterator* iter = db_->NewIterator(ReadOptions()); + + iter->SeekToFirst(); + ASSERT_EQ(IterStatus(iter), "(invalid)"); + + iter->SeekToLast(); + ASSERT_EQ(IterStatus(iter), "(invalid)"); + + iter->Seek("foo"); + ASSERT_EQ(IterStatus(iter), "(invalid)"); + + delete iter; +} + +TEST(DBTest, IterSingle) { + ASSERT_OK(Put("a", "va")); + Iterator* iter = db_->NewIterator(ReadOptions()); + + iter->SeekToFirst(); + ASSERT_EQ(IterStatus(iter), "a->va"); + iter->Next(); + ASSERT_EQ(IterStatus(iter), "(invalid)"); + iter->SeekToFirst(); + ASSERT_EQ(IterStatus(iter), "a->va"); + iter->Prev(); + ASSERT_EQ(IterStatus(iter), "(invalid)"); + + iter->SeekToLast(); + ASSERT_EQ(IterStatus(iter), "a->va"); + iter->Next(); + ASSERT_EQ(IterStatus(iter), "(invalid)"); + iter->SeekToLast(); + ASSERT_EQ(IterStatus(iter), "a->va"); + iter->Prev(); + ASSERT_EQ(IterStatus(iter), "(invalid)"); + + iter->Seek(""); + ASSERT_EQ(IterStatus(iter), "a->va"); + iter->Next(); + ASSERT_EQ(IterStatus(iter), "(invalid)"); + + iter->Seek("a"); + ASSERT_EQ(IterStatus(iter), "a->va"); + iter->Next(); + ASSERT_EQ(IterStatus(iter), "(invalid)"); + + iter->Seek("b"); + ASSERT_EQ(IterStatus(iter), "(invalid)"); + + delete iter; +} + +TEST(DBTest, IterMulti) { + ASSERT_OK(Put("a", "va")); + ASSERT_OK(Put("b", "vb")); + ASSERT_OK(Put("c", "vc")); + Iterator* iter = db_->NewIterator(ReadOptions()); + + iter->SeekToFirst(); + ASSERT_EQ(IterStatus(iter), "a->va"); + iter->Next(); + ASSERT_EQ(IterStatus(iter), "b->vb"); + iter->Next(); + ASSERT_EQ(IterStatus(iter), "c->vc"); + iter->Next(); + ASSERT_EQ(IterStatus(iter), "(invalid)"); + iter->SeekToFirst(); + ASSERT_EQ(IterStatus(iter), "a->va"); + iter->Prev(); + ASSERT_EQ(IterStatus(iter), "(invalid)"); + + iter->SeekToLast(); + ASSERT_EQ(IterStatus(iter), "c->vc"); + iter->Prev(); + ASSERT_EQ(IterStatus(iter), "b->vb"); + iter->Prev(); + ASSERT_EQ(IterStatus(iter), "a->va"); + iter->Prev(); + ASSERT_EQ(IterStatus(iter), "(invalid)"); + iter->SeekToLast(); + ASSERT_EQ(IterStatus(iter), "c->vc"); + iter->Next(); + ASSERT_EQ(IterStatus(iter), "(invalid)"); + + iter->Seek(""); + ASSERT_EQ(IterStatus(iter), "a->va"); + iter->Seek("a"); + ASSERT_EQ(IterStatus(iter), "a->va"); + iter->Seek("ax"); + ASSERT_EQ(IterStatus(iter), "b->vb"); + iter->Seek("b"); + ASSERT_EQ(IterStatus(iter), "b->vb"); + iter->Seek("z"); + ASSERT_EQ(IterStatus(iter), "(invalid)"); + + // Switch from reverse to forward + iter->SeekToLast(); + iter->Prev(); + iter->Prev(); + iter->Next(); + ASSERT_EQ(IterStatus(iter), "b->vb"); + + // Switch from forward to reverse + iter->SeekToFirst(); + iter->Next(); + iter->Next(); + iter->Prev(); + ASSERT_EQ(IterStatus(iter), "b->vb"); + + // Make sure iter stays at snapshot + ASSERT_OK(Put("a", "va2")); + ASSERT_OK(Put("a2", "va3")); + ASSERT_OK(Put("b", "vb2")); + ASSERT_OK(Put("c", "vc2")); + ASSERT_OK(Delete("b")); + iter->SeekToFirst(); + ASSERT_EQ(IterStatus(iter), "a->va"); + iter->Next(); + ASSERT_EQ(IterStatus(iter), "b->vb"); + iter->Next(); + ASSERT_EQ(IterStatus(iter), "c->vc"); + iter->Next(); + ASSERT_EQ(IterStatus(iter), "(invalid)"); + iter->SeekToLast(); + ASSERT_EQ(IterStatus(iter), "c->vc"); + iter->Prev(); + ASSERT_EQ(IterStatus(iter), "b->vb"); + iter->Prev(); + ASSERT_EQ(IterStatus(iter), "a->va"); + iter->Prev(); + ASSERT_EQ(IterStatus(iter), "(invalid)"); + + delete iter; +} + +TEST(DBTest, IterSmallAndLargeMix) { + ASSERT_OK(Put("a", "va")); + ASSERT_OK(Put("b", std::string(100000, 'b'))); + ASSERT_OK(Put("c", "vc")); + ASSERT_OK(Put("d", std::string(100000, 'd'))); + ASSERT_OK(Put("e", std::string(100000, 'e'))); + + Iterator* iter = db_->NewIterator(ReadOptions()); + + iter->SeekToFirst(); + ASSERT_EQ(IterStatus(iter), "a->va"); + iter->Next(); + ASSERT_EQ(IterStatus(iter), "b->" + std::string(100000, 'b')); + iter->Next(); + ASSERT_EQ(IterStatus(iter), "c->vc"); + iter->Next(); + ASSERT_EQ(IterStatus(iter), "d->" + std::string(100000, 'd')); + iter->Next(); + ASSERT_EQ(IterStatus(iter), "e->" + std::string(100000, 'e')); + iter->Next(); + ASSERT_EQ(IterStatus(iter), "(invalid)"); + + iter->SeekToLast(); + ASSERT_EQ(IterStatus(iter), "e->" + std::string(100000, 'e')); + iter->Prev(); + ASSERT_EQ(IterStatus(iter), "d->" + std::string(100000, 'd')); + iter->Prev(); + ASSERT_EQ(IterStatus(iter), "c->vc"); + iter->Prev(); + ASSERT_EQ(IterStatus(iter), "b->" + std::string(100000, 'b')); + iter->Prev(); + ASSERT_EQ(IterStatus(iter), "a->va"); + iter->Prev(); + ASSERT_EQ(IterStatus(iter), "(invalid)"); + + delete iter; +} + +TEST(DBTest, IterMultiWithDelete) { + do { + ASSERT_OK(Put("a", "va")); + ASSERT_OK(Put("b", "vb")); + ASSERT_OK(Put("c", "vc")); + ASSERT_OK(Delete("b")); + ASSERT_EQ("NOT_FOUND", Get("b")); + + Iterator* iter = db_->NewIterator(ReadOptions()); + iter->Seek("c"); + ASSERT_EQ(IterStatus(iter), "c->vc"); + iter->Prev(); + ASSERT_EQ(IterStatus(iter), "a->va"); + delete iter; + } while (ChangeOptions()); +} + +TEST(DBTest, Recover) { + do { + ASSERT_OK(Put("foo", "v1")); + ASSERT_OK(Put("baz", "v5")); + + Reopen(); + ASSERT_EQ("v1", Get("foo")); + + ASSERT_EQ("v1", Get("foo")); + ASSERT_EQ("v5", Get("baz")); + ASSERT_OK(Put("bar", "v2")); + ASSERT_OK(Put("foo", "v3")); + + Reopen(); + ASSERT_EQ("v3", Get("foo")); + ASSERT_OK(Put("foo", "v4")); + ASSERT_EQ("v4", Get("foo")); + ASSERT_EQ("v2", Get("bar")); + ASSERT_EQ("v5", Get("baz")); + } while (ChangeOptions()); +} + +TEST(DBTest, RecoveryWithEmptyLog) { + do { + ASSERT_OK(Put("foo", "v1")); + ASSERT_OK(Put("foo", "v2")); + Reopen(); + Reopen(); + ASSERT_OK(Put("foo", "v3")); + Reopen(); + ASSERT_EQ("v3", Get("foo")); + } while (ChangeOptions()); +} + +// Check that writes done during a memtable compaction are recovered +// if the database is shutdown during the memtable compaction. +TEST(DBTest, RecoverDuringMemtableCompaction) { + do { + Options options = CurrentOptions(); + options.env = env_; + options.write_buffer_size = 1000000; + Reopen(&options); + + // Trigger a long memtable compaction and reopen the database during it + ASSERT_OK(Put("foo", "v1")); // Goes to 1st log file + ASSERT_OK(Put("big1", std::string(10000000, 'x'))); // Fills memtable + ASSERT_OK(Put("big2", std::string(1000, 'y'))); // Triggers compaction + ASSERT_OK(Put("bar", "v2")); // Goes to new log file + + Reopen(&options); + ASSERT_EQ("v1", Get("foo")); + ASSERT_EQ("v2", Get("bar")); + ASSERT_EQ(std::string(10000000, 'x'), Get("big1")); + ASSERT_EQ(std::string(1000, 'y'), Get("big2")); + } while (ChangeOptions()); +} + +static std::string Key(int i) { + char buf[100]; + snprintf(buf, sizeof(buf), "key%06d", i); + return std::string(buf); +} + +TEST(DBTest, MinorCompactionsHappen) { + Options options = CurrentOptions(); + options.write_buffer_size = 10000; + Reopen(&options); + + const int N = 500; + + int starting_num_tables = TotalTableFiles(); + for (int i = 0; i < N; i++) { + ASSERT_OK(Put(Key(i), Key(i) + std::string(1000, 'v'))); + } + int ending_num_tables = TotalTableFiles(); + ASSERT_GT(ending_num_tables, starting_num_tables); + + for (int i = 0; i < N; i++) { + ASSERT_EQ(Key(i) + std::string(1000, 'v'), Get(Key(i))); + } + + Reopen(); + + for (int i = 0; i < N; i++) { + ASSERT_EQ(Key(i) + std::string(1000, 'v'), Get(Key(i))); + } +} + +TEST(DBTest, RecoverWithLargeLog) { + { + Options options = CurrentOptions(); + Reopen(&options); + ASSERT_OK(Put("big1", std::string(200000, '1'))); + ASSERT_OK(Put("big2", std::string(200000, '2'))); + ASSERT_OK(Put("small3", std::string(10, '3'))); + ASSERT_OK(Put("small4", std::string(10, '4'))); + ASSERT_EQ(NumTableFilesAtLevel(0), 0); + } + + // Make sure that if we re-open with a small write buffer size that + // we flush table files in the middle of a large log file. + Options options = CurrentOptions(); + options.write_buffer_size = 100000; + Reopen(&options); + ASSERT_EQ(NumTableFilesAtLevel(0), 3); + ASSERT_EQ(std::string(200000, '1'), Get("big1")); + ASSERT_EQ(std::string(200000, '2'), Get("big2")); + ASSERT_EQ(std::string(10, '3'), Get("small3")); + ASSERT_EQ(std::string(10, '4'), Get("small4")); + ASSERT_GT(NumTableFilesAtLevel(0), 1); +} + +TEST(DBTest, CompactionsGenerateMultipleFiles) { + Options options = CurrentOptions(); + options.write_buffer_size = 100000000; // Large write buffer + Reopen(&options); + + Random rnd(301); + + // Write 8MB (80 values, each 100K) + ASSERT_EQ(NumTableFilesAtLevel(0), 0); + std::vector values; + for (int i = 0; i < 80; i++) { + values.push_back(RandomString(&rnd, 100000)); + ASSERT_OK(Put(Key(i), values[i])); + } + + // Reopening moves updates to level-0 + Reopen(&options); + dbfull()->TEST_CompactRange(0, NULL, NULL); + + ASSERT_EQ(NumTableFilesAtLevel(0), 0); + ASSERT_GT(NumTableFilesAtLevel(1), 1); + for (int i = 0; i < 80; i++) { + ASSERT_EQ(Get(Key(i)), values[i]); + } +} + +TEST(DBTest, RepeatedWritesToSameKey) { + Options options = CurrentOptions(); + options.env = env_; + options.write_buffer_size = 100000; // Small write buffer + Reopen(&options); + + // We must have at most one file per level except for level-0, + // which may have up to kL0_StopWritesTrigger files. + const int kMaxFiles = config::kNumLevels + config::kL0_StopWritesTrigger; + + Random rnd(301); + std::string value = RandomString(&rnd, 2 * options.write_buffer_size); + for (int i = 0; i < 5 * kMaxFiles; i++) { + Put("key", value); + ASSERT_LE(TotalTableFiles(), kMaxFiles); + fprintf(stderr, "after %d: %d files\n", int(i+1), TotalTableFiles()); + } +} + +TEST(DBTest, SparseMerge) { + Options options = CurrentOptions(); + options.compression = kNoCompression; + Reopen(&options); + + FillLevels("A", "Z"); + + // Suppose there is: + // small amount of data with prefix A + // large amount of data with prefix B + // small amount of data with prefix C + // and that recent updates have made small changes to all three prefixes. + // Check that we do not do a compaction that merges all of B in one shot. + const std::string value(1000, 'x'); + Put("A", "va"); + // Write approximately 100MB of "B" values + for (int i = 0; i < 100000; i++) { + char key[100]; + snprintf(key, sizeof(key), "B%010d", i); + Put(key, value); + } + Put("C", "vc"); + dbfull()->TEST_CompactMemTable(); + dbfull()->TEST_CompactRange(0, NULL, NULL); + + // Make sparse update + Put("A", "va2"); + Put("B100", "bvalue2"); + Put("C", "vc2"); + dbfull()->TEST_CompactMemTable(); + + // Compactions should not cause us to create a situation where + // a file overlaps too much data at the next level. + ASSERT_LE(dbfull()->TEST_MaxNextLevelOverlappingBytes(), 20*1048576); + dbfull()->TEST_CompactRange(0, NULL, NULL); + ASSERT_LE(dbfull()->TEST_MaxNextLevelOverlappingBytes(), 20*1048576); + dbfull()->TEST_CompactRange(1, NULL, NULL); + ASSERT_LE(dbfull()->TEST_MaxNextLevelOverlappingBytes(), 20*1048576); +} + +static bool Between(uint64_t val, uint64_t low, uint64_t high) { + bool result = (val >= low) && (val <= high); + if (!result) { + fprintf(stderr, "Value %llu is not in range [%llu, %llu]\n", + (unsigned long long)(val), + (unsigned long long)(low), + (unsigned long long)(high)); + } + return result; +} + +TEST(DBTest, ApproximateSizes) { + do { + Options options = CurrentOptions(); + options.write_buffer_size = 100000000; // Large write buffer + options.compression = kNoCompression; + DestroyAndReopen(); + + ASSERT_TRUE(Between(Size("", "xyz"), 0, 0)); + Reopen(&options); + ASSERT_TRUE(Between(Size("", "xyz"), 0, 0)); + + // Write 8MB (80 values, each 100K) + ASSERT_EQ(NumTableFilesAtLevel(0), 0); + const int N = 80; + static const int S1 = 100000; + static const int S2 = 105000; // Allow some expansion from metadata + Random rnd(301); + for (int i = 0; i < N; i++) { + ASSERT_OK(Put(Key(i), RandomString(&rnd, S1))); + } + + // 0 because GetApproximateSizes() does not account for memtable space + ASSERT_TRUE(Between(Size("", Key(50)), 0, 0)); + + // Check sizes across recovery by reopening a few times + for (int run = 0; run < 3; run++) { + Reopen(&options); + + for (int compact_start = 0; compact_start < N; compact_start += 10) { + for (int i = 0; i < N; i += 10) { + ASSERT_TRUE(Between(Size("", Key(i)), S1*i, S2*i)); + ASSERT_TRUE(Between(Size("", Key(i)+".suffix"), S1*(i+1), S2*(i+1))); + ASSERT_TRUE(Between(Size(Key(i), Key(i+10)), S1*10, S2*10)); + } + ASSERT_TRUE(Between(Size("", Key(50)), S1*50, S2*50)); + ASSERT_TRUE(Between(Size("", Key(50)+".suffix"), S1*50, S2*50)); + + std::string cstart_str = Key(compact_start); + std::string cend_str = Key(compact_start + 9); + Slice cstart = cstart_str; + Slice cend = cend_str; + dbfull()->TEST_CompactRange(0, &cstart, &cend); + } + + ASSERT_EQ(NumTableFilesAtLevel(0), 0); + ASSERT_GT(NumTableFilesAtLevel(1), 0); + } + } while (ChangeOptions()); +} + +TEST(DBTest, ApproximateSizes_MixOfSmallAndLarge) { + do { + Options options = CurrentOptions(); + options.compression = kNoCompression; + Reopen(); + + Random rnd(301); + std::string big1 = RandomString(&rnd, 100000); + ASSERT_OK(Put(Key(0), RandomString(&rnd, 10000))); + ASSERT_OK(Put(Key(1), RandomString(&rnd, 10000))); + ASSERT_OK(Put(Key(2), big1)); + ASSERT_OK(Put(Key(3), RandomString(&rnd, 10000))); + ASSERT_OK(Put(Key(4), big1)); + ASSERT_OK(Put(Key(5), RandomString(&rnd, 10000))); + ASSERT_OK(Put(Key(6), RandomString(&rnd, 300000))); + ASSERT_OK(Put(Key(7), RandomString(&rnd, 10000))); + + // Check sizes across recovery by reopening a few times + for (int run = 0; run < 3; run++) { + Reopen(&options); + + ASSERT_TRUE(Between(Size("", Key(0)), 0, 0)); + ASSERT_TRUE(Between(Size("", Key(1)), 10000, 11000)); + ASSERT_TRUE(Between(Size("", Key(2)), 20000, 21000)); + ASSERT_TRUE(Between(Size("", Key(3)), 120000, 121000)); + ASSERT_TRUE(Between(Size("", Key(4)), 130000, 131000)); + ASSERT_TRUE(Between(Size("", Key(5)), 230000, 231000)); + ASSERT_TRUE(Between(Size("", Key(6)), 240000, 241000)); + ASSERT_TRUE(Between(Size("", Key(7)), 540000, 541000)); + ASSERT_TRUE(Between(Size("", Key(8)), 550000, 560000)); + + ASSERT_TRUE(Between(Size(Key(3), Key(5)), 110000, 111000)); + + dbfull()->TEST_CompactRange(0, NULL, NULL); + } + } while (ChangeOptions()); +} + +TEST(DBTest, IteratorPinsRef) { + Put("foo", "hello"); + + // Get iterator that will yield the current contents of the DB. + Iterator* iter = db_->NewIterator(ReadOptions()); + + // Write to force compactions + Put("foo", "newvalue1"); + for (int i = 0; i < 100; i++) { + ASSERT_OK(Put(Key(i), Key(i) + std::string(100000, 'v'))); // 100K values + } + Put("foo", "newvalue2"); + + iter->SeekToFirst(); + ASSERT_TRUE(iter->Valid()); + ASSERT_EQ("foo", iter->key().ToString()); + ASSERT_EQ("hello", iter->value().ToString()); + iter->Next(); + ASSERT_TRUE(!iter->Valid()); + delete iter; +} + +TEST(DBTest, Snapshot) { + do { + Put("foo", "v1"); + const Snapshot* s1 = db_->GetSnapshot(); + Put("foo", "v2"); + const Snapshot* s2 = db_->GetSnapshot(); + Put("foo", "v3"); + const Snapshot* s3 = db_->GetSnapshot(); + + Put("foo", "v4"); + ASSERT_EQ("v1", Get("foo", s1)); + ASSERT_EQ("v2", Get("foo", s2)); + ASSERT_EQ("v3", Get("foo", s3)); + ASSERT_EQ("v4", Get("foo")); + + db_->ReleaseSnapshot(s3); + ASSERT_EQ("v1", Get("foo", s1)); + ASSERT_EQ("v2", Get("foo", s2)); + ASSERT_EQ("v4", Get("foo")); + + db_->ReleaseSnapshot(s1); + ASSERT_EQ("v2", Get("foo", s2)); + ASSERT_EQ("v4", Get("foo")); + + db_->ReleaseSnapshot(s2); + ASSERT_EQ("v4", Get("foo")); + } while (ChangeOptions()); +} + +TEST(DBTest, HiddenValuesAreRemoved) { + do { + Random rnd(301); + FillLevels("a", "z"); + + std::string big = RandomString(&rnd, 50000); + Put("foo", big); + Put("pastfoo", "v"); + const Snapshot* snapshot = db_->GetSnapshot(); + Put("foo", "tiny"); + Put("pastfoo2", "v2"); // Advance sequence number one more + + ASSERT_OK(dbfull()->TEST_CompactMemTable()); + ASSERT_GT(NumTableFilesAtLevel(0), 0); + + ASSERT_EQ(big, Get("foo", snapshot)); + ASSERT_TRUE(Between(Size("", "pastfoo"), 50000, 60000)); + db_->ReleaseSnapshot(snapshot); + ASSERT_EQ(AllEntriesFor("foo"), "[ tiny, " + big + " ]"); + Slice x("x"); + dbfull()->TEST_CompactRange(0, NULL, &x); + ASSERT_EQ(AllEntriesFor("foo"), "[ tiny ]"); + ASSERT_EQ(NumTableFilesAtLevel(0), 0); + ASSERT_GE(NumTableFilesAtLevel(1), 1); + dbfull()->TEST_CompactRange(1, NULL, &x); + ASSERT_EQ(AllEntriesFor("foo"), "[ tiny ]"); + + ASSERT_TRUE(Between(Size("", "pastfoo"), 0, 1000)); + } while (ChangeOptions()); +} + +TEST(DBTest, DeletionMarkers1) { + Put("foo", "v1"); + ASSERT_OK(dbfull()->TEST_CompactMemTable()); + const int last = config::kMaxMemCompactLevel; + ASSERT_EQ(NumTableFilesAtLevel(last), 1); // foo => v1 is now in last level + + // Place a table at level last-1 to prevent merging with preceding mutation + Put("a", "begin"); + Put("z", "end"); + dbfull()->TEST_CompactMemTable(); + ASSERT_EQ(NumTableFilesAtLevel(last), 1); + ASSERT_EQ(NumTableFilesAtLevel(last-1), 1); + + Delete("foo"); + Put("foo", "v2"); + ASSERT_EQ(AllEntriesFor("foo"), "[ v2, DEL, v1 ]"); + ASSERT_OK(dbfull()->TEST_CompactMemTable()); // Moves to level last-2 + ASSERT_EQ(AllEntriesFor("foo"), "[ v2, DEL, v1 ]"); + Slice z("z"); + dbfull()->TEST_CompactRange(last-2, NULL, &z); + // DEL eliminated, but v1 remains because we aren't compacting that level + // (DEL can be eliminated because v2 hides v1). + ASSERT_EQ(AllEntriesFor("foo"), "[ v2, v1 ]"); + dbfull()->TEST_CompactRange(last-1, NULL, NULL); + // Merging last-1 w/ last, so we are the base level for "foo", so + // DEL is removed. (as is v1). + ASSERT_EQ(AllEntriesFor("foo"), "[ v2 ]"); +} + +TEST(DBTest, DeletionMarkers2) { + Put("foo", "v1"); + ASSERT_OK(dbfull()->TEST_CompactMemTable()); + const int last = config::kMaxMemCompactLevel; + ASSERT_EQ(NumTableFilesAtLevel(last), 1); // foo => v1 is now in last level + + // Place a table at level last-1 to prevent merging with preceding mutation + Put("a", "begin"); + Put("z", "end"); + dbfull()->TEST_CompactMemTable(); + ASSERT_EQ(NumTableFilesAtLevel(last), 1); + ASSERT_EQ(NumTableFilesAtLevel(last-1), 1); + + Delete("foo"); + ASSERT_EQ(AllEntriesFor("foo"), "[ DEL, v1 ]"); + ASSERT_OK(dbfull()->TEST_CompactMemTable()); // Moves to level last-2 + ASSERT_EQ(AllEntriesFor("foo"), "[ DEL, v1 ]"); + dbfull()->TEST_CompactRange(last-2, NULL, NULL); + // DEL kept: "last" file overlaps + ASSERT_EQ(AllEntriesFor("foo"), "[ DEL, v1 ]"); + dbfull()->TEST_CompactRange(last-1, NULL, NULL); + // Merging last-1 w/ last, so we are the base level for "foo", so + // DEL is removed. (as is v1). + ASSERT_EQ(AllEntriesFor("foo"), "[ ]"); +} + +TEST(DBTest, OverlapInLevel0) { + do { + ASSERT_EQ(config::kMaxMemCompactLevel, 2) << "Fix test to match config"; + + // Fill levels 1 and 2 to disable the pushing of new memtables to levels > 0. + ASSERT_OK(Put("100", "v100")); + ASSERT_OK(Put("999", "v999")); + dbfull()->TEST_CompactMemTable(); + ASSERT_OK(Delete("100")); + ASSERT_OK(Delete("999")); + dbfull()->TEST_CompactMemTable(); + ASSERT_EQ("0,1,1", FilesPerLevel()); + + // Make files spanning the following ranges in level-0: + // files[0] 200 .. 900 + // files[1] 300 .. 500 + // Note that files are sorted by smallest key. + ASSERT_OK(Put("300", "v300")); + ASSERT_OK(Put("500", "v500")); + dbfull()->TEST_CompactMemTable(); + ASSERT_OK(Put("200", "v200")); + ASSERT_OK(Put("600", "v600")); + ASSERT_OK(Put("900", "v900")); + dbfull()->TEST_CompactMemTable(); + ASSERT_EQ("2,1,1", FilesPerLevel()); + + // Compact away the placeholder files we created initially + dbfull()->TEST_CompactRange(1, NULL, NULL); + dbfull()->TEST_CompactRange(2, NULL, NULL); + ASSERT_EQ("2", FilesPerLevel()); + + // Do a memtable compaction. Before bug-fix, the compaction would + // not detect the overlap with level-0 files and would incorrectly place + // the deletion in a deeper level. + ASSERT_OK(Delete("600")); + dbfull()->TEST_CompactMemTable(); + ASSERT_EQ("3", FilesPerLevel()); + ASSERT_EQ("NOT_FOUND", Get("600")); + } while (ChangeOptions()); +} + +TEST(DBTest, L0_CompactionBug_Issue44_a) { + Reopen(); + ASSERT_OK(Put("b", "v")); + Reopen(); + ASSERT_OK(Delete("b")); + ASSERT_OK(Delete("a")); + Reopen(); + ASSERT_OK(Delete("a")); + Reopen(); + ASSERT_OK(Put("a", "v")); + Reopen(); + Reopen(); + ASSERT_EQ("(a->v)", Contents()); + DelayMilliseconds(1000); // Wait for compaction to finish + ASSERT_EQ("(a->v)", Contents()); +} + +TEST(DBTest, L0_CompactionBug_Issue44_b) { + Reopen(); + Put("",""); + Reopen(); + Delete("e"); + Put("",""); + Reopen(); + Put("c", "cv"); + Reopen(); + Put("",""); + Reopen(); + Put("",""); + DelayMilliseconds(1000); // Wait for compaction to finish + Reopen(); + Put("d","dv"); + Reopen(); + Put("",""); + Reopen(); + Delete("d"); + Delete("b"); + Reopen(); + ASSERT_EQ("(->)(c->cv)", Contents()); + DelayMilliseconds(1000); // Wait for compaction to finish + ASSERT_EQ("(->)(c->cv)", Contents()); +} + +TEST(DBTest, ComparatorCheck) { + class NewComparator : public Comparator { + public: + virtual const char* Name() const { return "leveldb.NewComparator"; } + virtual int Compare(const Slice& a, const Slice& b) const { + return BytewiseComparator()->Compare(a, b); + } + virtual void FindShortestSeparator(std::string* s, const Slice& l) const { + BytewiseComparator()->FindShortestSeparator(s, l); + } + virtual void FindShortSuccessor(std::string* key) const { + BytewiseComparator()->FindShortSuccessor(key); + } + }; + NewComparator cmp; + Options new_options = CurrentOptions(); + new_options.comparator = &cmp; + Status s = TryReopen(&new_options); + ASSERT_TRUE(!s.ok()); + ASSERT_TRUE(s.ToString().find("comparator") != std::string::npos) + << s.ToString(); +} + +TEST(DBTest, CustomComparator) { + class NumberComparator : public Comparator { + public: + virtual const char* Name() const { return "test.NumberComparator"; } + virtual int Compare(const Slice& a, const Slice& b) const { + return ToNumber(a) - ToNumber(b); + } + virtual void FindShortestSeparator(std::string* s, const Slice& l) const { + ToNumber(*s); // Check format + ToNumber(l); // Check format + } + virtual void FindShortSuccessor(std::string* key) const { + ToNumber(*key); // Check format + } + private: + static int ToNumber(const Slice& x) { + // Check that there are no extra characters. + ASSERT_TRUE(x.size() >= 2 && x[0] == '[' && x[x.size()-1] == ']') + << EscapeString(x); + int val; + char ignored; + ASSERT_TRUE(sscanf(x.ToString().c_str(), "[%i]%c", &val, &ignored) == 1) + << EscapeString(x); + return val; + } + }; + NumberComparator cmp; + Options new_options = CurrentOptions(); + new_options.create_if_missing = true; + new_options.comparator = &cmp; + new_options.filter_policy = NULL; // Cannot use bloom filters + new_options.write_buffer_size = 1000; // Compact more often + DestroyAndReopen(&new_options); + ASSERT_OK(Put("[10]", "ten")); + ASSERT_OK(Put("[0x14]", "twenty")); + for (int i = 0; i < 2; i++) { + ASSERT_EQ("ten", Get("[10]")); + ASSERT_EQ("ten", Get("[0xa]")); + ASSERT_EQ("twenty", Get("[20]")); + ASSERT_EQ("twenty", Get("[0x14]")); + ASSERT_EQ("NOT_FOUND", Get("[15]")); + ASSERT_EQ("NOT_FOUND", Get("[0xf]")); + Compact("[0]", "[9999]"); + } + + for (int run = 0; run < 2; run++) { + for (int i = 0; i < 1000; i++) { + char buf[100]; + snprintf(buf, sizeof(buf), "[%d]", i*10); + ASSERT_OK(Put(buf, buf)); + } + Compact("[0]", "[1000000]"); + } +} + +TEST(DBTest, ManualCompaction) { + ASSERT_EQ(config::kMaxMemCompactLevel, 2) + << "Need to update this test to match kMaxMemCompactLevel"; + + MakeTables(3, "p", "q"); + ASSERT_EQ("1,1,1", FilesPerLevel()); + + // Compaction range falls before files + Compact("", "c"); + ASSERT_EQ("1,1,1", FilesPerLevel()); + + // Compaction range falls after files + Compact("r", "z"); + ASSERT_EQ("1,1,1", FilesPerLevel()); + + // Compaction range overlaps files + Compact("p1", "p9"); + ASSERT_EQ("0,0,1", FilesPerLevel()); + + // Populate a different range + MakeTables(3, "c", "e"); + ASSERT_EQ("1,1,2", FilesPerLevel()); + + // Compact just the new range + Compact("b", "f"); + ASSERT_EQ("0,0,2", FilesPerLevel()); + + // Compact all + MakeTables(1, "a", "z"); + ASSERT_EQ("0,1,2", FilesPerLevel()); + db_->CompactRange(NULL, NULL); + ASSERT_EQ("0,0,1", FilesPerLevel()); +} + +TEST(DBTest, DBOpen_Options) { + std::string dbname = test::TmpDir() + "/db_options_test"; + DestroyDB(dbname, Options()); + + // Does not exist, and create_if_missing == false: error + DB* db = NULL; + Options opts; + opts.create_if_missing = false; + Status s = DB::Open(opts, dbname, &db); + ASSERT_TRUE(strstr(s.ToString().c_str(), "does not exist") != NULL); + ASSERT_TRUE(db == NULL); + + // Does not exist, and create_if_missing == true: OK + opts.create_if_missing = true; + s = DB::Open(opts, dbname, &db); + ASSERT_OK(s); + ASSERT_TRUE(db != NULL); + + delete db; + db = NULL; + + // Does exist, and error_if_exists == true: error + opts.create_if_missing = false; + opts.error_if_exists = true; + s = DB::Open(opts, dbname, &db); + ASSERT_TRUE(strstr(s.ToString().c_str(), "exists") != NULL); + ASSERT_TRUE(db == NULL); + + // Does exist, and error_if_exists == false: OK + opts.create_if_missing = true; + opts.error_if_exists = false; + s = DB::Open(opts, dbname, &db); + ASSERT_OK(s); + ASSERT_TRUE(db != NULL); + + delete db; + db = NULL; +} + +TEST(DBTest, Locking) { + DB* db2 = NULL; + Status s = DB::Open(CurrentOptions(), dbname_, &db2); + ASSERT_TRUE(!s.ok()) << "Locking did not prevent re-opening db"; +} + +// Check that number of files does not grow when we are out of space +TEST(DBTest, NoSpace) { + Options options = CurrentOptions(); + options.env = env_; + Reopen(&options); + + ASSERT_OK(Put("foo", "v1")); + ASSERT_EQ("v1", Get("foo")); + Compact("a", "z"); + const int num_files = CountFiles(); + env_->no_space_.Release_Store(env_); // Force out-of-space errors + for (int i = 0; i < 10; i++) { + for (int level = 0; level < config::kNumLevels-1; level++) { + dbfull()->TEST_CompactRange(level, NULL, NULL); + } + } + env_->no_space_.Release_Store(NULL); + ASSERT_LT(CountFiles(), num_files + 3); +} + +TEST(DBTest, NonWritableFileSystem) { + Options options = CurrentOptions(); + options.write_buffer_size = 1000; + options.env = env_; + Reopen(&options); + ASSERT_OK(Put("foo", "v1")); + env_->non_writable_.Release_Store(env_); // Force errors for new files + std::string big(100000, 'x'); + int errors = 0; + for (int i = 0; i < 20; i++) { + fprintf(stderr, "iter %d; errors %d\n", i, errors); + if (!Put("foo", big).ok()) { + errors++; + DelayMilliseconds(100); + } + } + ASSERT_GT(errors, 0); + env_->non_writable_.Release_Store(NULL); +} + +TEST(DBTest, WriteSyncError) { + // Check that log sync errors cause the DB to disallow future writes. + + // (a) Cause log sync calls to fail + Options options = CurrentOptions(); + options.env = env_; + Reopen(&options); + env_->data_sync_error_.Release_Store(env_); + + // (b) Normal write should succeed + WriteOptions w; + ASSERT_OK(db_->Put(w, "k1", "v1")); + ASSERT_EQ("v1", Get("k1")); + + // (c) Do a sync write; should fail + w.sync = true; + ASSERT_TRUE(!db_->Put(w, "k2", "v2").ok()); + ASSERT_EQ("v1", Get("k1")); + ASSERT_EQ("NOT_FOUND", Get("k2")); + + // (d) make sync behave normally + env_->data_sync_error_.Release_Store(NULL); + + // (e) Do a non-sync write; should fail + w.sync = false; + ASSERT_TRUE(!db_->Put(w, "k3", "v3").ok()); + ASSERT_EQ("v1", Get("k1")); + ASSERT_EQ("NOT_FOUND", Get("k2")); + ASSERT_EQ("NOT_FOUND", Get("k3")); +} + +TEST(DBTest, ManifestWriteError) { + // Test for the following problem: + // (a) Compaction produces file F + // (b) Log record containing F is written to MANIFEST file, but Sync() fails + // (c) GC deletes F + // (d) After reopening DB, reads fail since deleted F is named in log record + + // We iterate twice. In the second iteration, everything is the + // same except the log record never makes it to the MANIFEST file. + for (int iter = 0; iter < 2; iter++) { + port::AtomicPointer* error_type = (iter == 0) + ? &env_->manifest_sync_error_ + : &env_->manifest_write_error_; + + // Insert foo=>bar mapping + Options options = CurrentOptions(); + options.env = env_; + options.create_if_missing = true; + options.error_if_exists = false; + DestroyAndReopen(&options); + ASSERT_OK(Put("foo", "bar")); + ASSERT_EQ("bar", Get("foo")); + + // Memtable compaction (will succeed) + dbfull()->TEST_CompactMemTable(); + ASSERT_EQ("bar", Get("foo")); + const int last = config::kMaxMemCompactLevel; + ASSERT_EQ(NumTableFilesAtLevel(last), 1); // foo=>bar is now in last level + + // Merging compaction (will fail) + error_type->Release_Store(env_); + dbfull()->TEST_CompactRange(last, NULL, NULL); // Should fail + ASSERT_EQ("bar", Get("foo")); + + // Recovery: should not lose data + error_type->Release_Store(NULL); + Reopen(&options); + ASSERT_EQ("bar", Get("foo")); + } +} + +TEST(DBTest, MissingSSTFile) { + ASSERT_OK(Put("foo", "bar")); + ASSERT_EQ("bar", Get("foo")); + + // Dump the memtable to disk. + dbfull()->TEST_CompactMemTable(); + ASSERT_EQ("bar", Get("foo")); + + Close(); + ASSERT_TRUE(DeleteAnSSTFile()); + Options options = CurrentOptions(); + options.paranoid_checks = true; + Status s = TryReopen(&options); + ASSERT_TRUE(!s.ok()); + ASSERT_TRUE(s.ToString().find("issing") != std::string::npos) + << s.ToString(); +} + +TEST(DBTest, StillReadSST) { + ASSERT_OK(Put("foo", "bar")); + ASSERT_EQ("bar", Get("foo")); + + // Dump the memtable to disk. + dbfull()->TEST_CompactMemTable(); + ASSERT_EQ("bar", Get("foo")); + Close(); + ASSERT_GT(RenameLDBToSST(), 0); + Options options = CurrentOptions(); + options.paranoid_checks = true; + Status s = TryReopen(&options); + ASSERT_TRUE(s.ok()); + ASSERT_EQ("bar", Get("foo")); +} + +TEST(DBTest, FilesDeletedAfterCompaction) { + ASSERT_OK(Put("foo", "v2")); + Compact("a", "z"); + const int num_files = CountFiles(); + for (int i = 0; i < 10; i++) { + ASSERT_OK(Put("foo", "v2")); + Compact("a", "z"); + } + ASSERT_EQ(CountFiles(), num_files); +} + +TEST(DBTest, BloomFilter) { + env_->count_random_reads_ = true; + Options options = CurrentOptions(); + options.env = env_; + options.block_cache = NewLRUCache(0); // Prevent cache hits + options.filter_policy = NewBloomFilterPolicy(10); + Reopen(&options); + + // Populate multiple layers + const int N = 10000; + for (int i = 0; i < N; i++) { + ASSERT_OK(Put(Key(i), Key(i))); + } + Compact("a", "z"); + for (int i = 0; i < N; i += 100) { + ASSERT_OK(Put(Key(i), Key(i))); + } + dbfull()->TEST_CompactMemTable(); + + // Prevent auto compactions triggered by seeks + env_->delay_data_sync_.Release_Store(env_); + + // Lookup present keys. Should rarely read from small sstable. + env_->random_read_counter_.Reset(); + for (int i = 0; i < N; i++) { + ASSERT_EQ(Key(i), Get(Key(i))); + } + int reads = env_->random_read_counter_.Read(); + fprintf(stderr, "%d present => %d reads\n", N, reads); + ASSERT_GE(reads, N); + ASSERT_LE(reads, N + 2*N/100); + + // Lookup present keys. Should rarely read from either sstable. + env_->random_read_counter_.Reset(); + for (int i = 0; i < N; i++) { + ASSERT_EQ("NOT_FOUND", Get(Key(i) + ".missing")); + } + reads = env_->random_read_counter_.Read(); + fprintf(stderr, "%d missing => %d reads\n", N, reads); + ASSERT_LE(reads, 3*N/100); + + env_->delay_data_sync_.Release_Store(NULL); + Close(); + delete options.block_cache; + delete options.filter_policy; +} + +// Multi-threaded test: +namespace { + +static const int kNumThreads = 4; +static const int kTestSeconds = 10; +static const int kNumKeys = 1000; + +struct MTState { + DBTest* test; + port::AtomicPointer stop; + port::AtomicPointer counter[kNumThreads]; + port::AtomicPointer thread_done[kNumThreads]; +}; + +struct MTThread { + MTState* state; + int id; +}; + +static void MTThreadBody(void* arg) { + MTThread* t = reinterpret_cast(arg); + int id = t->id; + DB* db = t->state->test->db_; + uintptr_t counter = 0; + fprintf(stderr, "... starting thread %d\n", id); + Random rnd(1000 + id); + std::string value; + char valbuf[1500]; + while (t->state->stop.Acquire_Load() == NULL) { + t->state->counter[id].Release_Store(reinterpret_cast(counter)); + + int key = rnd.Uniform(kNumKeys); + char keybuf[20]; + snprintf(keybuf, sizeof(keybuf), "%016d", key); + + if (rnd.OneIn(2)) { + // Write values of the form . + // We add some padding for force compactions. + snprintf(valbuf, sizeof(valbuf), "%d.%d.%-1000d", + key, id, static_cast(counter)); + ASSERT_OK(db->Put(WriteOptions(), Slice(keybuf), Slice(valbuf))); + } else { + // Read a value and verify that it matches the pattern written above. + Status s = db->Get(ReadOptions(), Slice(keybuf), &value); + if (s.IsNotFound()) { + // Key has not yet been written + } else { + // Check that the writer thread counter is >= the counter in the value + ASSERT_OK(s); + int k, w, c; + ASSERT_EQ(3, sscanf(value.c_str(), "%d.%d.%d", &k, &w, &c)) << value; + ASSERT_EQ(k, key); + ASSERT_GE(w, 0); + ASSERT_LT(w, kNumThreads); + ASSERT_LE(static_cast(c), reinterpret_cast( + t->state->counter[w].Acquire_Load())); + } + } + counter++; + } + t->state->thread_done[id].Release_Store(t); + fprintf(stderr, "... stopping thread %d after %d ops\n", id, int(counter)); +} + +} // namespace + +TEST(DBTest, MultiThreaded) { + do { + // Initialize state + MTState mt; + mt.test = this; + mt.stop.Release_Store(0); + for (int id = 0; id < kNumThreads; id++) { + mt.counter[id].Release_Store(0); + mt.thread_done[id].Release_Store(0); + } + + // Start threads + MTThread thread[kNumThreads]; + for (int id = 0; id < kNumThreads; id++) { + thread[id].state = &mt; + thread[id].id = id; + env_->StartThread(MTThreadBody, &thread[id]); + } + + // Let them run for a while + DelayMilliseconds(kTestSeconds * 1000); + + // Stop the threads and wait for them to finish + mt.stop.Release_Store(&mt); + for (int id = 0; id < kNumThreads; id++) { + while (mt.thread_done[id].Acquire_Load() == NULL) { + DelayMilliseconds(100); + } + } + } while (ChangeOptions()); +} + +namespace { +typedef std::map KVMap; +} + +class ModelDB: public DB { + public: + class ModelSnapshot : public Snapshot { + public: + KVMap map_; + }; + + explicit ModelDB(const Options& options): options_(options) { } + ~ModelDB() { } + virtual Status Put(const WriteOptions& o, const Slice& k, const Slice& v) { + return DB::Put(o, k, v); + } + virtual Status Delete(const WriteOptions& o, const Slice& key) { + return DB::Delete(o, key); + } + virtual Status Get(const ReadOptions& options, + const Slice& key, std::string* value) { + assert(false); // Not implemented + return Status::NotFound(key); + } + virtual Iterator* NewIterator(const ReadOptions& options) { + if (options.snapshot == NULL) { + KVMap* saved = new KVMap; + *saved = map_; + return new ModelIter(saved, true); + } else { + const KVMap* snapshot_state = + &(reinterpret_cast(options.snapshot)->map_); + return new ModelIter(snapshot_state, false); + } + } + virtual const Snapshot* GetSnapshot() { + ModelSnapshot* snapshot = new ModelSnapshot; + snapshot->map_ = map_; + return snapshot; + } + + virtual void ReleaseSnapshot(const Snapshot* snapshot) { + delete reinterpret_cast(snapshot); + } + virtual Status Write(const WriteOptions& options, WriteBatch* batch) { + class Handler : public WriteBatch::Handler { + public: + KVMap* map_; + virtual void Put(const Slice& key, const Slice& value) { + (*map_)[key.ToString()] = value.ToString(); + } + virtual void Delete(const Slice& key) { + map_->erase(key.ToString()); + } + }; + Handler handler; + handler.map_ = &map_; + return batch->Iterate(&handler); + } + + virtual bool GetProperty(const Slice& property, std::string* value) { + return false; + } + virtual void GetApproximateSizes(const Range* r, int n, uint64_t* sizes) { + for (int i = 0; i < n; i++) { + sizes[i] = 0; + } + } + virtual void CompactRange(const Slice* start, const Slice* end) { + } + + private: + class ModelIter: public Iterator { + public: + ModelIter(const KVMap* map, bool owned) + : map_(map), owned_(owned), iter_(map_->end()) { + } + ~ModelIter() { + if (owned_) delete map_; + } + virtual bool Valid() const { return iter_ != map_->end(); } + virtual void SeekToFirst() { iter_ = map_->begin(); } + virtual void SeekToLast() { + if (map_->empty()) { + iter_ = map_->end(); + } else { + iter_ = map_->find(map_->rbegin()->first); + } + } + virtual void Seek(const Slice& k) { + iter_ = map_->lower_bound(k.ToString()); + } + virtual void Next() { ++iter_; } + virtual void Prev() { --iter_; } + virtual Slice key() const { return iter_->first; } + virtual Slice value() const { return iter_->second; } + virtual Status status() const { return Status::OK(); } + private: + const KVMap* const map_; + const bool owned_; // Do we own map_ + KVMap::const_iterator iter_; + }; + const Options options_; + KVMap map_; +}; + +static std::string RandomKey(Random* rnd) { + int len = (rnd->OneIn(3) + ? 1 // Short sometimes to encourage collisions + : (rnd->OneIn(100) ? rnd->Skewed(10) : rnd->Uniform(10))); + return test::RandomKey(rnd, len); +} + +static bool CompareIterators(int step, + DB* model, + DB* db, + const Snapshot* model_snap, + const Snapshot* db_snap) { + ReadOptions options; + options.snapshot = model_snap; + Iterator* miter = model->NewIterator(options); + options.snapshot = db_snap; + Iterator* dbiter = db->NewIterator(options); + bool ok = true; + int count = 0; + for (miter->SeekToFirst(), dbiter->SeekToFirst(); + ok && miter->Valid() && dbiter->Valid(); + miter->Next(), dbiter->Next()) { + count++; + if (miter->key().compare(dbiter->key()) != 0) { + fprintf(stderr, "step %d: Key mismatch: '%s' vs. '%s'\n", + step, + EscapeString(miter->key()).c_str(), + EscapeString(dbiter->key()).c_str()); + ok = false; + break; + } + + if (miter->value().compare(dbiter->value()) != 0) { + fprintf(stderr, "step %d: Value mismatch for key '%s': '%s' vs. '%s'\n", + step, + EscapeString(miter->key()).c_str(), + EscapeString(miter->value()).c_str(), + EscapeString(miter->value()).c_str()); + ok = false; + } + } + + if (ok) { + if (miter->Valid() != dbiter->Valid()) { + fprintf(stderr, "step %d: Mismatch at end of iterators: %d vs. %d\n", + step, miter->Valid(), dbiter->Valid()); + ok = false; + } + } + fprintf(stderr, "%d entries compared: ok=%d\n", count, ok); + delete miter; + delete dbiter; + return ok; +} + +TEST(DBTest, Randomized) { + Random rnd(test::RandomSeed()); + do { + ModelDB model(CurrentOptions()); + const int N = 10000; + const Snapshot* model_snap = NULL; + const Snapshot* db_snap = NULL; + std::string k, v; + for (int step = 0; step < N; step++) { + if (step % 100 == 0) { + fprintf(stderr, "Step %d of %d\n", step, N); + } + // TODO(sanjay): Test Get() works + int p = rnd.Uniform(100); + if (p < 45) { // Put + k = RandomKey(&rnd); + v = RandomString(&rnd, + rnd.OneIn(20) + ? 100 + rnd.Uniform(100) + : rnd.Uniform(8)); + ASSERT_OK(model.Put(WriteOptions(), k, v)); + ASSERT_OK(db_->Put(WriteOptions(), k, v)); + + } else if (p < 90) { // Delete + k = RandomKey(&rnd); + ASSERT_OK(model.Delete(WriteOptions(), k)); + ASSERT_OK(db_->Delete(WriteOptions(), k)); + + + } else { // Multi-element batch + WriteBatch b; + const int num = rnd.Uniform(8); + for (int i = 0; i < num; i++) { + if (i == 0 || !rnd.OneIn(10)) { + k = RandomKey(&rnd); + } else { + // Periodically re-use the same key from the previous iter, so + // we have multiple entries in the write batch for the same key + } + if (rnd.OneIn(2)) { + v = RandomString(&rnd, rnd.Uniform(10)); + b.Put(k, v); + } else { + b.Delete(k); + } + } + ASSERT_OK(model.Write(WriteOptions(), &b)); + ASSERT_OK(db_->Write(WriteOptions(), &b)); + } + + if ((step % 100) == 0) { + ASSERT_TRUE(CompareIterators(step, &model, db_, NULL, NULL)); + ASSERT_TRUE(CompareIterators(step, &model, db_, model_snap, db_snap)); + // Save a snapshot from each DB this time that we'll use next + // time we compare things, to make sure the current state is + // preserved with the snapshot + if (model_snap != NULL) model.ReleaseSnapshot(model_snap); + if (db_snap != NULL) db_->ReleaseSnapshot(db_snap); + + Reopen(); + ASSERT_TRUE(CompareIterators(step, &model, db_, NULL, NULL)); + + model_snap = model.GetSnapshot(); + db_snap = db_->GetSnapshot(); + } + } + if (model_snap != NULL) model.ReleaseSnapshot(model_snap); + if (db_snap != NULL) db_->ReleaseSnapshot(db_snap); + } while (ChangeOptions()); +} + +std::string MakeKey(unsigned int num) { + char buf[30]; + snprintf(buf, sizeof(buf), "%016u", num); + return std::string(buf); +} + +void BM_LogAndApply(int iters, int num_base_files) { + std::string dbname = test::TmpDir() + "/leveldb_test_benchmark"; + DestroyDB(dbname, Options()); + + DB* db = NULL; + Options opts; + opts.create_if_missing = true; + Status s = DB::Open(opts, dbname, &db); + ASSERT_OK(s); + ASSERT_TRUE(db != NULL); + + delete db; + db = NULL; + + Env* env = Env::Default(); + + port::Mutex mu; + MutexLock l(&mu); + + InternalKeyComparator cmp(BytewiseComparator()); + Options options; + VersionSet vset(dbname, &options, NULL, &cmp); + ASSERT_OK(vset.Recover()); + VersionEdit vbase; + uint64_t fnum = 1; + for (int i = 0; i < num_base_files; i++) { + InternalKey start(MakeKey(2*fnum), 1, kTypeValue); + InternalKey limit(MakeKey(2*fnum+1), 1, kTypeDeletion); + vbase.AddFile(2, fnum++, 1 /* file size */, start, limit); + } + ASSERT_OK(vset.LogAndApply(&vbase, &mu)); + + uint64_t start_micros = env->NowMicros(); + + for (int i = 0; i < iters; i++) { + VersionEdit vedit; + vedit.DeleteFile(2, fnum); + InternalKey start(MakeKey(2*fnum), 1, kTypeValue); + InternalKey limit(MakeKey(2*fnum+1), 1, kTypeDeletion); + vedit.AddFile(2, fnum++, 1 /* file size */, start, limit); + vset.LogAndApply(&vedit, &mu); + } + uint64_t stop_micros = env->NowMicros(); + unsigned int us = stop_micros - start_micros; + char buf[16]; + snprintf(buf, sizeof(buf), "%d", num_base_files); + fprintf(stderr, + "BM_LogAndApply/%-6s %8d iters : %9u us (%7.0f us / iter)\n", + buf, iters, us, ((float)us) / iters); +} + +} // namespace leveldb + +int main(int argc, char** argv) { + if (argc > 1 && std::string(argv[1]) == "--benchmark") { + leveldb::BM_LogAndApply(1000, 1); + leveldb::BM_LogAndApply(1000, 100); + leveldb::BM_LogAndApply(1000, 10000); + leveldb::BM_LogAndApply(100, 100000); + return 0; + } + + return leveldb::test::RunAllTests(); +} diff --git a/src/leveldb/db/dbformat.cc b/src/leveldb/db/dbformat.cc new file mode 100644 index 0000000..20a7ca4 --- /dev/null +++ b/src/leveldb/db/dbformat.cc @@ -0,0 +1,140 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include +#include "db/dbformat.h" +#include "port/port.h" +#include "util/coding.h" + +namespace leveldb { + +static uint64_t PackSequenceAndType(uint64_t seq, ValueType t) { + assert(seq <= kMaxSequenceNumber); + assert(t <= kValueTypeForSeek); + return (seq << 8) | t; +} + +void AppendInternalKey(std::string* result, const ParsedInternalKey& key) { + result->append(key.user_key.data(), key.user_key.size()); + PutFixed64(result, PackSequenceAndType(key.sequence, key.type)); +} + +std::string ParsedInternalKey::DebugString() const { + char buf[50]; + snprintf(buf, sizeof(buf), "' @ %llu : %d", + (unsigned long long) sequence, + int(type)); + std::string result = "'"; + result += EscapeString(user_key.ToString()); + result += buf; + return result; +} + +std::string InternalKey::DebugString() const { + std::string result; + ParsedInternalKey parsed; + if (ParseInternalKey(rep_, &parsed)) { + result = parsed.DebugString(); + } else { + result = "(bad)"; + result.append(EscapeString(rep_)); + } + return result; +} + +const char* InternalKeyComparator::Name() const { + return "leveldb.InternalKeyComparator"; +} + +int InternalKeyComparator::Compare(const Slice& akey, const Slice& bkey) const { + // Order by: + // increasing user key (according to user-supplied comparator) + // decreasing sequence number + // decreasing type (though sequence# should be enough to disambiguate) + int r = user_comparator_->Compare(ExtractUserKey(akey), ExtractUserKey(bkey)); + if (r == 0) { + const uint64_t anum = DecodeFixed64(akey.data() + akey.size() - 8); + const uint64_t bnum = DecodeFixed64(bkey.data() + bkey.size() - 8); + if (anum > bnum) { + r = -1; + } else if (anum < bnum) { + r = +1; + } + } + return r; +} + +void InternalKeyComparator::FindShortestSeparator( + std::string* start, + const Slice& limit) const { + // Attempt to shorten the user portion of the key + Slice user_start = ExtractUserKey(*start); + Slice user_limit = ExtractUserKey(limit); + std::string tmp(user_start.data(), user_start.size()); + user_comparator_->FindShortestSeparator(&tmp, user_limit); + if (tmp.size() < user_start.size() && + user_comparator_->Compare(user_start, tmp) < 0) { + // User key has become shorter physically, but larger logically. + // Tack on the earliest possible number to the shortened user key. + PutFixed64(&tmp, PackSequenceAndType(kMaxSequenceNumber,kValueTypeForSeek)); + assert(this->Compare(*start, tmp) < 0); + assert(this->Compare(tmp, limit) < 0); + start->swap(tmp); + } +} + +void InternalKeyComparator::FindShortSuccessor(std::string* key) const { + Slice user_key = ExtractUserKey(*key); + std::string tmp(user_key.data(), user_key.size()); + user_comparator_->FindShortSuccessor(&tmp); + if (tmp.size() < user_key.size() && + user_comparator_->Compare(user_key, tmp) < 0) { + // User key has become shorter physically, but larger logically. + // Tack on the earliest possible number to the shortened user key. + PutFixed64(&tmp, PackSequenceAndType(kMaxSequenceNumber,kValueTypeForSeek)); + assert(this->Compare(*key, tmp) < 0); + key->swap(tmp); + } +} + +const char* InternalFilterPolicy::Name() const { + return user_policy_->Name(); +} + +void InternalFilterPolicy::CreateFilter(const Slice* keys, int n, + std::string* dst) const { + // We rely on the fact that the code in table.cc does not mind us + // adjusting keys[]. + Slice* mkey = const_cast(keys); + for (int i = 0; i < n; i++) { + mkey[i] = ExtractUserKey(keys[i]); + // TODO(sanjay): Suppress dups? + } + user_policy_->CreateFilter(keys, n, dst); +} + +bool InternalFilterPolicy::KeyMayMatch(const Slice& key, const Slice& f) const { + return user_policy_->KeyMayMatch(ExtractUserKey(key), f); +} + +LookupKey::LookupKey(const Slice& user_key, SequenceNumber s) { + size_t usize = user_key.size(); + size_t needed = usize + 13; // A conservative estimate + char* dst; + if (needed <= sizeof(space_)) { + dst = space_; + } else { + dst = new char[needed]; + } + start_ = dst; + dst = EncodeVarint32(dst, usize + 8); + kstart_ = dst; + memcpy(dst, user_key.data(), usize); + dst += usize; + EncodeFixed64(dst, PackSequenceAndType(s, kValueTypeForSeek)); + dst += 8; + end_ = dst; +} + +} // namespace leveldb diff --git a/src/leveldb/db/dbformat.h b/src/leveldb/db/dbformat.h new file mode 100644 index 0000000..5d8a032 --- /dev/null +++ b/src/leveldb/db/dbformat.h @@ -0,0 +1,230 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#ifndef STORAGE_LEVELDB_DB_FORMAT_H_ +#define STORAGE_LEVELDB_DB_FORMAT_H_ + +#include +#include "leveldb/comparator.h" +#include "leveldb/db.h" +#include "leveldb/filter_policy.h" +#include "leveldb/slice.h" +#include "leveldb/table_builder.h" +#include "util/coding.h" +#include "util/logging.h" + +namespace leveldb { + +// Grouping of constants. We may want to make some of these +// parameters set via options. +namespace config { +static const int kNumLevels = 7; + +// Level-0 compaction is started when we hit this many files. +static const int kL0_CompactionTrigger = 4; + +// Soft limit on number of level-0 files. We slow down writes at this point. +static const int kL0_SlowdownWritesTrigger = 8; + +// Maximum number of level-0 files. We stop writes at this point. +static const int kL0_StopWritesTrigger = 12; + +// Maximum level to which a new compacted memtable is pushed if it +// does not create overlap. We try to push to level 2 to avoid the +// relatively expensive level 0=>1 compactions and to avoid some +// expensive manifest file operations. We do not push all the way to +// the largest level since that can generate a lot of wasted disk +// space if the same key space is being repeatedly overwritten. +static const int kMaxMemCompactLevel = 2; + +// Approximate gap in bytes between samples of data read during iteration. +static const int kReadBytesPeriod = 1048576; + +} // namespace config + +class InternalKey; + +// Value types encoded as the last component of internal keys. +// DO NOT CHANGE THESE ENUM VALUES: they are embedded in the on-disk +// data structures. +enum ValueType { + kTypeDeletion = 0x0, + kTypeValue = 0x1 +}; +// kValueTypeForSeek defines the ValueType that should be passed when +// constructing a ParsedInternalKey object for seeking to a particular +// sequence number (since we sort sequence numbers in decreasing order +// and the value type is embedded as the low 8 bits in the sequence +// number in internal keys, we need to use the highest-numbered +// ValueType, not the lowest). +static const ValueType kValueTypeForSeek = kTypeValue; + +typedef uint64_t SequenceNumber; + +// We leave eight bits empty at the bottom so a type and sequence# +// can be packed together into 64-bits. +static const SequenceNumber kMaxSequenceNumber = + ((0x1ull << 56) - 1); + +struct ParsedInternalKey { + Slice user_key; + SequenceNumber sequence; + ValueType type; + + ParsedInternalKey() { } // Intentionally left uninitialized (for speed) + ParsedInternalKey(const Slice& u, const SequenceNumber& seq, ValueType t) + : user_key(u), sequence(seq), type(t) { } + std::string DebugString() const; +}; + +// Return the length of the encoding of "key". +inline size_t InternalKeyEncodingLength(const ParsedInternalKey& key) { + return key.user_key.size() + 8; +} + +// Append the serialization of "key" to *result. +extern void AppendInternalKey(std::string* result, + const ParsedInternalKey& key); + +// Attempt to parse an internal key from "internal_key". On success, +// stores the parsed data in "*result", and returns true. +// +// On error, returns false, leaves "*result" in an undefined state. +extern bool ParseInternalKey(const Slice& internal_key, + ParsedInternalKey* result); + +// Returns the user key portion of an internal key. +inline Slice ExtractUserKey(const Slice& internal_key) { + assert(internal_key.size() >= 8); + return Slice(internal_key.data(), internal_key.size() - 8); +} + +inline ValueType ExtractValueType(const Slice& internal_key) { + assert(internal_key.size() >= 8); + const size_t n = internal_key.size(); + uint64_t num = DecodeFixed64(internal_key.data() + n - 8); + unsigned char c = num & 0xff; + return static_cast(c); +} + +// A comparator for internal keys that uses a specified comparator for +// the user key portion and breaks ties by decreasing sequence number. +class InternalKeyComparator : public Comparator { + private: + const Comparator* user_comparator_; + public: + explicit InternalKeyComparator(const Comparator* c) : user_comparator_(c) { } + virtual const char* Name() const; + virtual int Compare(const Slice& a, const Slice& b) const; + virtual void FindShortestSeparator( + std::string* start, + const Slice& limit) const; + virtual void FindShortSuccessor(std::string* key) const; + + const Comparator* user_comparator() const { return user_comparator_; } + + int Compare(const InternalKey& a, const InternalKey& b) const; +}; + +// Filter policy wrapper that converts from internal keys to user keys +class InternalFilterPolicy : public FilterPolicy { + private: + const FilterPolicy* const user_policy_; + public: + explicit InternalFilterPolicy(const FilterPolicy* p) : user_policy_(p) { } + virtual const char* Name() const; + virtual void CreateFilter(const Slice* keys, int n, std::string* dst) const; + virtual bool KeyMayMatch(const Slice& key, const Slice& filter) const; +}; + +// Modules in this directory should keep internal keys wrapped inside +// the following class instead of plain strings so that we do not +// incorrectly use string comparisons instead of an InternalKeyComparator. +class InternalKey { + private: + std::string rep_; + public: + InternalKey() { } // Leave rep_ as empty to indicate it is invalid + InternalKey(const Slice& user_key, SequenceNumber s, ValueType t) { + AppendInternalKey(&rep_, ParsedInternalKey(user_key, s, t)); + } + + void DecodeFrom(const Slice& s) { rep_.assign(s.data(), s.size()); } + Slice Encode() const { + assert(!rep_.empty()); + return rep_; + } + + Slice user_key() const { return ExtractUserKey(rep_); } + + void SetFrom(const ParsedInternalKey& p) { + rep_.clear(); + AppendInternalKey(&rep_, p); + } + + void Clear() { rep_.clear(); } + + std::string DebugString() const; +}; + +inline int InternalKeyComparator::Compare( + const InternalKey& a, const InternalKey& b) const { + return Compare(a.Encode(), b.Encode()); +} + +inline bool ParseInternalKey(const Slice& internal_key, + ParsedInternalKey* result) { + const size_t n = internal_key.size(); + if (n < 8) return false; + uint64_t num = DecodeFixed64(internal_key.data() + n - 8); + unsigned char c = num & 0xff; + result->sequence = num >> 8; + result->type = static_cast(c); + result->user_key = Slice(internal_key.data(), n - 8); + return (c <= static_cast(kTypeValue)); +} + +// A helper class useful for DBImpl::Get() +class LookupKey { + public: + // Initialize *this for looking up user_key at a snapshot with + // the specified sequence number. + LookupKey(const Slice& user_key, SequenceNumber sequence); + + ~LookupKey(); + + // Return a key suitable for lookup in a MemTable. + Slice memtable_key() const { return Slice(start_, end_ - start_); } + + // Return an internal key (suitable for passing to an internal iterator) + Slice internal_key() const { return Slice(kstart_, end_ - kstart_); } + + // Return the user key + Slice user_key() const { return Slice(kstart_, end_ - kstart_ - 8); } + + private: + // We construct a char array of the form: + // klength varint32 <-- start_ + // userkey char[klength] <-- kstart_ + // tag uint64 + // <-- end_ + // The array is a suitable MemTable key. + // The suffix starting with "userkey" can be used as an InternalKey. + const char* start_; + const char* kstart_; + const char* end_; + char space_[200]; // Avoid allocation for short keys + + // No copying allowed + LookupKey(const LookupKey&); + void operator=(const LookupKey&); +}; + +inline LookupKey::~LookupKey() { + if (start_ != space_) delete[] start_; +} + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_DB_FORMAT_H_ diff --git a/src/leveldb/db/dbformat_test.cc b/src/leveldb/db/dbformat_test.cc new file mode 100644 index 0000000..5d82f5d --- /dev/null +++ b/src/leveldb/db/dbformat_test.cc @@ -0,0 +1,112 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "db/dbformat.h" +#include "util/logging.h" +#include "util/testharness.h" + +namespace leveldb { + +static std::string IKey(const std::string& user_key, + uint64_t seq, + ValueType vt) { + std::string encoded; + AppendInternalKey(&encoded, ParsedInternalKey(user_key, seq, vt)); + return encoded; +} + +static std::string Shorten(const std::string& s, const std::string& l) { + std::string result = s; + InternalKeyComparator(BytewiseComparator()).FindShortestSeparator(&result, l); + return result; +} + +static std::string ShortSuccessor(const std::string& s) { + std::string result = s; + InternalKeyComparator(BytewiseComparator()).FindShortSuccessor(&result); + return result; +} + +static void TestKey(const std::string& key, + uint64_t seq, + ValueType vt) { + std::string encoded = IKey(key, seq, vt); + + Slice in(encoded); + ParsedInternalKey decoded("", 0, kTypeValue); + + ASSERT_TRUE(ParseInternalKey(in, &decoded)); + ASSERT_EQ(key, decoded.user_key.ToString()); + ASSERT_EQ(seq, decoded.sequence); + ASSERT_EQ(vt, decoded.type); + + ASSERT_TRUE(!ParseInternalKey(Slice("bar"), &decoded)); +} + +class FormatTest { }; + +TEST(FormatTest, InternalKey_EncodeDecode) { + const char* keys[] = { "", "k", "hello", "longggggggggggggggggggggg" }; + const uint64_t seq[] = { + 1, 2, 3, + (1ull << 8) - 1, 1ull << 8, (1ull << 8) + 1, + (1ull << 16) - 1, 1ull << 16, (1ull << 16) + 1, + (1ull << 32) - 1, 1ull << 32, (1ull << 32) + 1 + }; + for (int k = 0; k < sizeof(keys) / sizeof(keys[0]); k++) { + for (int s = 0; s < sizeof(seq) / sizeof(seq[0]); s++) { + TestKey(keys[k], seq[s], kTypeValue); + TestKey("hello", 1, kTypeDeletion); + } + } +} + +TEST(FormatTest, InternalKeyShortSeparator) { + // When user keys are same + ASSERT_EQ(IKey("foo", 100, kTypeValue), + Shorten(IKey("foo", 100, kTypeValue), + IKey("foo", 99, kTypeValue))); + ASSERT_EQ(IKey("foo", 100, kTypeValue), + Shorten(IKey("foo", 100, kTypeValue), + IKey("foo", 101, kTypeValue))); + ASSERT_EQ(IKey("foo", 100, kTypeValue), + Shorten(IKey("foo", 100, kTypeValue), + IKey("foo", 100, kTypeValue))); + ASSERT_EQ(IKey("foo", 100, kTypeValue), + Shorten(IKey("foo", 100, kTypeValue), + IKey("foo", 100, kTypeDeletion))); + + // When user keys are misordered + ASSERT_EQ(IKey("foo", 100, kTypeValue), + Shorten(IKey("foo", 100, kTypeValue), + IKey("bar", 99, kTypeValue))); + + // When user keys are different, but correctly ordered + ASSERT_EQ(IKey("g", kMaxSequenceNumber, kValueTypeForSeek), + Shorten(IKey("foo", 100, kTypeValue), + IKey("hello", 200, kTypeValue))); + + // When start user key is prefix of limit user key + ASSERT_EQ(IKey("foo", 100, kTypeValue), + Shorten(IKey("foo", 100, kTypeValue), + IKey("foobar", 200, kTypeValue))); + + // When limit user key is prefix of start user key + ASSERT_EQ(IKey("foobar", 100, kTypeValue), + Shorten(IKey("foobar", 100, kTypeValue), + IKey("foo", 200, kTypeValue))); +} + +TEST(FormatTest, InternalKeyShortestSuccessor) { + ASSERT_EQ(IKey("g", kMaxSequenceNumber, kValueTypeForSeek), + ShortSuccessor(IKey("foo", 100, kTypeValue))); + ASSERT_EQ(IKey("\xff\xff", 100, kTypeValue), + ShortSuccessor(IKey("\xff\xff", 100, kTypeValue))); +} + +} // namespace leveldb + +int main(int argc, char** argv) { + return leveldb::test::RunAllTests(); +} diff --git a/src/leveldb/db/filename.cc b/src/leveldb/db/filename.cc new file mode 100644 index 0000000..da32946 --- /dev/null +++ b/src/leveldb/db/filename.cc @@ -0,0 +1,144 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include +#include +#include "db/filename.h" +#include "db/dbformat.h" +#include "leveldb/env.h" +#include "util/logging.h" + +namespace leveldb { + +// A utility routine: write "data" to the named file and Sync() it. +extern Status WriteStringToFileSync(Env* env, const Slice& data, + const std::string& fname); + +static std::string MakeFileName(const std::string& name, uint64_t number, + const char* suffix) { + char buf[100]; + snprintf(buf, sizeof(buf), "/%06llu.%s", + static_cast(number), + suffix); + return name + buf; +} + +std::string LogFileName(const std::string& name, uint64_t number) { + assert(number > 0); + return MakeFileName(name, number, "log"); +} + +std::string TableFileName(const std::string& name, uint64_t number) { + assert(number > 0); + return MakeFileName(name, number, "ldb"); +} + +std::string SSTTableFileName(const std::string& name, uint64_t number) { + assert(number > 0); + return MakeFileName(name, number, "sst"); +} + +std::string DescriptorFileName(const std::string& dbname, uint64_t number) { + assert(number > 0); + char buf[100]; + snprintf(buf, sizeof(buf), "/MANIFEST-%06llu", + static_cast(number)); + return dbname + buf; +} + +std::string CurrentFileName(const std::string& dbname) { + return dbname + "/CURRENT"; +} + +std::string LockFileName(const std::string& dbname) { + return dbname + "/LOCK"; +} + +std::string TempFileName(const std::string& dbname, uint64_t number) { + assert(number > 0); + return MakeFileName(dbname, number, "dbtmp"); +} + +std::string InfoLogFileName(const std::string& dbname) { + return dbname + "/LOG"; +} + +// Return the name of the old info log file for "dbname". +std::string OldInfoLogFileName(const std::string& dbname) { + return dbname + "/LOG.old"; +} + + +// Owned filenames have the form: +// dbname/CURRENT +// dbname/LOCK +// dbname/LOG +// dbname/LOG.old +// dbname/MANIFEST-[0-9]+ +// dbname/[0-9]+.(log|sst|ldb) +bool ParseFileName(const std::string& fname, + uint64_t* number, + FileType* type) { + Slice rest(fname); + if (rest == "CURRENT") { + *number = 0; + *type = kCurrentFile; + } else if (rest == "LOCK") { + *number = 0; + *type = kDBLockFile; + } else if (rest == "LOG" || rest == "LOG.old") { + *number = 0; + *type = kInfoLogFile; + } else if (rest.starts_with("MANIFEST-")) { + rest.remove_prefix(strlen("MANIFEST-")); + uint64_t num; + if (!ConsumeDecimalNumber(&rest, &num)) { + return false; + } + if (!rest.empty()) { + return false; + } + *type = kDescriptorFile; + *number = num; + } else { + // Avoid strtoull() to keep filename format independent of the + // current locale + uint64_t num; + if (!ConsumeDecimalNumber(&rest, &num)) { + return false; + } + Slice suffix = rest; + if (suffix == Slice(".log")) { + *type = kLogFile; + } else if (suffix == Slice(".sst") || suffix == Slice(".ldb")) { + *type = kTableFile; + } else if (suffix == Slice(".dbtmp")) { + *type = kTempFile; + } else { + return false; + } + *number = num; + } + return true; +} + +Status SetCurrentFile(Env* env, const std::string& dbname, + uint64_t descriptor_number) { + // Remove leading "dbname/" and add newline to manifest file name + std::string manifest = DescriptorFileName(dbname, descriptor_number); + Slice contents = manifest; + assert(contents.starts_with(dbname + "/")); + contents.remove_prefix(dbname.size() + 1); + std::string tmp = TempFileName(dbname, descriptor_number); + Status s = WriteStringToFileSync(env, contents.ToString() + "\n", tmp); + if (s.ok()) { + s = env->RenameFile(tmp, CurrentFileName(dbname)); + } + if (!s.ok()) { + env->DeleteFile(tmp); + } + return s; +} + +} // namespace leveldb diff --git a/src/leveldb/db/filename.h b/src/leveldb/db/filename.h new file mode 100644 index 0000000..87a7526 --- /dev/null +++ b/src/leveldb/db/filename.h @@ -0,0 +1,85 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. +// +// File names used by DB code + +#ifndef STORAGE_LEVELDB_DB_FILENAME_H_ +#define STORAGE_LEVELDB_DB_FILENAME_H_ + +#include +#include +#include "leveldb/slice.h" +#include "leveldb/status.h" +#include "port/port.h" + +namespace leveldb { + +class Env; + +enum FileType { + kLogFile, + kDBLockFile, + kTableFile, + kDescriptorFile, + kCurrentFile, + kTempFile, + kInfoLogFile // Either the current one, or an old one +}; + +// Return the name of the log file with the specified number +// in the db named by "dbname". The result will be prefixed with +// "dbname". +extern std::string LogFileName(const std::string& dbname, uint64_t number); + +// Return the name of the sstable with the specified number +// in the db named by "dbname". The result will be prefixed with +// "dbname". +extern std::string TableFileName(const std::string& dbname, uint64_t number); + +// Return the legacy file name for an sstable with the specified number +// in the db named by "dbname". The result will be prefixed with +// "dbname". +extern std::string SSTTableFileName(const std::string& dbname, uint64_t number); + +// Return the name of the descriptor file for the db named by +// "dbname" and the specified incarnation number. The result will be +// prefixed with "dbname". +extern std::string DescriptorFileName(const std::string& dbname, + uint64_t number); + +// Return the name of the current file. This file contains the name +// of the current manifest file. The result will be prefixed with +// "dbname". +extern std::string CurrentFileName(const std::string& dbname); + +// Return the name of the lock file for the db named by +// "dbname". The result will be prefixed with "dbname". +extern std::string LockFileName(const std::string& dbname); + +// Return the name of a temporary file owned by the db named "dbname". +// The result will be prefixed with "dbname". +extern std::string TempFileName(const std::string& dbname, uint64_t number); + +// Return the name of the info log file for "dbname". +extern std::string InfoLogFileName(const std::string& dbname); + +// Return the name of the old info log file for "dbname". +extern std::string OldInfoLogFileName(const std::string& dbname); + +// If filename is a leveldb file, store the type of the file in *type. +// The number encoded in the filename is stored in *number. If the +// filename was successfully parsed, returns true. Else return false. +extern bool ParseFileName(const std::string& filename, + uint64_t* number, + FileType* type); + +// Make the CURRENT file point to the descriptor file with the +// specified number. +extern Status SetCurrentFile(Env* env, const std::string& dbname, + uint64_t descriptor_number); + + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_DB_FILENAME_H_ diff --git a/src/leveldb/db/filename_test.cc b/src/leveldb/db/filename_test.cc new file mode 100644 index 0000000..a32556d --- /dev/null +++ b/src/leveldb/db/filename_test.cc @@ -0,0 +1,123 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "db/filename.h" + +#include "db/dbformat.h" +#include "port/port.h" +#include "util/logging.h" +#include "util/testharness.h" + +namespace leveldb { + +class FileNameTest { }; + +TEST(FileNameTest, Parse) { + Slice db; + FileType type; + uint64_t number; + + // Successful parses + static struct { + const char* fname; + uint64_t number; + FileType type; + } cases[] = { + { "100.log", 100, kLogFile }, + { "0.log", 0, kLogFile }, + { "0.sst", 0, kTableFile }, + { "0.ldb", 0, kTableFile }, + { "CURRENT", 0, kCurrentFile }, + { "LOCK", 0, kDBLockFile }, + { "MANIFEST-2", 2, kDescriptorFile }, + { "MANIFEST-7", 7, kDescriptorFile }, + { "LOG", 0, kInfoLogFile }, + { "LOG.old", 0, kInfoLogFile }, + { "18446744073709551615.log", 18446744073709551615ull, kLogFile }, + }; + for (int i = 0; i < sizeof(cases) / sizeof(cases[0]); i++) { + std::string f = cases[i].fname; + ASSERT_TRUE(ParseFileName(f, &number, &type)) << f; + ASSERT_EQ(cases[i].type, type) << f; + ASSERT_EQ(cases[i].number, number) << f; + } + + // Errors + static const char* errors[] = { + "", + "foo", + "foo-dx-100.log", + ".log", + "", + "manifest", + "CURREN", + "CURRENTX", + "MANIFES", + "MANIFEST", + "MANIFEST-", + "XMANIFEST-3", + "MANIFEST-3x", + "LOC", + "LOCKx", + "LO", + "LOGx", + "18446744073709551616.log", + "184467440737095516150.log", + "100", + "100.", + "100.lop" + }; + for (int i = 0; i < sizeof(errors) / sizeof(errors[0]); i++) { + std::string f = errors[i]; + ASSERT_TRUE(!ParseFileName(f, &number, &type)) << f; + } +} + +TEST(FileNameTest, Construction) { + uint64_t number; + FileType type; + std::string fname; + + fname = CurrentFileName("foo"); + ASSERT_EQ("foo/", std::string(fname.data(), 4)); + ASSERT_TRUE(ParseFileName(fname.c_str() + 4, &number, &type)); + ASSERT_EQ(0, number); + ASSERT_EQ(kCurrentFile, type); + + fname = LockFileName("foo"); + ASSERT_EQ("foo/", std::string(fname.data(), 4)); + ASSERT_TRUE(ParseFileName(fname.c_str() + 4, &number, &type)); + ASSERT_EQ(0, number); + ASSERT_EQ(kDBLockFile, type); + + fname = LogFileName("foo", 192); + ASSERT_EQ("foo/", std::string(fname.data(), 4)); + ASSERT_TRUE(ParseFileName(fname.c_str() + 4, &number, &type)); + ASSERT_EQ(192, number); + ASSERT_EQ(kLogFile, type); + + fname = TableFileName("bar", 200); + ASSERT_EQ("bar/", std::string(fname.data(), 4)); + ASSERT_TRUE(ParseFileName(fname.c_str() + 4, &number, &type)); + ASSERT_EQ(200, number); + ASSERT_EQ(kTableFile, type); + + fname = DescriptorFileName("bar", 100); + ASSERT_EQ("bar/", std::string(fname.data(), 4)); + ASSERT_TRUE(ParseFileName(fname.c_str() + 4, &number, &type)); + ASSERT_EQ(100, number); + ASSERT_EQ(kDescriptorFile, type); + + fname = TempFileName("tmp", 999); + ASSERT_EQ("tmp/", std::string(fname.data(), 4)); + ASSERT_TRUE(ParseFileName(fname.c_str() + 4, &number, &type)); + ASSERT_EQ(999, number); + ASSERT_EQ(kTempFile, type); +} + +} // namespace leveldb + +int main(int argc, char** argv) { + return leveldb::test::RunAllTests(); +} diff --git a/src/leveldb/db/leveldb_main.cc b/src/leveldb/db/leveldb_main.cc new file mode 100644 index 0000000..995d761 --- /dev/null +++ b/src/leveldb/db/leveldb_main.cc @@ -0,0 +1,238 @@ +// Copyright (c) 2012 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include +#include "db/dbformat.h" +#include "db/filename.h" +#include "db/log_reader.h" +#include "db/version_edit.h" +#include "db/write_batch_internal.h" +#include "leveldb/env.h" +#include "leveldb/iterator.h" +#include "leveldb/options.h" +#include "leveldb/status.h" +#include "leveldb/table.h" +#include "leveldb/write_batch.h" +#include "util/logging.h" + +namespace leveldb { + +namespace { + +bool GuessType(const std::string& fname, FileType* type) { + size_t pos = fname.rfind('/'); + std::string basename; + if (pos == std::string::npos) { + basename = fname; + } else { + basename = std::string(fname.data() + pos + 1, fname.size() - pos - 1); + } + uint64_t ignored; + return ParseFileName(basename, &ignored, type); +} + +// Notified when log reader encounters corruption. +class CorruptionReporter : public log::Reader::Reporter { + public: + virtual void Corruption(size_t bytes, const Status& status) { + printf("corruption: %d bytes; %s\n", + static_cast(bytes), + status.ToString().c_str()); + } +}; + +// Print contents of a log file. (*func)() is called on every record. +bool PrintLogContents(Env* env, const std::string& fname, + void (*func)(Slice)) { + SequentialFile* file; + Status s = env->NewSequentialFile(fname, &file); + if (!s.ok()) { + fprintf(stderr, "%s\n", s.ToString().c_str()); + return false; + } + CorruptionReporter reporter; + log::Reader reader(file, &reporter, true, 0); + Slice record; + std::string scratch; + while (reader.ReadRecord(&record, &scratch)) { + printf("--- offset %llu; ", + static_cast(reader.LastRecordOffset())); + (*func)(record); + } + delete file; + return true; +} + +// Called on every item found in a WriteBatch. +class WriteBatchItemPrinter : public WriteBatch::Handler { + public: + uint64_t offset_; + uint64_t sequence_; + + virtual void Put(const Slice& key, const Slice& value) { + printf(" put '%s' '%s'\n", + EscapeString(key).c_str(), + EscapeString(value).c_str()); + } + virtual void Delete(const Slice& key) { + printf(" del '%s'\n", + EscapeString(key).c_str()); + } +}; + + +// Called on every log record (each one of which is a WriteBatch) +// found in a kLogFile. +static void WriteBatchPrinter(Slice record) { + if (record.size() < 12) { + printf("log record length %d is too small\n", + static_cast(record.size())); + return; + } + WriteBatch batch; + WriteBatchInternal::SetContents(&batch, record); + printf("sequence %llu\n", + static_cast(WriteBatchInternal::Sequence(&batch))); + WriteBatchItemPrinter batch_item_printer; + Status s = batch.Iterate(&batch_item_printer); + if (!s.ok()) { + printf(" error: %s\n", s.ToString().c_str()); + } +} + +bool DumpLog(Env* env, const std::string& fname) { + return PrintLogContents(env, fname, WriteBatchPrinter); +} + +// Called on every log record (each one of which is a WriteBatch) +// found in a kDescriptorFile. +static void VersionEditPrinter(Slice record) { + VersionEdit edit; + Status s = edit.DecodeFrom(record); + if (!s.ok()) { + printf("%s\n", s.ToString().c_str()); + return; + } + printf("%s", edit.DebugString().c_str()); +} + +bool DumpDescriptor(Env* env, const std::string& fname) { + return PrintLogContents(env, fname, VersionEditPrinter); +} + +bool DumpTable(Env* env, const std::string& fname) { + uint64_t file_size; + RandomAccessFile* file = NULL; + Table* table = NULL; + Status s = env->GetFileSize(fname, &file_size); + if (s.ok()) { + s = env->NewRandomAccessFile(fname, &file); + } + if (s.ok()) { + // We use the default comparator, which may or may not match the + // comparator used in this database. However this should not cause + // problems since we only use Table operations that do not require + // any comparisons. In particular, we do not call Seek or Prev. + s = Table::Open(Options(), file, file_size, &table); + } + if (!s.ok()) { + fprintf(stderr, "%s\n", s.ToString().c_str()); + delete table; + delete file; + return false; + } + + ReadOptions ro; + ro.fill_cache = false; + Iterator* iter = table->NewIterator(ro); + for (iter->SeekToFirst(); iter->Valid(); iter->Next()) { + ParsedInternalKey key; + if (!ParseInternalKey(iter->key(), &key)) { + printf("badkey '%s' => '%s'\n", + EscapeString(iter->key()).c_str(), + EscapeString(iter->value()).c_str()); + } else { + char kbuf[20]; + const char* type; + if (key.type == kTypeDeletion) { + type = "del"; + } else if (key.type == kTypeValue) { + type = "val"; + } else { + snprintf(kbuf, sizeof(kbuf), "%d", static_cast(key.type)); + type = kbuf; + } + printf("'%s' @ %8llu : %s => '%s'\n", + EscapeString(key.user_key).c_str(), + static_cast(key.sequence), + type, + EscapeString(iter->value()).c_str()); + } + } + s = iter->status(); + if (!s.ok()) { + printf("iterator error: %s\n", s.ToString().c_str()); + } + + delete iter; + delete table; + delete file; + return true; +} + +bool DumpFile(Env* env, const std::string& fname) { + FileType ftype; + if (!GuessType(fname, &ftype)) { + fprintf(stderr, "%s: unknown file type\n", fname.c_str()); + return false; + } + switch (ftype) { + case kLogFile: return DumpLog(env, fname); + case kDescriptorFile: return DumpDescriptor(env, fname); + case kTableFile: return DumpTable(env, fname); + + default: { + fprintf(stderr, "%s: not a dump-able file type\n", fname.c_str()); + break; + } + } + return false; +} + +bool HandleDumpCommand(Env* env, char** files, int num) { + bool ok = true; + for (int i = 0; i < num; i++) { + ok &= DumpFile(env, files[i]); + } + return ok; +} + +} +} // namespace leveldb + +static void Usage() { + fprintf( + stderr, + "Usage: leveldbutil command...\n" + " dump files... -- dump contents of specified files\n" + ); +} + +int main(int argc, char** argv) { + leveldb::Env* env = leveldb::Env::Default(); + bool ok = true; + if (argc < 2) { + Usage(); + ok = false; + } else { + std::string command = argv[1]; + if (command == "dump") { + ok = leveldb::HandleDumpCommand(env, argv+2, argc-2); + } else { + Usage(); + ok = false; + } + } + return (ok ? 0 : 1); +} diff --git a/src/leveldb/db/log_format.h b/src/leveldb/db/log_format.h new file mode 100644 index 0000000..2690cb9 --- /dev/null +++ b/src/leveldb/db/log_format.h @@ -0,0 +1,35 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. +// +// Log format information shared by reader and writer. +// See ../doc/log_format.txt for more detail. + +#ifndef STORAGE_LEVELDB_DB_LOG_FORMAT_H_ +#define STORAGE_LEVELDB_DB_LOG_FORMAT_H_ + +namespace leveldb { +namespace log { + +enum RecordType { + // Zero is reserved for preallocated files + kZeroType = 0, + + kFullType = 1, + + // For fragments + kFirstType = 2, + kMiddleType = 3, + kLastType = 4 +}; +static const int kMaxRecordType = kLastType; + +static const int kBlockSize = 32768; + +// Header is checksum (4 bytes), type (1 byte), length (2 bytes). +static const int kHeaderSize = 4 + 1 + 2; + +} // namespace log +} // namespace leveldb + +#endif // STORAGE_LEVELDB_DB_LOG_FORMAT_H_ diff --git a/src/leveldb/db/log_reader.cc b/src/leveldb/db/log_reader.cc new file mode 100644 index 0000000..4919216 --- /dev/null +++ b/src/leveldb/db/log_reader.cc @@ -0,0 +1,266 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "db/log_reader.h" + +#include +#include "leveldb/env.h" +#include "util/coding.h" +#include "util/crc32c.h" + +namespace leveldb { +namespace log { + +Reader::Reporter::~Reporter() { +} + +Reader::Reader(SequentialFile* file, Reporter* reporter, bool checksum, + uint64_t initial_offset) + : file_(file), + reporter_(reporter), + checksum_(checksum), + backing_store_(new char[kBlockSize]), + buffer_(), + eof_(false), + last_record_offset_(0), + end_of_buffer_offset_(0), + initial_offset_(initial_offset) { +} + +Reader::~Reader() { + delete[] backing_store_; +} + +bool Reader::SkipToInitialBlock() { + size_t offset_in_block = initial_offset_ % kBlockSize; + uint64_t block_start_location = initial_offset_ - offset_in_block; + + // Don't search a block if we'd be in the trailer + if (offset_in_block > kBlockSize - 6) { + offset_in_block = 0; + block_start_location += kBlockSize; + } + + end_of_buffer_offset_ = block_start_location; + + // Skip to start of first block that can contain the initial record + if (block_start_location > 0) { + Status skip_status = file_->Skip(block_start_location); + if (!skip_status.ok()) { + ReportDrop(block_start_location, skip_status); + return false; + } + } + + return true; +} + +bool Reader::ReadRecord(Slice* record, std::string* scratch) { + if (last_record_offset_ < initial_offset_) { + if (!SkipToInitialBlock()) { + return false; + } + } + + scratch->clear(); + record->clear(); + bool in_fragmented_record = false; + // Record offset of the logical record that we're reading + // 0 is a dummy value to make compilers happy + uint64_t prospective_record_offset = 0; + + Slice fragment; + while (true) { + uint64_t physical_record_offset = end_of_buffer_offset_ - buffer_.size(); + const unsigned int record_type = ReadPhysicalRecord(&fragment); + switch (record_type) { + case kFullType: + if (in_fragmented_record) { + // Handle bug in earlier versions of log::Writer where + // it could emit an empty kFirstType record at the tail end + // of a block followed by a kFullType or kFirstType record + // at the beginning of the next block. + if (scratch->empty()) { + in_fragmented_record = false; + } else { + ReportCorruption(scratch->size(), "partial record without end(1)"); + } + } + prospective_record_offset = physical_record_offset; + scratch->clear(); + *record = fragment; + last_record_offset_ = prospective_record_offset; + return true; + + case kFirstType: + if (in_fragmented_record) { + // Handle bug in earlier versions of log::Writer where + // it could emit an empty kFirstType record at the tail end + // of a block followed by a kFullType or kFirstType record + // at the beginning of the next block. + if (scratch->empty()) { + in_fragmented_record = false; + } else { + ReportCorruption(scratch->size(), "partial record without end(2)"); + } + } + prospective_record_offset = physical_record_offset; + scratch->assign(fragment.data(), fragment.size()); + in_fragmented_record = true; + break; + + case kMiddleType: + if (!in_fragmented_record) { + ReportCorruption(fragment.size(), + "missing start of fragmented record(1)"); + } else { + scratch->append(fragment.data(), fragment.size()); + } + break; + + case kLastType: + if (!in_fragmented_record) { + ReportCorruption(fragment.size(), + "missing start of fragmented record(2)"); + } else { + scratch->append(fragment.data(), fragment.size()); + *record = Slice(*scratch); + last_record_offset_ = prospective_record_offset; + return true; + } + break; + + case kEof: + if (in_fragmented_record) { + // This can be caused by the writer dying immediately after + // writing a physical record but before completing the next; don't + // treat it as a corruption, just ignore the entire logical record. + scratch->clear(); + } + return false; + + case kBadRecord: + if (in_fragmented_record) { + ReportCorruption(scratch->size(), "error in middle of record"); + in_fragmented_record = false; + scratch->clear(); + } + break; + + default: { + char buf[40]; + snprintf(buf, sizeof(buf), "unknown record type %u", record_type); + ReportCorruption( + (fragment.size() + (in_fragmented_record ? scratch->size() : 0)), + buf); + in_fragmented_record = false; + scratch->clear(); + break; + } + } + } + return false; +} + +uint64_t Reader::LastRecordOffset() { + return last_record_offset_; +} + +void Reader::ReportCorruption(size_t bytes, const char* reason) { + ReportDrop(bytes, Status::Corruption(reason)); +} + +void Reader::ReportDrop(size_t bytes, const Status& reason) { + if (reporter_ != NULL && + end_of_buffer_offset_ - buffer_.size() - bytes >= initial_offset_) { + reporter_->Corruption(bytes, reason); + } +} + +unsigned int Reader::ReadPhysicalRecord(Slice* result) { + while (true) { + if (buffer_.size() < kHeaderSize) { + if (!eof_) { + // Last read was a full read, so this is a trailer to skip + buffer_.clear(); + Status status = file_->Read(kBlockSize, &buffer_, backing_store_); + end_of_buffer_offset_ += buffer_.size(); + if (!status.ok()) { + buffer_.clear(); + ReportDrop(kBlockSize, status); + eof_ = true; + return kEof; + } else if (buffer_.size() < kBlockSize) { + eof_ = true; + } + continue; + } else { + // Note that if buffer_ is non-empty, we have a truncated header at the + // end of the file, which can be caused by the writer crashing in the + // middle of writing the header. Instead of considering this an error, + // just report EOF. + buffer_.clear(); + return kEof; + } + } + + // Parse the header + const char* header = buffer_.data(); + const uint32_t a = static_cast(header[4]) & 0xff; + const uint32_t b = static_cast(header[5]) & 0xff; + const unsigned int type = header[6]; + const uint32_t length = a | (b << 8); + if (kHeaderSize + length > buffer_.size()) { + size_t drop_size = buffer_.size(); + buffer_.clear(); + if (!eof_) { + ReportCorruption(drop_size, "bad record length"); + return kBadRecord; + } + // If the end of the file has been reached without reading |length| bytes + // of payload, assume the writer died in the middle of writing the record. + // Don't report a corruption. + return kEof; + } + + if (type == kZeroType && length == 0) { + // Skip zero length record without reporting any drops since + // such records are produced by the mmap based writing code in + // env_posix.cc that preallocates file regions. + buffer_.clear(); + return kBadRecord; + } + + // Check crc + if (checksum_) { + uint32_t expected_crc = crc32c::Unmask(DecodeFixed32(header)); + uint32_t actual_crc = crc32c::Value(header + 6, 1 + length); + if (actual_crc != expected_crc) { + // Drop the rest of the buffer since "length" itself may have + // been corrupted and if we trust it, we could find some + // fragment of a real log record that just happens to look + // like a valid log record. + size_t drop_size = buffer_.size(); + buffer_.clear(); + ReportCorruption(drop_size, "checksum mismatch"); + return kBadRecord; + } + } + + buffer_.remove_prefix(kHeaderSize + length); + + // Skip physical record that started before initial_offset_ + if (end_of_buffer_offset_ - buffer_.size() - kHeaderSize - length < + initial_offset_) { + result->clear(); + return kBadRecord; + } + + *result = Slice(header + kHeaderSize, length); + return type; + } +} + +} // namespace log +} // namespace leveldb diff --git a/src/leveldb/db/log_reader.h b/src/leveldb/db/log_reader.h new file mode 100644 index 0000000..82d4bee --- /dev/null +++ b/src/leveldb/db/log_reader.h @@ -0,0 +1,108 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#ifndef STORAGE_LEVELDB_DB_LOG_READER_H_ +#define STORAGE_LEVELDB_DB_LOG_READER_H_ + +#include + +#include "db/log_format.h" +#include "leveldb/slice.h" +#include "leveldb/status.h" + +namespace leveldb { + +class SequentialFile; + +namespace log { + +class Reader { + public: + // Interface for reporting errors. + class Reporter { + public: + virtual ~Reporter(); + + // Some corruption was detected. "size" is the approximate number + // of bytes dropped due to the corruption. + virtual void Corruption(size_t bytes, const Status& status) = 0; + }; + + // Create a reader that will return log records from "*file". + // "*file" must remain live while this Reader is in use. + // + // If "reporter" is non-NULL, it is notified whenever some data is + // dropped due to a detected corruption. "*reporter" must remain + // live while this Reader is in use. + // + // If "checksum" is true, verify checksums if available. + // + // The Reader will start reading at the first record located at physical + // position >= initial_offset within the file. + Reader(SequentialFile* file, Reporter* reporter, bool checksum, + uint64_t initial_offset); + + ~Reader(); + + // Read the next record into *record. Returns true if read + // successfully, false if we hit end of the input. May use + // "*scratch" as temporary storage. The contents filled in *record + // will only be valid until the next mutating operation on this + // reader or the next mutation to *scratch. + bool ReadRecord(Slice* record, std::string* scratch); + + // Returns the physical offset of the last record returned by ReadRecord. + // + // Undefined before the first call to ReadRecord. + uint64_t LastRecordOffset(); + + private: + SequentialFile* const file_; + Reporter* const reporter_; + bool const checksum_; + char* const backing_store_; + Slice buffer_; + bool eof_; // Last Read() indicated EOF by returning < kBlockSize + + // Offset of the last record returned by ReadRecord. + uint64_t last_record_offset_; + // Offset of the first location past the end of buffer_. + uint64_t end_of_buffer_offset_; + + // Offset at which to start looking for the first record to return + uint64_t const initial_offset_; + + // Extend record types with the following special values + enum { + kEof = kMaxRecordType + 1, + // Returned whenever we find an invalid physical record. + // Currently there are three situations in which this happens: + // * The record has an invalid CRC (ReadPhysicalRecord reports a drop) + // * The record is a 0-length record (No drop is reported) + // * The record is below constructor's initial_offset (No drop is reported) + kBadRecord = kMaxRecordType + 2 + }; + + // Skips all blocks that are completely before "initial_offset_". + // + // Returns true on success. Handles reporting. + bool SkipToInitialBlock(); + + // Return type, or one of the preceding special values + unsigned int ReadPhysicalRecord(Slice* result); + + // Reports dropped bytes to the reporter. + // buffer_ must be updated to remove the dropped bytes prior to invocation. + void ReportCorruption(size_t bytes, const char* reason); + void ReportDrop(size_t bytes, const Status& reason); + + // No copying allowed + Reader(const Reader&); + void operator=(const Reader&); +}; + +} // namespace log +} // namespace leveldb + +#endif // STORAGE_LEVELDB_DB_LOG_READER_H_ diff --git a/src/leveldb/db/log_test.cc b/src/leveldb/db/log_test.cc new file mode 100644 index 0000000..91d3caa --- /dev/null +++ b/src/leveldb/db/log_test.cc @@ -0,0 +1,530 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "db/log_reader.h" +#include "db/log_writer.h" +#include "leveldb/env.h" +#include "util/coding.h" +#include "util/crc32c.h" +#include "util/random.h" +#include "util/testharness.h" + +namespace leveldb { +namespace log { + +// Construct a string of the specified length made out of the supplied +// partial string. +static std::string BigString(const std::string& partial_string, size_t n) { + std::string result; + while (result.size() < n) { + result.append(partial_string); + } + result.resize(n); + return result; +} + +// Construct a string from a number +static std::string NumberString(int n) { + char buf[50]; + snprintf(buf, sizeof(buf), "%d.", n); + return std::string(buf); +} + +// Return a skewed potentially long string +static std::string RandomSkewedString(int i, Random* rnd) { + return BigString(NumberString(i), rnd->Skewed(17)); +} + +class LogTest { + private: + class StringDest : public WritableFile { + public: + std::string contents_; + + virtual Status Close() { return Status::OK(); } + virtual Status Flush() { return Status::OK(); } + virtual Status Sync() { return Status::OK(); } + virtual Status Append(const Slice& slice) { + contents_.append(slice.data(), slice.size()); + return Status::OK(); + } + }; + + class StringSource : public SequentialFile { + public: + Slice contents_; + bool force_error_; + bool returned_partial_; + StringSource() : force_error_(false), returned_partial_(false) { } + + virtual Status Read(size_t n, Slice* result, char* scratch) { + ASSERT_TRUE(!returned_partial_) << "must not Read() after eof/error"; + + if (force_error_) { + force_error_ = false; + returned_partial_ = true; + return Status::Corruption("read error"); + } + + if (contents_.size() < n) { + n = contents_.size(); + returned_partial_ = true; + } + *result = Slice(contents_.data(), n); + contents_.remove_prefix(n); + return Status::OK(); + } + + virtual Status Skip(uint64_t n) { + if (n > contents_.size()) { + contents_.clear(); + return Status::NotFound("in-memory file skipepd past end"); + } + + contents_.remove_prefix(n); + + return Status::OK(); + } + }; + + class ReportCollector : public Reader::Reporter { + public: + size_t dropped_bytes_; + std::string message_; + + ReportCollector() : dropped_bytes_(0) { } + virtual void Corruption(size_t bytes, const Status& status) { + dropped_bytes_ += bytes; + message_.append(status.ToString()); + } + }; + + StringDest dest_; + StringSource source_; + ReportCollector report_; + bool reading_; + Writer writer_; + Reader reader_; + + // Record metadata for testing initial offset functionality + static size_t initial_offset_record_sizes_[]; + static uint64_t initial_offset_last_record_offsets_[]; + + public: + LogTest() : reading_(false), + writer_(&dest_), + reader_(&source_, &report_, true/*checksum*/, + 0/*initial_offset*/) { + } + + void Write(const std::string& msg) { + ASSERT_TRUE(!reading_) << "Write() after starting to read"; + writer_.AddRecord(Slice(msg)); + } + + size_t WrittenBytes() const { + return dest_.contents_.size(); + } + + std::string Read() { + if (!reading_) { + reading_ = true; + source_.contents_ = Slice(dest_.contents_); + } + std::string scratch; + Slice record; + if (reader_.ReadRecord(&record, &scratch)) { + return record.ToString(); + } else { + return "EOF"; + } + } + + void IncrementByte(int offset, int delta) { + dest_.contents_[offset] += delta; + } + + void SetByte(int offset, char new_byte) { + dest_.contents_[offset] = new_byte; + } + + void ShrinkSize(int bytes) { + dest_.contents_.resize(dest_.contents_.size() - bytes); + } + + void FixChecksum(int header_offset, int len) { + // Compute crc of type/len/data + uint32_t crc = crc32c::Value(&dest_.contents_[header_offset+6], 1 + len); + crc = crc32c::Mask(crc); + EncodeFixed32(&dest_.contents_[header_offset], crc); + } + + void ForceError() { + source_.force_error_ = true; + } + + size_t DroppedBytes() const { + return report_.dropped_bytes_; + } + + std::string ReportMessage() const { + return report_.message_; + } + + // Returns OK iff recorded error message contains "msg" + std::string MatchError(const std::string& msg) const { + if (report_.message_.find(msg) == std::string::npos) { + return report_.message_; + } else { + return "OK"; + } + } + + void WriteInitialOffsetLog() { + for (int i = 0; i < 4; i++) { + std::string record(initial_offset_record_sizes_[i], + static_cast('a' + i)); + Write(record); + } + } + + void CheckOffsetPastEndReturnsNoRecords(uint64_t offset_past_end) { + WriteInitialOffsetLog(); + reading_ = true; + source_.contents_ = Slice(dest_.contents_); + Reader* offset_reader = new Reader(&source_, &report_, true/*checksum*/, + WrittenBytes() + offset_past_end); + Slice record; + std::string scratch; + ASSERT_TRUE(!offset_reader->ReadRecord(&record, &scratch)); + delete offset_reader; + } + + void CheckInitialOffsetRecord(uint64_t initial_offset, + int expected_record_offset) { + WriteInitialOffsetLog(); + reading_ = true; + source_.contents_ = Slice(dest_.contents_); + Reader* offset_reader = new Reader(&source_, &report_, true/*checksum*/, + initial_offset); + Slice record; + std::string scratch; + ASSERT_TRUE(offset_reader->ReadRecord(&record, &scratch)); + ASSERT_EQ(initial_offset_record_sizes_[expected_record_offset], + record.size()); + ASSERT_EQ(initial_offset_last_record_offsets_[expected_record_offset], + offset_reader->LastRecordOffset()); + ASSERT_EQ((char)('a' + expected_record_offset), record.data()[0]); + delete offset_reader; + } + +}; + +size_t LogTest::initial_offset_record_sizes_[] = + {10000, // Two sizable records in first block + 10000, + 2 * log::kBlockSize - 1000, // Span three blocks + 1}; + +uint64_t LogTest::initial_offset_last_record_offsets_[] = + {0, + kHeaderSize + 10000, + 2 * (kHeaderSize + 10000), + 2 * (kHeaderSize + 10000) + + (2 * log::kBlockSize - 1000) + 3 * kHeaderSize}; + + +TEST(LogTest, Empty) { + ASSERT_EQ("EOF", Read()); +} + +TEST(LogTest, ReadWrite) { + Write("foo"); + Write("bar"); + Write(""); + Write("xxxx"); + ASSERT_EQ("foo", Read()); + ASSERT_EQ("bar", Read()); + ASSERT_EQ("", Read()); + ASSERT_EQ("xxxx", Read()); + ASSERT_EQ("EOF", Read()); + ASSERT_EQ("EOF", Read()); // Make sure reads at eof work +} + +TEST(LogTest, ManyBlocks) { + for (int i = 0; i < 100000; i++) { + Write(NumberString(i)); + } + for (int i = 0; i < 100000; i++) { + ASSERT_EQ(NumberString(i), Read()); + } + ASSERT_EQ("EOF", Read()); +} + +TEST(LogTest, Fragmentation) { + Write("small"); + Write(BigString("medium", 50000)); + Write(BigString("large", 100000)); + ASSERT_EQ("small", Read()); + ASSERT_EQ(BigString("medium", 50000), Read()); + ASSERT_EQ(BigString("large", 100000), Read()); + ASSERT_EQ("EOF", Read()); +} + +TEST(LogTest, MarginalTrailer) { + // Make a trailer that is exactly the same length as an empty record. + const int n = kBlockSize - 2*kHeaderSize; + Write(BigString("foo", n)); + ASSERT_EQ(kBlockSize - kHeaderSize, WrittenBytes()); + Write(""); + Write("bar"); + ASSERT_EQ(BigString("foo", n), Read()); + ASSERT_EQ("", Read()); + ASSERT_EQ("bar", Read()); + ASSERT_EQ("EOF", Read()); +} + +TEST(LogTest, MarginalTrailer2) { + // Make a trailer that is exactly the same length as an empty record. + const int n = kBlockSize - 2*kHeaderSize; + Write(BigString("foo", n)); + ASSERT_EQ(kBlockSize - kHeaderSize, WrittenBytes()); + Write("bar"); + ASSERT_EQ(BigString("foo", n), Read()); + ASSERT_EQ("bar", Read()); + ASSERT_EQ("EOF", Read()); + ASSERT_EQ(0, DroppedBytes()); + ASSERT_EQ("", ReportMessage()); +} + +TEST(LogTest, ShortTrailer) { + const int n = kBlockSize - 2*kHeaderSize + 4; + Write(BigString("foo", n)); + ASSERT_EQ(kBlockSize - kHeaderSize + 4, WrittenBytes()); + Write(""); + Write("bar"); + ASSERT_EQ(BigString("foo", n), Read()); + ASSERT_EQ("", Read()); + ASSERT_EQ("bar", Read()); + ASSERT_EQ("EOF", Read()); +} + +TEST(LogTest, AlignedEof) { + const int n = kBlockSize - 2*kHeaderSize + 4; + Write(BigString("foo", n)); + ASSERT_EQ(kBlockSize - kHeaderSize + 4, WrittenBytes()); + ASSERT_EQ(BigString("foo", n), Read()); + ASSERT_EQ("EOF", Read()); +} + +TEST(LogTest, RandomRead) { + const int N = 500; + Random write_rnd(301); + for (int i = 0; i < N; i++) { + Write(RandomSkewedString(i, &write_rnd)); + } + Random read_rnd(301); + for (int i = 0; i < N; i++) { + ASSERT_EQ(RandomSkewedString(i, &read_rnd), Read()); + } + ASSERT_EQ("EOF", Read()); +} + +// Tests of all the error paths in log_reader.cc follow: + +TEST(LogTest, ReadError) { + Write("foo"); + ForceError(); + ASSERT_EQ("EOF", Read()); + ASSERT_EQ(kBlockSize, DroppedBytes()); + ASSERT_EQ("OK", MatchError("read error")); +} + +TEST(LogTest, BadRecordType) { + Write("foo"); + // Type is stored in header[6] + IncrementByte(6, 100); + FixChecksum(0, 3); + ASSERT_EQ("EOF", Read()); + ASSERT_EQ(3, DroppedBytes()); + ASSERT_EQ("OK", MatchError("unknown record type")); +} + +TEST(LogTest, TruncatedTrailingRecordIsIgnored) { + Write("foo"); + ShrinkSize(4); // Drop all payload as well as a header byte + ASSERT_EQ("EOF", Read()); + // Truncated last record is ignored, not treated as an error. + ASSERT_EQ(0, DroppedBytes()); + ASSERT_EQ("", ReportMessage()); +} + +TEST(LogTest, BadLength) { + const int kPayloadSize = kBlockSize - kHeaderSize; + Write(BigString("bar", kPayloadSize)); + Write("foo"); + // Least significant size byte is stored in header[4]. + IncrementByte(4, 1); + ASSERT_EQ("foo", Read()); + ASSERT_EQ(kBlockSize, DroppedBytes()); + ASSERT_EQ("OK", MatchError("bad record length")); +} + +TEST(LogTest, BadLengthAtEndIsIgnored) { + Write("foo"); + ShrinkSize(1); + ASSERT_EQ("EOF", Read()); + ASSERT_EQ(0, DroppedBytes()); + ASSERT_EQ("", ReportMessage()); +} + +TEST(LogTest, ChecksumMismatch) { + Write("foo"); + IncrementByte(0, 10); + ASSERT_EQ("EOF", Read()); + ASSERT_EQ(10, DroppedBytes()); + ASSERT_EQ("OK", MatchError("checksum mismatch")); +} + +TEST(LogTest, UnexpectedMiddleType) { + Write("foo"); + SetByte(6, kMiddleType); + FixChecksum(0, 3); + ASSERT_EQ("EOF", Read()); + ASSERT_EQ(3, DroppedBytes()); + ASSERT_EQ("OK", MatchError("missing start")); +} + +TEST(LogTest, UnexpectedLastType) { + Write("foo"); + SetByte(6, kLastType); + FixChecksum(0, 3); + ASSERT_EQ("EOF", Read()); + ASSERT_EQ(3, DroppedBytes()); + ASSERT_EQ("OK", MatchError("missing start")); +} + +TEST(LogTest, UnexpectedFullType) { + Write("foo"); + Write("bar"); + SetByte(6, kFirstType); + FixChecksum(0, 3); + ASSERT_EQ("bar", Read()); + ASSERT_EQ("EOF", Read()); + ASSERT_EQ(3, DroppedBytes()); + ASSERT_EQ("OK", MatchError("partial record without end")); +} + +TEST(LogTest, UnexpectedFirstType) { + Write("foo"); + Write(BigString("bar", 100000)); + SetByte(6, kFirstType); + FixChecksum(0, 3); + ASSERT_EQ(BigString("bar", 100000), Read()); + ASSERT_EQ("EOF", Read()); + ASSERT_EQ(3, DroppedBytes()); + ASSERT_EQ("OK", MatchError("partial record without end")); +} + +TEST(LogTest, MissingLastIsIgnored) { + Write(BigString("bar", kBlockSize)); + // Remove the LAST block, including header. + ShrinkSize(14); + ASSERT_EQ("EOF", Read()); + ASSERT_EQ("", ReportMessage()); + ASSERT_EQ(0, DroppedBytes()); +} + +TEST(LogTest, PartialLastIsIgnored) { + Write(BigString("bar", kBlockSize)); + // Cause a bad record length in the LAST block. + ShrinkSize(1); + ASSERT_EQ("EOF", Read()); + ASSERT_EQ("", ReportMessage()); + ASSERT_EQ(0, DroppedBytes()); +} + +TEST(LogTest, ErrorJoinsRecords) { + // Consider two fragmented records: + // first(R1) last(R1) first(R2) last(R2) + // where the middle two fragments disappear. We do not want + // first(R1),last(R2) to get joined and returned as a valid record. + + // Write records that span two blocks + Write(BigString("foo", kBlockSize)); + Write(BigString("bar", kBlockSize)); + Write("correct"); + + // Wipe the middle block + for (int offset = kBlockSize; offset < 2*kBlockSize; offset++) { + SetByte(offset, 'x'); + } + + ASSERT_EQ("correct", Read()); + ASSERT_EQ("EOF", Read()); + const int dropped = DroppedBytes(); + ASSERT_LE(dropped, 2*kBlockSize + 100); + ASSERT_GE(dropped, 2*kBlockSize); +} + +TEST(LogTest, ReadStart) { + CheckInitialOffsetRecord(0, 0); +} + +TEST(LogTest, ReadSecondOneOff) { + CheckInitialOffsetRecord(1, 1); +} + +TEST(LogTest, ReadSecondTenThousand) { + CheckInitialOffsetRecord(10000, 1); +} + +TEST(LogTest, ReadSecondStart) { + CheckInitialOffsetRecord(10007, 1); +} + +TEST(LogTest, ReadThirdOneOff) { + CheckInitialOffsetRecord(10008, 2); +} + +TEST(LogTest, ReadThirdStart) { + CheckInitialOffsetRecord(20014, 2); +} + +TEST(LogTest, ReadFourthOneOff) { + CheckInitialOffsetRecord(20015, 3); +} + +TEST(LogTest, ReadFourthFirstBlockTrailer) { + CheckInitialOffsetRecord(log::kBlockSize - 4, 3); +} + +TEST(LogTest, ReadFourthMiddleBlock) { + CheckInitialOffsetRecord(log::kBlockSize + 1, 3); +} + +TEST(LogTest, ReadFourthLastBlock) { + CheckInitialOffsetRecord(2 * log::kBlockSize + 1, 3); +} + +TEST(LogTest, ReadFourthStart) { + CheckInitialOffsetRecord( + 2 * (kHeaderSize + 1000) + (2 * log::kBlockSize - 1000) + 3 * kHeaderSize, + 3); +} + +TEST(LogTest, ReadEnd) { + CheckOffsetPastEndReturnsNoRecords(0); +} + +TEST(LogTest, ReadPastEnd) { + CheckOffsetPastEndReturnsNoRecords(5); +} + +} // namespace log +} // namespace leveldb + +int main(int argc, char** argv) { + return leveldb::test::RunAllTests(); +} diff --git a/src/leveldb/db/log_writer.cc b/src/leveldb/db/log_writer.cc new file mode 100644 index 0000000..2da99ac --- /dev/null +++ b/src/leveldb/db/log_writer.cc @@ -0,0 +1,103 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "db/log_writer.h" + +#include +#include "leveldb/env.h" +#include "util/coding.h" +#include "util/crc32c.h" + +namespace leveldb { +namespace log { + +Writer::Writer(WritableFile* dest) + : dest_(dest), + block_offset_(0) { + for (int i = 0; i <= kMaxRecordType; i++) { + char t = static_cast(i); + type_crc_[i] = crc32c::Value(&t, 1); + } +} + +Writer::~Writer() { +} + +Status Writer::AddRecord(const Slice& slice) { + const char* ptr = slice.data(); + size_t left = slice.size(); + + // Fragment the record if necessary and emit it. Note that if slice + // is empty, we still want to iterate once to emit a single + // zero-length record + Status s; + bool begin = true; + do { + const int leftover = kBlockSize - block_offset_; + assert(leftover >= 0); + if (leftover < kHeaderSize) { + // Switch to a new block + if (leftover > 0) { + // Fill the trailer (literal below relies on kHeaderSize being 7) + assert(kHeaderSize == 7); + dest_->Append(Slice("\x00\x00\x00\x00\x00\x00", leftover)); + } + block_offset_ = 0; + } + + // Invariant: we never leave < kHeaderSize bytes in a block. + assert(kBlockSize - block_offset_ - kHeaderSize >= 0); + + const size_t avail = kBlockSize - block_offset_ - kHeaderSize; + const size_t fragment_length = (left < avail) ? left : avail; + + RecordType type; + const bool end = (left == fragment_length); + if (begin && end) { + type = kFullType; + } else if (begin) { + type = kFirstType; + } else if (end) { + type = kLastType; + } else { + type = kMiddleType; + } + + s = EmitPhysicalRecord(type, ptr, fragment_length); + ptr += fragment_length; + left -= fragment_length; + begin = false; + } while (s.ok() && left > 0); + return s; +} + +Status Writer::EmitPhysicalRecord(RecordType t, const char* ptr, size_t n) { + assert(n <= 0xffff); // Must fit in two bytes + assert(block_offset_ + kHeaderSize + n <= kBlockSize); + + // Format the header + char buf[kHeaderSize]; + buf[4] = static_cast(n & 0xff); + buf[5] = static_cast(n >> 8); + buf[6] = static_cast(t); + + // Compute the crc of the record type and the payload. + uint32_t crc = crc32c::Extend(type_crc_[t], ptr, n); + crc = crc32c::Mask(crc); // Adjust for storage + EncodeFixed32(buf, crc); + + // Write the header and the payload + Status s = dest_->Append(Slice(buf, kHeaderSize)); + if (s.ok()) { + s = dest_->Append(Slice(ptr, n)); + if (s.ok()) { + s = dest_->Flush(); + } + } + block_offset_ += kHeaderSize + n; + return s; +} + +} // namespace log +} // namespace leveldb diff --git a/src/leveldb/db/log_writer.h b/src/leveldb/db/log_writer.h new file mode 100644 index 0000000..a3a954d --- /dev/null +++ b/src/leveldb/db/log_writer.h @@ -0,0 +1,48 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#ifndef STORAGE_LEVELDB_DB_LOG_WRITER_H_ +#define STORAGE_LEVELDB_DB_LOG_WRITER_H_ + +#include +#include "db/log_format.h" +#include "leveldb/slice.h" +#include "leveldb/status.h" + +namespace leveldb { + +class WritableFile; + +namespace log { + +class Writer { + public: + // Create a writer that will append data to "*dest". + // "*dest" must be initially empty. + // "*dest" must remain live while this Writer is in use. + explicit Writer(WritableFile* dest); + ~Writer(); + + Status AddRecord(const Slice& slice); + + private: + WritableFile* dest_; + int block_offset_; // Current offset in block + + // crc32c values for all supported record types. These are + // pre-computed to reduce the overhead of computing the crc of the + // record type stored in the header. + uint32_t type_crc_[kMaxRecordType + 1]; + + Status EmitPhysicalRecord(RecordType type, const char* ptr, size_t length); + + // No copying allowed + Writer(const Writer&); + void operator=(const Writer&); +}; + +} // namespace log +} // namespace leveldb + +#endif // STORAGE_LEVELDB_DB_LOG_WRITER_H_ diff --git a/src/leveldb/db/memtable.cc b/src/leveldb/db/memtable.cc new file mode 100644 index 0000000..bfec0a7 --- /dev/null +++ b/src/leveldb/db/memtable.cc @@ -0,0 +1,145 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "db/memtable.h" +#include "db/dbformat.h" +#include "leveldb/comparator.h" +#include "leveldb/env.h" +#include "leveldb/iterator.h" +#include "util/coding.h" + +namespace leveldb { + +static Slice GetLengthPrefixedSlice(const char* data) { + uint32_t len; + const char* p = data; + p = GetVarint32Ptr(p, p + 5, &len); // +5: we assume "p" is not corrupted + return Slice(p, len); +} + +MemTable::MemTable(const InternalKeyComparator& cmp) + : comparator_(cmp), + refs_(0), + table_(comparator_, &arena_) { +} + +MemTable::~MemTable() { + assert(refs_ == 0); +} + +size_t MemTable::ApproximateMemoryUsage() { return arena_.MemoryUsage(); } + +int MemTable::KeyComparator::operator()(const char* aptr, const char* bptr) + const { + // Internal keys are encoded as length-prefixed strings. + Slice a = GetLengthPrefixedSlice(aptr); + Slice b = GetLengthPrefixedSlice(bptr); + return comparator.Compare(a, b); +} + +// Encode a suitable internal key target for "target" and return it. +// Uses *scratch as scratch space, and the returned pointer will point +// into this scratch space. +static const char* EncodeKey(std::string* scratch, const Slice& target) { + scratch->clear(); + PutVarint32(scratch, target.size()); + scratch->append(target.data(), target.size()); + return scratch->data(); +} + +class MemTableIterator: public Iterator { + public: + explicit MemTableIterator(MemTable::Table* table) : iter_(table) { } + + virtual bool Valid() const { return iter_.Valid(); } + virtual void Seek(const Slice& k) { iter_.Seek(EncodeKey(&tmp_, k)); } + virtual void SeekToFirst() { iter_.SeekToFirst(); } + virtual void SeekToLast() { iter_.SeekToLast(); } + virtual void Next() { iter_.Next(); } + virtual void Prev() { iter_.Prev(); } + virtual Slice key() const { return GetLengthPrefixedSlice(iter_.key()); } + virtual Slice value() const { + Slice key_slice = GetLengthPrefixedSlice(iter_.key()); + return GetLengthPrefixedSlice(key_slice.data() + key_slice.size()); + } + + virtual Status status() const { return Status::OK(); } + + private: + MemTable::Table::Iterator iter_; + std::string tmp_; // For passing to EncodeKey + + // No copying allowed + MemTableIterator(const MemTableIterator&); + void operator=(const MemTableIterator&); +}; + +Iterator* MemTable::NewIterator() { + return new MemTableIterator(&table_); +} + +void MemTable::Add(SequenceNumber s, ValueType type, + const Slice& key, + const Slice& value) { + // Format of an entry is concatenation of: + // key_size : varint32 of internal_key.size() + // key bytes : char[internal_key.size()] + // value_size : varint32 of value.size() + // value bytes : char[value.size()] + size_t key_size = key.size(); + size_t val_size = value.size(); + size_t internal_key_size = key_size + 8; + const size_t encoded_len = + VarintLength(internal_key_size) + internal_key_size + + VarintLength(val_size) + val_size; + char* buf = arena_.Allocate(encoded_len); + char* p = EncodeVarint32(buf, internal_key_size); + memcpy(p, key.data(), key_size); + p += key_size; + EncodeFixed64(p, (s << 8) | type); + p += 8; + p = EncodeVarint32(p, val_size); + memcpy(p, value.data(), val_size); + assert((p + val_size) - buf == encoded_len); + table_.Insert(buf); +} + +bool MemTable::Get(const LookupKey& key, std::string* value, Status* s) { + Slice memkey = key.memtable_key(); + Table::Iterator iter(&table_); + iter.Seek(memkey.data()); + if (iter.Valid()) { + // entry format is: + // klength varint32 + // userkey char[klength] + // tag uint64 + // vlength varint32 + // value char[vlength] + // Check that it belongs to same user key. We do not check the + // sequence number since the Seek() call above should have skipped + // all entries with overly large sequence numbers. + const char* entry = iter.key(); + uint32_t key_length; + const char* key_ptr = GetVarint32Ptr(entry, entry+5, &key_length); + if (comparator_.comparator.user_comparator()->Compare( + Slice(key_ptr, key_length - 8), + key.user_key()) == 0) { + // Correct user key + const uint64_t tag = DecodeFixed64(key_ptr + key_length - 8); + switch (static_cast(tag & 0xff)) { + case kTypeValue: { + Slice v = GetLengthPrefixedSlice(key_ptr + key_length); + value->assign(v.data(), v.size()); + return true; + } + case kTypeDeletion: + *s = Status::NotFound(Slice()); + return true; + } + } + } + return false; +} + +} // namespace leveldb diff --git a/src/leveldb/db/memtable.h b/src/leveldb/db/memtable.h new file mode 100644 index 0000000..92e90bb --- /dev/null +++ b/src/leveldb/db/memtable.h @@ -0,0 +1,91 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#ifndef STORAGE_LEVELDB_DB_MEMTABLE_H_ +#define STORAGE_LEVELDB_DB_MEMTABLE_H_ + +#include +#include "leveldb/db.h" +#include "db/dbformat.h" +#include "db/skiplist.h" +#include "util/arena.h" + +namespace leveldb { + +class InternalKeyComparator; +class Mutex; +class MemTableIterator; + +class MemTable { + public: + // MemTables are reference counted. The initial reference count + // is zero and the caller must call Ref() at least once. + explicit MemTable(const InternalKeyComparator& comparator); + + // Increase reference count. + void Ref() { ++refs_; } + + // Drop reference count. Delete if no more references exist. + void Unref() { + --refs_; + assert(refs_ >= 0); + if (refs_ <= 0) { + delete this; + } + } + + // Returns an estimate of the number of bytes of data in use by this + // data structure. + // + // REQUIRES: external synchronization to prevent simultaneous + // operations on the same MemTable. + size_t ApproximateMemoryUsage(); + + // Return an iterator that yields the contents of the memtable. + // + // The caller must ensure that the underlying MemTable remains live + // while the returned iterator is live. The keys returned by this + // iterator are internal keys encoded by AppendInternalKey in the + // db/format.{h,cc} module. + Iterator* NewIterator(); + + // Add an entry into memtable that maps key to value at the + // specified sequence number and with the specified type. + // Typically value will be empty if type==kTypeDeletion. + void Add(SequenceNumber seq, ValueType type, + const Slice& key, + const Slice& value); + + // If memtable contains a value for key, store it in *value and return true. + // If memtable contains a deletion for key, store a NotFound() error + // in *status and return true. + // Else, return false. + bool Get(const LookupKey& key, std::string* value, Status* s); + + private: + ~MemTable(); // Private since only Unref() should be used to delete it + + struct KeyComparator { + const InternalKeyComparator comparator; + explicit KeyComparator(const InternalKeyComparator& c) : comparator(c) { } + int operator()(const char* a, const char* b) const; + }; + friend class MemTableIterator; + friend class MemTableBackwardIterator; + + typedef SkipList Table; + + KeyComparator comparator_; + int refs_; + Arena arena_; + Table table_; + + // No copying allowed + MemTable(const MemTable&); + void operator=(const MemTable&); +}; + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_DB_MEMTABLE_H_ diff --git a/src/leveldb/db/repair.cc b/src/leveldb/db/repair.cc new file mode 100644 index 0000000..7727faf --- /dev/null +++ b/src/leveldb/db/repair.cc @@ -0,0 +1,461 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. +// +// We recover the contents of the descriptor from the other files we find. +// (1) Any log files are first converted to tables +// (2) We scan every table to compute +// (a) smallest/largest for the table +// (b) largest sequence number in the table +// (3) We generate descriptor contents: +// - log number is set to zero +// - next-file-number is set to 1 + largest file number we found +// - last-sequence-number is set to largest sequence# found across +// all tables (see 2c) +// - compaction pointers are cleared +// - every table file is added at level 0 +// +// Possible optimization 1: +// (a) Compute total size and use to pick appropriate max-level M +// (b) Sort tables by largest sequence# in the table +// (c) For each table: if it overlaps earlier table, place in level-0, +// else place in level-M. +// Possible optimization 2: +// Store per-table metadata (smallest, largest, largest-seq#, ...) +// in the table's meta section to speed up ScanTable. + +#include "db/builder.h" +#include "db/db_impl.h" +#include "db/dbformat.h" +#include "db/filename.h" +#include "db/log_reader.h" +#include "db/log_writer.h" +#include "db/memtable.h" +#include "db/table_cache.h" +#include "db/version_edit.h" +#include "db/write_batch_internal.h" +#include "leveldb/comparator.h" +#include "leveldb/db.h" +#include "leveldb/env.h" + +namespace leveldb { + +namespace { + +class Repairer { + public: + Repairer(const std::string& dbname, const Options& options) + : dbname_(dbname), + env_(options.env), + icmp_(options.comparator), + ipolicy_(options.filter_policy), + options_(SanitizeOptions(dbname, &icmp_, &ipolicy_, options)), + owns_info_log_(options_.info_log != options.info_log), + owns_cache_(options_.block_cache != options.block_cache), + next_file_number_(1) { + // TableCache can be small since we expect each table to be opened once. + table_cache_ = new TableCache(dbname_, &options_, 10); + } + + ~Repairer() { + delete table_cache_; + if (owns_info_log_) { + delete options_.info_log; + } + if (owns_cache_) { + delete options_.block_cache; + } + } + + Status Run() { + Status status = FindFiles(); + if (status.ok()) { + ConvertLogFilesToTables(); + ExtractMetaData(); + status = WriteDescriptor(); + } + if (status.ok()) { + unsigned long long bytes = 0; + for (size_t i = 0; i < tables_.size(); i++) { + bytes += tables_[i].meta.file_size; + } + Log(options_.info_log, + "**** Repaired leveldb %s; " + "recovered %d files; %llu bytes. " + "Some data may have been lost. " + "****", + dbname_.c_str(), + static_cast(tables_.size()), + bytes); + } + return status; + } + + private: + struct TableInfo { + FileMetaData meta; + SequenceNumber max_sequence; + }; + + std::string const dbname_; + Env* const env_; + InternalKeyComparator const icmp_; + InternalFilterPolicy const ipolicy_; + Options const options_; + bool owns_info_log_; + bool owns_cache_; + TableCache* table_cache_; + VersionEdit edit_; + + std::vector manifests_; + std::vector table_numbers_; + std::vector logs_; + std::vector tables_; + uint64_t next_file_number_; + + Status FindFiles() { + std::vector filenames; + Status status = env_->GetChildren(dbname_, &filenames); + if (!status.ok()) { + return status; + } + if (filenames.empty()) { + return Status::IOError(dbname_, "repair found no files"); + } + + uint64_t number; + FileType type; + for (size_t i = 0; i < filenames.size(); i++) { + if (ParseFileName(filenames[i], &number, &type)) { + if (type == kDescriptorFile) { + manifests_.push_back(filenames[i]); + } else { + if (number + 1 > next_file_number_) { + next_file_number_ = number + 1; + } + if (type == kLogFile) { + logs_.push_back(number); + } else if (type == kTableFile) { + table_numbers_.push_back(number); + } else { + // Ignore other files + } + } + } + } + return status; + } + + void ConvertLogFilesToTables() { + for (size_t i = 0; i < logs_.size(); i++) { + std::string logname = LogFileName(dbname_, logs_[i]); + Status status = ConvertLogToTable(logs_[i]); + if (!status.ok()) { + Log(options_.info_log, "Log #%llu: ignoring conversion error: %s", + (unsigned long long) logs_[i], + status.ToString().c_str()); + } + ArchiveFile(logname); + } + } + + Status ConvertLogToTable(uint64_t log) { + struct LogReporter : public log::Reader::Reporter { + Env* env; + Logger* info_log; + uint64_t lognum; + virtual void Corruption(size_t bytes, const Status& s) { + // We print error messages for corruption, but continue repairing. + Log(info_log, "Log #%llu: dropping %d bytes; %s", + (unsigned long long) lognum, + static_cast(bytes), + s.ToString().c_str()); + } + }; + + // Open the log file + std::string logname = LogFileName(dbname_, log); + SequentialFile* lfile; + Status status = env_->NewSequentialFile(logname, &lfile); + if (!status.ok()) { + return status; + } + + // Create the log reader. + LogReporter reporter; + reporter.env = env_; + reporter.info_log = options_.info_log; + reporter.lognum = log; + // We intentially make log::Reader do checksumming so that + // corruptions cause entire commits to be skipped instead of + // propagating bad information (like overly large sequence + // numbers). + log::Reader reader(lfile, &reporter, false/*do not checksum*/, + 0/*initial_offset*/); + + // Read all the records and add to a memtable + std::string scratch; + Slice record; + WriteBatch batch; + MemTable* mem = new MemTable(icmp_); + mem->Ref(); + int counter = 0; + while (reader.ReadRecord(&record, &scratch)) { + if (record.size() < 12) { + reporter.Corruption( + record.size(), Status::Corruption("log record too small")); + continue; + } + WriteBatchInternal::SetContents(&batch, record); + status = WriteBatchInternal::InsertInto(&batch, mem); + if (status.ok()) { + counter += WriteBatchInternal::Count(&batch); + } else { + Log(options_.info_log, "Log #%llu: ignoring %s", + (unsigned long long) log, + status.ToString().c_str()); + status = Status::OK(); // Keep going with rest of file + } + } + delete lfile; + + // Do not record a version edit for this conversion to a Table + // since ExtractMetaData() will also generate edits. + FileMetaData meta; + meta.number = next_file_number_++; + Iterator* iter = mem->NewIterator(); + status = BuildTable(dbname_, env_, options_, table_cache_, iter, &meta); + delete iter; + mem->Unref(); + mem = NULL; + if (status.ok()) { + if (meta.file_size > 0) { + table_numbers_.push_back(meta.number); + } + } + Log(options_.info_log, "Log #%llu: %d ops saved to Table #%llu %s", + (unsigned long long) log, + counter, + (unsigned long long) meta.number, + status.ToString().c_str()); + return status; + } + + void ExtractMetaData() { + for (size_t i = 0; i < table_numbers_.size(); i++) { + ScanTable(table_numbers_[i]); + } + } + + Iterator* NewTableIterator(const FileMetaData& meta) { + // Same as compaction iterators: if paranoid_checks are on, turn + // on checksum verification. + ReadOptions r; + r.verify_checksums = options_.paranoid_checks; + return table_cache_->NewIterator(r, meta.number, meta.file_size); + } + + void ScanTable(uint64_t number) { + TableInfo t; + t.meta.number = number; + std::string fname = TableFileName(dbname_, number); + Status status = env_->GetFileSize(fname, &t.meta.file_size); + if (!status.ok()) { + // Try alternate file name. + fname = SSTTableFileName(dbname_, number); + Status s2 = env_->GetFileSize(fname, &t.meta.file_size); + if (s2.ok()) { + status = Status::OK(); + } + } + if (!status.ok()) { + ArchiveFile(TableFileName(dbname_, number)); + ArchiveFile(SSTTableFileName(dbname_, number)); + Log(options_.info_log, "Table #%llu: dropped: %s", + (unsigned long long) t.meta.number, + status.ToString().c_str()); + return; + } + + // Extract metadata by scanning through table. + int counter = 0; + Iterator* iter = NewTableIterator(t.meta); + bool empty = true; + ParsedInternalKey parsed; + t.max_sequence = 0; + for (iter->SeekToFirst(); iter->Valid(); iter->Next()) { + Slice key = iter->key(); + if (!ParseInternalKey(key, &parsed)) { + Log(options_.info_log, "Table #%llu: unparsable key %s", + (unsigned long long) t.meta.number, + EscapeString(key).c_str()); + continue; + } + + counter++; + if (empty) { + empty = false; + t.meta.smallest.DecodeFrom(key); + } + t.meta.largest.DecodeFrom(key); + if (parsed.sequence > t.max_sequence) { + t.max_sequence = parsed.sequence; + } + } + if (!iter->status().ok()) { + status = iter->status(); + } + delete iter; + Log(options_.info_log, "Table #%llu: %d entries %s", + (unsigned long long) t.meta.number, + counter, + status.ToString().c_str()); + + if (status.ok()) { + tables_.push_back(t); + } else { + RepairTable(fname, t); // RepairTable archives input file. + } + } + + void RepairTable(const std::string& src, TableInfo t) { + // We will copy src contents to a new table and then rename the + // new table over the source. + + // Create builder. + std::string copy = TableFileName(dbname_, next_file_number_++); + WritableFile* file; + Status s = env_->NewWritableFile(copy, &file); + if (!s.ok()) { + return; + } + TableBuilder* builder = new TableBuilder(options_, file); + + // Copy data. + Iterator* iter = NewTableIterator(t.meta); + int counter = 0; + for (iter->SeekToFirst(); iter->Valid(); iter->Next()) { + builder->Add(iter->key(), iter->value()); + counter++; + } + delete iter; + + ArchiveFile(src); + if (counter == 0) { + builder->Abandon(); // Nothing to save + } else { + s = builder->Finish(); + if (s.ok()) { + t.meta.file_size = builder->FileSize(); + } + } + delete builder; + builder = NULL; + + if (s.ok()) { + s = file->Close(); + } + delete file; + file = NULL; + + if (counter > 0 && s.ok()) { + std::string orig = TableFileName(dbname_, t.meta.number); + s = env_->RenameFile(copy, orig); + if (s.ok()) { + Log(options_.info_log, "Table #%llu: %d entries repaired", + (unsigned long long) t.meta.number, counter); + tables_.push_back(t); + } + } + if (!s.ok()) { + env_->DeleteFile(copy); + } + } + + Status WriteDescriptor() { + std::string tmp = TempFileName(dbname_, 1); + WritableFile* file; + Status status = env_->NewWritableFile(tmp, &file); + if (!status.ok()) { + return status; + } + + SequenceNumber max_sequence = 0; + for (size_t i = 0; i < tables_.size(); i++) { + if (max_sequence < tables_[i].max_sequence) { + max_sequence = tables_[i].max_sequence; + } + } + + edit_.SetComparatorName(icmp_.user_comparator()->Name()); + edit_.SetLogNumber(0); + edit_.SetNextFile(next_file_number_); + edit_.SetLastSequence(max_sequence); + + for (size_t i = 0; i < tables_.size(); i++) { + // TODO(opt): separate out into multiple levels + const TableInfo& t = tables_[i]; + edit_.AddFile(0, t.meta.number, t.meta.file_size, + t.meta.smallest, t.meta.largest); + } + + //fprintf(stderr, "NewDescriptor:\n%s\n", edit_.DebugString().c_str()); + { + log::Writer log(file); + std::string record; + edit_.EncodeTo(&record); + status = log.AddRecord(record); + } + if (status.ok()) { + status = file->Close(); + } + delete file; + file = NULL; + + if (!status.ok()) { + env_->DeleteFile(tmp); + } else { + // Discard older manifests + for (size_t i = 0; i < manifests_.size(); i++) { + ArchiveFile(dbname_ + "/" + manifests_[i]); + } + + // Install new manifest + status = env_->RenameFile(tmp, DescriptorFileName(dbname_, 1)); + if (status.ok()) { + status = SetCurrentFile(env_, dbname_, 1); + } else { + env_->DeleteFile(tmp); + } + } + return status; + } + + void ArchiveFile(const std::string& fname) { + // Move into another directory. E.g., for + // dir/foo + // rename to + // dir/lost/foo + const char* slash = strrchr(fname.c_str(), '/'); + std::string new_dir; + if (slash != NULL) { + new_dir.assign(fname.data(), slash - fname.data()); + } + new_dir.append("/lost"); + env_->CreateDir(new_dir); // Ignore error + std::string new_file = new_dir; + new_file.append("/"); + new_file.append((slash == NULL) ? fname.c_str() : slash + 1); + Status s = env_->RenameFile(fname, new_file); + Log(options_.info_log, "Archiving %s: %s\n", + fname.c_str(), s.ToString().c_str()); + } +}; +} // namespace + +Status RepairDB(const std::string& dbname, const Options& options) { + Repairer repairer(dbname, options); + return repairer.Run(); +} + +} // namespace leveldb diff --git a/src/leveldb/db/skiplist.h b/src/leveldb/db/skiplist.h new file mode 100644 index 0000000..af85be6 --- /dev/null +++ b/src/leveldb/db/skiplist.h @@ -0,0 +1,379 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. +// +// Thread safety +// ------------- +// +// Writes require external synchronization, most likely a mutex. +// Reads require a guarantee that the SkipList will not be destroyed +// while the read is in progress. Apart from that, reads progress +// without any internal locking or synchronization. +// +// Invariants: +// +// (1) Allocated nodes are never deleted until the SkipList is +// destroyed. This is trivially guaranteed by the code since we +// never delete any skip list nodes. +// +// (2) The contents of a Node except for the next/prev pointers are +// immutable after the Node has been linked into the SkipList. +// Only Insert() modifies the list, and it is careful to initialize +// a node and use release-stores to publish the nodes in one or +// more lists. +// +// ... prev vs. next pointer ordering ... + +#include +#include +#include "port/port.h" +#include "util/arena.h" +#include "util/random.h" + +namespace leveldb { + +class Arena; + +template +class SkipList { + private: + struct Node; + + public: + // Create a new SkipList object that will use "cmp" for comparing keys, + // and will allocate memory using "*arena". Objects allocated in the arena + // must remain allocated for the lifetime of the skiplist object. + explicit SkipList(Comparator cmp, Arena* arena); + + // Insert key into the list. + // REQUIRES: nothing that compares equal to key is currently in the list. + void Insert(const Key& key); + + // Returns true iff an entry that compares equal to key is in the list. + bool Contains(const Key& key) const; + + // Iteration over the contents of a skip list + class Iterator { + public: + // Initialize an iterator over the specified list. + // The returned iterator is not valid. + explicit Iterator(const SkipList* list); + + // Returns true iff the iterator is positioned at a valid node. + bool Valid() const; + + // Returns the key at the current position. + // REQUIRES: Valid() + const Key& key() const; + + // Advances to the next position. + // REQUIRES: Valid() + void Next(); + + // Advances to the previous position. + // REQUIRES: Valid() + void Prev(); + + // Advance to the first entry with a key >= target + void Seek(const Key& target); + + // Position at the first entry in list. + // Final state of iterator is Valid() iff list is not empty. + void SeekToFirst(); + + // Position at the last entry in list. + // Final state of iterator is Valid() iff list is not empty. + void SeekToLast(); + + private: + const SkipList* list_; + Node* node_; + // Intentionally copyable + }; + + private: + enum { kMaxHeight = 12 }; + + // Immutable after construction + Comparator const compare_; + Arena* const arena_; // Arena used for allocations of nodes + + Node* const head_; + + // Modified only by Insert(). Read racily by readers, but stale + // values are ok. + port::AtomicPointer max_height_; // Height of the entire list + + inline int GetMaxHeight() const { + return static_cast( + reinterpret_cast(max_height_.NoBarrier_Load())); + } + + // Read/written only by Insert(). + Random rnd_; + + Node* NewNode(const Key& key, int height); + int RandomHeight(); + bool Equal(const Key& a, const Key& b) const { return (compare_(a, b) == 0); } + + // Return true if key is greater than the data stored in "n" + bool KeyIsAfterNode(const Key& key, Node* n) const; + + // Return the earliest node that comes at or after key. + // Return NULL if there is no such node. + // + // If prev is non-NULL, fills prev[level] with pointer to previous + // node at "level" for every level in [0..max_height_-1]. + Node* FindGreaterOrEqual(const Key& key, Node** prev) const; + + // Return the latest node with a key < key. + // Return head_ if there is no such node. + Node* FindLessThan(const Key& key) const; + + // Return the last node in the list. + // Return head_ if list is empty. + Node* FindLast() const; + + // No copying allowed + SkipList(const SkipList&); + void operator=(const SkipList&); +}; + +// Implementation details follow +template +struct SkipList::Node { + explicit Node(const Key& k) : key(k) { } + + Key const key; + + // Accessors/mutators for links. Wrapped in methods so we can + // add the appropriate barriers as necessary. + Node* Next(int n) { + assert(n >= 0); + // Use an 'acquire load' so that we observe a fully initialized + // version of the returned Node. + return reinterpret_cast(next_[n].Acquire_Load()); + } + void SetNext(int n, Node* x) { + assert(n >= 0); + // Use a 'release store' so that anybody who reads through this + // pointer observes a fully initialized version of the inserted node. + next_[n].Release_Store(x); + } + + // No-barrier variants that can be safely used in a few locations. + Node* NoBarrier_Next(int n) { + assert(n >= 0); + return reinterpret_cast(next_[n].NoBarrier_Load()); + } + void NoBarrier_SetNext(int n, Node* x) { + assert(n >= 0); + next_[n].NoBarrier_Store(x); + } + + private: + // Array of length equal to the node height. next_[0] is lowest level link. + port::AtomicPointer next_[1]; +}; + +template +typename SkipList::Node* +SkipList::NewNode(const Key& key, int height) { + char* mem = arena_->AllocateAligned( + sizeof(Node) + sizeof(port::AtomicPointer) * (height - 1)); + return new (mem) Node(key); +} + +template +inline SkipList::Iterator::Iterator(const SkipList* list) { + list_ = list; + node_ = NULL; +} + +template +inline bool SkipList::Iterator::Valid() const { + return node_ != NULL; +} + +template +inline const Key& SkipList::Iterator::key() const { + assert(Valid()); + return node_->key; +} + +template +inline void SkipList::Iterator::Next() { + assert(Valid()); + node_ = node_->Next(0); +} + +template +inline void SkipList::Iterator::Prev() { + // Instead of using explicit "prev" links, we just search for the + // last node that falls before key. + assert(Valid()); + node_ = list_->FindLessThan(node_->key); + if (node_ == list_->head_) { + node_ = NULL; + } +} + +template +inline void SkipList::Iterator::Seek(const Key& target) { + node_ = list_->FindGreaterOrEqual(target, NULL); +} + +template +inline void SkipList::Iterator::SeekToFirst() { + node_ = list_->head_->Next(0); +} + +template +inline void SkipList::Iterator::SeekToLast() { + node_ = list_->FindLast(); + if (node_ == list_->head_) { + node_ = NULL; + } +} + +template +int SkipList::RandomHeight() { + // Increase height with probability 1 in kBranching + static const unsigned int kBranching = 4; + int height = 1; + while (height < kMaxHeight && ((rnd_.Next() % kBranching) == 0)) { + height++; + } + assert(height > 0); + assert(height <= kMaxHeight); + return height; +} + +template +bool SkipList::KeyIsAfterNode(const Key& key, Node* n) const { + // NULL n is considered infinite + return (n != NULL) && (compare_(n->key, key) < 0); +} + +template +typename SkipList::Node* SkipList::FindGreaterOrEqual(const Key& key, Node** prev) + const { + Node* x = head_; + int level = GetMaxHeight() - 1; + while (true) { + Node* next = x->Next(level); + if (KeyIsAfterNode(key, next)) { + // Keep searching in this list + x = next; + } else { + if (prev != NULL) prev[level] = x; + if (level == 0) { + return next; + } else { + // Switch to next list + level--; + } + } + } +} + +template +typename SkipList::Node* +SkipList::FindLessThan(const Key& key) const { + Node* x = head_; + int level = GetMaxHeight() - 1; + while (true) { + assert(x == head_ || compare_(x->key, key) < 0); + Node* next = x->Next(level); + if (next == NULL || compare_(next->key, key) >= 0) { + if (level == 0) { + return x; + } else { + // Switch to next list + level--; + } + } else { + x = next; + } + } +} + +template +typename SkipList::Node* SkipList::FindLast() + const { + Node* x = head_; + int level = GetMaxHeight() - 1; + while (true) { + Node* next = x->Next(level); + if (next == NULL) { + if (level == 0) { + return x; + } else { + // Switch to next list + level--; + } + } else { + x = next; + } + } +} + +template +SkipList::SkipList(Comparator cmp, Arena* arena) + : compare_(cmp), + arena_(arena), + head_(NewNode(0 /* any key will do */, kMaxHeight)), + max_height_(reinterpret_cast(1)), + rnd_(0xdeadbeef) { + for (int i = 0; i < kMaxHeight; i++) { + head_->SetNext(i, NULL); + } +} + +template +void SkipList::Insert(const Key& key) { + // TODO(opt): We can use a barrier-free variant of FindGreaterOrEqual() + // here since Insert() is externally synchronized. + Node* prev[kMaxHeight]; + Node* x = FindGreaterOrEqual(key, prev); + + // Our data structure does not allow duplicate insertion + assert(x == NULL || !Equal(key, x->key)); + + int height = RandomHeight(); + if (height > GetMaxHeight()) { + for (int i = GetMaxHeight(); i < height; i++) { + prev[i] = head_; + } + //fprintf(stderr, "Change height from %d to %d\n", max_height_, height); + + // It is ok to mutate max_height_ without any synchronization + // with concurrent readers. A concurrent reader that observes + // the new value of max_height_ will see either the old value of + // new level pointers from head_ (NULL), or a new value set in + // the loop below. In the former case the reader will + // immediately drop to the next level since NULL sorts after all + // keys. In the latter case the reader will use the new node. + max_height_.NoBarrier_Store(reinterpret_cast(height)); + } + + x = NewNode(key, height); + for (int i = 0; i < height; i++) { + // NoBarrier_SetNext() suffices since we will add a barrier when + // we publish a pointer to "x" in prev[i]. + x->NoBarrier_SetNext(i, prev[i]->NoBarrier_Next(i)); + prev[i]->SetNext(i, x); + } +} + +template +bool SkipList::Contains(const Key& key) const { + Node* x = FindGreaterOrEqual(key, NULL); + if (x != NULL && Equal(key, x->key)) { + return true; + } else { + return false; + } +} + +} // namespace leveldb diff --git a/src/leveldb/db/skiplist_test.cc b/src/leveldb/db/skiplist_test.cc new file mode 100644 index 0000000..c78f4b4 --- /dev/null +++ b/src/leveldb/db/skiplist_test.cc @@ -0,0 +1,378 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "db/skiplist.h" +#include +#include "leveldb/env.h" +#include "util/arena.h" +#include "util/hash.h" +#include "util/random.h" +#include "util/testharness.h" + +namespace leveldb { + +typedef uint64_t Key; + +struct Comparator { + int operator()(const Key& a, const Key& b) const { + if (a < b) { + return -1; + } else if (a > b) { + return +1; + } else { + return 0; + } + } +}; + +class SkipTest { }; + +TEST(SkipTest, Empty) { + Arena arena; + Comparator cmp; + SkipList list(cmp, &arena); + ASSERT_TRUE(!list.Contains(10)); + + SkipList::Iterator iter(&list); + ASSERT_TRUE(!iter.Valid()); + iter.SeekToFirst(); + ASSERT_TRUE(!iter.Valid()); + iter.Seek(100); + ASSERT_TRUE(!iter.Valid()); + iter.SeekToLast(); + ASSERT_TRUE(!iter.Valid()); +} + +TEST(SkipTest, InsertAndLookup) { + const int N = 2000; + const int R = 5000; + Random rnd(1000); + std::set keys; + Arena arena; + Comparator cmp; + SkipList list(cmp, &arena); + for (int i = 0; i < N; i++) { + Key key = rnd.Next() % R; + if (keys.insert(key).second) { + list.Insert(key); + } + } + + for (int i = 0; i < R; i++) { + if (list.Contains(i)) { + ASSERT_EQ(keys.count(i), 1); + } else { + ASSERT_EQ(keys.count(i), 0); + } + } + + // Simple iterator tests + { + SkipList::Iterator iter(&list); + ASSERT_TRUE(!iter.Valid()); + + iter.Seek(0); + ASSERT_TRUE(iter.Valid()); + ASSERT_EQ(*(keys.begin()), iter.key()); + + iter.SeekToFirst(); + ASSERT_TRUE(iter.Valid()); + ASSERT_EQ(*(keys.begin()), iter.key()); + + iter.SeekToLast(); + ASSERT_TRUE(iter.Valid()); + ASSERT_EQ(*(keys.rbegin()), iter.key()); + } + + // Forward iteration test + for (int i = 0; i < R; i++) { + SkipList::Iterator iter(&list); + iter.Seek(i); + + // Compare against model iterator + std::set::iterator model_iter = keys.lower_bound(i); + for (int j = 0; j < 3; j++) { + if (model_iter == keys.end()) { + ASSERT_TRUE(!iter.Valid()); + break; + } else { + ASSERT_TRUE(iter.Valid()); + ASSERT_EQ(*model_iter, iter.key()); + ++model_iter; + iter.Next(); + } + } + } + + // Backward iteration test + { + SkipList::Iterator iter(&list); + iter.SeekToLast(); + + // Compare against model iterator + for (std::set::reverse_iterator model_iter = keys.rbegin(); + model_iter != keys.rend(); + ++model_iter) { + ASSERT_TRUE(iter.Valid()); + ASSERT_EQ(*model_iter, iter.key()); + iter.Prev(); + } + ASSERT_TRUE(!iter.Valid()); + } +} + +// We want to make sure that with a single writer and multiple +// concurrent readers (with no synchronization other than when a +// reader's iterator is created), the reader always observes all the +// data that was present in the skip list when the iterator was +// constructor. Because insertions are happening concurrently, we may +// also observe new values that were inserted since the iterator was +// constructed, but we should never miss any values that were present +// at iterator construction time. +// +// We generate multi-part keys: +// +// where: +// key is in range [0..K-1] +// gen is a generation number for key +// hash is hash(key,gen) +// +// The insertion code picks a random key, sets gen to be 1 + the last +// generation number inserted for that key, and sets hash to Hash(key,gen). +// +// At the beginning of a read, we snapshot the last inserted +// generation number for each key. We then iterate, including random +// calls to Next() and Seek(). For every key we encounter, we +// check that it is either expected given the initial snapshot or has +// been concurrently added since the iterator started. +class ConcurrentTest { + private: + static const uint32_t K = 4; + + static uint64_t key(Key key) { return (key >> 40); } + static uint64_t gen(Key key) { return (key >> 8) & 0xffffffffu; } + static uint64_t hash(Key key) { return key & 0xff; } + + static uint64_t HashNumbers(uint64_t k, uint64_t g) { + uint64_t data[2] = { k, g }; + return Hash(reinterpret_cast(data), sizeof(data), 0); + } + + static Key MakeKey(uint64_t k, uint64_t g) { + assert(sizeof(Key) == sizeof(uint64_t)); + assert(k <= K); // We sometimes pass K to seek to the end of the skiplist + assert(g <= 0xffffffffu); + return ((k << 40) | (g << 8) | (HashNumbers(k, g) & 0xff)); + } + + static bool IsValidKey(Key k) { + return hash(k) == (HashNumbers(key(k), gen(k)) & 0xff); + } + + static Key RandomTarget(Random* rnd) { + switch (rnd->Next() % 10) { + case 0: + // Seek to beginning + return MakeKey(0, 0); + case 1: + // Seek to end + return MakeKey(K, 0); + default: + // Seek to middle + return MakeKey(rnd->Next() % K, 0); + } + } + + // Per-key generation + struct State { + port::AtomicPointer generation[K]; + void Set(int k, intptr_t v) { + generation[k].Release_Store(reinterpret_cast(v)); + } + intptr_t Get(int k) { + return reinterpret_cast(generation[k].Acquire_Load()); + } + + State() { + for (int k = 0; k < K; k++) { + Set(k, 0); + } + } + }; + + // Current state of the test + State current_; + + Arena arena_; + + // SkipList is not protected by mu_. We just use a single writer + // thread to modify it. + SkipList list_; + + public: + ConcurrentTest() : list_(Comparator(), &arena_) { } + + // REQUIRES: External synchronization + void WriteStep(Random* rnd) { + const uint32_t k = rnd->Next() % K; + const intptr_t g = current_.Get(k) + 1; + const Key key = MakeKey(k, g); + list_.Insert(key); + current_.Set(k, g); + } + + void ReadStep(Random* rnd) { + // Remember the initial committed state of the skiplist. + State initial_state; + for (int k = 0; k < K; k++) { + initial_state.Set(k, current_.Get(k)); + } + + Key pos = RandomTarget(rnd); + SkipList::Iterator iter(&list_); + iter.Seek(pos); + while (true) { + Key current; + if (!iter.Valid()) { + current = MakeKey(K, 0); + } else { + current = iter.key(); + ASSERT_TRUE(IsValidKey(current)) << current; + } + ASSERT_LE(pos, current) << "should not go backwards"; + + // Verify that everything in [pos,current) was not present in + // initial_state. + while (pos < current) { + ASSERT_LT(key(pos), K) << pos; + + // Note that generation 0 is never inserted, so it is ok if + // <*,0,*> is missing. + ASSERT_TRUE((gen(pos) == 0) || + (gen(pos) > initial_state.Get(key(pos))) + ) << "key: " << key(pos) + << "; gen: " << gen(pos) + << "; initgen: " + << initial_state.Get(key(pos)); + + // Advance to next key in the valid key space + if (key(pos) < key(current)) { + pos = MakeKey(key(pos) + 1, 0); + } else { + pos = MakeKey(key(pos), gen(pos) + 1); + } + } + + if (!iter.Valid()) { + break; + } + + if (rnd->Next() % 2) { + iter.Next(); + pos = MakeKey(key(pos), gen(pos) + 1); + } else { + Key new_target = RandomTarget(rnd); + if (new_target > pos) { + pos = new_target; + iter.Seek(new_target); + } + } + } + } +}; +const uint32_t ConcurrentTest::K; + +// Simple test that does single-threaded testing of the ConcurrentTest +// scaffolding. +TEST(SkipTest, ConcurrentWithoutThreads) { + ConcurrentTest test; + Random rnd(test::RandomSeed()); + for (int i = 0; i < 10000; i++) { + test.ReadStep(&rnd); + test.WriteStep(&rnd); + } +} + +class TestState { + public: + ConcurrentTest t_; + int seed_; + port::AtomicPointer quit_flag_; + + enum ReaderState { + STARTING, + RUNNING, + DONE + }; + + explicit TestState(int s) + : seed_(s), + quit_flag_(NULL), + state_(STARTING), + state_cv_(&mu_) {} + + void Wait(ReaderState s) { + mu_.Lock(); + while (state_ != s) { + state_cv_.Wait(); + } + mu_.Unlock(); + } + + void Change(ReaderState s) { + mu_.Lock(); + state_ = s; + state_cv_.Signal(); + mu_.Unlock(); + } + + private: + port::Mutex mu_; + ReaderState state_; + port::CondVar state_cv_; +}; + +static void ConcurrentReader(void* arg) { + TestState* state = reinterpret_cast(arg); + Random rnd(state->seed_); + int64_t reads = 0; + state->Change(TestState::RUNNING); + while (!state->quit_flag_.Acquire_Load()) { + state->t_.ReadStep(&rnd); + ++reads; + } + state->Change(TestState::DONE); +} + +static void RunConcurrent(int run) { + const int seed = test::RandomSeed() + (run * 100); + Random rnd(seed); + const int N = 1000; + const int kSize = 1000; + for (int i = 0; i < N; i++) { + if ((i % 100) == 0) { + fprintf(stderr, "Run %d of %d\n", i, N); + } + TestState state(seed + 1); + Env::Default()->Schedule(ConcurrentReader, &state); + state.Wait(TestState::RUNNING); + for (int i = 0; i < kSize; i++) { + state.t_.WriteStep(&rnd); + } + state.quit_flag_.Release_Store(&state); // Any non-NULL arg will do + state.Wait(TestState::DONE); + } +} + +TEST(SkipTest, Concurrent1) { RunConcurrent(1); } +TEST(SkipTest, Concurrent2) { RunConcurrent(2); } +TEST(SkipTest, Concurrent3) { RunConcurrent(3); } +TEST(SkipTest, Concurrent4) { RunConcurrent(4); } +TEST(SkipTest, Concurrent5) { RunConcurrent(5); } + +} // namespace leveldb + +int main(int argc, char** argv) { + return leveldb::test::RunAllTests(); +} diff --git a/src/leveldb/db/snapshot.h b/src/leveldb/db/snapshot.h new file mode 100644 index 0000000..e7f8fd2 --- /dev/null +++ b/src/leveldb/db/snapshot.h @@ -0,0 +1,66 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#ifndef STORAGE_LEVELDB_DB_SNAPSHOT_H_ +#define STORAGE_LEVELDB_DB_SNAPSHOT_H_ + +#include "leveldb/db.h" + +namespace leveldb { + +class SnapshotList; + +// Snapshots are kept in a doubly-linked list in the DB. +// Each SnapshotImpl corresponds to a particular sequence number. +class SnapshotImpl : public Snapshot { + public: + SequenceNumber number_; // const after creation + + private: + friend class SnapshotList; + + // SnapshotImpl is kept in a doubly-linked circular list + SnapshotImpl* prev_; + SnapshotImpl* next_; + + SnapshotList* list_; // just for sanity checks +}; + +class SnapshotList { + public: + SnapshotList() { + list_.prev_ = &list_; + list_.next_ = &list_; + } + + bool empty() const { return list_.next_ == &list_; } + SnapshotImpl* oldest() const { assert(!empty()); return list_.next_; } + SnapshotImpl* newest() const { assert(!empty()); return list_.prev_; } + + const SnapshotImpl* New(SequenceNumber seq) { + SnapshotImpl* s = new SnapshotImpl; + s->number_ = seq; + s->list_ = this; + s->next_ = &list_; + s->prev_ = list_.prev_; + s->prev_->next_ = s; + s->next_->prev_ = s; + return s; + } + + void Delete(const SnapshotImpl* s) { + assert(s->list_ == this); + s->prev_->next_ = s->next_; + s->next_->prev_ = s->prev_; + delete s; + } + + private: + // Dummy head of doubly-linked list of snapshots + SnapshotImpl list_; +}; + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_DB_SNAPSHOT_H_ diff --git a/src/leveldb/db/table_cache.cc b/src/leveldb/db/table_cache.cc new file mode 100644 index 0000000..e3d82cd --- /dev/null +++ b/src/leveldb/db/table_cache.cc @@ -0,0 +1,127 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "db/table_cache.h" + +#include "db/filename.h" +#include "leveldb/env.h" +#include "leveldb/table.h" +#include "util/coding.h" + +namespace leveldb { + +struct TableAndFile { + RandomAccessFile* file; + Table* table; +}; + +static void DeleteEntry(const Slice& key, void* value) { + TableAndFile* tf = reinterpret_cast(value); + delete tf->table; + delete tf->file; + delete tf; +} + +static void UnrefEntry(void* arg1, void* arg2) { + Cache* cache = reinterpret_cast(arg1); + Cache::Handle* h = reinterpret_cast(arg2); + cache->Release(h); +} + +TableCache::TableCache(const std::string& dbname, + const Options* options, + int entries) + : env_(options->env), + dbname_(dbname), + options_(options), + cache_(NewLRUCache(entries)) { +} + +TableCache::~TableCache() { + delete cache_; +} + +Status TableCache::FindTable(uint64_t file_number, uint64_t file_size, + Cache::Handle** handle) { + Status s; + char buf[sizeof(file_number)]; + EncodeFixed64(buf, file_number); + Slice key(buf, sizeof(buf)); + *handle = cache_->Lookup(key); + if (*handle == NULL) { + std::string fname = TableFileName(dbname_, file_number); + RandomAccessFile* file = NULL; + Table* table = NULL; + s = env_->NewRandomAccessFile(fname, &file); + if (!s.ok()) { + std::string old_fname = SSTTableFileName(dbname_, file_number); + if (env_->NewRandomAccessFile(old_fname, &file).ok()) { + s = Status::OK(); + } + } + if (s.ok()) { + s = Table::Open(*options_, file, file_size, &table); + } + + if (!s.ok()) { + assert(table == NULL); + delete file; + // We do not cache error results so that if the error is transient, + // or somebody repairs the file, we recover automatically. + } else { + TableAndFile* tf = new TableAndFile; + tf->file = file; + tf->table = table; + *handle = cache_->Insert(key, tf, 1, &DeleteEntry); + } + } + return s; +} + +Iterator* TableCache::NewIterator(const ReadOptions& options, + uint64_t file_number, + uint64_t file_size, + Table** tableptr) { + if (tableptr != NULL) { + *tableptr = NULL; + } + + Cache::Handle* handle = NULL; + Status s = FindTable(file_number, file_size, &handle); + if (!s.ok()) { + return NewErrorIterator(s); + } + + Table* table = reinterpret_cast(cache_->Value(handle))->table; + Iterator* result = table->NewIterator(options); + result->RegisterCleanup(&UnrefEntry, cache_, handle); + if (tableptr != NULL) { + *tableptr = table; + } + return result; +} + +Status TableCache::Get(const ReadOptions& options, + uint64_t file_number, + uint64_t file_size, + const Slice& k, + void* arg, + void (*saver)(void*, const Slice&, const Slice&)) { + Cache::Handle* handle = NULL; + Status s = FindTable(file_number, file_size, &handle); + if (s.ok()) { + Table* t = reinterpret_cast(cache_->Value(handle))->table; + s = t->InternalGet(options, k, arg, saver); + cache_->Release(handle); + } + return s; +} + +void TableCache::Evict(uint64_t file_number) { + char buf[sizeof(file_number)]; + EncodeFixed64(buf, file_number); + cache_->Erase(Slice(buf, sizeof(buf))); +} + +} // namespace leveldb diff --git a/src/leveldb/db/table_cache.h b/src/leveldb/db/table_cache.h new file mode 100644 index 0000000..8cf4aaf --- /dev/null +++ b/src/leveldb/db/table_cache.h @@ -0,0 +1,61 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. +// +// Thread-safe (provides internal synchronization) + +#ifndef STORAGE_LEVELDB_DB_TABLE_CACHE_H_ +#define STORAGE_LEVELDB_DB_TABLE_CACHE_H_ + +#include +#include +#include "db/dbformat.h" +#include "leveldb/cache.h" +#include "leveldb/table.h" +#include "port/port.h" + +namespace leveldb { + +class Env; + +class TableCache { + public: + TableCache(const std::string& dbname, const Options* options, int entries); + ~TableCache(); + + // Return an iterator for the specified file number (the corresponding + // file length must be exactly "file_size" bytes). If "tableptr" is + // non-NULL, also sets "*tableptr" to point to the Table object + // underlying the returned iterator, or NULL if no Table object underlies + // the returned iterator. The returned "*tableptr" object is owned by + // the cache and should not be deleted, and is valid for as long as the + // returned iterator is live. + Iterator* NewIterator(const ReadOptions& options, + uint64_t file_number, + uint64_t file_size, + Table** tableptr = NULL); + + // If a seek to internal key "k" in specified file finds an entry, + // call (*handle_result)(arg, found_key, found_value). + Status Get(const ReadOptions& options, + uint64_t file_number, + uint64_t file_size, + const Slice& k, + void* arg, + void (*handle_result)(void*, const Slice&, const Slice&)); + + // Evict any entry for the specified file number + void Evict(uint64_t file_number); + + private: + Env* const env_; + const std::string dbname_; + const Options* options_; + Cache* cache_; + + Status FindTable(uint64_t file_number, uint64_t file_size, Cache::Handle**); +}; + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_DB_TABLE_CACHE_H_ diff --git a/src/leveldb/db/version_edit.cc b/src/leveldb/db/version_edit.cc new file mode 100644 index 0000000..f10a2d5 --- /dev/null +++ b/src/leveldb/db/version_edit.cc @@ -0,0 +1,266 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "db/version_edit.h" + +#include "db/version_set.h" +#include "util/coding.h" + +namespace leveldb { + +// Tag numbers for serialized VersionEdit. These numbers are written to +// disk and should not be changed. +enum Tag { + kComparator = 1, + kLogNumber = 2, + kNextFileNumber = 3, + kLastSequence = 4, + kCompactPointer = 5, + kDeletedFile = 6, + kNewFile = 7, + // 8 was used for large value refs + kPrevLogNumber = 9 +}; + +void VersionEdit::Clear() { + comparator_.clear(); + log_number_ = 0; + prev_log_number_ = 0; + last_sequence_ = 0; + next_file_number_ = 0; + has_comparator_ = false; + has_log_number_ = false; + has_prev_log_number_ = false; + has_next_file_number_ = false; + has_last_sequence_ = false; + deleted_files_.clear(); + new_files_.clear(); +} + +void VersionEdit::EncodeTo(std::string* dst) const { + if (has_comparator_) { + PutVarint32(dst, kComparator); + PutLengthPrefixedSlice(dst, comparator_); + } + if (has_log_number_) { + PutVarint32(dst, kLogNumber); + PutVarint64(dst, log_number_); + } + if (has_prev_log_number_) { + PutVarint32(dst, kPrevLogNumber); + PutVarint64(dst, prev_log_number_); + } + if (has_next_file_number_) { + PutVarint32(dst, kNextFileNumber); + PutVarint64(dst, next_file_number_); + } + if (has_last_sequence_) { + PutVarint32(dst, kLastSequence); + PutVarint64(dst, last_sequence_); + } + + for (size_t i = 0; i < compact_pointers_.size(); i++) { + PutVarint32(dst, kCompactPointer); + PutVarint32(dst, compact_pointers_[i].first); // level + PutLengthPrefixedSlice(dst, compact_pointers_[i].second.Encode()); + } + + for (DeletedFileSet::const_iterator iter = deleted_files_.begin(); + iter != deleted_files_.end(); + ++iter) { + PutVarint32(dst, kDeletedFile); + PutVarint32(dst, iter->first); // level + PutVarint64(dst, iter->second); // file number + } + + for (size_t i = 0; i < new_files_.size(); i++) { + const FileMetaData& f = new_files_[i].second; + PutVarint32(dst, kNewFile); + PutVarint32(dst, new_files_[i].first); // level + PutVarint64(dst, f.number); + PutVarint64(dst, f.file_size); + PutLengthPrefixedSlice(dst, f.smallest.Encode()); + PutLengthPrefixedSlice(dst, f.largest.Encode()); + } +} + +static bool GetInternalKey(Slice* input, InternalKey* dst) { + Slice str; + if (GetLengthPrefixedSlice(input, &str)) { + dst->DecodeFrom(str); + return true; + } else { + return false; + } +} + +static bool GetLevel(Slice* input, int* level) { + uint32_t v; + if (GetVarint32(input, &v) && + v < config::kNumLevels) { + *level = v; + return true; + } else { + return false; + } +} + +Status VersionEdit::DecodeFrom(const Slice& src) { + Clear(); + Slice input = src; + const char* msg = NULL; + uint32_t tag; + + // Temporary storage for parsing + int level; + uint64_t number; + FileMetaData f; + Slice str; + InternalKey key; + + while (msg == NULL && GetVarint32(&input, &tag)) { + switch (tag) { + case kComparator: + if (GetLengthPrefixedSlice(&input, &str)) { + comparator_ = str.ToString(); + has_comparator_ = true; + } else { + msg = "comparator name"; + } + break; + + case kLogNumber: + if (GetVarint64(&input, &log_number_)) { + has_log_number_ = true; + } else { + msg = "log number"; + } + break; + + case kPrevLogNumber: + if (GetVarint64(&input, &prev_log_number_)) { + has_prev_log_number_ = true; + } else { + msg = "previous log number"; + } + break; + + case kNextFileNumber: + if (GetVarint64(&input, &next_file_number_)) { + has_next_file_number_ = true; + } else { + msg = "next file number"; + } + break; + + case kLastSequence: + if (GetVarint64(&input, &last_sequence_)) { + has_last_sequence_ = true; + } else { + msg = "last sequence number"; + } + break; + + case kCompactPointer: + if (GetLevel(&input, &level) && + GetInternalKey(&input, &key)) { + compact_pointers_.push_back(std::make_pair(level, key)); + } else { + msg = "compaction pointer"; + } + break; + + case kDeletedFile: + if (GetLevel(&input, &level) && + GetVarint64(&input, &number)) { + deleted_files_.insert(std::make_pair(level, number)); + } else { + msg = "deleted file"; + } + break; + + case kNewFile: + if (GetLevel(&input, &level) && + GetVarint64(&input, &f.number) && + GetVarint64(&input, &f.file_size) && + GetInternalKey(&input, &f.smallest) && + GetInternalKey(&input, &f.largest)) { + new_files_.push_back(std::make_pair(level, f)); + } else { + msg = "new-file entry"; + } + break; + + default: + msg = "unknown tag"; + break; + } + } + + if (msg == NULL && !input.empty()) { + msg = "invalid tag"; + } + + Status result; + if (msg != NULL) { + result = Status::Corruption("VersionEdit", msg); + } + return result; +} + +std::string VersionEdit::DebugString() const { + std::string r; + r.append("VersionEdit {"); + if (has_comparator_) { + r.append("\n Comparator: "); + r.append(comparator_); + } + if (has_log_number_) { + r.append("\n LogNumber: "); + AppendNumberTo(&r, log_number_); + } + if (has_prev_log_number_) { + r.append("\n PrevLogNumber: "); + AppendNumberTo(&r, prev_log_number_); + } + if (has_next_file_number_) { + r.append("\n NextFile: "); + AppendNumberTo(&r, next_file_number_); + } + if (has_last_sequence_) { + r.append("\n LastSeq: "); + AppendNumberTo(&r, last_sequence_); + } + for (size_t i = 0; i < compact_pointers_.size(); i++) { + r.append("\n CompactPointer: "); + AppendNumberTo(&r, compact_pointers_[i].first); + r.append(" "); + r.append(compact_pointers_[i].second.DebugString()); + } + for (DeletedFileSet::const_iterator iter = deleted_files_.begin(); + iter != deleted_files_.end(); + ++iter) { + r.append("\n DeleteFile: "); + AppendNumberTo(&r, iter->first); + r.append(" "); + AppendNumberTo(&r, iter->second); + } + for (size_t i = 0; i < new_files_.size(); i++) { + const FileMetaData& f = new_files_[i].second; + r.append("\n AddFile: "); + AppendNumberTo(&r, new_files_[i].first); + r.append(" "); + AppendNumberTo(&r, f.number); + r.append(" "); + AppendNumberTo(&r, f.file_size); + r.append(" "); + r.append(f.smallest.DebugString()); + r.append(" .. "); + r.append(f.largest.DebugString()); + } + r.append("\n}\n"); + return r; +} + +} // namespace leveldb diff --git a/src/leveldb/db/version_edit.h b/src/leveldb/db/version_edit.h new file mode 100644 index 0000000..eaef77b --- /dev/null +++ b/src/leveldb/db/version_edit.h @@ -0,0 +1,107 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#ifndef STORAGE_LEVELDB_DB_VERSION_EDIT_H_ +#define STORAGE_LEVELDB_DB_VERSION_EDIT_H_ + +#include +#include +#include +#include "db/dbformat.h" + +namespace leveldb { + +class VersionSet; + +struct FileMetaData { + int refs; + int allowed_seeks; // Seeks allowed until compaction + uint64_t number; + uint64_t file_size; // File size in bytes + InternalKey smallest; // Smallest internal key served by table + InternalKey largest; // Largest internal key served by table + + FileMetaData() : refs(0), allowed_seeks(1 << 30), file_size(0) { } +}; + +class VersionEdit { + public: + VersionEdit() { Clear(); } + ~VersionEdit() { } + + void Clear(); + + void SetComparatorName(const Slice& name) { + has_comparator_ = true; + comparator_ = name.ToString(); + } + void SetLogNumber(uint64_t num) { + has_log_number_ = true; + log_number_ = num; + } + void SetPrevLogNumber(uint64_t num) { + has_prev_log_number_ = true; + prev_log_number_ = num; + } + void SetNextFile(uint64_t num) { + has_next_file_number_ = true; + next_file_number_ = num; + } + void SetLastSequence(SequenceNumber seq) { + has_last_sequence_ = true; + last_sequence_ = seq; + } + void SetCompactPointer(int level, const InternalKey& key) { + compact_pointers_.push_back(std::make_pair(level, key)); + } + + // Add the specified file at the specified number. + // REQUIRES: This version has not been saved (see VersionSet::SaveTo) + // REQUIRES: "smallest" and "largest" are smallest and largest keys in file + void AddFile(int level, uint64_t file, + uint64_t file_size, + const InternalKey& smallest, + const InternalKey& largest) { + FileMetaData f; + f.number = file; + f.file_size = file_size; + f.smallest = smallest; + f.largest = largest; + new_files_.push_back(std::make_pair(level, f)); + } + + // Delete the specified "file" from the specified "level". + void DeleteFile(int level, uint64_t file) { + deleted_files_.insert(std::make_pair(level, file)); + } + + void EncodeTo(std::string* dst) const; + Status DecodeFrom(const Slice& src); + + std::string DebugString() const; + + private: + friend class VersionSet; + + typedef std::set< std::pair > DeletedFileSet; + + std::string comparator_; + uint64_t log_number_; + uint64_t prev_log_number_; + uint64_t next_file_number_; + SequenceNumber last_sequence_; + bool has_comparator_; + bool has_log_number_; + bool has_prev_log_number_; + bool has_next_file_number_; + bool has_last_sequence_; + + std::vector< std::pair > compact_pointers_; + DeletedFileSet deleted_files_; + std::vector< std::pair > new_files_; +}; + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_DB_VERSION_EDIT_H_ diff --git a/src/leveldb/db/version_edit_test.cc b/src/leveldb/db/version_edit_test.cc new file mode 100644 index 0000000..280310b --- /dev/null +++ b/src/leveldb/db/version_edit_test.cc @@ -0,0 +1,46 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "db/version_edit.h" +#include "util/testharness.h" + +namespace leveldb { + +static void TestEncodeDecode(const VersionEdit& edit) { + std::string encoded, encoded2; + edit.EncodeTo(&encoded); + VersionEdit parsed; + Status s = parsed.DecodeFrom(encoded); + ASSERT_TRUE(s.ok()) << s.ToString(); + parsed.EncodeTo(&encoded2); + ASSERT_EQ(encoded, encoded2); +} + +class VersionEditTest { }; + +TEST(VersionEditTest, EncodeDecode) { + static const uint64_t kBig = 1ull << 50; + + VersionEdit edit; + for (int i = 0; i < 4; i++) { + TestEncodeDecode(edit); + edit.AddFile(3, kBig + 300 + i, kBig + 400 + i, + InternalKey("foo", kBig + 500 + i, kTypeValue), + InternalKey("zoo", kBig + 600 + i, kTypeDeletion)); + edit.DeleteFile(4, kBig + 700 + i); + edit.SetCompactPointer(i, InternalKey("x", kBig + 900 + i, kTypeValue)); + } + + edit.SetComparatorName("foo"); + edit.SetLogNumber(kBig + 100); + edit.SetNextFile(kBig + 200); + edit.SetLastSequence(kBig + 1000); + TestEncodeDecode(edit); +} + +} // namespace leveldb + +int main(int argc, char** argv) { + return leveldb::test::RunAllTests(); +} diff --git a/src/leveldb/db/version_set.cc b/src/leveldb/db/version_set.cc new file mode 100644 index 0000000..aa83df5 --- /dev/null +++ b/src/leveldb/db/version_set.cc @@ -0,0 +1,1484 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "db/version_set.h" + +#include +#include +#include "db/filename.h" +#include "db/log_reader.h" +#include "db/log_writer.h" +#include "db/memtable.h" +#include "db/table_cache.h" +#include "leveldb/env.h" +#include "leveldb/table_builder.h" +#include "table/merger.h" +#include "table/two_level_iterator.h" +#include "util/coding.h" +#include "util/logging.h" + +namespace leveldb { + +static const int kTargetFileSize = 2 * 1048576; + +// Maximum bytes of overlaps in grandparent (i.e., level+2) before we +// stop building a single file in a level->level+1 compaction. +static const int64_t kMaxGrandParentOverlapBytes = 10 * kTargetFileSize; + +// Maximum number of bytes in all compacted files. We avoid expanding +// the lower level file set of a compaction if it would make the +// total compaction cover more than this many bytes. +static const int64_t kExpandedCompactionByteSizeLimit = 25 * kTargetFileSize; + +static double MaxBytesForLevel(int level) { + // Note: the result for level zero is not really used since we set + // the level-0 compaction threshold based on number of files. + double result = 10 * 1048576.0; // Result for both level-0 and level-1 + while (level > 1) { + result *= 10; + level--; + } + return result; +} + +static uint64_t MaxFileSizeForLevel(int level) { + return kTargetFileSize; // We could vary per level to reduce number of files? +} + +static int64_t TotalFileSize(const std::vector& files) { + int64_t sum = 0; + for (size_t i = 0; i < files.size(); i++) { + sum += files[i]->file_size; + } + return sum; +} + +Version::~Version() { + assert(refs_ == 0); + + // Remove from linked list + prev_->next_ = next_; + next_->prev_ = prev_; + + // Drop references to files + for (int level = 0; level < config::kNumLevels; level++) { + for (size_t i = 0; i < files_[level].size(); i++) { + FileMetaData* f = files_[level][i]; + assert(f->refs > 0); + f->refs--; + if (f->refs <= 0) { + delete f; + } + } + } +} + +int FindFile(const InternalKeyComparator& icmp, + const std::vector& files, + const Slice& key) { + uint32_t left = 0; + uint32_t right = files.size(); + while (left < right) { + uint32_t mid = (left + right) / 2; + const FileMetaData* f = files[mid]; + if (icmp.InternalKeyComparator::Compare(f->largest.Encode(), key) < 0) { + // Key at "mid.largest" is < "target". Therefore all + // files at or before "mid" are uninteresting. + left = mid + 1; + } else { + // Key at "mid.largest" is >= "target". Therefore all files + // after "mid" are uninteresting. + right = mid; + } + } + return right; +} + +static bool AfterFile(const Comparator* ucmp, + const Slice* user_key, const FileMetaData* f) { + // NULL user_key occurs before all keys and is therefore never after *f + return (user_key != NULL && + ucmp->Compare(*user_key, f->largest.user_key()) > 0); +} + +static bool BeforeFile(const Comparator* ucmp, + const Slice* user_key, const FileMetaData* f) { + // NULL user_key occurs after all keys and is therefore never before *f + return (user_key != NULL && + ucmp->Compare(*user_key, f->smallest.user_key()) < 0); +} + +bool SomeFileOverlapsRange( + const InternalKeyComparator& icmp, + bool disjoint_sorted_files, + const std::vector& files, + const Slice* smallest_user_key, + const Slice* largest_user_key) { + const Comparator* ucmp = icmp.user_comparator(); + if (!disjoint_sorted_files) { + // Need to check against all files + for (size_t i = 0; i < files.size(); i++) { + const FileMetaData* f = files[i]; + if (AfterFile(ucmp, smallest_user_key, f) || + BeforeFile(ucmp, largest_user_key, f)) { + // No overlap + } else { + return true; // Overlap + } + } + return false; + } + + // Binary search over file list + uint32_t index = 0; + if (smallest_user_key != NULL) { + // Find the earliest possible internal key for smallest_user_key + InternalKey small(*smallest_user_key, kMaxSequenceNumber,kValueTypeForSeek); + index = FindFile(icmp, files, small.Encode()); + } + + if (index >= files.size()) { + // beginning of range is after all files, so no overlap. + return false; + } + + return !BeforeFile(ucmp, largest_user_key, files[index]); +} + +// An internal iterator. For a given version/level pair, yields +// information about the files in the level. For a given entry, key() +// is the largest key that occurs in the file, and value() is an +// 16-byte value containing the file number and file size, both +// encoded using EncodeFixed64. +class Version::LevelFileNumIterator : public Iterator { + public: + LevelFileNumIterator(const InternalKeyComparator& icmp, + const std::vector* flist) + : icmp_(icmp), + flist_(flist), + index_(flist->size()) { // Marks as invalid + } + virtual bool Valid() const { + return index_ < flist_->size(); + } + virtual void Seek(const Slice& target) { + index_ = FindFile(icmp_, *flist_, target); + } + virtual void SeekToFirst() { index_ = 0; } + virtual void SeekToLast() { + index_ = flist_->empty() ? 0 : flist_->size() - 1; + } + virtual void Next() { + assert(Valid()); + index_++; + } + virtual void Prev() { + assert(Valid()); + if (index_ == 0) { + index_ = flist_->size(); // Marks as invalid + } else { + index_--; + } + } + Slice key() const { + assert(Valid()); + return (*flist_)[index_]->largest.Encode(); + } + Slice value() const { + assert(Valid()); + EncodeFixed64(value_buf_, (*flist_)[index_]->number); + EncodeFixed64(value_buf_+8, (*flist_)[index_]->file_size); + return Slice(value_buf_, sizeof(value_buf_)); + } + virtual Status status() const { return Status::OK(); } + private: + const InternalKeyComparator icmp_; + const std::vector* const flist_; + uint32_t index_; + + // Backing store for value(). Holds the file number and size. + mutable char value_buf_[16]; +}; + +static Iterator* GetFileIterator(void* arg, + const ReadOptions& options, + const Slice& file_value) { + TableCache* cache = reinterpret_cast(arg); + if (file_value.size() != 16) { + return NewErrorIterator( + Status::Corruption("FileReader invoked with unexpected value")); + } else { + return cache->NewIterator(options, + DecodeFixed64(file_value.data()), + DecodeFixed64(file_value.data() + 8)); + } +} + +Iterator* Version::NewConcatenatingIterator(const ReadOptions& options, + int level) const { + return NewTwoLevelIterator( + new LevelFileNumIterator(vset_->icmp_, &files_[level]), + &GetFileIterator, vset_->table_cache_, options); +} + +void Version::AddIterators(const ReadOptions& options, + std::vector* iters) { + // Merge all level zero files together since they may overlap + for (size_t i = 0; i < files_[0].size(); i++) { + iters->push_back( + vset_->table_cache_->NewIterator( + options, files_[0][i]->number, files_[0][i]->file_size)); + } + + // For levels > 0, we can use a concatenating iterator that sequentially + // walks through the non-overlapping files in the level, opening them + // lazily. + for (int level = 1; level < config::kNumLevels; level++) { + if (!files_[level].empty()) { + iters->push_back(NewConcatenatingIterator(options, level)); + } + } +} + +// Callback from TableCache::Get() +namespace { +enum SaverState { + kNotFound, + kFound, + kDeleted, + kCorrupt, +}; +struct Saver { + SaverState state; + const Comparator* ucmp; + Slice user_key; + std::string* value; +}; +} +static void SaveValue(void* arg, const Slice& ikey, const Slice& v) { + Saver* s = reinterpret_cast(arg); + ParsedInternalKey parsed_key; + if (!ParseInternalKey(ikey, &parsed_key)) { + s->state = kCorrupt; + } else { + if (s->ucmp->Compare(parsed_key.user_key, s->user_key) == 0) { + s->state = (parsed_key.type == kTypeValue) ? kFound : kDeleted; + if (s->state == kFound) { + s->value->assign(v.data(), v.size()); + } + } + } +} + +static bool NewestFirst(FileMetaData* a, FileMetaData* b) { + return a->number > b->number; +} + +void Version::ForEachOverlapping(Slice user_key, Slice internal_key, + void* arg, + bool (*func)(void*, int, FileMetaData*)) { + // TODO(sanjay): Change Version::Get() to use this function. + const Comparator* ucmp = vset_->icmp_.user_comparator(); + + // Search level-0 in order from newest to oldest. + std::vector tmp; + tmp.reserve(files_[0].size()); + for (uint32_t i = 0; i < files_[0].size(); i++) { + FileMetaData* f = files_[0][i]; + if (ucmp->Compare(user_key, f->smallest.user_key()) >= 0 && + ucmp->Compare(user_key, f->largest.user_key()) <= 0) { + tmp.push_back(f); + } + } + if (!tmp.empty()) { + std::sort(tmp.begin(), tmp.end(), NewestFirst); + for (uint32_t i = 0; i < tmp.size(); i++) { + if (!(*func)(arg, 0, tmp[i])) { + return; + } + } + } + + // Search other levels. + for (int level = 1; level < config::kNumLevels; level++) { + size_t num_files = files_[level].size(); + if (num_files == 0) continue; + + // Binary search to find earliest index whose largest key >= internal_key. + uint32_t index = FindFile(vset_->icmp_, files_[level], internal_key); + if (index < num_files) { + FileMetaData* f = files_[level][index]; + if (ucmp->Compare(user_key, f->smallest.user_key()) < 0) { + // All of "f" is past any data for user_key + } else { + if (!(*func)(arg, level, f)) { + return; + } + } + } + } +} + +Status Version::Get(const ReadOptions& options, + const LookupKey& k, + std::string* value, + GetStats* stats) { + Slice ikey = k.internal_key(); + Slice user_key = k.user_key(); + const Comparator* ucmp = vset_->icmp_.user_comparator(); + Status s; + + stats->seek_file = NULL; + stats->seek_file_level = -1; + FileMetaData* last_file_read = NULL; + int last_file_read_level = -1; + + // We can search level-by-level since entries never hop across + // levels. Therefore we are guaranteed that if we find data + // in an smaller level, later levels are irrelevant. + std::vector tmp; + FileMetaData* tmp2; + for (int level = 0; level < config::kNumLevels; level++) { + size_t num_files = files_[level].size(); + if (num_files == 0) continue; + + // Get the list of files to search in this level + FileMetaData* const* files = &files_[level][0]; + if (level == 0) { + // Level-0 files may overlap each other. Find all files that + // overlap user_key and process them in order from newest to oldest. + tmp.reserve(num_files); + for (uint32_t i = 0; i < num_files; i++) { + FileMetaData* f = files[i]; + if (ucmp->Compare(user_key, f->smallest.user_key()) >= 0 && + ucmp->Compare(user_key, f->largest.user_key()) <= 0) { + tmp.push_back(f); + } + } + if (tmp.empty()) continue; + + std::sort(tmp.begin(), tmp.end(), NewestFirst); + files = &tmp[0]; + num_files = tmp.size(); + } else { + // Binary search to find earliest index whose largest key >= ikey. + uint32_t index = FindFile(vset_->icmp_, files_[level], ikey); + if (index >= num_files) { + files = NULL; + num_files = 0; + } else { + tmp2 = files[index]; + if (ucmp->Compare(user_key, tmp2->smallest.user_key()) < 0) { + // All of "tmp2" is past any data for user_key + files = NULL; + num_files = 0; + } else { + files = &tmp2; + num_files = 1; + } + } + } + + for (uint32_t i = 0; i < num_files; ++i) { + if (last_file_read != NULL && stats->seek_file == NULL) { + // We have had more than one seek for this read. Charge the 1st file. + stats->seek_file = last_file_read; + stats->seek_file_level = last_file_read_level; + } + + FileMetaData* f = files[i]; + last_file_read = f; + last_file_read_level = level; + + Saver saver; + saver.state = kNotFound; + saver.ucmp = ucmp; + saver.user_key = user_key; + saver.value = value; + s = vset_->table_cache_->Get(options, f->number, f->file_size, + ikey, &saver, SaveValue); + if (!s.ok()) { + return s; + } + switch (saver.state) { + case kNotFound: + break; // Keep searching in other files + case kFound: + return s; + case kDeleted: + s = Status::NotFound(Slice()); // Use empty error message for speed + return s; + case kCorrupt: + s = Status::Corruption("corrupted key for ", user_key); + return s; + } + } + } + + return Status::NotFound(Slice()); // Use an empty error message for speed +} + +bool Version::UpdateStats(const GetStats& stats) { + FileMetaData* f = stats.seek_file; + if (f != NULL) { + f->allowed_seeks--; + if (f->allowed_seeks <= 0 && file_to_compact_ == NULL) { + file_to_compact_ = f; + file_to_compact_level_ = stats.seek_file_level; + return true; + } + } + return false; +} + +bool Version::RecordReadSample(Slice internal_key) { + ParsedInternalKey ikey; + if (!ParseInternalKey(internal_key, &ikey)) { + return false; + } + + struct State { + GetStats stats; // Holds first matching file + int matches; + + static bool Match(void* arg, int level, FileMetaData* f) { + State* state = reinterpret_cast(arg); + state->matches++; + if (state->matches == 1) { + // Remember first match. + state->stats.seek_file = f; + state->stats.seek_file_level = level; + } + // We can stop iterating once we have a second match. + return state->matches < 2; + } + }; + + State state; + state.matches = 0; + ForEachOverlapping(ikey.user_key, internal_key, &state, &State::Match); + + // Must have at least two matches since we want to merge across + // files. But what if we have a single file that contains many + // overwrites and deletions? Should we have another mechanism for + // finding such files? + if (state.matches >= 2) { + // 1MB cost is about 1 seek (see comment in Builder::Apply). + return UpdateStats(state.stats); + } + return false; +} + +void Version::Ref() { + ++refs_; +} + +void Version::Unref() { + assert(this != &vset_->dummy_versions_); + assert(refs_ >= 1); + --refs_; + if (refs_ == 0) { + delete this; + } +} + +bool Version::OverlapInLevel(int level, + const Slice* smallest_user_key, + const Slice* largest_user_key) { + return SomeFileOverlapsRange(vset_->icmp_, (level > 0), files_[level], + smallest_user_key, largest_user_key); +} + +int Version::PickLevelForMemTableOutput( + const Slice& smallest_user_key, + const Slice& largest_user_key) { + int level = 0; + if (!OverlapInLevel(0, &smallest_user_key, &largest_user_key)) { + // Push to next level if there is no overlap in next level, + // and the #bytes overlapping in the level after that are limited. + InternalKey start(smallest_user_key, kMaxSequenceNumber, kValueTypeForSeek); + InternalKey limit(largest_user_key, 0, static_cast(0)); + std::vector overlaps; + while (level < config::kMaxMemCompactLevel) { + if (OverlapInLevel(level + 1, &smallest_user_key, &largest_user_key)) { + break; + } + if (level + 2 < config::kNumLevels) { + // Check that file does not overlap too many grandparent bytes. + GetOverlappingInputs(level + 2, &start, &limit, &overlaps); + const int64_t sum = TotalFileSize(overlaps); + if (sum > kMaxGrandParentOverlapBytes) { + break; + } + } + level++; + } + } + return level; +} + +// Store in "*inputs" all files in "level" that overlap [begin,end] +void Version::GetOverlappingInputs( + int level, + const InternalKey* begin, + const InternalKey* end, + std::vector* inputs) { + assert(level >= 0); + assert(level < config::kNumLevels); + inputs->clear(); + Slice user_begin, user_end; + if (begin != NULL) { + user_begin = begin->user_key(); + } + if (end != NULL) { + user_end = end->user_key(); + } + const Comparator* user_cmp = vset_->icmp_.user_comparator(); + for (size_t i = 0; i < files_[level].size(); ) { + FileMetaData* f = files_[level][i++]; + const Slice file_start = f->smallest.user_key(); + const Slice file_limit = f->largest.user_key(); + if (begin != NULL && user_cmp->Compare(file_limit, user_begin) < 0) { + // "f" is completely before specified range; skip it + } else if (end != NULL && user_cmp->Compare(file_start, user_end) > 0) { + // "f" is completely after specified range; skip it + } else { + inputs->push_back(f); + if (level == 0) { + // Level-0 files may overlap each other. So check if the newly + // added file has expanded the range. If so, restart search. + if (begin != NULL && user_cmp->Compare(file_start, user_begin) < 0) { + user_begin = file_start; + inputs->clear(); + i = 0; + } else if (end != NULL && user_cmp->Compare(file_limit, user_end) > 0) { + user_end = file_limit; + inputs->clear(); + i = 0; + } + } + } + } +} + +std::string Version::DebugString() const { + std::string r; + for (int level = 0; level < config::kNumLevels; level++) { + // E.g., + // --- level 1 --- + // 17:123['a' .. 'd'] + // 20:43['e' .. 'g'] + r.append("--- level "); + AppendNumberTo(&r, level); + r.append(" ---\n"); + const std::vector& files = files_[level]; + for (size_t i = 0; i < files.size(); i++) { + r.push_back(' '); + AppendNumberTo(&r, files[i]->number); + r.push_back(':'); + AppendNumberTo(&r, files[i]->file_size); + r.append("["); + r.append(files[i]->smallest.DebugString()); + r.append(" .. "); + r.append(files[i]->largest.DebugString()); + r.append("]\n"); + } + } + return r; +} + +// A helper class so we can efficiently apply a whole sequence +// of edits to a particular state without creating intermediate +// Versions that contain full copies of the intermediate state. +class VersionSet::Builder { + private: + // Helper to sort by v->files_[file_number].smallest + struct BySmallestKey { + const InternalKeyComparator* internal_comparator; + + bool operator()(FileMetaData* f1, FileMetaData* f2) const { + int r = internal_comparator->Compare(f1->smallest, f2->smallest); + if (r != 0) { + return (r < 0); + } else { + // Break ties by file number + return (f1->number < f2->number); + } + } + }; + + typedef std::set FileSet; + struct LevelState { + std::set deleted_files; + FileSet* added_files; + }; + + VersionSet* vset_; + Version* base_; + LevelState levels_[config::kNumLevels]; + + public: + // Initialize a builder with the files from *base and other info from *vset + Builder(VersionSet* vset, Version* base) + : vset_(vset), + base_(base) { + base_->Ref(); + BySmallestKey cmp; + cmp.internal_comparator = &vset_->icmp_; + for (int level = 0; level < config::kNumLevels; level++) { + levels_[level].added_files = new FileSet(cmp); + } + } + + ~Builder() { + for (int level = 0; level < config::kNumLevels; level++) { + const FileSet* added = levels_[level].added_files; + std::vector to_unref; + to_unref.reserve(added->size()); + for (FileSet::const_iterator it = added->begin(); + it != added->end(); ++it) { + to_unref.push_back(*it); + } + delete added; + for (uint32_t i = 0; i < to_unref.size(); i++) { + FileMetaData* f = to_unref[i]; + f->refs--; + if (f->refs <= 0) { + delete f; + } + } + } + base_->Unref(); + } + + // Apply all of the edits in *edit to the current state. + void Apply(VersionEdit* edit) { + // Update compaction pointers + for (size_t i = 0; i < edit->compact_pointers_.size(); i++) { + const int level = edit->compact_pointers_[i].first; + vset_->compact_pointer_[level] = + edit->compact_pointers_[i].second.Encode().ToString(); + } + + // Delete files + const VersionEdit::DeletedFileSet& del = edit->deleted_files_; + for (VersionEdit::DeletedFileSet::const_iterator iter = del.begin(); + iter != del.end(); + ++iter) { + const int level = iter->first; + const uint64_t number = iter->second; + levels_[level].deleted_files.insert(number); + } + + // Add new files + for (size_t i = 0; i < edit->new_files_.size(); i++) { + const int level = edit->new_files_[i].first; + FileMetaData* f = new FileMetaData(edit->new_files_[i].second); + f->refs = 1; + + // We arrange to automatically compact this file after + // a certain number of seeks. Let's assume: + // (1) One seek costs 10ms + // (2) Writing or reading 1MB costs 10ms (100MB/s) + // (3) A compaction of 1MB does 25MB of IO: + // 1MB read from this level + // 10-12MB read from next level (boundaries may be misaligned) + // 10-12MB written to next level + // This implies that 25 seeks cost the same as the compaction + // of 1MB of data. I.e., one seek costs approximately the + // same as the compaction of 40KB of data. We are a little + // conservative and allow approximately one seek for every 16KB + // of data before triggering a compaction. + f->allowed_seeks = (f->file_size / 16384); + if (f->allowed_seeks < 100) f->allowed_seeks = 100; + + levels_[level].deleted_files.erase(f->number); + levels_[level].added_files->insert(f); + } + } + + // Save the current state in *v. + void SaveTo(Version* v) { + BySmallestKey cmp; + cmp.internal_comparator = &vset_->icmp_; + for (int level = 0; level < config::kNumLevels; level++) { + // Merge the set of added files with the set of pre-existing files. + // Drop any deleted files. Store the result in *v. + const std::vector& base_files = base_->files_[level]; + std::vector::const_iterator base_iter = base_files.begin(); + std::vector::const_iterator base_end = base_files.end(); + const FileSet* added = levels_[level].added_files; + v->files_[level].reserve(base_files.size() + added->size()); + for (FileSet::const_iterator added_iter = added->begin(); + added_iter != added->end(); + ++added_iter) { + // Add all smaller files listed in base_ + for (std::vector::const_iterator bpos + = std::upper_bound(base_iter, base_end, *added_iter, cmp); + base_iter != bpos; + ++base_iter) { + MaybeAddFile(v, level, *base_iter); + } + + MaybeAddFile(v, level, *added_iter); + } + + // Add remaining base files + for (; base_iter != base_end; ++base_iter) { + MaybeAddFile(v, level, *base_iter); + } + +#ifndef NDEBUG + // Make sure there is no overlap in levels > 0 + if (level > 0) { + for (uint32_t i = 1; i < v->files_[level].size(); i++) { + const InternalKey& prev_end = v->files_[level][i-1]->largest; + const InternalKey& this_begin = v->files_[level][i]->smallest; + if (vset_->icmp_.Compare(prev_end, this_begin) >= 0) { + fprintf(stderr, "overlapping ranges in same level %s vs. %s\n", + prev_end.DebugString().c_str(), + this_begin.DebugString().c_str()); + abort(); + } + } + } +#endif + } + } + + void MaybeAddFile(Version* v, int level, FileMetaData* f) { + if (levels_[level].deleted_files.count(f->number) > 0) { + // File is deleted: do nothing + } else { + std::vector* files = &v->files_[level]; + if (level > 0 && !files->empty()) { + // Must not overlap + assert(vset_->icmp_.Compare((*files)[files->size()-1]->largest, + f->smallest) < 0); + } + f->refs++; + files->push_back(f); + } + } +}; + +VersionSet::VersionSet(const std::string& dbname, + const Options* options, + TableCache* table_cache, + const InternalKeyComparator* cmp) + : env_(options->env), + dbname_(dbname), + options_(options), + table_cache_(table_cache), + icmp_(*cmp), + next_file_number_(2), + manifest_file_number_(0), // Filled by Recover() + last_sequence_(0), + log_number_(0), + prev_log_number_(0), + descriptor_file_(NULL), + descriptor_log_(NULL), + dummy_versions_(this), + current_(NULL) { + AppendVersion(new Version(this)); +} + +VersionSet::~VersionSet() { + current_->Unref(); + assert(dummy_versions_.next_ == &dummy_versions_); // List must be empty + delete descriptor_log_; + delete descriptor_file_; +} + +void VersionSet::AppendVersion(Version* v) { + // Make "v" current + assert(v->refs_ == 0); + assert(v != current_); + if (current_ != NULL) { + current_->Unref(); + } + current_ = v; + v->Ref(); + + // Append to linked list + v->prev_ = dummy_versions_.prev_; + v->next_ = &dummy_versions_; + v->prev_->next_ = v; + v->next_->prev_ = v; +} + +Status VersionSet::LogAndApply(VersionEdit* edit, port::Mutex* mu) { + if (edit->has_log_number_) { + assert(edit->log_number_ >= log_number_); + assert(edit->log_number_ < next_file_number_); + } else { + edit->SetLogNumber(log_number_); + } + + if (!edit->has_prev_log_number_) { + edit->SetPrevLogNumber(prev_log_number_); + } + + edit->SetNextFile(next_file_number_); + edit->SetLastSequence(last_sequence_); + + Version* v = new Version(this); + { + Builder builder(this, current_); + builder.Apply(edit); + builder.SaveTo(v); + } + Finalize(v); + + // Initialize new descriptor log file if necessary by creating + // a temporary file that contains a snapshot of the current version. + std::string new_manifest_file; + Status s; + if (descriptor_log_ == NULL) { + // No reason to unlock *mu here since we only hit this path in the + // first call to LogAndApply (when opening the database). + assert(descriptor_file_ == NULL); + new_manifest_file = DescriptorFileName(dbname_, manifest_file_number_); + edit->SetNextFile(next_file_number_); + s = env_->NewWritableFile(new_manifest_file, &descriptor_file_); + if (s.ok()) { + descriptor_log_ = new log::Writer(descriptor_file_); + s = WriteSnapshot(descriptor_log_); + } + } + + // Unlock during expensive MANIFEST log write + { + mu->Unlock(); + + // Write new record to MANIFEST log + if (s.ok()) { + std::string record; + edit->EncodeTo(&record); + s = descriptor_log_->AddRecord(record); + if (s.ok()) { + s = descriptor_file_->Sync(); + } + if (!s.ok()) { + Log(options_->info_log, "MANIFEST write: %s\n", s.ToString().c_str()); + } + } + + // If we just created a new descriptor file, install it by writing a + // new CURRENT file that points to it. + if (s.ok() && !new_manifest_file.empty()) { + s = SetCurrentFile(env_, dbname_, manifest_file_number_); + } + + mu->Lock(); + } + + // Install the new version + if (s.ok()) { + AppendVersion(v); + log_number_ = edit->log_number_; + prev_log_number_ = edit->prev_log_number_; + } else { + delete v; + if (!new_manifest_file.empty()) { + delete descriptor_log_; + delete descriptor_file_; + descriptor_log_ = NULL; + descriptor_file_ = NULL; + env_->DeleteFile(new_manifest_file); + } + } + + return s; +} + +Status VersionSet::Recover() { + struct LogReporter : public log::Reader::Reporter { + Status* status; + virtual void Corruption(size_t bytes, const Status& s) { + if (this->status->ok()) *this->status = s; + } + }; + + // Read "CURRENT" file, which contains a pointer to the current manifest file + std::string current; + Status s = ReadFileToString(env_, CurrentFileName(dbname_), ¤t); + if (!s.ok()) { + return s; + } + if (current.empty() || current[current.size()-1] != '\n') { + return Status::Corruption("CURRENT file does not end with newline"); + } + current.resize(current.size() - 1); + + std::string dscname = dbname_ + "/" + current; + SequentialFile* file; + s = env_->NewSequentialFile(dscname, &file); + if (!s.ok()) { + return s; + } + + bool have_log_number = false; + bool have_prev_log_number = false; + bool have_next_file = false; + bool have_last_sequence = false; + uint64_t next_file = 0; + uint64_t last_sequence = 0; + uint64_t log_number = 0; + uint64_t prev_log_number = 0; + Builder builder(this, current_); + + { + LogReporter reporter; + reporter.status = &s; + log::Reader reader(file, &reporter, true/*checksum*/, 0/*initial_offset*/); + Slice record; + std::string scratch; + while (reader.ReadRecord(&record, &scratch) && s.ok()) { + VersionEdit edit; + s = edit.DecodeFrom(record); + if (s.ok()) { + if (edit.has_comparator_ && + edit.comparator_ != icmp_.user_comparator()->Name()) { + s = Status::InvalidArgument( + edit.comparator_ + " does not match existing comparator ", + icmp_.user_comparator()->Name()); + } + } + + if (s.ok()) { + builder.Apply(&edit); + } + + if (edit.has_log_number_) { + log_number = edit.log_number_; + have_log_number = true; + } + + if (edit.has_prev_log_number_) { + prev_log_number = edit.prev_log_number_; + have_prev_log_number = true; + } + + if (edit.has_next_file_number_) { + next_file = edit.next_file_number_; + have_next_file = true; + } + + if (edit.has_last_sequence_) { + last_sequence = edit.last_sequence_; + have_last_sequence = true; + } + } + } + delete file; + file = NULL; + + if (s.ok()) { + if (!have_next_file) { + s = Status::Corruption("no meta-nextfile entry in descriptor"); + } else if (!have_log_number) { + s = Status::Corruption("no meta-lognumber entry in descriptor"); + } else if (!have_last_sequence) { + s = Status::Corruption("no last-sequence-number entry in descriptor"); + } + + if (!have_prev_log_number) { + prev_log_number = 0; + } + + MarkFileNumberUsed(prev_log_number); + MarkFileNumberUsed(log_number); + } + + if (s.ok()) { + Version* v = new Version(this); + builder.SaveTo(v); + // Install recovered version + Finalize(v); + AppendVersion(v); + manifest_file_number_ = next_file; + next_file_number_ = next_file + 1; + last_sequence_ = last_sequence; + log_number_ = log_number; + prev_log_number_ = prev_log_number; + } + + return s; +} + +void VersionSet::MarkFileNumberUsed(uint64_t number) { + if (next_file_number_ <= number) { + next_file_number_ = number + 1; + } +} + +void VersionSet::Finalize(Version* v) { + // Precomputed best level for next compaction + int best_level = -1; + double best_score = -1; + + for (int level = 0; level < config::kNumLevels-1; level++) { + double score; + if (level == 0) { + // We treat level-0 specially by bounding the number of files + // instead of number of bytes for two reasons: + // + // (1) With larger write-buffer sizes, it is nice not to do too + // many level-0 compactions. + // + // (2) The files in level-0 are merged on every read and + // therefore we wish to avoid too many files when the individual + // file size is small (perhaps because of a small write-buffer + // setting, or very high compression ratios, or lots of + // overwrites/deletions). + score = v->files_[level].size() / + static_cast(config::kL0_CompactionTrigger); + } else { + // Compute the ratio of current size to size limit. + const uint64_t level_bytes = TotalFileSize(v->files_[level]); + score = static_cast(level_bytes) / MaxBytesForLevel(level); + } + + if (score > best_score) { + best_level = level; + best_score = score; + } + } + + v->compaction_level_ = best_level; + v->compaction_score_ = best_score; +} + +Status VersionSet::WriteSnapshot(log::Writer* log) { + // TODO: Break up into multiple records to reduce memory usage on recovery? + + // Save metadata + VersionEdit edit; + edit.SetComparatorName(icmp_.user_comparator()->Name()); + + // Save compaction pointers + for (int level = 0; level < config::kNumLevels; level++) { + if (!compact_pointer_[level].empty()) { + InternalKey key; + key.DecodeFrom(compact_pointer_[level]); + edit.SetCompactPointer(level, key); + } + } + + // Save files + for (int level = 0; level < config::kNumLevels; level++) { + const std::vector& files = current_->files_[level]; + for (size_t i = 0; i < files.size(); i++) { + const FileMetaData* f = files[i]; + edit.AddFile(level, f->number, f->file_size, f->smallest, f->largest); + } + } + + std::string record; + edit.EncodeTo(&record); + return log->AddRecord(record); +} + +int VersionSet::NumLevelFiles(int level) const { + assert(level >= 0); + assert(level < config::kNumLevels); + return current_->files_[level].size(); +} + +const char* VersionSet::LevelSummary(LevelSummaryStorage* scratch) const { + // Update code if kNumLevels changes + assert(config::kNumLevels == 7); + snprintf(scratch->buffer, sizeof(scratch->buffer), + "files[ %d %d %d %d %d %d %d ]", + int(current_->files_[0].size()), + int(current_->files_[1].size()), + int(current_->files_[2].size()), + int(current_->files_[3].size()), + int(current_->files_[4].size()), + int(current_->files_[5].size()), + int(current_->files_[6].size())); + return scratch->buffer; +} + +uint64_t VersionSet::ApproximateOffsetOf(Version* v, const InternalKey& ikey) { + uint64_t result = 0; + for (int level = 0; level < config::kNumLevels; level++) { + const std::vector& files = v->files_[level]; + for (size_t i = 0; i < files.size(); i++) { + if (icmp_.Compare(files[i]->largest, ikey) <= 0) { + // Entire file is before "ikey", so just add the file size + result += files[i]->file_size; + } else if (icmp_.Compare(files[i]->smallest, ikey) > 0) { + // Entire file is after "ikey", so ignore + if (level > 0) { + // Files other than level 0 are sorted by meta->smallest, so + // no further files in this level will contain data for + // "ikey". + break; + } + } else { + // "ikey" falls in the range for this table. Add the + // approximate offset of "ikey" within the table. + Table* tableptr; + Iterator* iter = table_cache_->NewIterator( + ReadOptions(), files[i]->number, files[i]->file_size, &tableptr); + if (tableptr != NULL) { + result += tableptr->ApproximateOffsetOf(ikey.Encode()); + } + delete iter; + } + } + } + return result; +} + +void VersionSet::AddLiveFiles(std::set* live) { + for (Version* v = dummy_versions_.next_; + v != &dummy_versions_; + v = v->next_) { + for (int level = 0; level < config::kNumLevels; level++) { + const std::vector& files = v->files_[level]; + for (size_t i = 0; i < files.size(); i++) { + live->insert(files[i]->number); + } + } + } +} + +int64_t VersionSet::NumLevelBytes(int level) const { + assert(level >= 0); + assert(level < config::kNumLevels); + return TotalFileSize(current_->files_[level]); +} + +int64_t VersionSet::MaxNextLevelOverlappingBytes() { + int64_t result = 0; + std::vector overlaps; + for (int level = 1; level < config::kNumLevels - 1; level++) { + for (size_t i = 0; i < current_->files_[level].size(); i++) { + const FileMetaData* f = current_->files_[level][i]; + current_->GetOverlappingInputs(level+1, &f->smallest, &f->largest, + &overlaps); + const int64_t sum = TotalFileSize(overlaps); + if (sum > result) { + result = sum; + } + } + } + return result; +} + +// Stores the minimal range that covers all entries in inputs in +// *smallest, *largest. +// REQUIRES: inputs is not empty +void VersionSet::GetRange(const std::vector& inputs, + InternalKey* smallest, + InternalKey* largest) { + assert(!inputs.empty()); + smallest->Clear(); + largest->Clear(); + for (size_t i = 0; i < inputs.size(); i++) { + FileMetaData* f = inputs[i]; + if (i == 0) { + *smallest = f->smallest; + *largest = f->largest; + } else { + if (icmp_.Compare(f->smallest, *smallest) < 0) { + *smallest = f->smallest; + } + if (icmp_.Compare(f->largest, *largest) > 0) { + *largest = f->largest; + } + } + } +} + +// Stores the minimal range that covers all entries in inputs1 and inputs2 +// in *smallest, *largest. +// REQUIRES: inputs is not empty +void VersionSet::GetRange2(const std::vector& inputs1, + const std::vector& inputs2, + InternalKey* smallest, + InternalKey* largest) { + std::vector all = inputs1; + all.insert(all.end(), inputs2.begin(), inputs2.end()); + GetRange(all, smallest, largest); +} + +Iterator* VersionSet::MakeInputIterator(Compaction* c) { + ReadOptions options; + options.verify_checksums = options_->paranoid_checks; + options.fill_cache = false; + + // Level-0 files have to be merged together. For other levels, + // we will make a concatenating iterator per level. + // TODO(opt): use concatenating iterator for level-0 if there is no overlap + const int space = (c->level() == 0 ? c->inputs_[0].size() + 1 : 2); + Iterator** list = new Iterator*[space]; + int num = 0; + for (int which = 0; which < 2; which++) { + if (!c->inputs_[which].empty()) { + if (c->level() + which == 0) { + const std::vector& files = c->inputs_[which]; + for (size_t i = 0; i < files.size(); i++) { + list[num++] = table_cache_->NewIterator( + options, files[i]->number, files[i]->file_size); + } + } else { + // Create concatenating iterator for the files from this level + list[num++] = NewTwoLevelIterator( + new Version::LevelFileNumIterator(icmp_, &c->inputs_[which]), + &GetFileIterator, table_cache_, options); + } + } + } + assert(num <= space); + Iterator* result = NewMergingIterator(&icmp_, list, num); + delete[] list; + return result; +} + +Compaction* VersionSet::PickCompaction() { + Compaction* c; + int level; + + // We prefer compactions triggered by too much data in a level over + // the compactions triggered by seeks. + const bool size_compaction = (current_->compaction_score_ >= 1); + const bool seek_compaction = (current_->file_to_compact_ != NULL); + if (size_compaction) { + level = current_->compaction_level_; + assert(level >= 0); + assert(level+1 < config::kNumLevels); + c = new Compaction(level); + + // Pick the first file that comes after compact_pointer_[level] + for (size_t i = 0; i < current_->files_[level].size(); i++) { + FileMetaData* f = current_->files_[level][i]; + if (compact_pointer_[level].empty() || + icmp_.Compare(f->largest.Encode(), compact_pointer_[level]) > 0) { + c->inputs_[0].push_back(f); + break; + } + } + if (c->inputs_[0].empty()) { + // Wrap-around to the beginning of the key space + c->inputs_[0].push_back(current_->files_[level][0]); + } + } else if (seek_compaction) { + level = current_->file_to_compact_level_; + c = new Compaction(level); + c->inputs_[0].push_back(current_->file_to_compact_); + } else { + return NULL; + } + + c->input_version_ = current_; + c->input_version_->Ref(); + + // Files in level 0 may overlap each other, so pick up all overlapping ones + if (level == 0) { + InternalKey smallest, largest; + GetRange(c->inputs_[0], &smallest, &largest); + // Note that the next call will discard the file we placed in + // c->inputs_[0] earlier and replace it with an overlapping set + // which will include the picked file. + current_->GetOverlappingInputs(0, &smallest, &largest, &c->inputs_[0]); + assert(!c->inputs_[0].empty()); + } + + SetupOtherInputs(c); + + return c; +} + +void VersionSet::SetupOtherInputs(Compaction* c) { + const int level = c->level(); + InternalKey smallest, largest; + GetRange(c->inputs_[0], &smallest, &largest); + + current_->GetOverlappingInputs(level+1, &smallest, &largest, &c->inputs_[1]); + + // Get entire range covered by compaction + InternalKey all_start, all_limit; + GetRange2(c->inputs_[0], c->inputs_[1], &all_start, &all_limit); + + // See if we can grow the number of inputs in "level" without + // changing the number of "level+1" files we pick up. + if (!c->inputs_[1].empty()) { + std::vector expanded0; + current_->GetOverlappingInputs(level, &all_start, &all_limit, &expanded0); + const int64_t inputs0_size = TotalFileSize(c->inputs_[0]); + const int64_t inputs1_size = TotalFileSize(c->inputs_[1]); + const int64_t expanded0_size = TotalFileSize(expanded0); + if (expanded0.size() > c->inputs_[0].size() && + inputs1_size + expanded0_size < kExpandedCompactionByteSizeLimit) { + InternalKey new_start, new_limit; + GetRange(expanded0, &new_start, &new_limit); + std::vector expanded1; + current_->GetOverlappingInputs(level+1, &new_start, &new_limit, + &expanded1); + if (expanded1.size() == c->inputs_[1].size()) { + Log(options_->info_log, + "Expanding@%d %d+%d (%ld+%ld bytes) to %d+%d (%ld+%ld bytes)\n", + level, + int(c->inputs_[0].size()), + int(c->inputs_[1].size()), + long(inputs0_size), long(inputs1_size), + int(expanded0.size()), + int(expanded1.size()), + long(expanded0_size), long(inputs1_size)); + smallest = new_start; + largest = new_limit; + c->inputs_[0] = expanded0; + c->inputs_[1] = expanded1; + GetRange2(c->inputs_[0], c->inputs_[1], &all_start, &all_limit); + } + } + } + + // Compute the set of grandparent files that overlap this compaction + // (parent == level+1; grandparent == level+2) + if (level + 2 < config::kNumLevels) { + current_->GetOverlappingInputs(level + 2, &all_start, &all_limit, + &c->grandparents_); + } + + if (false) { + Log(options_->info_log, "Compacting %d '%s' .. '%s'", + level, + smallest.DebugString().c_str(), + largest.DebugString().c_str()); + } + + // Update the place where we will do the next compaction for this level. + // We update this immediately instead of waiting for the VersionEdit + // to be applied so that if the compaction fails, we will try a different + // key range next time. + compact_pointer_[level] = largest.Encode().ToString(); + c->edit_.SetCompactPointer(level, largest); +} + +Compaction* VersionSet::CompactRange( + int level, + const InternalKey* begin, + const InternalKey* end) { + std::vector inputs; + current_->GetOverlappingInputs(level, begin, end, &inputs); + if (inputs.empty()) { + return NULL; + } + + // Avoid compacting too much in one shot in case the range is large. + // But we cannot do this for level-0 since level-0 files can overlap + // and we must not pick one file and drop another older file if the + // two files overlap. + if (level > 0) { + const uint64_t limit = MaxFileSizeForLevel(level); + uint64_t total = 0; + for (size_t i = 0; i < inputs.size(); i++) { + uint64_t s = inputs[i]->file_size; + total += s; + if (total >= limit) { + inputs.resize(i + 1); + break; + } + } + } + + Compaction* c = new Compaction(level); + c->input_version_ = current_; + c->input_version_->Ref(); + c->inputs_[0] = inputs; + SetupOtherInputs(c); + return c; +} + +Compaction::Compaction(int level) + : level_(level), + max_output_file_size_(MaxFileSizeForLevel(level)), + input_version_(NULL), + grandparent_index_(0), + seen_key_(false), + overlapped_bytes_(0) { + for (int i = 0; i < config::kNumLevels; i++) { + level_ptrs_[i] = 0; + } +} + +Compaction::~Compaction() { + if (input_version_ != NULL) { + input_version_->Unref(); + } +} + +bool Compaction::IsTrivialMove() const { + // Avoid a move if there is lots of overlapping grandparent data. + // Otherwise, the move could create a parent file that will require + // a very expensive merge later on. + return (num_input_files(0) == 1 && + num_input_files(1) == 0 && + TotalFileSize(grandparents_) <= kMaxGrandParentOverlapBytes); +} + +void Compaction::AddInputDeletions(VersionEdit* edit) { + for (int which = 0; which < 2; which++) { + for (size_t i = 0; i < inputs_[which].size(); i++) { + edit->DeleteFile(level_ + which, inputs_[which][i]->number); + } + } +} + +bool Compaction::IsBaseLevelForKey(const Slice& user_key) { + // Maybe use binary search to find right entry instead of linear search? + const Comparator* user_cmp = input_version_->vset_->icmp_.user_comparator(); + for (int lvl = level_ + 2; lvl < config::kNumLevels; lvl++) { + const std::vector& files = input_version_->files_[lvl]; + for (; level_ptrs_[lvl] < files.size(); ) { + FileMetaData* f = files[level_ptrs_[lvl]]; + if (user_cmp->Compare(user_key, f->largest.user_key()) <= 0) { + // We've advanced far enough + if (user_cmp->Compare(user_key, f->smallest.user_key()) >= 0) { + // Key falls in this file's range, so definitely not base level + return false; + } + break; + } + level_ptrs_[lvl]++; + } + } + return true; +} + +bool Compaction::ShouldStopBefore(const Slice& internal_key) { + // Scan to find earliest grandparent file that contains key. + const InternalKeyComparator* icmp = &input_version_->vset_->icmp_; + while (grandparent_index_ < grandparents_.size() && + icmp->Compare(internal_key, + grandparents_[grandparent_index_]->largest.Encode()) > 0) { + if (seen_key_) { + overlapped_bytes_ += grandparents_[grandparent_index_]->file_size; + } + grandparent_index_++; + } + seen_key_ = true; + + if (overlapped_bytes_ > kMaxGrandParentOverlapBytes) { + // Too much overlap for current output; start new output + overlapped_bytes_ = 0; + return true; + } else { + return false; + } +} + +void Compaction::ReleaseInputs() { + if (input_version_ != NULL) { + input_version_->Unref(); + input_version_ = NULL; + } +} + +} // namespace leveldb diff --git a/src/leveldb/db/version_set.h b/src/leveldb/db/version_set.h new file mode 100644 index 0000000..8dc14b8 --- /dev/null +++ b/src/leveldb/db/version_set.h @@ -0,0 +1,396 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. +// +// The representation of a DBImpl consists of a set of Versions. The +// newest version is called "current". Older versions may be kept +// around to provide a consistent view to live iterators. +// +// Each Version keeps track of a set of Table files per level. The +// entire set of versions is maintained in a VersionSet. +// +// Version,VersionSet are thread-compatible, but require external +// synchronization on all accesses. + +#ifndef STORAGE_LEVELDB_DB_VERSION_SET_H_ +#define STORAGE_LEVELDB_DB_VERSION_SET_H_ + +#include +#include +#include +#include "db/dbformat.h" +#include "db/version_edit.h" +#include "port/port.h" +#include "port/thread_annotations.h" + +namespace leveldb { + +namespace log { class Writer; } + +class Compaction; +class Iterator; +class MemTable; +class TableBuilder; +class TableCache; +class Version; +class VersionSet; +class WritableFile; + +// Return the smallest index i such that files[i]->largest >= key. +// Return files.size() if there is no such file. +// REQUIRES: "files" contains a sorted list of non-overlapping files. +extern int FindFile(const InternalKeyComparator& icmp, + const std::vector& files, + const Slice& key); + +// Returns true iff some file in "files" overlaps the user key range +// [*smallest,*largest]. +// smallest==NULL represents a key smaller than all keys in the DB. +// largest==NULL represents a key largest than all keys in the DB. +// REQUIRES: If disjoint_sorted_files, files[] contains disjoint ranges +// in sorted order. +extern bool SomeFileOverlapsRange( + const InternalKeyComparator& icmp, + bool disjoint_sorted_files, + const std::vector& files, + const Slice* smallest_user_key, + const Slice* largest_user_key); + +class Version { + public: + // Append to *iters a sequence of iterators that will + // yield the contents of this Version when merged together. + // REQUIRES: This version has been saved (see VersionSet::SaveTo) + void AddIterators(const ReadOptions&, std::vector* iters); + + // Lookup the value for key. If found, store it in *val and + // return OK. Else return a non-OK status. Fills *stats. + // REQUIRES: lock is not held + struct GetStats { + FileMetaData* seek_file; + int seek_file_level; + }; + Status Get(const ReadOptions&, const LookupKey& key, std::string* val, + GetStats* stats); + + // Adds "stats" into the current state. Returns true if a new + // compaction may need to be triggered, false otherwise. + // REQUIRES: lock is held + bool UpdateStats(const GetStats& stats); + + // Record a sample of bytes read at the specified internal key. + // Samples are taken approximately once every config::kReadBytesPeriod + // bytes. Returns true if a new compaction may need to be triggered. + // REQUIRES: lock is held + bool RecordReadSample(Slice key); + + // Reference count management (so Versions do not disappear out from + // under live iterators) + void Ref(); + void Unref(); + + void GetOverlappingInputs( + int level, + const InternalKey* begin, // NULL means before all keys + const InternalKey* end, // NULL means after all keys + std::vector* inputs); + + // Returns true iff some file in the specified level overlaps + // some part of [*smallest_user_key,*largest_user_key]. + // smallest_user_key==NULL represents a key smaller than all keys in the DB. + // largest_user_key==NULL represents a key largest than all keys in the DB. + bool OverlapInLevel(int level, + const Slice* smallest_user_key, + const Slice* largest_user_key); + + // Return the level at which we should place a new memtable compaction + // result that covers the range [smallest_user_key,largest_user_key]. + int PickLevelForMemTableOutput(const Slice& smallest_user_key, + const Slice& largest_user_key); + + int NumFiles(int level) const { return files_[level].size(); } + + // Return a human readable string that describes this version's contents. + std::string DebugString() const; + + private: + friend class Compaction; + friend class VersionSet; + + class LevelFileNumIterator; + Iterator* NewConcatenatingIterator(const ReadOptions&, int level) const; + + // Call func(arg, level, f) for every file that overlaps user_key in + // order from newest to oldest. If an invocation of func returns + // false, makes no more calls. + // + // REQUIRES: user portion of internal_key == user_key. + void ForEachOverlapping(Slice user_key, Slice internal_key, + void* arg, + bool (*func)(void*, int, FileMetaData*)); + + VersionSet* vset_; // VersionSet to which this Version belongs + Version* next_; // Next version in linked list + Version* prev_; // Previous version in linked list + int refs_; // Number of live refs to this version + + // List of files per level + std::vector files_[config::kNumLevels]; + + // Next file to compact based on seek stats. + FileMetaData* file_to_compact_; + int file_to_compact_level_; + + // Level that should be compacted next and its compaction score. + // Score < 1 means compaction is not strictly needed. These fields + // are initialized by Finalize(). + double compaction_score_; + int compaction_level_; + + explicit Version(VersionSet* vset) + : vset_(vset), next_(this), prev_(this), refs_(0), + file_to_compact_(NULL), + file_to_compact_level_(-1), + compaction_score_(-1), + compaction_level_(-1) { + } + + ~Version(); + + // No copying allowed + Version(const Version&); + void operator=(const Version&); +}; + +class VersionSet { + public: + VersionSet(const std::string& dbname, + const Options* options, + TableCache* table_cache, + const InternalKeyComparator*); + ~VersionSet(); + + // Apply *edit to the current version to form a new descriptor that + // is both saved to persistent state and installed as the new + // current version. Will release *mu while actually writing to the file. + // REQUIRES: *mu is held on entry. + // REQUIRES: no other thread concurrently calls LogAndApply() + Status LogAndApply(VersionEdit* edit, port::Mutex* mu) + EXCLUSIVE_LOCKS_REQUIRED(mu); + + // Recover the last saved descriptor from persistent storage. + Status Recover(); + + // Return the current version. + Version* current() const { return current_; } + + // Return the current manifest file number + uint64_t ManifestFileNumber() const { return manifest_file_number_; } + + // Allocate and return a new file number + uint64_t NewFileNumber() { return next_file_number_++; } + + // Arrange to reuse "file_number" unless a newer file number has + // already been allocated. + // REQUIRES: "file_number" was returned by a call to NewFileNumber(). + void ReuseFileNumber(uint64_t file_number) { + if (next_file_number_ == file_number + 1) { + next_file_number_ = file_number; + } + } + + // Return the number of Table files at the specified level. + int NumLevelFiles(int level) const; + + // Return the combined file size of all files at the specified level. + int64_t NumLevelBytes(int level) const; + + // Return the last sequence number. + uint64_t LastSequence() const { return last_sequence_; } + + // Set the last sequence number to s. + void SetLastSequence(uint64_t s) { + assert(s >= last_sequence_); + last_sequence_ = s; + } + + // Mark the specified file number as used. + void MarkFileNumberUsed(uint64_t number); + + // Return the current log file number. + uint64_t LogNumber() const { return log_number_; } + + // Return the log file number for the log file that is currently + // being compacted, or zero if there is no such log file. + uint64_t PrevLogNumber() const { return prev_log_number_; } + + // Pick level and inputs for a new compaction. + // Returns NULL if there is no compaction to be done. + // Otherwise returns a pointer to a heap-allocated object that + // describes the compaction. Caller should delete the result. + Compaction* PickCompaction(); + + // Return a compaction object for compacting the range [begin,end] in + // the specified level. Returns NULL if there is nothing in that + // level that overlaps the specified range. Caller should delete + // the result. + Compaction* CompactRange( + int level, + const InternalKey* begin, + const InternalKey* end); + + // Return the maximum overlapping data (in bytes) at next level for any + // file at a level >= 1. + int64_t MaxNextLevelOverlappingBytes(); + + // Create an iterator that reads over the compaction inputs for "*c". + // The caller should delete the iterator when no longer needed. + Iterator* MakeInputIterator(Compaction* c); + + // Returns true iff some level needs a compaction. + bool NeedsCompaction() const { + Version* v = current_; + return (v->compaction_score_ >= 1) || (v->file_to_compact_ != NULL); + } + + // Add all files listed in any live version to *live. + // May also mutate some internal state. + void AddLiveFiles(std::set* live); + + // Return the approximate offset in the database of the data for + // "key" as of version "v". + uint64_t ApproximateOffsetOf(Version* v, const InternalKey& key); + + // Return a human-readable short (single-line) summary of the number + // of files per level. Uses *scratch as backing store. + struct LevelSummaryStorage { + char buffer[100]; + }; + const char* LevelSummary(LevelSummaryStorage* scratch) const; + + private: + class Builder; + + friend class Compaction; + friend class Version; + + void Finalize(Version* v); + + void GetRange(const std::vector& inputs, + InternalKey* smallest, + InternalKey* largest); + + void GetRange2(const std::vector& inputs1, + const std::vector& inputs2, + InternalKey* smallest, + InternalKey* largest); + + void SetupOtherInputs(Compaction* c); + + // Save current contents to *log + Status WriteSnapshot(log::Writer* log); + + void AppendVersion(Version* v); + + Env* const env_; + const std::string dbname_; + const Options* const options_; + TableCache* const table_cache_; + const InternalKeyComparator icmp_; + uint64_t next_file_number_; + uint64_t manifest_file_number_; + uint64_t last_sequence_; + uint64_t log_number_; + uint64_t prev_log_number_; // 0 or backing store for memtable being compacted + + // Opened lazily + WritableFile* descriptor_file_; + log::Writer* descriptor_log_; + Version dummy_versions_; // Head of circular doubly-linked list of versions. + Version* current_; // == dummy_versions_.prev_ + + // Per-level key at which the next compaction at that level should start. + // Either an empty string, or a valid InternalKey. + std::string compact_pointer_[config::kNumLevels]; + + // No copying allowed + VersionSet(const VersionSet&); + void operator=(const VersionSet&); +}; + +// A Compaction encapsulates information about a compaction. +class Compaction { + public: + ~Compaction(); + + // Return the level that is being compacted. Inputs from "level" + // and "level+1" will be merged to produce a set of "level+1" files. + int level() const { return level_; } + + // Return the object that holds the edits to the descriptor done + // by this compaction. + VersionEdit* edit() { return &edit_; } + + // "which" must be either 0 or 1 + int num_input_files(int which) const { return inputs_[which].size(); } + + // Return the ith input file at "level()+which" ("which" must be 0 or 1). + FileMetaData* input(int which, int i) const { return inputs_[which][i]; } + + // Maximum size of files to build during this compaction. + uint64_t MaxOutputFileSize() const { return max_output_file_size_; } + + // Is this a trivial compaction that can be implemented by just + // moving a single input file to the next level (no merging or splitting) + bool IsTrivialMove() const; + + // Add all inputs to this compaction as delete operations to *edit. + void AddInputDeletions(VersionEdit* edit); + + // Returns true if the information we have available guarantees that + // the compaction is producing data in "level+1" for which no data exists + // in levels greater than "level+1". + bool IsBaseLevelForKey(const Slice& user_key); + + // Returns true iff we should stop building the current output + // before processing "internal_key". + bool ShouldStopBefore(const Slice& internal_key); + + // Release the input version for the compaction, once the compaction + // is successful. + void ReleaseInputs(); + + private: + friend class Version; + friend class VersionSet; + + explicit Compaction(int level); + + int level_; + uint64_t max_output_file_size_; + Version* input_version_; + VersionEdit edit_; + + // Each compaction reads inputs from "level_" and "level_+1" + std::vector inputs_[2]; // The two sets of inputs + + // State used to check for number of of overlapping grandparent files + // (parent == level_ + 1, grandparent == level_ + 2) + std::vector grandparents_; + size_t grandparent_index_; // Index in grandparent_starts_ + bool seen_key_; // Some output key has been seen + int64_t overlapped_bytes_; // Bytes of overlap between current output + // and grandparent files + + // State for implementing IsBaseLevelForKey + + // level_ptrs_ holds indices into input_version_->levels_: our state + // is that we are positioned at one of the file ranges for each + // higher level than the ones involved in this compaction (i.e. for + // all L >= level_ + 2). + size_t level_ptrs_[config::kNumLevels]; +}; + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_DB_VERSION_SET_H_ diff --git a/src/leveldb/db/version_set_test.cc b/src/leveldb/db/version_set_test.cc new file mode 100644 index 0000000..501e34d --- /dev/null +++ b/src/leveldb/db/version_set_test.cc @@ -0,0 +1,179 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "db/version_set.h" +#include "util/logging.h" +#include "util/testharness.h" +#include "util/testutil.h" + +namespace leveldb { + +class FindFileTest { + public: + std::vector files_; + bool disjoint_sorted_files_; + + FindFileTest() : disjoint_sorted_files_(true) { } + + ~FindFileTest() { + for (int i = 0; i < files_.size(); i++) { + delete files_[i]; + } + } + + void Add(const char* smallest, const char* largest, + SequenceNumber smallest_seq = 100, + SequenceNumber largest_seq = 100) { + FileMetaData* f = new FileMetaData; + f->number = files_.size() + 1; + f->smallest = InternalKey(smallest, smallest_seq, kTypeValue); + f->largest = InternalKey(largest, largest_seq, kTypeValue); + files_.push_back(f); + } + + int Find(const char* key) { + InternalKey target(key, 100, kTypeValue); + InternalKeyComparator cmp(BytewiseComparator()); + return FindFile(cmp, files_, target.Encode()); + } + + bool Overlaps(const char* smallest, const char* largest) { + InternalKeyComparator cmp(BytewiseComparator()); + Slice s(smallest != NULL ? smallest : ""); + Slice l(largest != NULL ? largest : ""); + return SomeFileOverlapsRange(cmp, disjoint_sorted_files_, files_, + (smallest != NULL ? &s : NULL), + (largest != NULL ? &l : NULL)); + } +}; + +TEST(FindFileTest, Empty) { + ASSERT_EQ(0, Find("foo")); + ASSERT_TRUE(! Overlaps("a", "z")); + ASSERT_TRUE(! Overlaps(NULL, "z")); + ASSERT_TRUE(! Overlaps("a", NULL)); + ASSERT_TRUE(! Overlaps(NULL, NULL)); +} + +TEST(FindFileTest, Single) { + Add("p", "q"); + ASSERT_EQ(0, Find("a")); + ASSERT_EQ(0, Find("p")); + ASSERT_EQ(0, Find("p1")); + ASSERT_EQ(0, Find("q")); + ASSERT_EQ(1, Find("q1")); + ASSERT_EQ(1, Find("z")); + + ASSERT_TRUE(! Overlaps("a", "b")); + ASSERT_TRUE(! Overlaps("z1", "z2")); + ASSERT_TRUE(Overlaps("a", "p")); + ASSERT_TRUE(Overlaps("a", "q")); + ASSERT_TRUE(Overlaps("a", "z")); + ASSERT_TRUE(Overlaps("p", "p1")); + ASSERT_TRUE(Overlaps("p", "q")); + ASSERT_TRUE(Overlaps("p", "z")); + ASSERT_TRUE(Overlaps("p1", "p2")); + ASSERT_TRUE(Overlaps("p1", "z")); + ASSERT_TRUE(Overlaps("q", "q")); + ASSERT_TRUE(Overlaps("q", "q1")); + + ASSERT_TRUE(! Overlaps(NULL, "j")); + ASSERT_TRUE(! Overlaps("r", NULL)); + ASSERT_TRUE(Overlaps(NULL, "p")); + ASSERT_TRUE(Overlaps(NULL, "p1")); + ASSERT_TRUE(Overlaps("q", NULL)); + ASSERT_TRUE(Overlaps(NULL, NULL)); +} + + +TEST(FindFileTest, Multiple) { + Add("150", "200"); + Add("200", "250"); + Add("300", "350"); + Add("400", "450"); + ASSERT_EQ(0, Find("100")); + ASSERT_EQ(0, Find("150")); + ASSERT_EQ(0, Find("151")); + ASSERT_EQ(0, Find("199")); + ASSERT_EQ(0, Find("200")); + ASSERT_EQ(1, Find("201")); + ASSERT_EQ(1, Find("249")); + ASSERT_EQ(1, Find("250")); + ASSERT_EQ(2, Find("251")); + ASSERT_EQ(2, Find("299")); + ASSERT_EQ(2, Find("300")); + ASSERT_EQ(2, Find("349")); + ASSERT_EQ(2, Find("350")); + ASSERT_EQ(3, Find("351")); + ASSERT_EQ(3, Find("400")); + ASSERT_EQ(3, Find("450")); + ASSERT_EQ(4, Find("451")); + + ASSERT_TRUE(! Overlaps("100", "149")); + ASSERT_TRUE(! Overlaps("251", "299")); + ASSERT_TRUE(! Overlaps("451", "500")); + ASSERT_TRUE(! Overlaps("351", "399")); + + ASSERT_TRUE(Overlaps("100", "150")); + ASSERT_TRUE(Overlaps("100", "200")); + ASSERT_TRUE(Overlaps("100", "300")); + ASSERT_TRUE(Overlaps("100", "400")); + ASSERT_TRUE(Overlaps("100", "500")); + ASSERT_TRUE(Overlaps("375", "400")); + ASSERT_TRUE(Overlaps("450", "450")); + ASSERT_TRUE(Overlaps("450", "500")); +} + +TEST(FindFileTest, MultipleNullBoundaries) { + Add("150", "200"); + Add("200", "250"); + Add("300", "350"); + Add("400", "450"); + ASSERT_TRUE(! Overlaps(NULL, "149")); + ASSERT_TRUE(! Overlaps("451", NULL)); + ASSERT_TRUE(Overlaps(NULL, NULL)); + ASSERT_TRUE(Overlaps(NULL, "150")); + ASSERT_TRUE(Overlaps(NULL, "199")); + ASSERT_TRUE(Overlaps(NULL, "200")); + ASSERT_TRUE(Overlaps(NULL, "201")); + ASSERT_TRUE(Overlaps(NULL, "400")); + ASSERT_TRUE(Overlaps(NULL, "800")); + ASSERT_TRUE(Overlaps("100", NULL)); + ASSERT_TRUE(Overlaps("200", NULL)); + ASSERT_TRUE(Overlaps("449", NULL)); + ASSERT_TRUE(Overlaps("450", NULL)); +} + +TEST(FindFileTest, OverlapSequenceChecks) { + Add("200", "200", 5000, 3000); + ASSERT_TRUE(! Overlaps("199", "199")); + ASSERT_TRUE(! Overlaps("201", "300")); + ASSERT_TRUE(Overlaps("200", "200")); + ASSERT_TRUE(Overlaps("190", "200")); + ASSERT_TRUE(Overlaps("200", "210")); +} + +TEST(FindFileTest, OverlappingFiles) { + Add("150", "600"); + Add("400", "500"); + disjoint_sorted_files_ = false; + ASSERT_TRUE(! Overlaps("100", "149")); + ASSERT_TRUE(! Overlaps("601", "700")); + ASSERT_TRUE(Overlaps("100", "150")); + ASSERT_TRUE(Overlaps("100", "200")); + ASSERT_TRUE(Overlaps("100", "300")); + ASSERT_TRUE(Overlaps("100", "400")); + ASSERT_TRUE(Overlaps("100", "500")); + ASSERT_TRUE(Overlaps("375", "400")); + ASSERT_TRUE(Overlaps("450", "450")); + ASSERT_TRUE(Overlaps("450", "500")); + ASSERT_TRUE(Overlaps("450", "700")); + ASSERT_TRUE(Overlaps("600", "700")); +} + +} // namespace leveldb + +int main(int argc, char** argv) { + return leveldb::test::RunAllTests(); +} diff --git a/src/leveldb/db/write_batch.cc b/src/leveldb/db/write_batch.cc new file mode 100644 index 0000000..33f4a42 --- /dev/null +++ b/src/leveldb/db/write_batch.cc @@ -0,0 +1,147 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. +// +// WriteBatch::rep_ := +// sequence: fixed64 +// count: fixed32 +// data: record[count] +// record := +// kTypeValue varstring varstring | +// kTypeDeletion varstring +// varstring := +// len: varint32 +// data: uint8[len] + +#include "leveldb/write_batch.h" + +#include "leveldb/db.h" +#include "db/dbformat.h" +#include "db/memtable.h" +#include "db/write_batch_internal.h" +#include "util/coding.h" + +namespace leveldb { + +// WriteBatch header has an 8-byte sequence number followed by a 4-byte count. +static const size_t kHeader = 12; + +WriteBatch::WriteBatch() { + Clear(); +} + +WriteBatch::~WriteBatch() { } + +WriteBatch::Handler::~Handler() { } + +void WriteBatch::Clear() { + rep_.clear(); + rep_.resize(kHeader); +} + +Status WriteBatch::Iterate(Handler* handler) const { + Slice input(rep_); + if (input.size() < kHeader) { + return Status::Corruption("malformed WriteBatch (too small)"); + } + + input.remove_prefix(kHeader); + Slice key, value; + int found = 0; + while (!input.empty()) { + found++; + char tag = input[0]; + input.remove_prefix(1); + switch (tag) { + case kTypeValue: + if (GetLengthPrefixedSlice(&input, &key) && + GetLengthPrefixedSlice(&input, &value)) { + handler->Put(key, value); + } else { + return Status::Corruption("bad WriteBatch Put"); + } + break; + case kTypeDeletion: + if (GetLengthPrefixedSlice(&input, &key)) { + handler->Delete(key); + } else { + return Status::Corruption("bad WriteBatch Delete"); + } + break; + default: + return Status::Corruption("unknown WriteBatch tag"); + } + } + if (found != WriteBatchInternal::Count(this)) { + return Status::Corruption("WriteBatch has wrong count"); + } else { + return Status::OK(); + } +} + +int WriteBatchInternal::Count(const WriteBatch* b) { + return DecodeFixed32(b->rep_.data() + 8); +} + +void WriteBatchInternal::SetCount(WriteBatch* b, int n) { + EncodeFixed32(&b->rep_[8], n); +} + +SequenceNumber WriteBatchInternal::Sequence(const WriteBatch* b) { + return SequenceNumber(DecodeFixed64(b->rep_.data())); +} + +void WriteBatchInternal::SetSequence(WriteBatch* b, SequenceNumber seq) { + EncodeFixed64(&b->rep_[0], seq); +} + +void WriteBatch::Put(const Slice& key, const Slice& value) { + WriteBatchInternal::SetCount(this, WriteBatchInternal::Count(this) + 1); + rep_.push_back(static_cast(kTypeValue)); + PutLengthPrefixedSlice(&rep_, key); + PutLengthPrefixedSlice(&rep_, value); +} + +void WriteBatch::Delete(const Slice& key) { + WriteBatchInternal::SetCount(this, WriteBatchInternal::Count(this) + 1); + rep_.push_back(static_cast(kTypeDeletion)); + PutLengthPrefixedSlice(&rep_, key); +} + +namespace { +class MemTableInserter : public WriteBatch::Handler { + public: + SequenceNumber sequence_; + MemTable* mem_; + + virtual void Put(const Slice& key, const Slice& value) { + mem_->Add(sequence_, kTypeValue, key, value); + sequence_++; + } + virtual void Delete(const Slice& key) { + mem_->Add(sequence_, kTypeDeletion, key, Slice()); + sequence_++; + } +}; +} // namespace + +Status WriteBatchInternal::InsertInto(const WriteBatch* b, + MemTable* memtable) { + MemTableInserter inserter; + inserter.sequence_ = WriteBatchInternal::Sequence(b); + inserter.mem_ = memtable; + return b->Iterate(&inserter); +} + +void WriteBatchInternal::SetContents(WriteBatch* b, const Slice& contents) { + assert(contents.size() >= kHeader); + b->rep_.assign(contents.data(), contents.size()); +} + +void WriteBatchInternal::Append(WriteBatch* dst, const WriteBatch* src) { + SetCount(dst, Count(dst) + Count(src)); + assert(src->rep_.size() >= kHeader); + dst->rep_.append(src->rep_.data() + kHeader, src->rep_.size() - kHeader); +} + +} // namespace leveldb diff --git a/src/leveldb/db/write_batch_internal.h b/src/leveldb/db/write_batch_internal.h new file mode 100644 index 0000000..4423a7f --- /dev/null +++ b/src/leveldb/db/write_batch_internal.h @@ -0,0 +1,49 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#ifndef STORAGE_LEVELDB_DB_WRITE_BATCH_INTERNAL_H_ +#define STORAGE_LEVELDB_DB_WRITE_BATCH_INTERNAL_H_ + +#include "leveldb/write_batch.h" + +namespace leveldb { + +class MemTable; + +// WriteBatchInternal provides static methods for manipulating a +// WriteBatch that we don't want in the public WriteBatch interface. +class WriteBatchInternal { + public: + // Return the number of entries in the batch. + static int Count(const WriteBatch* batch); + + // Set the count for the number of entries in the batch. + static void SetCount(WriteBatch* batch, int n); + + // Return the seqeunce number for the start of this batch. + static SequenceNumber Sequence(const WriteBatch* batch); + + // Store the specified number as the seqeunce number for the start of + // this batch. + static void SetSequence(WriteBatch* batch, SequenceNumber seq); + + static Slice Contents(const WriteBatch* batch) { + return Slice(batch->rep_); + } + + static size_t ByteSize(const WriteBatch* batch) { + return batch->rep_.size(); + } + + static void SetContents(WriteBatch* batch, const Slice& contents); + + static Status InsertInto(const WriteBatch* batch, MemTable* memtable); + + static void Append(WriteBatch* dst, const WriteBatch* src); +}; + +} // namespace leveldb + + +#endif // STORAGE_LEVELDB_DB_WRITE_BATCH_INTERNAL_H_ diff --git a/src/leveldb/db/write_batch_test.cc b/src/leveldb/db/write_batch_test.cc new file mode 100644 index 0000000..9064e3d --- /dev/null +++ b/src/leveldb/db/write_batch_test.cc @@ -0,0 +1,120 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "leveldb/db.h" + +#include "db/memtable.h" +#include "db/write_batch_internal.h" +#include "leveldb/env.h" +#include "util/logging.h" +#include "util/testharness.h" + +namespace leveldb { + +static std::string PrintContents(WriteBatch* b) { + InternalKeyComparator cmp(BytewiseComparator()); + MemTable* mem = new MemTable(cmp); + mem->Ref(); + std::string state; + Status s = WriteBatchInternal::InsertInto(b, mem); + int count = 0; + Iterator* iter = mem->NewIterator(); + for (iter->SeekToFirst(); iter->Valid(); iter->Next()) { + ParsedInternalKey ikey; + ASSERT_TRUE(ParseInternalKey(iter->key(), &ikey)); + switch (ikey.type) { + case kTypeValue: + state.append("Put("); + state.append(ikey.user_key.ToString()); + state.append(", "); + state.append(iter->value().ToString()); + state.append(")"); + count++; + break; + case kTypeDeletion: + state.append("Delete("); + state.append(ikey.user_key.ToString()); + state.append(")"); + count++; + break; + } + state.append("@"); + state.append(NumberToString(ikey.sequence)); + } + delete iter; + if (!s.ok()) { + state.append("ParseError()"); + } else if (count != WriteBatchInternal::Count(b)) { + state.append("CountMismatch()"); + } + mem->Unref(); + return state; +} + +class WriteBatchTest { }; + +TEST(WriteBatchTest, Empty) { + WriteBatch batch; + ASSERT_EQ("", PrintContents(&batch)); + ASSERT_EQ(0, WriteBatchInternal::Count(&batch)); +} + +TEST(WriteBatchTest, Multiple) { + WriteBatch batch; + batch.Put(Slice("foo"), Slice("bar")); + batch.Delete(Slice("box")); + batch.Put(Slice("baz"), Slice("boo")); + WriteBatchInternal::SetSequence(&batch, 100); + ASSERT_EQ(100, WriteBatchInternal::Sequence(&batch)); + ASSERT_EQ(3, WriteBatchInternal::Count(&batch)); + ASSERT_EQ("Put(baz, boo)@102" + "Delete(box)@101" + "Put(foo, bar)@100", + PrintContents(&batch)); +} + +TEST(WriteBatchTest, Corruption) { + WriteBatch batch; + batch.Put(Slice("foo"), Slice("bar")); + batch.Delete(Slice("box")); + WriteBatchInternal::SetSequence(&batch, 200); + Slice contents = WriteBatchInternal::Contents(&batch); + WriteBatchInternal::SetContents(&batch, + Slice(contents.data(),contents.size()-1)); + ASSERT_EQ("Put(foo, bar)@200" + "ParseError()", + PrintContents(&batch)); +} + +TEST(WriteBatchTest, Append) { + WriteBatch b1, b2; + WriteBatchInternal::SetSequence(&b1, 200); + WriteBatchInternal::SetSequence(&b2, 300); + WriteBatchInternal::Append(&b1, &b2); + ASSERT_EQ("", + PrintContents(&b1)); + b2.Put("a", "va"); + WriteBatchInternal::Append(&b1, &b2); + ASSERT_EQ("Put(a, va)@200", + PrintContents(&b1)); + b2.Clear(); + b2.Put("b", "vb"); + WriteBatchInternal::Append(&b1, &b2); + ASSERT_EQ("Put(a, va)@200" + "Put(b, vb)@201", + PrintContents(&b1)); + b2.Delete("foo"); + WriteBatchInternal::Append(&b1, &b2); + ASSERT_EQ("Put(a, va)@200" + "Put(b, vb)@202" + "Put(b, vb)@201" + "Delete(foo)@203", + PrintContents(&b1)); +} + +} // namespace leveldb + +int main(int argc, char** argv) { + return leveldb::test::RunAllTests(); +} diff --git a/src/leveldb/doc/bench/db_bench_sqlite3.cc b/src/leveldb/doc/bench/db_bench_sqlite3.cc new file mode 100644 index 0000000..e63aaa8 --- /dev/null +++ b/src/leveldb/doc/bench/db_bench_sqlite3.cc @@ -0,0 +1,718 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include +#include +#include +#include "util/histogram.h" +#include "util/random.h" +#include "util/testutil.h" + +// Comma-separated list of operations to run in the specified order +// Actual benchmarks: +// +// fillseq -- write N values in sequential key order in async mode +// fillseqsync -- write N/100 values in sequential key order in sync mode +// fillseqbatch -- batch write N values in sequential key order in async mode +// fillrandom -- write N values in random key order in async mode +// fillrandsync -- write N/100 values in random key order in sync mode +// fillrandbatch -- batch write N values in sequential key order in async mode +// overwrite -- overwrite N values in random key order in async mode +// fillrand100K -- write N/1000 100K values in random order in async mode +// fillseq100K -- write N/1000 100K values in sequential order in async mode +// readseq -- read N times sequentially +// readrandom -- read N times in random order +// readrand100K -- read N/1000 100K values in sequential order in async mode +static const char* FLAGS_benchmarks = + "fillseq," + "fillseqsync," + "fillseqbatch," + "fillrandom," + "fillrandsync," + "fillrandbatch," + "overwrite," + "overwritebatch," + "readrandom," + "readseq," + "fillrand100K," + "fillseq100K," + "readseq," + "readrand100K," + ; + +// Number of key/values to place in database +static int FLAGS_num = 1000000; + +// Number of read operations to do. If negative, do FLAGS_num reads. +static int FLAGS_reads = -1; + +// Size of each value +static int FLAGS_value_size = 100; + +// Print histogram of operation timings +static bool FLAGS_histogram = false; + +// Arrange to generate values that shrink to this fraction of +// their original size after compression +static double FLAGS_compression_ratio = 0.5; + +// Page size. Default 1 KB. +static int FLAGS_page_size = 1024; + +// Number of pages. +// Default cache size = FLAGS_page_size * FLAGS_num_pages = 4 MB. +static int FLAGS_num_pages = 4096; + +// If true, do not destroy the existing database. If you set this +// flag and also specify a benchmark that wants a fresh database, that +// benchmark will fail. +static bool FLAGS_use_existing_db = false; + +// If true, we allow batch writes to occur +static bool FLAGS_transaction = true; + +// If true, we enable Write-Ahead Logging +static bool FLAGS_WAL_enabled = true; + +// Use the db with the following name. +static const char* FLAGS_db = NULL; + +inline +static void ExecErrorCheck(int status, char *err_msg) { + if (status != SQLITE_OK) { + fprintf(stderr, "SQL error: %s\n", err_msg); + sqlite3_free(err_msg); + exit(1); + } +} + +inline +static void StepErrorCheck(int status) { + if (status != SQLITE_DONE) { + fprintf(stderr, "SQL step error: status = %d\n", status); + exit(1); + } +} + +inline +static void ErrorCheck(int status) { + if (status != SQLITE_OK) { + fprintf(stderr, "sqlite3 error: status = %d\n", status); + exit(1); + } +} + +inline +static void WalCheckpoint(sqlite3* db_) { + // Flush all writes to disk + if (FLAGS_WAL_enabled) { + sqlite3_wal_checkpoint_v2(db_, NULL, SQLITE_CHECKPOINT_FULL, NULL, NULL); + } +} + +namespace leveldb { + +// Helper for quickly generating random data. +namespace { +class RandomGenerator { + private: + std::string data_; + int pos_; + + public: + RandomGenerator() { + // We use a limited amount of data over and over again and ensure + // that it is larger than the compression window (32KB), and also + // large enough to serve all typical value sizes we want to write. + Random rnd(301); + std::string piece; + while (data_.size() < 1048576) { + // Add a short fragment that is as compressible as specified + // by FLAGS_compression_ratio. + test::CompressibleString(&rnd, FLAGS_compression_ratio, 100, &piece); + data_.append(piece); + } + pos_ = 0; + } + + Slice Generate(int len) { + if (pos_ + len > data_.size()) { + pos_ = 0; + assert(len < data_.size()); + } + pos_ += len; + return Slice(data_.data() + pos_ - len, len); + } +}; + +static Slice TrimSpace(Slice s) { + int start = 0; + while (start < s.size() && isspace(s[start])) { + start++; + } + int limit = s.size(); + while (limit > start && isspace(s[limit-1])) { + limit--; + } + return Slice(s.data() + start, limit - start); +} + +} // namespace + +class Benchmark { + private: + sqlite3* db_; + int db_num_; + int num_; + int reads_; + double start_; + double last_op_finish_; + int64_t bytes_; + std::string message_; + Histogram hist_; + RandomGenerator gen_; + Random rand_; + + // State kept for progress messages + int done_; + int next_report_; // When to report next + + void PrintHeader() { + const int kKeySize = 16; + PrintEnvironment(); + fprintf(stdout, "Keys: %d bytes each\n", kKeySize); + fprintf(stdout, "Values: %d bytes each\n", FLAGS_value_size); + fprintf(stdout, "Entries: %d\n", num_); + fprintf(stdout, "RawSize: %.1f MB (estimated)\n", + ((static_cast(kKeySize + FLAGS_value_size) * num_) + / 1048576.0)); + PrintWarnings(); + fprintf(stdout, "------------------------------------------------\n"); + } + + void PrintWarnings() { +#if defined(__GNUC__) && !defined(__OPTIMIZE__) + fprintf(stdout, + "WARNING: Optimization is disabled: benchmarks unnecessarily slow\n" + ); +#endif +#ifndef NDEBUG + fprintf(stdout, + "WARNING: Assertions are enabled; benchmarks unnecessarily slow\n"); +#endif + } + + void PrintEnvironment() { + fprintf(stderr, "SQLite: version %s\n", SQLITE_VERSION); + +#if defined(__linux) + time_t now = time(NULL); + fprintf(stderr, "Date: %s", ctime(&now)); // ctime() adds newline + + FILE* cpuinfo = fopen("/proc/cpuinfo", "r"); + if (cpuinfo != NULL) { + char line[1000]; + int num_cpus = 0; + std::string cpu_type; + std::string cache_size; + while (fgets(line, sizeof(line), cpuinfo) != NULL) { + const char* sep = strchr(line, ':'); + if (sep == NULL) { + continue; + } + Slice key = TrimSpace(Slice(line, sep - 1 - line)); + Slice val = TrimSpace(Slice(sep + 1)); + if (key == "model name") { + ++num_cpus; + cpu_type = val.ToString(); + } else if (key == "cache size") { + cache_size = val.ToString(); + } + } + fclose(cpuinfo); + fprintf(stderr, "CPU: %d * %s\n", num_cpus, cpu_type.c_str()); + fprintf(stderr, "CPUCache: %s\n", cache_size.c_str()); + } +#endif + } + + void Start() { + start_ = Env::Default()->NowMicros() * 1e-6; + bytes_ = 0; + message_.clear(); + last_op_finish_ = start_; + hist_.Clear(); + done_ = 0; + next_report_ = 100; + } + + void FinishedSingleOp() { + if (FLAGS_histogram) { + double now = Env::Default()->NowMicros() * 1e-6; + double micros = (now - last_op_finish_) * 1e6; + hist_.Add(micros); + if (micros > 20000) { + fprintf(stderr, "long op: %.1f micros%30s\r", micros, ""); + fflush(stderr); + } + last_op_finish_ = now; + } + + done_++; + if (done_ >= next_report_) { + if (next_report_ < 1000) next_report_ += 100; + else if (next_report_ < 5000) next_report_ += 500; + else if (next_report_ < 10000) next_report_ += 1000; + else if (next_report_ < 50000) next_report_ += 5000; + else if (next_report_ < 100000) next_report_ += 10000; + else if (next_report_ < 500000) next_report_ += 50000; + else next_report_ += 100000; + fprintf(stderr, "... finished %d ops%30s\r", done_, ""); + fflush(stderr); + } + } + + void Stop(const Slice& name) { + double finish = Env::Default()->NowMicros() * 1e-6; + + // Pretend at least one op was done in case we are running a benchmark + // that does not call FinishedSingleOp(). + if (done_ < 1) done_ = 1; + + if (bytes_ > 0) { + char rate[100]; + snprintf(rate, sizeof(rate), "%6.1f MB/s", + (bytes_ / 1048576.0) / (finish - start_)); + if (!message_.empty()) { + message_ = std::string(rate) + " " + message_; + } else { + message_ = rate; + } + } + + fprintf(stdout, "%-12s : %11.3f micros/op;%s%s\n", + name.ToString().c_str(), + (finish - start_) * 1e6 / done_, + (message_.empty() ? "" : " "), + message_.c_str()); + if (FLAGS_histogram) { + fprintf(stdout, "Microseconds per op:\n%s\n", hist_.ToString().c_str()); + } + fflush(stdout); + } + + public: + enum Order { + SEQUENTIAL, + RANDOM + }; + enum DBState { + FRESH, + EXISTING + }; + + Benchmark() + : db_(NULL), + db_num_(0), + num_(FLAGS_num), + reads_(FLAGS_reads < 0 ? FLAGS_num : FLAGS_reads), + bytes_(0), + rand_(301) { + std::vector files; + std::string test_dir; + Env::Default()->GetTestDirectory(&test_dir); + Env::Default()->GetChildren(test_dir, &files); + if (!FLAGS_use_existing_db) { + for (int i = 0; i < files.size(); i++) { + if (Slice(files[i]).starts_with("dbbench_sqlite3")) { + std::string file_name(test_dir); + file_name += "/"; + file_name += files[i]; + Env::Default()->DeleteFile(file_name.c_str()); + } + } + } + } + + ~Benchmark() { + int status = sqlite3_close(db_); + ErrorCheck(status); + } + + void Run() { + PrintHeader(); + Open(); + + const char* benchmarks = FLAGS_benchmarks; + while (benchmarks != NULL) { + const char* sep = strchr(benchmarks, ','); + Slice name; + if (sep == NULL) { + name = benchmarks; + benchmarks = NULL; + } else { + name = Slice(benchmarks, sep - benchmarks); + benchmarks = sep + 1; + } + + bytes_ = 0; + Start(); + + bool known = true; + bool write_sync = false; + if (name == Slice("fillseq")) { + Write(write_sync, SEQUENTIAL, FRESH, num_, FLAGS_value_size, 1); + WalCheckpoint(db_); + } else if (name == Slice("fillseqbatch")) { + Write(write_sync, SEQUENTIAL, FRESH, num_, FLAGS_value_size, 1000); + WalCheckpoint(db_); + } else if (name == Slice("fillrandom")) { + Write(write_sync, RANDOM, FRESH, num_, FLAGS_value_size, 1); + WalCheckpoint(db_); + } else if (name == Slice("fillrandbatch")) { + Write(write_sync, RANDOM, FRESH, num_, FLAGS_value_size, 1000); + WalCheckpoint(db_); + } else if (name == Slice("overwrite")) { + Write(write_sync, RANDOM, EXISTING, num_, FLAGS_value_size, 1); + WalCheckpoint(db_); + } else if (name == Slice("overwritebatch")) { + Write(write_sync, RANDOM, EXISTING, num_, FLAGS_value_size, 1000); + WalCheckpoint(db_); + } else if (name == Slice("fillrandsync")) { + write_sync = true; + Write(write_sync, RANDOM, FRESH, num_ / 100, FLAGS_value_size, 1); + WalCheckpoint(db_); + } else if (name == Slice("fillseqsync")) { + write_sync = true; + Write(write_sync, SEQUENTIAL, FRESH, num_ / 100, FLAGS_value_size, 1); + WalCheckpoint(db_); + } else if (name == Slice("fillrand100K")) { + Write(write_sync, RANDOM, FRESH, num_ / 1000, 100 * 1000, 1); + WalCheckpoint(db_); + } else if (name == Slice("fillseq100K")) { + Write(write_sync, SEQUENTIAL, FRESH, num_ / 1000, 100 * 1000, 1); + WalCheckpoint(db_); + } else if (name == Slice("readseq")) { + ReadSequential(); + } else if (name == Slice("readrandom")) { + Read(RANDOM, 1); + } else if (name == Slice("readrand100K")) { + int n = reads_; + reads_ /= 1000; + Read(RANDOM, 1); + reads_ = n; + } else { + known = false; + if (name != Slice()) { // No error message for empty name + fprintf(stderr, "unknown benchmark '%s'\n", name.ToString().c_str()); + } + } + if (known) { + Stop(name); + } + } + } + + void Open() { + assert(db_ == NULL); + + int status; + char file_name[100]; + char* err_msg = NULL; + db_num_++; + + // Open database + std::string tmp_dir; + Env::Default()->GetTestDirectory(&tmp_dir); + snprintf(file_name, sizeof(file_name), + "%s/dbbench_sqlite3-%d.db", + tmp_dir.c_str(), + db_num_); + status = sqlite3_open(file_name, &db_); + if (status) { + fprintf(stderr, "open error: %s\n", sqlite3_errmsg(db_)); + exit(1); + } + + // Change SQLite cache size + char cache_size[100]; + snprintf(cache_size, sizeof(cache_size), "PRAGMA cache_size = %d", + FLAGS_num_pages); + status = sqlite3_exec(db_, cache_size, NULL, NULL, &err_msg); + ExecErrorCheck(status, err_msg); + + // FLAGS_page_size is defaulted to 1024 + if (FLAGS_page_size != 1024) { + char page_size[100]; + snprintf(page_size, sizeof(page_size), "PRAGMA page_size = %d", + FLAGS_page_size); + status = sqlite3_exec(db_, page_size, NULL, NULL, &err_msg); + ExecErrorCheck(status, err_msg); + } + + // Change journal mode to WAL if WAL enabled flag is on + if (FLAGS_WAL_enabled) { + std::string WAL_stmt = "PRAGMA journal_mode = WAL"; + + // LevelDB's default cache size is a combined 4 MB + std::string WAL_checkpoint = "PRAGMA wal_autocheckpoint = 4096"; + status = sqlite3_exec(db_, WAL_stmt.c_str(), NULL, NULL, &err_msg); + ExecErrorCheck(status, err_msg); + status = sqlite3_exec(db_, WAL_checkpoint.c_str(), NULL, NULL, &err_msg); + ExecErrorCheck(status, err_msg); + } + + // Change locking mode to exclusive and create tables/index for database + std::string locking_stmt = "PRAGMA locking_mode = EXCLUSIVE"; + std::string create_stmt = + "CREATE TABLE test (key blob, value blob, PRIMARY KEY(key))"; + std::string stmt_array[] = { locking_stmt, create_stmt }; + int stmt_array_length = sizeof(stmt_array) / sizeof(std::string); + for (int i = 0; i < stmt_array_length; i++) { + status = sqlite3_exec(db_, stmt_array[i].c_str(), NULL, NULL, &err_msg); + ExecErrorCheck(status, err_msg); + } + } + + void Write(bool write_sync, Order order, DBState state, + int num_entries, int value_size, int entries_per_batch) { + // Create new database if state == FRESH + if (state == FRESH) { + if (FLAGS_use_existing_db) { + message_ = "skipping (--use_existing_db is true)"; + return; + } + sqlite3_close(db_); + db_ = NULL; + Open(); + Start(); + } + + if (num_entries != num_) { + char msg[100]; + snprintf(msg, sizeof(msg), "(%d ops)", num_entries); + message_ = msg; + } + + char* err_msg = NULL; + int status; + + sqlite3_stmt *replace_stmt, *begin_trans_stmt, *end_trans_stmt; + std::string replace_str = "REPLACE INTO test (key, value) VALUES (?, ?)"; + std::string begin_trans_str = "BEGIN TRANSACTION;"; + std::string end_trans_str = "END TRANSACTION;"; + + // Check for synchronous flag in options + std::string sync_stmt = (write_sync) ? "PRAGMA synchronous = FULL" : + "PRAGMA synchronous = OFF"; + status = sqlite3_exec(db_, sync_stmt.c_str(), NULL, NULL, &err_msg); + ExecErrorCheck(status, err_msg); + + // Preparing sqlite3 statements + status = sqlite3_prepare_v2(db_, replace_str.c_str(), -1, + &replace_stmt, NULL); + ErrorCheck(status); + status = sqlite3_prepare_v2(db_, begin_trans_str.c_str(), -1, + &begin_trans_stmt, NULL); + ErrorCheck(status); + status = sqlite3_prepare_v2(db_, end_trans_str.c_str(), -1, + &end_trans_stmt, NULL); + ErrorCheck(status); + + bool transaction = (entries_per_batch > 1); + for (int i = 0; i < num_entries; i += entries_per_batch) { + // Begin write transaction + if (FLAGS_transaction && transaction) { + status = sqlite3_step(begin_trans_stmt); + StepErrorCheck(status); + status = sqlite3_reset(begin_trans_stmt); + ErrorCheck(status); + } + + // Create and execute SQL statements + for (int j = 0; j < entries_per_batch; j++) { + const char* value = gen_.Generate(value_size).data(); + + // Create values for key-value pair + const int k = (order == SEQUENTIAL) ? i + j : + (rand_.Next() % num_entries); + char key[100]; + snprintf(key, sizeof(key), "%016d", k); + + // Bind KV values into replace_stmt + status = sqlite3_bind_blob(replace_stmt, 1, key, 16, SQLITE_STATIC); + ErrorCheck(status); + status = sqlite3_bind_blob(replace_stmt, 2, value, + value_size, SQLITE_STATIC); + ErrorCheck(status); + + // Execute replace_stmt + bytes_ += value_size + strlen(key); + status = sqlite3_step(replace_stmt); + StepErrorCheck(status); + + // Reset SQLite statement for another use + status = sqlite3_clear_bindings(replace_stmt); + ErrorCheck(status); + status = sqlite3_reset(replace_stmt); + ErrorCheck(status); + + FinishedSingleOp(); + } + + // End write transaction + if (FLAGS_transaction && transaction) { + status = sqlite3_step(end_trans_stmt); + StepErrorCheck(status); + status = sqlite3_reset(end_trans_stmt); + ErrorCheck(status); + } + } + + status = sqlite3_finalize(replace_stmt); + ErrorCheck(status); + status = sqlite3_finalize(begin_trans_stmt); + ErrorCheck(status); + status = sqlite3_finalize(end_trans_stmt); + ErrorCheck(status); + } + + void Read(Order order, int entries_per_batch) { + int status; + sqlite3_stmt *read_stmt, *begin_trans_stmt, *end_trans_stmt; + + std::string read_str = "SELECT * FROM test WHERE key = ?"; + std::string begin_trans_str = "BEGIN TRANSACTION;"; + std::string end_trans_str = "END TRANSACTION;"; + + // Preparing sqlite3 statements + status = sqlite3_prepare_v2(db_, begin_trans_str.c_str(), -1, + &begin_trans_stmt, NULL); + ErrorCheck(status); + status = sqlite3_prepare_v2(db_, end_trans_str.c_str(), -1, + &end_trans_stmt, NULL); + ErrorCheck(status); + status = sqlite3_prepare_v2(db_, read_str.c_str(), -1, &read_stmt, NULL); + ErrorCheck(status); + + bool transaction = (entries_per_batch > 1); + for (int i = 0; i < reads_; i += entries_per_batch) { + // Begin read transaction + if (FLAGS_transaction && transaction) { + status = sqlite3_step(begin_trans_stmt); + StepErrorCheck(status); + status = sqlite3_reset(begin_trans_stmt); + ErrorCheck(status); + } + + // Create and execute SQL statements + for (int j = 0; j < entries_per_batch; j++) { + // Create key value + char key[100]; + int k = (order == SEQUENTIAL) ? i + j : (rand_.Next() % reads_); + snprintf(key, sizeof(key), "%016d", k); + + // Bind key value into read_stmt + status = sqlite3_bind_blob(read_stmt, 1, key, 16, SQLITE_STATIC); + ErrorCheck(status); + + // Execute read statement + while ((status = sqlite3_step(read_stmt)) == SQLITE_ROW) {} + StepErrorCheck(status); + + // Reset SQLite statement for another use + status = sqlite3_clear_bindings(read_stmt); + ErrorCheck(status); + status = sqlite3_reset(read_stmt); + ErrorCheck(status); + FinishedSingleOp(); + } + + // End read transaction + if (FLAGS_transaction && transaction) { + status = sqlite3_step(end_trans_stmt); + StepErrorCheck(status); + status = sqlite3_reset(end_trans_stmt); + ErrorCheck(status); + } + } + + status = sqlite3_finalize(read_stmt); + ErrorCheck(status); + status = sqlite3_finalize(begin_trans_stmt); + ErrorCheck(status); + status = sqlite3_finalize(end_trans_stmt); + ErrorCheck(status); + } + + void ReadSequential() { + int status; + sqlite3_stmt *pStmt; + std::string read_str = "SELECT * FROM test ORDER BY key"; + + status = sqlite3_prepare_v2(db_, read_str.c_str(), -1, &pStmt, NULL); + ErrorCheck(status); + for (int i = 0; i < reads_ && SQLITE_ROW == sqlite3_step(pStmt); i++) { + bytes_ += sqlite3_column_bytes(pStmt, 1) + sqlite3_column_bytes(pStmt, 2); + FinishedSingleOp(); + } + + status = sqlite3_finalize(pStmt); + ErrorCheck(status); + } + +}; + +} // namespace leveldb + +int main(int argc, char** argv) { + std::string default_db_path; + for (int i = 1; i < argc; i++) { + double d; + int n; + char junk; + if (leveldb::Slice(argv[i]).starts_with("--benchmarks=")) { + FLAGS_benchmarks = argv[i] + strlen("--benchmarks="); + } else if (sscanf(argv[i], "--histogram=%d%c", &n, &junk) == 1 && + (n == 0 || n == 1)) { + FLAGS_histogram = n; + } else if (sscanf(argv[i], "--compression_ratio=%lf%c", &d, &junk) == 1) { + FLAGS_compression_ratio = d; + } else if (sscanf(argv[i], "--use_existing_db=%d%c", &n, &junk) == 1 && + (n == 0 || n == 1)) { + FLAGS_use_existing_db = n; + } else if (sscanf(argv[i], "--num=%d%c", &n, &junk) == 1) { + FLAGS_num = n; + } else if (sscanf(argv[i], "--reads=%d%c", &n, &junk) == 1) { + FLAGS_reads = n; + } else if (sscanf(argv[i], "--value_size=%d%c", &n, &junk) == 1) { + FLAGS_value_size = n; + } else if (leveldb::Slice(argv[i]) == leveldb::Slice("--no_transaction")) { + FLAGS_transaction = false; + } else if (sscanf(argv[i], "--page_size=%d%c", &n, &junk) == 1) { + FLAGS_page_size = n; + } else if (sscanf(argv[i], "--num_pages=%d%c", &n, &junk) == 1) { + FLAGS_num_pages = n; + } else if (sscanf(argv[i], "--WAL_enabled=%d%c", &n, &junk) == 1 && + (n == 0 || n == 1)) { + FLAGS_WAL_enabled = n; + } else if (strncmp(argv[i], "--db=", 5) == 0) { + FLAGS_db = argv[i] + 5; + } else { + fprintf(stderr, "Invalid flag '%s'\n", argv[i]); + exit(1); + } + } + + // Choose a location for the test database if none given with --db= + if (FLAGS_db == NULL) { + leveldb::Env::Default()->GetTestDirectory(&default_db_path); + default_db_path += "/dbbench"; + FLAGS_db = default_db_path.c_str(); + } + + leveldb::Benchmark benchmark; + benchmark.Run(); + return 0; +} diff --git a/src/leveldb/doc/bench/db_bench_tree_db.cc b/src/leveldb/doc/bench/db_bench_tree_db.cc new file mode 100644 index 0000000..ed86f03 --- /dev/null +++ b/src/leveldb/doc/bench/db_bench_tree_db.cc @@ -0,0 +1,528 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include +#include +#include +#include "util/histogram.h" +#include "util/random.h" +#include "util/testutil.h" + +// Comma-separated list of operations to run in the specified order +// Actual benchmarks: +// +// fillseq -- write N values in sequential key order in async mode +// fillrandom -- write N values in random key order in async mode +// overwrite -- overwrite N values in random key order in async mode +// fillseqsync -- write N/100 values in sequential key order in sync mode +// fillrandsync -- write N/100 values in random key order in sync mode +// fillrand100K -- write N/1000 100K values in random order in async mode +// fillseq100K -- write N/1000 100K values in seq order in async mode +// readseq -- read N times sequentially +// readseq100K -- read N/1000 100K values in sequential order in async mode +// readrand100K -- read N/1000 100K values in sequential order in async mode +// readrandom -- read N times in random order +static const char* FLAGS_benchmarks = + "fillseq," + "fillseqsync," + "fillrandsync," + "fillrandom," + "overwrite," + "readrandom," + "readseq," + "fillrand100K," + "fillseq100K," + "readseq100K," + "readrand100K," + ; + +// Number of key/values to place in database +static int FLAGS_num = 1000000; + +// Number of read operations to do. If negative, do FLAGS_num reads. +static int FLAGS_reads = -1; + +// Size of each value +static int FLAGS_value_size = 100; + +// Arrange to generate values that shrink to this fraction of +// their original size after compression +static double FLAGS_compression_ratio = 0.5; + +// Print histogram of operation timings +static bool FLAGS_histogram = false; + +// Cache size. Default 4 MB +static int FLAGS_cache_size = 4194304; + +// Page size. Default 1 KB +static int FLAGS_page_size = 1024; + +// If true, do not destroy the existing database. If you set this +// flag and also specify a benchmark that wants a fresh database, that +// benchmark will fail. +static bool FLAGS_use_existing_db = false; + +// Compression flag. If true, compression is on. If false, compression +// is off. +static bool FLAGS_compression = true; + +// Use the db with the following name. +static const char* FLAGS_db = NULL; + +inline +static void DBSynchronize(kyotocabinet::TreeDB* db_) +{ + // Synchronize will flush writes to disk + if (!db_->synchronize()) { + fprintf(stderr, "synchronize error: %s\n", db_->error().name()); + } +} + +namespace leveldb { + +// Helper for quickly generating random data. +namespace { +class RandomGenerator { + private: + std::string data_; + int pos_; + + public: + RandomGenerator() { + // We use a limited amount of data over and over again and ensure + // that it is larger than the compression window (32KB), and also + // large enough to serve all typical value sizes we want to write. + Random rnd(301); + std::string piece; + while (data_.size() < 1048576) { + // Add a short fragment that is as compressible as specified + // by FLAGS_compression_ratio. + test::CompressibleString(&rnd, FLAGS_compression_ratio, 100, &piece); + data_.append(piece); + } + pos_ = 0; + } + + Slice Generate(int len) { + if (pos_ + len > data_.size()) { + pos_ = 0; + assert(len < data_.size()); + } + pos_ += len; + return Slice(data_.data() + pos_ - len, len); + } +}; + +static Slice TrimSpace(Slice s) { + int start = 0; + while (start < s.size() && isspace(s[start])) { + start++; + } + int limit = s.size(); + while (limit > start && isspace(s[limit-1])) { + limit--; + } + return Slice(s.data() + start, limit - start); +} + +} // namespace + +class Benchmark { + private: + kyotocabinet::TreeDB* db_; + int db_num_; + int num_; + int reads_; + double start_; + double last_op_finish_; + int64_t bytes_; + std::string message_; + Histogram hist_; + RandomGenerator gen_; + Random rand_; + kyotocabinet::LZOCompressor comp_; + + // State kept for progress messages + int done_; + int next_report_; // When to report next + + void PrintHeader() { + const int kKeySize = 16; + PrintEnvironment(); + fprintf(stdout, "Keys: %d bytes each\n", kKeySize); + fprintf(stdout, "Values: %d bytes each (%d bytes after compression)\n", + FLAGS_value_size, + static_cast(FLAGS_value_size * FLAGS_compression_ratio + 0.5)); + fprintf(stdout, "Entries: %d\n", num_); + fprintf(stdout, "RawSize: %.1f MB (estimated)\n", + ((static_cast(kKeySize + FLAGS_value_size) * num_) + / 1048576.0)); + fprintf(stdout, "FileSize: %.1f MB (estimated)\n", + (((kKeySize + FLAGS_value_size * FLAGS_compression_ratio) * num_) + / 1048576.0)); + PrintWarnings(); + fprintf(stdout, "------------------------------------------------\n"); + } + + void PrintWarnings() { +#if defined(__GNUC__) && !defined(__OPTIMIZE__) + fprintf(stdout, + "WARNING: Optimization is disabled: benchmarks unnecessarily slow\n" + ); +#endif +#ifndef NDEBUG + fprintf(stdout, + "WARNING: Assertions are enabled; benchmarks unnecessarily slow\n"); +#endif + } + + void PrintEnvironment() { + fprintf(stderr, "Kyoto Cabinet: version %s, lib ver %d, lib rev %d\n", + kyotocabinet::VERSION, kyotocabinet::LIBVER, kyotocabinet::LIBREV); + +#if defined(__linux) + time_t now = time(NULL); + fprintf(stderr, "Date: %s", ctime(&now)); // ctime() adds newline + + FILE* cpuinfo = fopen("/proc/cpuinfo", "r"); + if (cpuinfo != NULL) { + char line[1000]; + int num_cpus = 0; + std::string cpu_type; + std::string cache_size; + while (fgets(line, sizeof(line), cpuinfo) != NULL) { + const char* sep = strchr(line, ':'); + if (sep == NULL) { + continue; + } + Slice key = TrimSpace(Slice(line, sep - 1 - line)); + Slice val = TrimSpace(Slice(sep + 1)); + if (key == "model name") { + ++num_cpus; + cpu_type = val.ToString(); + } else if (key == "cache size") { + cache_size = val.ToString(); + } + } + fclose(cpuinfo); + fprintf(stderr, "CPU: %d * %s\n", num_cpus, cpu_type.c_str()); + fprintf(stderr, "CPUCache: %s\n", cache_size.c_str()); + } +#endif + } + + void Start() { + start_ = Env::Default()->NowMicros() * 1e-6; + bytes_ = 0; + message_.clear(); + last_op_finish_ = start_; + hist_.Clear(); + done_ = 0; + next_report_ = 100; + } + + void FinishedSingleOp() { + if (FLAGS_histogram) { + double now = Env::Default()->NowMicros() * 1e-6; + double micros = (now - last_op_finish_) * 1e6; + hist_.Add(micros); + if (micros > 20000) { + fprintf(stderr, "long op: %.1f micros%30s\r", micros, ""); + fflush(stderr); + } + last_op_finish_ = now; + } + + done_++; + if (done_ >= next_report_) { + if (next_report_ < 1000) next_report_ += 100; + else if (next_report_ < 5000) next_report_ += 500; + else if (next_report_ < 10000) next_report_ += 1000; + else if (next_report_ < 50000) next_report_ += 5000; + else if (next_report_ < 100000) next_report_ += 10000; + else if (next_report_ < 500000) next_report_ += 50000; + else next_report_ += 100000; + fprintf(stderr, "... finished %d ops%30s\r", done_, ""); + fflush(stderr); + } + } + + void Stop(const Slice& name) { + double finish = Env::Default()->NowMicros() * 1e-6; + + // Pretend at least one op was done in case we are running a benchmark + // that does not call FinishedSingleOp(). + if (done_ < 1) done_ = 1; + + if (bytes_ > 0) { + char rate[100]; + snprintf(rate, sizeof(rate), "%6.1f MB/s", + (bytes_ / 1048576.0) / (finish - start_)); + if (!message_.empty()) { + message_ = std::string(rate) + " " + message_; + } else { + message_ = rate; + } + } + + fprintf(stdout, "%-12s : %11.3f micros/op;%s%s\n", + name.ToString().c_str(), + (finish - start_) * 1e6 / done_, + (message_.empty() ? "" : " "), + message_.c_str()); + if (FLAGS_histogram) { + fprintf(stdout, "Microseconds per op:\n%s\n", hist_.ToString().c_str()); + } + fflush(stdout); + } + + public: + enum Order { + SEQUENTIAL, + RANDOM + }; + enum DBState { + FRESH, + EXISTING + }; + + Benchmark() + : db_(NULL), + num_(FLAGS_num), + reads_(FLAGS_reads < 0 ? FLAGS_num : FLAGS_reads), + bytes_(0), + rand_(301) { + std::vector files; + std::string test_dir; + Env::Default()->GetTestDirectory(&test_dir); + Env::Default()->GetChildren(test_dir.c_str(), &files); + if (!FLAGS_use_existing_db) { + for (int i = 0; i < files.size(); i++) { + if (Slice(files[i]).starts_with("dbbench_polyDB")) { + std::string file_name(test_dir); + file_name += "/"; + file_name += files[i]; + Env::Default()->DeleteFile(file_name.c_str()); + } + } + } + } + + ~Benchmark() { + if (!db_->close()) { + fprintf(stderr, "close error: %s\n", db_->error().name()); + } + } + + void Run() { + PrintHeader(); + Open(false); + + const char* benchmarks = FLAGS_benchmarks; + while (benchmarks != NULL) { + const char* sep = strchr(benchmarks, ','); + Slice name; + if (sep == NULL) { + name = benchmarks; + benchmarks = NULL; + } else { + name = Slice(benchmarks, sep - benchmarks); + benchmarks = sep + 1; + } + + Start(); + + bool known = true; + bool write_sync = false; + if (name == Slice("fillseq")) { + Write(write_sync, SEQUENTIAL, FRESH, num_, FLAGS_value_size, 1); + + } else if (name == Slice("fillrandom")) { + Write(write_sync, RANDOM, FRESH, num_, FLAGS_value_size, 1); + DBSynchronize(db_); + } else if (name == Slice("overwrite")) { + Write(write_sync, RANDOM, EXISTING, num_, FLAGS_value_size, 1); + DBSynchronize(db_); + } else if (name == Slice("fillrandsync")) { + write_sync = true; + Write(write_sync, RANDOM, FRESH, num_ / 100, FLAGS_value_size, 1); + DBSynchronize(db_); + } else if (name == Slice("fillseqsync")) { + write_sync = true; + Write(write_sync, SEQUENTIAL, FRESH, num_ / 100, FLAGS_value_size, 1); + DBSynchronize(db_); + } else if (name == Slice("fillrand100K")) { + Write(write_sync, RANDOM, FRESH, num_ / 1000, 100 * 1000, 1); + DBSynchronize(db_); + } else if (name == Slice("fillseq100K")) { + Write(write_sync, SEQUENTIAL, FRESH, num_ / 1000, 100 * 1000, 1); + DBSynchronize(db_); + } else if (name == Slice("readseq")) { + ReadSequential(); + } else if (name == Slice("readrandom")) { + ReadRandom(); + } else if (name == Slice("readrand100K")) { + int n = reads_; + reads_ /= 1000; + ReadRandom(); + reads_ = n; + } else if (name == Slice("readseq100K")) { + int n = reads_; + reads_ /= 1000; + ReadSequential(); + reads_ = n; + } else { + known = false; + if (name != Slice()) { // No error message for empty name + fprintf(stderr, "unknown benchmark '%s'\n", name.ToString().c_str()); + } + } + if (known) { + Stop(name); + } + } + } + + private: + void Open(bool sync) { + assert(db_ == NULL); + + // Initialize db_ + db_ = new kyotocabinet::TreeDB(); + char file_name[100]; + db_num_++; + std::string test_dir; + Env::Default()->GetTestDirectory(&test_dir); + snprintf(file_name, sizeof(file_name), + "%s/dbbench_polyDB-%d.kct", + test_dir.c_str(), + db_num_); + + // Create tuning options and open the database + int open_options = kyotocabinet::PolyDB::OWRITER | + kyotocabinet::PolyDB::OCREATE; + int tune_options = kyotocabinet::TreeDB::TSMALL | + kyotocabinet::TreeDB::TLINEAR; + if (FLAGS_compression) { + tune_options |= kyotocabinet::TreeDB::TCOMPRESS; + db_->tune_compressor(&comp_); + } + db_->tune_options(tune_options); + db_->tune_page_cache(FLAGS_cache_size); + db_->tune_page(FLAGS_page_size); + db_->tune_map(256LL<<20); + if (sync) { + open_options |= kyotocabinet::PolyDB::OAUTOSYNC; + } + if (!db_->open(file_name, open_options)) { + fprintf(stderr, "open error: %s\n", db_->error().name()); + } + } + + void Write(bool sync, Order order, DBState state, + int num_entries, int value_size, int entries_per_batch) { + // Create new database if state == FRESH + if (state == FRESH) { + if (FLAGS_use_existing_db) { + message_ = "skipping (--use_existing_db is true)"; + return; + } + delete db_; + db_ = NULL; + Open(sync); + Start(); // Do not count time taken to destroy/open + } + + if (num_entries != num_) { + char msg[100]; + snprintf(msg, sizeof(msg), "(%d ops)", num_entries); + message_ = msg; + } + + // Write to database + for (int i = 0; i < num_entries; i++) + { + const int k = (order == SEQUENTIAL) ? i : (rand_.Next() % num_entries); + char key[100]; + snprintf(key, sizeof(key), "%016d", k); + bytes_ += value_size + strlen(key); + std::string cpp_key = key; + if (!db_->set(cpp_key, gen_.Generate(value_size).ToString())) { + fprintf(stderr, "set error: %s\n", db_->error().name()); + } + FinishedSingleOp(); + } + } + + void ReadSequential() { + kyotocabinet::DB::Cursor* cur = db_->cursor(); + cur->jump(); + std::string ckey, cvalue; + while (cur->get(&ckey, &cvalue, true)) { + bytes_ += ckey.size() + cvalue.size(); + FinishedSingleOp(); + } + delete cur; + } + + void ReadRandom() { + std::string value; + for (int i = 0; i < reads_; i++) { + char key[100]; + const int k = rand_.Next() % reads_; + snprintf(key, sizeof(key), "%016d", k); + db_->get(key, &value); + FinishedSingleOp(); + } + } +}; + +} // namespace leveldb + +int main(int argc, char** argv) { + std::string default_db_path; + for (int i = 1; i < argc; i++) { + double d; + int n; + char junk; + if (leveldb::Slice(argv[i]).starts_with("--benchmarks=")) { + FLAGS_benchmarks = argv[i] + strlen("--benchmarks="); + } else if (sscanf(argv[i], "--compression_ratio=%lf%c", &d, &junk) == 1) { + FLAGS_compression_ratio = d; + } else if (sscanf(argv[i], "--histogram=%d%c", &n, &junk) == 1 && + (n == 0 || n == 1)) { + FLAGS_histogram = n; + } else if (sscanf(argv[i], "--num=%d%c", &n, &junk) == 1) { + FLAGS_num = n; + } else if (sscanf(argv[i], "--reads=%d%c", &n, &junk) == 1) { + FLAGS_reads = n; + } else if (sscanf(argv[i], "--value_size=%d%c", &n, &junk) == 1) { + FLAGS_value_size = n; + } else if (sscanf(argv[i], "--cache_size=%d%c", &n, &junk) == 1) { + FLAGS_cache_size = n; + } else if (sscanf(argv[i], "--page_size=%d%c", &n, &junk) == 1) { + FLAGS_page_size = n; + } else if (sscanf(argv[i], "--compression=%d%c", &n, &junk) == 1 && + (n == 0 || n == 1)) { + FLAGS_compression = (n == 1) ? true : false; + } else if (strncmp(argv[i], "--db=", 5) == 0) { + FLAGS_db = argv[i] + 5; + } else { + fprintf(stderr, "Invalid flag '%s'\n", argv[i]); + exit(1); + } + } + + // Choose a location for the test database if none given with --db= + if (FLAGS_db == NULL) { + leveldb::Env::Default()->GetTestDirectory(&default_db_path); + default_db_path += "/dbbench"; + FLAGS_db = default_db_path.c_str(); + } + + leveldb::Benchmark benchmark; + benchmark.Run(); + return 0; +} diff --git a/src/leveldb/doc/benchmark.html b/src/leveldb/doc/benchmark.html new file mode 100644 index 0000000..c463977 --- /dev/null +++ b/src/leveldb/doc/benchmark.html @@ -0,0 +1,459 @@ + + + +LevelDB Benchmarks + + + + +

LevelDB Benchmarks

+

Google, July 2011

+
+ +

In order to test LevelDB's performance, we benchmark it against other well-established database implementations. We compare LevelDB (revision 39) against SQLite3 (version 3.7.6.3) and Kyoto Cabinet's (version 1.2.67) TreeDB (a B+Tree based key-value store). We would like to acknowledge Scott Hess and Mikio Hirabayashi for their suggestions and contributions to the SQLite3 and Kyoto Cabinet benchmarks, respectively.

+ +

Benchmarks were all performed on a six-core Intel(R) Xeon(R) CPU X5650 @ 2.67GHz, with 12288 KB of total L3 cache and 12 GB of DDR3 RAM at 1333 MHz. (Note that LevelDB uses at most two CPUs since the benchmarks are single threaded: one to run the benchmark, and one for background compactions.) We ran the benchmarks on two machines (with identical processors), one with an Ext3 file system and one with an Ext4 file system. The machine with the Ext3 file system has a SATA Hitachi HDS721050CLA362 hard drive. The machine with the Ext4 file system has a SATA Samsung HD502HJ hard drive. Both hard drives spin at 7200 RPM and have hard drive write-caching enabled (using `hdparm -W 1 [device]`). The numbers reported below are the median of three measurements.

+ +

Benchmark Source Code

+

We wrote benchmark tools for SQLite and Kyoto TreeDB based on LevelDB's db_bench. The code for each of the benchmarks resides here:

+ + +

Custom Build Specifications

+
    +
  • LevelDB: LevelDB was compiled with the tcmalloc library and the Snappy compression library (revision 33). Assertions were disabled.
  • +
  • TreeDB: TreeDB was compiled using the LZO compression library (version 2.03). Furthermore, we enabled the TSMALL and TLINEAR options when opening the database in order to reduce the footprint of each record.
  • +
  • SQLite: We tuned SQLite's performance, by setting its locking mode to exclusive. We also enabled SQLite's write-ahead logging.
  • +
+ +

1. Baseline Performance

+

This section gives the baseline performance of all the +databases. Following sections show how performance changes as various +parameters are varied. For the baseline:

+
    +
  • Each database is allowed 4 MB of cache memory.
  • +
  • Databases are opened in asynchronous write mode. + (LevelDB's sync option, TreeDB's OAUTOSYNC option, and + SQLite3's synchronous options are all turned off). I.e., + every write is pushed to the operating system, but the + benchmark does not wait for the write to reach the disk.
  • +
  • Keys are 16 bytes each.
  • +
  • Value are 100 bytes each (with enough redundancy so that + a simple compressor shrinks them to 50% of their original + size).
  • +
  • Sequential reads/writes traverse the key space in increasing order.
  • +
  • Random reads/writes traverse the key space in random order.
  • +
+ +

A. Sequential Reads

+ + + + + + + + + + +
LevelDB4,030,000 ops/sec
 
Kyoto TreeDB1,010,000 ops/sec
 
SQLite3383,000 ops/sec
 
+

B. Random Reads

+ + + + + + + + + + +
LevelDB129,000 ops/sec
 
Kyoto TreeDB151,000 ops/sec
 
SQLite3134,000 ops/sec
 
+

C. Sequential Writes

+ + + + + + + + + + +
LevelDB779,000 ops/sec
 
Kyoto TreeDB342,000 ops/sec
 
SQLite348,600 ops/sec
 
+

D. Random Writes

+ + + + + + + + + + +
LevelDB164,000 ops/sec
 
Kyoto TreeDB88,500 ops/sec
 
SQLite39,860 ops/sec
 
+ +

LevelDB outperforms both SQLite3 and TreeDB in sequential and random write operations and sequential read operations. Kyoto Cabinet has the fastest random read operations.

+ +

2. Write Performance under Different Configurations

+

A. Large Values

+

For this benchmark, we start with an empty database, and write 100,000 byte values (~50% compressible). To keep the benchmark running time reasonable, we stop after writing 1000 values.

+

Sequential Writes

+ + + + + + + + + + +
LevelDB1,100 ops/sec
 
Kyoto TreeDB1,000 ops/sec
 
SQLite31,600 ops/sec
 
+

Random Writes

+ + + + + + + + + + +
LevelDB480 ops/sec
 
Kyoto TreeDB1,100 ops/sec
 
SQLite31,600 ops/sec
 
+

LevelDB doesn't perform as well with large values of 100,000 bytes each. This is because LevelDB writes keys and values at least twice: first time to the transaction log, and second time (during a compaction) to a sorted file. +With larger values, LevelDB's per-operation efficiency is swamped by the +cost of extra copies of large values.

+

B. Batch Writes

+

A batch write is a set of writes that are applied atomically to the underlying database. A single batch of N writes may be significantly faster than N individual writes. The following benchmark writes one thousand batches where each batch contains one thousand 100-byte values. TreeDB does not support batch writes and is omitted from this benchmark.

+

Sequential Writes

+ + + + + + + + + +
LevelDB840,000 entries/sec
 
(1.08x baseline)
SQLite3124,000 entries/sec
 
(2.55x baseline)
+

Random Writes

+ + + + + + + + + +
LevelDB221,000 entries/sec
 
(1.35x baseline)
SQLite322,000 entries/sec
 
(2.23x baseline)
+ +

Because of the way LevelDB persistent storage is organized, batches of +random writes are not much slower (only a factor of 4x) than batches +of sequential writes.

+ +

C. Synchronous Writes

+

In the following benchmark, we enable the synchronous writing modes +of all of the databases. Since this change significantly slows down the +benchmark, we stop after 10,000 writes. For synchronous write tests, we've +disabled hard drive write-caching (using `hdparm -W 0 [device]`).

+
    +
  • For LevelDB, we set WriteOptions.sync = true.
  • +
  • In TreeDB, we enabled TreeDB's OAUTOSYNC option.
  • +
  • For SQLite3, we set "PRAGMA synchronous = FULL".
  • +
+

Sequential Writes

+ + + + + + + + + + + + + +
LevelDB100 ops/sec
 
(0.003x baseline)
Kyoto TreeDB7 ops/sec
 
(0.0004x baseline)
SQLite388 ops/sec
 
(0.002x baseline)
+

Random Writes

+ + + + + + + + + + + + + +
LevelDB100 ops/sec
 
(0.015x baseline)
Kyoto TreeDB8 ops/sec
 
(0.001x baseline)
SQLite388 ops/sec
 
(0.009x baseline)
+ +

Also see the ext4 performance numbers below +since synchronous writes behave significantly differently +on ext3 and ext4.

+ +

D. Turning Compression Off

+ +

In the baseline measurements, LevelDB and TreeDB were using +light-weight compression +(Snappy for LevelDB, +and LZO for +TreeDB). SQLite3, by default does not use compression. The +experiments below show what happens when compression is disabled in +all of the databases (the SQLite3 numbers are just a copy of +its baseline measurements):

+ +

Sequential Writes

+ + + + + + + + + + + + + +
LevelDB594,000 ops/sec
 
(0.76x baseline)
Kyoto TreeDB485,000 ops/sec
 
(1.42x baseline)
SQLite348,600 ops/sec
 
(1.00x baseline)
+

Random Writes

+ + + + + + + + + + + + + +
LevelDB135,000 ops/sec
 
(0.82x baseline)
Kyoto TreeDB159,000 ops/sec
 
(1.80x baseline)
SQLite39,860 ops/sec
 
(1.00x baseline)
+ +

LevelDB's write performance is better with compression than without +since compression decreases the amount of data that has to be written +to disk. Therefore LevelDB users can leave compression enabled in +most scenarios without having worry about a tradeoff between space +usage and performance. TreeDB's performance on the other hand is +better without compression than with compression. Presumably this is +because TreeDB's compression library (LZO) is more expensive than +LevelDB's compression library (Snappy).

+ +

E. Using More Memory

+

We increased the overall cache size for each database to 128 MB. For LevelDB, we partitioned 128 MB into a 120 MB write buffer and 8 MB of cache (up from 2 MB of write buffer and 2 MB of cache). For SQLite3, we kept the page size at 1024 bytes, but increased the number of pages to 131,072 (up from 4096). For TreeDB, we also kept the page size at 1024 bytes, but increased the cache size to 128 MB (up from 4 MB).

+

Sequential Writes

+ + + + + + + + + + + + + +
LevelDB812,000 ops/sec
 
(1.04x baseline)
Kyoto TreeDB321,000 ops/sec
 
(0.94x baseline)
SQLite348,500 ops/sec
 
(1.00x baseline)
+

Random Writes

+ + + + + + + + + + + + + +
LevelDB355,000 ops/sec
 
(2.16x baseline)
Kyoto TreeDB284,000 ops/sec
 
(3.21x baseline)
SQLite39,670 ops/sec
 
(0.98x baseline)
+ +

SQLite's performance does not change substantially when compared to +the baseline, but the random write performance for both LevelDB and +TreeDB increases significantly. LevelDB's performance improves +because a larger write buffer reduces the need to merge sorted files +(since it creates a smaller number of larger sorted files). TreeDB's +performance goes up because the entire database is available in memory +for fast in-place updates.

+ +

3. Read Performance under Different Configurations

+

A. Larger Caches

+

We increased the overall memory usage to 128 MB for each database. +For LevelDB, we allocated 8 MB to LevelDB's write buffer and 120 MB +to LevelDB's cache. The other databases don't differentiate between a +write buffer and a cache, so we simply set their cache size to 128 +MB.

+

Sequential Reads

+ + + + + + + + + + + + + +
LevelDB5,210,000 ops/sec
 
(1.29x baseline)
Kyoto TreeDB1,070,000 ops/sec
 
(1.06x baseline)
SQLite3609,000 ops/sec
 
(1.59x baseline)
+ +

Random Reads

+ + + + + + + + + + + + + +
LevelDB190,000 ops/sec
 
(1.47x baseline)
Kyoto TreeDB463,000 ops/sec
 
(3.07x baseline)
SQLite3186,000 ops/sec
 
(1.39x baseline)
+ +

As expected, the read performance of all of the databases increases +when the caches are enlarged. In particular, TreeDB seems to make +very effective use of a cache that is large enough to hold the entire +database.

+ +

B. No Compression Reads

+

For this benchmark, we populated a database with 1 million entries consisting of 16 byte keys and 100 byte values. We compiled LevelDB and Kyoto Cabinet without compression support, so results that are read out from the database are already uncompressed. We've listed the SQLite3 baseline read performance as a point of comparison.

+

Sequential Reads

+ + + + + + + + + + + + + +
LevelDB4,880,000 ops/sec
 
(1.21x baseline)
Kyoto TreeDB1,230,000 ops/sec
 
(3.60x baseline)
SQLite3383,000 ops/sec
 
(1.00x baseline)
+

Random Reads

+ + + + + + + + + + + + + +
LevelDB149,000 ops/sec
 
(1.16x baseline)
Kyoto TreeDB175,000 ops/sec
 
(1.16x baseline)
SQLite3134,000 ops/sec
 
(1.00x baseline)
+ +

Performance of both LevelDB and TreeDB improves a small amount when +compression is disabled. Note however that under different workloads, +performance may very well be better with compression if it allows more +of the working set to fit in memory.

+ +

Note about Ext4 Filesystems

+

The preceding numbers are for an ext3 file system. Synchronous writes are much slower under ext4 (LevelDB drops to ~31 writes / second and TreeDB drops to ~5 writes / second; SQLite3's synchronous writes do not noticeably drop) due to ext4's different handling of fsync / msync calls. Even LevelDB's asynchronous write performance drops somewhat since it spreads its storage across multiple files and issues fsync calls when switching to a new file.

+ +

Acknowledgements

+

Jeff Dean and Sanjay Ghemawat wrote LevelDB. Kevin Tseng wrote and compiled these benchmarks. Mikio Hirabayashi, Scott Hess, and Gabor Cselle provided help and advice.

+ + diff --git a/src/leveldb/doc/doc.css b/src/leveldb/doc/doc.css new file mode 100644 index 0000000..700c564 --- /dev/null +++ b/src/leveldb/doc/doc.css @@ -0,0 +1,89 @@ +body { + margin-left: 0.5in; + margin-right: 0.5in; + background: white; + color: black; +} + +h1 { + margin-left: -0.2in; + font-size: 14pt; +} +h2 { + margin-left: -0in; + font-size: 12pt; +} +h3 { + margin-left: -0in; +} +h4 { + margin-left: -0in; +} +hr { + margin-left: -0in; +} + +/* Definition lists: definition term bold */ +dt { + font-weight: bold; +} + +address { + text-align: center; +} +code,samp,var { + color: blue; +} +kbd { + color: #600000; +} +div.note p { + float: right; + width: 3in; + margin-right: 0%; + padding: 1px; + border: 2px solid #6060a0; + background-color: #fffff0; +} + +ul { + margin-top: -0em; + margin-bottom: -0em; +} + +ol { + margin-top: -0em; + margin-bottom: -0em; +} + +UL.nobullets { + list-style-type: none; + list-style-image: none; + margin-left: -1em; +} + +p { + margin: 1em 0 1em 0; + padding: 0 0 0 0; +} + +pre { + line-height: 1.3em; + padding: 0.4em 0 0.8em 0; + margin: 0 0 0 0; + border: 0 0 0 0; + color: blue; +} + +.datatable { + margin-left: auto; + margin-right: auto; + margin-top: 2em; + margin-bottom: 2em; + border: 1px solid; +} + +.datatable td,th { + padding: 0 0.5em 0 0.5em; + text-align: right; +} diff --git a/src/leveldb/doc/impl.html b/src/leveldb/doc/impl.html new file mode 100644 index 0000000..28817fe --- /dev/null +++ b/src/leveldb/doc/impl.html @@ -0,0 +1,213 @@ + + + + +Leveldb file layout and compactions + + + + +

Files

+ +The implementation of leveldb is similar in spirit to the +representation of a single + +Bigtable tablet (section 5.3). +However the organization of the files that make up the representation +is somewhat different and is explained below. + +

+Each database is represented by a set of files stored in a directory. +There are several different types of files as documented below: +

+

Log files

+

+A log file (*.log) stores a sequence of recent updates. Each update +is appended to the current log file. When the log file reaches a +pre-determined size (approximately 4MB by default), it is converted +to a sorted table (see below) and a new log file is created for future +updates. +

+A copy of the current log file is kept in an in-memory structure (the +memtable). This copy is consulted on every read so that read +operations reflect all logged updates. +

+

Sorted tables

+

+A sorted table (*.sst) stores a sequence of entries sorted by key. +Each entry is either a value for the key, or a deletion marker for the +key. (Deletion markers are kept around to hide obsolete values +present in older sorted tables). +

+The set of sorted tables are organized into a sequence of levels. The +sorted table generated from a log file is placed in a special young +level (also called level-0). When the number of young files exceeds a +certain threshold (currently four), all of the young files are merged +together with all of the overlapping level-1 files to produce a +sequence of new level-1 files (we create a new level-1 file for every +2MB of data.) +

+Files in the young level may contain overlapping keys. However files +in other levels have distinct non-overlapping key ranges. Consider +level number L where L >= 1. When the combined size of files in +level-L exceeds (10^L) MB (i.e., 10MB for level-1, 100MB for level-2, +...), one file in level-L, and all of the overlapping files in +level-(L+1) are merged to form a set of new files for level-(L+1). +These merges have the effect of gradually migrating new updates from +the young level to the largest level using only bulk reads and writes +(i.e., minimizing expensive seeks). + +

Manifest

+

+A MANIFEST file lists the set of sorted tables that make up each +level, the corresponding key ranges, and other important metadata. +A new MANIFEST file (with a new number embedded in the file name) +is created whenever the database is reopened. The MANIFEST file is +formatted as a log, and changes made to the serving state (as files +are added or removed) are appended to this log. +

+

Current

+

+CURRENT is a simple text file that contains the name of the latest +MANIFEST file. +

+

Info logs

+

+Informational messages are printed to files named LOG and LOG.old. +

+

Others

+

+Other files used for miscellaneous purposes may also be present +(LOCK, *.dbtmp). + +

Level 0

+When the log file grows above a certain size (1MB by default): +
    +
  • Create a brand new memtable and log file and direct future updates here +
  • In the background: +
      +
    • Write the contents of the previous memtable to an sstable +
    • Discard the memtable +
    • Delete the old log file and the old memtable +
    • Add the new sstable to the young (level-0) level. +
    +
+ +

Compactions

+ +

+When the size of level L exceeds its limit, we compact it in a +background thread. The compaction picks a file from level L and all +overlapping files from the next level L+1. Note that if a level-L +file overlaps only part of a level-(L+1) file, the entire file at +level-(L+1) is used as an input to the compaction and will be +discarded after the compaction. Aside: because level-0 is special +(files in it may overlap each other), we treat compactions from +level-0 to level-1 specially: a level-0 compaction may pick more than +one level-0 file in case some of these files overlap each other. + +

+A compaction merges the contents of the picked files to produce a +sequence of level-(L+1) files. We switch to producing a new +level-(L+1) file after the current output file has reached the target +file size (2MB). We also switch to a new output file when the key +range of the current output file has grown enough to overlap more then +ten level-(L+2) files. This last rule ensures that a later compaction +of a level-(L+1) file will not pick up too much data from level-(L+2). + +

+The old files are discarded and the new files are added to the serving +state. + +

+Compactions for a particular level rotate through the key space. In +more detail, for each level L, we remember the ending key of the last +compaction at level L. The next compaction for level L will pick the +first file that starts after this key (wrapping around to the +beginning of the key space if there is no such file). + +

+Compactions drop overwritten values. They also drop deletion markers +if there are no higher numbered levels that contain a file whose range +overlaps the current key. + +

Timing

+ +Level-0 compactions will read up to four 1MB files from level-0, and +at worst all the level-1 files (10MB). I.e., we will read 14MB and +write 14MB. + +

+Other than the special level-0 compactions, we will pick one 2MB file +from level L. In the worst case, this will overlap ~ 12 files from +level L+1 (10 because level-(L+1) is ten times the size of level-L, +and another two at the boundaries since the file ranges at level-L +will usually not be aligned with the file ranges at level-L+1). The +compaction will therefore read 26MB and write 26MB. Assuming a disk +IO rate of 100MB/s (ballpark range for modern drives), the worst +compaction cost will be approximately 0.5 second. + +

+If we throttle the background writing to something small, say 10% of +the full 100MB/s speed, a compaction may take up to 5 seconds. If the +user is writing at 10MB/s, we might build up lots of level-0 files +(~50 to hold the 5*10MB). This may signficantly increase the cost of +reads due to the overhead of merging more files together on every +read. + +

+Solution 1: To reduce this problem, we might want to increase the log +switching threshold when the number of level-0 files is large. Though +the downside is that the larger this threshold, the more memory we will +need to hold the corresponding memtable. + +

+Solution 2: We might want to decrease write rate artificially when the +number of level-0 files goes up. + +

+Solution 3: We work on reducing the cost of very wide merges. +Perhaps most of the level-0 files will have their blocks sitting +uncompressed in the cache and we will only need to worry about the +O(N) complexity in the merging iterator. + +

Number of files

+ +Instead of always making 2MB files, we could make larger files for +larger levels to reduce the total file count, though at the expense of +more bursty compactions. Alternatively, we could shard the set of +files into multiple directories. + +

+An experiment on an ext3 filesystem on Feb 04, 2011 shows +the following timings to do 100K file opens in directories with +varying number of files: + + + + + +
Files in directoryMicroseconds to open a file
10009
1000010
10000016
+So maybe even the sharding is not necessary on modern filesystems? + +

Recovery

+ +
    +
  • Read CURRENT to find name of the latest committed MANIFEST +
  • Read the named MANIFEST file +
  • Clean up stale files +
  • We could open all sstables here, but it is probably better to be lazy... +
  • Convert log chunk to a new level-0 sstable +
  • Start directing new writes to a new log file with recovered sequence# +
+ +

Garbage collection of files

+ +DeleteObsoleteFiles() is called at the end of every +compaction and at the end of recovery. It finds the names of all +files in the database. It deletes all log files that are not the +current log file. It deletes all table files that are not referenced +from some level and are not the output of an active compaction. + + + diff --git a/src/leveldb/doc/index.html b/src/leveldb/doc/index.html new file mode 100644 index 0000000..3ed0ed9 --- /dev/null +++ b/src/leveldb/doc/index.html @@ -0,0 +1,549 @@ + + + + +Leveldb + + + +

Leveldb

+
Jeff Dean, Sanjay Ghemawat
+

+The leveldb library provides a persistent key value store. Keys and +values are arbitrary byte arrays. The keys are ordered within the key +value store according to a user-specified comparator function. + +

+

Opening A Database

+

+A leveldb database has a name which corresponds to a file system +directory. All of the contents of database are stored in this +directory. The following example shows how to open a database, +creating it if necessary: +

+

+  #include <assert>
+  #include "leveldb/db.h"
+
+  leveldb::DB* db;
+  leveldb::Options options;
+  options.create_if_missing = true;
+  leveldb::Status status = leveldb::DB::Open(options, "/tmp/testdb", &db);
+  assert(status.ok());
+  ...
+
+If you want to raise an error if the database already exists, add +the following line before the leveldb::DB::Open call: +
+  options.error_if_exists = true;
+
+

Status

+

+You may have noticed the leveldb::Status type above. Values of this +type are returned by most functions in leveldb that may encounter an +error. You can check if such a result is ok, and also print an +associated error message: +

+

+   leveldb::Status s = ...;
+   if (!s.ok()) cerr << s.ToString() << endl;
+
+

Closing A Database

+

+When you are done with a database, just delete the database object. +Example: +

+

+  ... open the db as described above ...
+  ... do something with db ...
+  delete db;
+
+

Reads And Writes

+

+The database provides Put, Delete, and Get methods to +modify/query the database. For example, the following code +moves the value stored under key1 to key2. +

+  std::string value;
+  leveldb::Status s = db->Get(leveldb::ReadOptions(), key1, &value);
+  if (s.ok()) s = db->Put(leveldb::WriteOptions(), key2, value);
+  if (s.ok()) s = db->Delete(leveldb::WriteOptions(), key1);
+
+ +

Atomic Updates

+

+Note that if the process dies after the Put of key2 but before the +delete of key1, the same value may be left stored under multiple keys. +Such problems can be avoided by using the WriteBatch class to +atomically apply a set of updates: +

+

+  #include "leveldb/write_batch.h"
+  ...
+  std::string value;
+  leveldb::Status s = db->Get(leveldb::ReadOptions(), key1, &value);
+  if (s.ok()) {
+    leveldb::WriteBatch batch;
+    batch.Delete(key1);
+    batch.Put(key2, value);
+    s = db->Write(leveldb::WriteOptions(), &batch);
+  }
+
+The WriteBatch holds a sequence of edits to be made to the database, +and these edits within the batch are applied in order. Note that we +called Delete before Put so that if key1 is identical to key2, +we do not end up erroneously dropping the value entirely. +

+Apart from its atomicity benefits, WriteBatch may also be used to +speed up bulk updates by placing lots of individual mutations into the +same batch. + +

Synchronous Writes

+By default, each write to leveldb is asynchronous: it +returns after pushing the write from the process into the operating +system. The transfer from operating system memory to the underlying +persistent storage happens asynchronously. The sync flag +can be turned on for a particular write to make the write operation +not return until the data being written has been pushed all the way to +persistent storage. (On Posix systems, this is implemented by calling +either fsync(...) or fdatasync(...) or +msync(..., MS_SYNC) before the write operation returns.) +
+  leveldb::WriteOptions write_options;
+  write_options.sync = true;
+  db->Put(write_options, ...);
+
+Asynchronous writes are often more than a thousand times as fast as +synchronous writes. The downside of asynchronous writes is that a +crash of the machine may cause the last few updates to be lost. Note +that a crash of just the writing process (i.e., not a reboot) will not +cause any loss since even when sync is false, an update +is pushed from the process memory into the operating system before it +is considered done. + +

+Asynchronous writes can often be used safely. For example, when +loading a large amount of data into the database you can handle lost +updates by restarting the bulk load after a crash. A hybrid scheme is +also possible where every Nth write is synchronous, and in the event +of a crash, the bulk load is restarted just after the last synchronous +write finished by the previous run. (The synchronous write can update +a marker that describes where to restart on a crash.) + +

+WriteBatch provides an alternative to asynchronous writes. +Multiple updates may be placed in the same WriteBatch and +applied together using a synchronous write (i.e., +write_options.sync is set to true). The extra cost of +the synchronous write will be amortized across all of the writes in +the batch. + +

+

Concurrency

+

+A database may only be opened by one process at a time. +The leveldb implementation acquires a lock from the +operating system to prevent misuse. Within a single process, the +same leveldb::DB object may be safely shared by multiple +concurrent threads. I.e., different threads may write into or fetch +iterators or call Get on the same database without any +external synchronization (the leveldb implementation will +automatically do the required synchronization). However other objects +(like Iterator and WriteBatch) may require external synchronization. +If two threads share such an object, they must protect access to it +using their own locking protocol. More details are available in +the public header files. +

+

Iteration

+

+The following example demonstrates how to print all key,value pairs +in a database. +

+

+  leveldb::Iterator* it = db->NewIterator(leveldb::ReadOptions());
+  for (it->SeekToFirst(); it->Valid(); it->Next()) {
+    cout << it->key().ToString() << ": "  << it->value().ToString() << endl;
+  }
+  assert(it->status().ok());  // Check for any errors found during the scan
+  delete it;
+
+The following variation shows how to process just the keys in the +range [start,limit): +

+

+  for (it->Seek(start);
+       it->Valid() && it->key().ToString() < limit;
+       it->Next()) {
+    ...
+  }
+
+You can also process entries in reverse order. (Caveat: reverse +iteration may be somewhat slower than forward iteration.) +

+

+  for (it->SeekToLast(); it->Valid(); it->Prev()) {
+    ...
+  }
+
+

Snapshots

+

+Snapshots provide consistent read-only views over the entire state of +the key-value store. ReadOptions::snapshot may be non-NULL to indicate +that a read should operate on a particular version of the DB state. +If ReadOptions::snapshot is NULL, the read will operate on an +implicit snapshot of the current state. +

+Snapshots are created by the DB::GetSnapshot() method: +

+

+  leveldb::ReadOptions options;
+  options.snapshot = db->GetSnapshot();
+  ... apply some updates to db ...
+  leveldb::Iterator* iter = db->NewIterator(options);
+  ... read using iter to view the state when the snapshot was created ...
+  delete iter;
+  db->ReleaseSnapshot(options.snapshot);
+
+Note that when a snapshot is no longer needed, it should be released +using the DB::ReleaseSnapshot interface. This allows the +implementation to get rid of state that was being maintained just to +support reading as of that snapshot. +

Slice

+

+The return value of the it->key() and it->value() calls above +are instances of the leveldb::Slice type. Slice is a simple +structure that contains a length and a pointer to an external byte +array. Returning a Slice is a cheaper alternative to returning a +std::string since we do not need to copy potentially large keys and +values. In addition, leveldb methods do not return null-terminated +C-style strings since leveldb keys and values are allowed to +contain '\0' bytes. +

+C++ strings and null-terminated C-style strings can be easily converted +to a Slice: +

+

+   leveldb::Slice s1 = "hello";
+
+   std::string str("world");
+   leveldb::Slice s2 = str;
+
+A Slice can be easily converted back to a C++ string: +
+   std::string str = s1.ToString();
+   assert(str == std::string("hello"));
+
+Be careful when using Slices since it is up to the caller to ensure that +the external byte array into which the Slice points remains live while +the Slice is in use. For example, the following is buggy: +

+

+   leveldb::Slice slice;
+   if (...) {
+     std::string str = ...;
+     slice = str;
+   }
+   Use(slice);
+
+When the if statement goes out of scope, str will be destroyed and the +backing storage for slice will disappear. +

+

Comparators

+

+The preceding examples used the default ordering function for key, +which orders bytes lexicographically. You can however supply a custom +comparator when opening a database. For example, suppose each +database key consists of two numbers and we should sort by the first +number, breaking ties by the second number. First, define a proper +subclass of leveldb::Comparator that expresses these rules: +

+

+  class TwoPartComparator : public leveldb::Comparator {
+   public:
+    // Three-way comparison function:
+    //   if a < b: negative result
+    //   if a > b: positive result
+    //   else: zero result
+    int Compare(const leveldb::Slice& a, const leveldb::Slice& b) const {
+      int a1, a2, b1, b2;
+      ParseKey(a, &a1, &a2);
+      ParseKey(b, &b1, &b2);
+      if (a1 < b1) return -1;
+      if (a1 > b1) return +1;
+      if (a2 < b2) return -1;
+      if (a2 > b2) return +1;
+      return 0;
+    }
+
+    // Ignore the following methods for now:
+    const char* Name() const { return "TwoPartComparator"; }
+    void FindShortestSeparator(std::string*, const leveldb::Slice&) const { }
+    void FindShortSuccessor(std::string*) const { }
+  };
+
+Now create a database using this custom comparator: +

+

+  TwoPartComparator cmp;
+  leveldb::DB* db;
+  leveldb::Options options;
+  options.create_if_missing = true;
+  options.comparator = &cmp;
+  leveldb::Status status = leveldb::DB::Open(options, "/tmp/testdb", &db);
+  ...
+
+

Backwards compatibility

+

+The result of the comparator's Name method is attached to the +database when it is created, and is checked on every subsequent +database open. If the name changes, the leveldb::DB::Open call will +fail. Therefore, change the name if and only if the new key format +and comparison function are incompatible with existing databases, and +it is ok to discard the contents of all existing databases. +

+You can however still gradually evolve your key format over time with +a little bit of pre-planning. For example, you could store a version +number at the end of each key (one byte should suffice for most uses). +When you wish to switch to a new key format (e.g., adding an optional +third part to the keys processed by TwoPartComparator), +(a) keep the same comparator name (b) increment the version number +for new keys (c) change the comparator function so it uses the +version numbers found in the keys to decide how to interpret them. +

+

Performance

+

+Performance can be tuned by changing the default values of the +types defined in include/leveldb/options.h. + +

+

Block size

+

+leveldb groups adjacent keys together into the same block and such a +block is the unit of transfer to and from persistent storage. The +default block size is approximately 4096 uncompressed bytes. +Applications that mostly do bulk scans over the contents of the +database may wish to increase this size. Applications that do a lot +of point reads of small values may wish to switch to a smaller block +size if performance measurements indicate an improvement. There isn't +much benefit in using blocks smaller than one kilobyte, or larger than +a few megabytes. Also note that compression will be more effective +with larger block sizes. +

+

Compression

+

+Each block is individually compressed before being written to +persistent storage. Compression is on by default since the default +compression method is very fast, and is automatically disabled for +uncompressible data. In rare cases, applications may want to disable +compression entirely, but should only do so if benchmarks show a +performance improvement: +

+

+  leveldb::Options options;
+  options.compression = leveldb::kNoCompression;
+  ... leveldb::DB::Open(options, name, ...) ....
+
+

Cache

+

+The contents of the database are stored in a set of files in the +filesystem and each file stores a sequence of compressed blocks. If +options.cache is non-NULL, it is used to cache frequently used +uncompressed block contents. +

+

+  #include "leveldb/cache.h"
+
+  leveldb::Options options;
+  options.cache = leveldb::NewLRUCache(100 * 1048576);  // 100MB cache
+  leveldb::DB* db;
+  leveldb::DB::Open(options, name, &db);
+  ... use the db ...
+  delete db
+  delete options.cache;
+
+Note that the cache holds uncompressed data, and therefore it should +be sized according to application level data sizes, without any +reduction from compression. (Caching of compressed blocks is left to +the operating system buffer cache, or any custom Env +implementation provided by the client.) +

+When performing a bulk read, the application may wish to disable +caching so that the data processed by the bulk read does not end up +displacing most of the cached contents. A per-iterator option can be +used to achieve this: +

+

+  leveldb::ReadOptions options;
+  options.fill_cache = false;
+  leveldb::Iterator* it = db->NewIterator(options);
+  for (it->SeekToFirst(); it->Valid(); it->Next()) {
+    ...
+  }
+
+

Key Layout

+

+Note that the unit of disk transfer and caching is a block. Adjacent +keys (according to the database sort order) will usually be placed in +the same block. Therefore the application can improve its performance +by placing keys that are accessed together near each other and placing +infrequently used keys in a separate region of the key space. +

+For example, suppose we are implementing a simple file system on top +of leveldb. The types of entries we might wish to store are: +

+

+   filename -> permission-bits, length, list of file_block_ids
+   file_block_id -> data
+
+We might want to prefix filename keys with one letter (say '/') and the +file_block_id keys with a different letter (say '0') so that scans +over just the metadata do not force us to fetch and cache bulky file +contents. +

+

Filters

+

+Because of the way leveldb data is organized on disk, +a single Get() call may involve multiple reads from disk. +The optional FilterPolicy mechanism can be used to reduce +the number of disk reads substantially. +

+   leveldb::Options options;
+   options.filter_policy = NewBloomFilterPolicy(10);
+   leveldb::DB* db;
+   leveldb::DB::Open(options, "/tmp/testdb", &db);
+   ... use the database ...
+   delete db;
+   delete options.filter_policy;
+
+The preceding code associates a +Bloom filter +based filtering policy with the database. Bloom filter based +filtering relies on keeping some number of bits of data in memory per +key (in this case 10 bits per key since that is the argument we passed +to NewBloomFilterPolicy). This filter will reduce the number of unnecessary +disk reads needed for Get() calls by a factor of +approximately a 100. Increasing the bits per key will lead to a +larger reduction at the cost of more memory usage. We recommend that +applications whose working set does not fit in memory and that do a +lot of random reads set a filter policy. +

+If you are using a custom comparator, you should ensure that the filter +policy you are using is compatible with your comparator. For example, +consider a comparator that ignores trailing spaces when comparing keys. +NewBloomFilterPolicy must not be used with such a comparator. +Instead, the application should provide a custom filter policy that +also ignores trailing spaces. For example: +

+  class CustomFilterPolicy : public leveldb::FilterPolicy {
+   private:
+    FilterPolicy* builtin_policy_;
+   public:
+    CustomFilterPolicy() : builtin_policy_(NewBloomFilterPolicy(10)) { }
+    ~CustomFilterPolicy() { delete builtin_policy_; }
+
+    const char* Name() const { return "IgnoreTrailingSpacesFilter"; }
+
+    void CreateFilter(const Slice* keys, int n, std::string* dst) const {
+      // Use builtin bloom filter code after removing trailing spaces
+      std::vector<Slice> trimmed(n);
+      for (int i = 0; i < n; i++) {
+        trimmed[i] = RemoveTrailingSpaces(keys[i]);
+      }
+      return builtin_policy_->CreateFilter(&trimmed[i], n, dst);
+    }
+
+    bool KeyMayMatch(const Slice& key, const Slice& filter) const {
+      // Use builtin bloom filter code after removing trailing spaces
+      return builtin_policy_->KeyMayMatch(RemoveTrailingSpaces(key), filter);
+    }
+  };
+
+

+Advanced applications may provide a filter policy that does not use +a bloom filter but uses some other mechanism for summarizing a set +of keys. See leveldb/filter_policy.h for detail. +

+

Checksums

+

+leveldb associates checksums with all data it stores in the file system. +There are two separate controls provided over how aggressively these +checksums are verified: +

+

    +
  • ReadOptions::verify_checksums may be set to true to force + checksum verification of all data that is read from the file system on + behalf of a particular read. By default, no such verification is + done. +

    +

  • Options::paranoid_checks may be set to true before opening a + database to make the database implementation raise an error as soon as + it detects an internal corruption. Depending on which portion of the + database has been corrupted, the error may be raised when the database + is opened, or later by another database operation. By default, + paranoid checking is off so that the database can be used even if + parts of its persistent storage have been corrupted. +

    + If a database is corrupted (perhaps it cannot be opened when + paranoid checking is turned on), the leveldb::RepairDB function + may be used to recover as much of the data as possible +

    +

+

Approximate Sizes

+

+The GetApproximateSizes method can used to get the approximate +number of bytes of file system space used by one or more key ranges. +

+

+   leveldb::Range ranges[2];
+   ranges[0] = leveldb::Range("a", "c");
+   ranges[1] = leveldb::Range("x", "z");
+   uint64_t sizes[2];
+   leveldb::Status s = db->GetApproximateSizes(ranges, 2, sizes);
+
+The preceding call will set sizes[0] to the approximate number of +bytes of file system space used by the key range [a..c) and +sizes[1] to the approximate number of bytes used by the key range +[x..z). +

+

Environment

+

+All file operations (and other operating system calls) issued by the +leveldb implementation are routed through a leveldb::Env object. +Sophisticated clients may wish to provide their own Env +implementation to get better control. For example, an application may +introduce artificial delays in the file IO paths to limit the impact +of leveldb on other activities in the system. +

+

+  class SlowEnv : public leveldb::Env {
+    .. implementation of the Env interface ...
+  };
+
+  SlowEnv env;
+  leveldb::Options options;
+  options.env = &env;
+  Status s = leveldb::DB::Open(options, ...);
+
+

Porting

+

+leveldb may be ported to a new platform by providing platform +specific implementations of the types/methods/functions exported by +leveldb/port/port.h. See leveldb/port/port_example.h for more +details. +

+In addition, the new platform may need a new default leveldb::Env +implementation. See leveldb/util/env_posix.h for an example. + +

Other Information

+ +

+Details about the leveldb implementation may be found in +the following documents: +

+ + + diff --git a/src/leveldb/doc/log_format.txt b/src/leveldb/doc/log_format.txt new file mode 100644 index 0000000..5228f62 --- /dev/null +++ b/src/leveldb/doc/log_format.txt @@ -0,0 +1,75 @@ +The log file contents are a sequence of 32KB blocks. The only +exception is that the tail of the file may contain a partial block. + +Each block consists of a sequence of records: + block := record* trailer? + record := + checksum: uint32 // crc32c of type and data[] ; little-endian + length: uint16 // little-endian + type: uint8 // One of FULL, FIRST, MIDDLE, LAST + data: uint8[length] + +A record never starts within the last six bytes of a block (since it +won't fit). Any leftover bytes here form the trailer, which must +consist entirely of zero bytes and must be skipped by readers. + +Aside: if exactly seven bytes are left in the current block, and a new +non-zero length record is added, the writer must emit a FIRST record +(which contains zero bytes of user data) to fill up the trailing seven +bytes of the block and then emit all of the user data in subsequent +blocks. + +More types may be added in the future. Some Readers may skip record +types they do not understand, others may report that some data was +skipped. + +FULL == 1 +FIRST == 2 +MIDDLE == 3 +LAST == 4 + +The FULL record contains the contents of an entire user record. + +FIRST, MIDDLE, LAST are types used for user records that have been +split into multiple fragments (typically because of block boundaries). +FIRST is the type of the first fragment of a user record, LAST is the +type of the last fragment of a user record, and MID is the type of all +interior fragments of a user record. + +Example: consider a sequence of user records: + A: length 1000 + B: length 97270 + C: length 8000 +A will be stored as a FULL record in the first block. + +B will be split into three fragments: first fragment occupies the rest +of the first block, second fragment occupies the entirety of the +second block, and the third fragment occupies a prefix of the third +block. This will leave six bytes free in the third block, which will +be left empty as the trailer. + +C will be stored as a FULL record in the fourth block. + +=================== + +Some benefits over the recordio format: + +(1) We do not need any heuristics for resyncing - just go to next +block boundary and scan. If there is a corruption, skip to the next +block. As a side-benefit, we do not get confused when part of the +contents of one log file are embedded as a record inside another log +file. + +(2) Splitting at approximate boundaries (e.g., for mapreduce) is +simple: find the next block boundary and skip records until we +hit a FULL or FIRST record. + +(3) We do not need extra buffering for large records. + +Some downsides compared to recordio format: + +(1) No packing of tiny records. This could be fixed by adding a new +record type, so it is a shortcoming of the current implementation, +not necessarily the format. + +(2) No compression. Again, this could be fixed by adding new record types. diff --git a/src/leveldb/doc/table_format.txt b/src/leveldb/doc/table_format.txt new file mode 100644 index 0000000..ca8f9b4 --- /dev/null +++ b/src/leveldb/doc/table_format.txt @@ -0,0 +1,104 @@ +File format +=========== + + + [data block 1] + [data block 2] + ... + [data block N] + [meta block 1] + ... + [meta block K] + [metaindex block] + [index block] + [Footer] (fixed size; starts at file_size - sizeof(Footer)) + + +The file contains internal pointers. Each such pointer is called +a BlockHandle and contains the following information: + offset: varint64 + size: varint64 +See https://developers.google.com/protocol-buffers/docs/encoding#varints +for an explanation of varint64 format. + +(1) The sequence of key/value pairs in the file are stored in sorted +order and partitioned into a sequence of data blocks. These blocks +come one after another at the beginning of the file. Each data block +is formatted according to the code in block_builder.cc, and then +optionally compressed. + +(2) After the data blocks we store a bunch of meta blocks. The +supported meta block types are described below. More meta block types +may be added in the future. Each meta block is again formatted using +block_builder.cc and then optionally compressed. + +(3) A "metaindex" block. It contains one entry for every other meta +block where the key is the name of the meta block and the value is a +BlockHandle pointing to that meta block. + +(4) An "index" block. This block contains one entry per data block, +where the key is a string >= last key in that data block and before +the first key in the successive data block. The value is the +BlockHandle for the data block. + +(6) At the very end of the file is a fixed length footer that contains +the BlockHandle of the metaindex and index blocks as well as a magic number. + metaindex_handle: char[p]; // Block handle for metaindex + index_handle: char[q]; // Block handle for index + padding: char[40-p-q]; // zeroed bytes to make fixed length + // (40==2*BlockHandle::kMaxEncodedLength) + magic: fixed64; // == 0xdb4775248b80fb57 (little-endian) + +"filter" Meta Block +------------------- + +If a "FilterPolicy" was specified when the database was opened, a +filter block is stored in each table. The "metaindex" block contains +an entry that maps from "filter." to the BlockHandle for the filter +block where "" is the string returned by the filter policy's +"Name()" method. + +The filter block stores a sequence of filters, where filter i contains +the output of FilterPolicy::CreateFilter() on all keys that are stored +in a block whose file offset falls within the range + + [ i*base ... (i+1)*base-1 ] + +Currently, "base" is 2KB. So for example, if blocks X and Y start in +the range [ 0KB .. 2KB-1 ], all of the keys in X and Y will be +converted to a filter by calling FilterPolicy::CreateFilter(), and the +resulting filter will be stored as the first filter in the filter +block. + +The filter block is formatted as follows: + + [filter 0] + [filter 1] + [filter 2] + ... + [filter N-1] + + [offset of filter 0] : 4 bytes + [offset of filter 1] : 4 bytes + [offset of filter 2] : 4 bytes + ... + [offset of filter N-1] : 4 bytes + + [offset of beginning of offset array] : 4 bytes + lg(base) : 1 byte + +The offset array at the end of the filter block allows efficient +mapping from a data block offset to the corresponding filter. + +"stats" Meta Block +------------------ + +This meta block contains a bunch of stats. The key is the name +of the statistic. The value contains the statistic. +TODO(postrelease): record following stats. + data size + index size + key size (uncompressed) + value size (uncompressed) + number of entries + number of data blocks diff --git a/src/leveldb/helpers/memenv/memenv.cc b/src/leveldb/helpers/memenv/memenv.cc new file mode 100644 index 0000000..5879de1 --- /dev/null +++ b/src/leveldb/helpers/memenv/memenv.cc @@ -0,0 +1,384 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "helpers/memenv/memenv.h" + +#include "leveldb/env.h" +#include "leveldb/status.h" +#include "port/port.h" +#include "util/mutexlock.h" +#include +#include +#include +#include + +namespace leveldb { + +namespace { + +class FileState { + public: + // FileStates are reference counted. The initial reference count is zero + // and the caller must call Ref() at least once. + FileState() : refs_(0), size_(0) {} + + // Increase the reference count. + void Ref() { + MutexLock lock(&refs_mutex_); + ++refs_; + } + + // Decrease the reference count. Delete if this is the last reference. + void Unref() { + bool do_delete = false; + + { + MutexLock lock(&refs_mutex_); + --refs_; + assert(refs_ >= 0); + if (refs_ <= 0) { + do_delete = true; + } + } + + if (do_delete) { + delete this; + } + } + + uint64_t Size() const { return size_; } + + Status Read(uint64_t offset, size_t n, Slice* result, char* scratch) const { + if (offset > size_) { + return Status::IOError("Offset greater than file size."); + } + const uint64_t available = size_ - offset; + if (n > available) { + n = available; + } + if (n == 0) { + *result = Slice(); + return Status::OK(); + } + + size_t block = offset / kBlockSize; + size_t block_offset = offset % kBlockSize; + + if (n <= kBlockSize - block_offset) { + // The requested bytes are all in the first block. + *result = Slice(blocks_[block] + block_offset, n); + return Status::OK(); + } + + size_t bytes_to_copy = n; + char* dst = scratch; + + while (bytes_to_copy > 0) { + size_t avail = kBlockSize - block_offset; + if (avail > bytes_to_copy) { + avail = bytes_to_copy; + } + memcpy(dst, blocks_[block] + block_offset, avail); + + bytes_to_copy -= avail; + dst += avail; + block++; + block_offset = 0; + } + + *result = Slice(scratch, n); + return Status::OK(); + } + + Status Append(const Slice& data) { + const char* src = data.data(); + size_t src_len = data.size(); + + while (src_len > 0) { + size_t avail; + size_t offset = size_ % kBlockSize; + + if (offset != 0) { + // There is some room in the last block. + avail = kBlockSize - offset; + } else { + // No room in the last block; push new one. + blocks_.push_back(new char[kBlockSize]); + avail = kBlockSize; + } + + if (avail > src_len) { + avail = src_len; + } + memcpy(blocks_.back() + offset, src, avail); + src_len -= avail; + src += avail; + size_ += avail; + } + + return Status::OK(); + } + + private: + // Private since only Unref() should be used to delete it. + ~FileState() { + for (std::vector::iterator i = blocks_.begin(); i != blocks_.end(); + ++i) { + delete [] *i; + } + } + + // No copying allowed. + FileState(const FileState&); + void operator=(const FileState&); + + port::Mutex refs_mutex_; + int refs_; // Protected by refs_mutex_; + + // The following fields are not protected by any mutex. They are only mutable + // while the file is being written, and concurrent access is not allowed + // to writable files. + std::vector blocks_; + uint64_t size_; + + enum { kBlockSize = 8 * 1024 }; +}; + +class SequentialFileImpl : public SequentialFile { + public: + explicit SequentialFileImpl(FileState* file) : file_(file), pos_(0) { + file_->Ref(); + } + + ~SequentialFileImpl() { + file_->Unref(); + } + + virtual Status Read(size_t n, Slice* result, char* scratch) { + Status s = file_->Read(pos_, n, result, scratch); + if (s.ok()) { + pos_ += result->size(); + } + return s; + } + + virtual Status Skip(uint64_t n) { + if (pos_ > file_->Size()) { + return Status::IOError("pos_ > file_->Size()"); + } + const size_t available = file_->Size() - pos_; + if (n > available) { + n = available; + } + pos_ += n; + return Status::OK(); + } + + private: + FileState* file_; + size_t pos_; +}; + +class RandomAccessFileImpl : public RandomAccessFile { + public: + explicit RandomAccessFileImpl(FileState* file) : file_(file) { + file_->Ref(); + } + + ~RandomAccessFileImpl() { + file_->Unref(); + } + + virtual Status Read(uint64_t offset, size_t n, Slice* result, + char* scratch) const { + return file_->Read(offset, n, result, scratch); + } + + private: + FileState* file_; +}; + +class WritableFileImpl : public WritableFile { + public: + WritableFileImpl(FileState* file) : file_(file) { + file_->Ref(); + } + + ~WritableFileImpl() { + file_->Unref(); + } + + virtual Status Append(const Slice& data) { + return file_->Append(data); + } + + virtual Status Close() { return Status::OK(); } + virtual Status Flush() { return Status::OK(); } + virtual Status Sync() { return Status::OK(); } + + private: + FileState* file_; +}; + +class NoOpLogger : public Logger { + public: + virtual void Logv(const char* format, va_list ap) { } +}; + +class InMemoryEnv : public EnvWrapper { + public: + explicit InMemoryEnv(Env* base_env) : EnvWrapper(base_env) { } + + virtual ~InMemoryEnv() { + for (FileSystem::iterator i = file_map_.begin(); i != file_map_.end(); ++i){ + i->second->Unref(); + } + } + + // Partial implementation of the Env interface. + virtual Status NewSequentialFile(const std::string& fname, + SequentialFile** result) { + MutexLock lock(&mutex_); + if (file_map_.find(fname) == file_map_.end()) { + *result = NULL; + return Status::IOError(fname, "File not found"); + } + + *result = new SequentialFileImpl(file_map_[fname]); + return Status::OK(); + } + + virtual Status NewRandomAccessFile(const std::string& fname, + RandomAccessFile** result) { + MutexLock lock(&mutex_); + if (file_map_.find(fname) == file_map_.end()) { + *result = NULL; + return Status::IOError(fname, "File not found"); + } + + *result = new RandomAccessFileImpl(file_map_[fname]); + return Status::OK(); + } + + virtual Status NewWritableFile(const std::string& fname, + WritableFile** result) { + MutexLock lock(&mutex_); + if (file_map_.find(fname) != file_map_.end()) { + DeleteFileInternal(fname); + } + + FileState* file = new FileState(); + file->Ref(); + file_map_[fname] = file; + + *result = new WritableFileImpl(file); + return Status::OK(); + } + + virtual bool FileExists(const std::string& fname) { + MutexLock lock(&mutex_); + return file_map_.find(fname) != file_map_.end(); + } + + virtual Status GetChildren(const std::string& dir, + std::vector* result) { + MutexLock lock(&mutex_); + result->clear(); + + for (FileSystem::iterator i = file_map_.begin(); i != file_map_.end(); ++i){ + const std::string& filename = i->first; + + if (filename.size() >= dir.size() + 1 && filename[dir.size()] == '/' && + Slice(filename).starts_with(Slice(dir))) { + result->push_back(filename.substr(dir.size() + 1)); + } + } + + return Status::OK(); + } + + void DeleteFileInternal(const std::string& fname) { + if (file_map_.find(fname) == file_map_.end()) { + return; + } + + file_map_[fname]->Unref(); + file_map_.erase(fname); + } + + virtual Status DeleteFile(const std::string& fname) { + MutexLock lock(&mutex_); + if (file_map_.find(fname) == file_map_.end()) { + return Status::IOError(fname, "File not found"); + } + + DeleteFileInternal(fname); + return Status::OK(); + } + + virtual Status CreateDir(const std::string& dirname) { + return Status::OK(); + } + + virtual Status DeleteDir(const std::string& dirname) { + return Status::OK(); + } + + virtual Status GetFileSize(const std::string& fname, uint64_t* file_size) { + MutexLock lock(&mutex_); + if (file_map_.find(fname) == file_map_.end()) { + return Status::IOError(fname, "File not found"); + } + + *file_size = file_map_[fname]->Size(); + return Status::OK(); + } + + virtual Status RenameFile(const std::string& src, + const std::string& target) { + MutexLock lock(&mutex_); + if (file_map_.find(src) == file_map_.end()) { + return Status::IOError(src, "File not found"); + } + + DeleteFileInternal(target); + file_map_[target] = file_map_[src]; + file_map_.erase(src); + return Status::OK(); + } + + virtual Status LockFile(const std::string& fname, FileLock** lock) { + *lock = new FileLock; + return Status::OK(); + } + + virtual Status UnlockFile(FileLock* lock) { + delete lock; + return Status::OK(); + } + + virtual Status GetTestDirectory(std::string* path) { + *path = "/test"; + return Status::OK(); + } + + virtual Status NewLogger(const std::string& fname, Logger** result) { + *result = new NoOpLogger; + return Status::OK(); + } + + private: + // Map from filenames to FileState objects, representing a simple file system. + typedef std::map FileSystem; + port::Mutex mutex_; + FileSystem file_map_; // Protected by mutex_. +}; + +} // namespace + +Env* NewMemEnv(Env* base_env) { + return new InMemoryEnv(base_env); +} + +} // namespace leveldb diff --git a/src/leveldb/helpers/memenv/memenv.h b/src/leveldb/helpers/memenv/memenv.h new file mode 100644 index 0000000..03b88de --- /dev/null +++ b/src/leveldb/helpers/memenv/memenv.h @@ -0,0 +1,20 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#ifndef STORAGE_LEVELDB_HELPERS_MEMENV_MEMENV_H_ +#define STORAGE_LEVELDB_HELPERS_MEMENV_MEMENV_H_ + +namespace leveldb { + +class Env; + +// Returns a new environment that stores its data in memory and delegates +// all non-file-storage tasks to base_env. The caller must delete the result +// when it is no longer needed. +// *base_env must remain live while the result is in use. +Env* NewMemEnv(Env* base_env); + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_HELPERS_MEMENV_MEMENV_H_ diff --git a/src/leveldb/helpers/memenv/memenv_test.cc b/src/leveldb/helpers/memenv/memenv_test.cc new file mode 100644 index 0000000..a44310f --- /dev/null +++ b/src/leveldb/helpers/memenv/memenv_test.cc @@ -0,0 +1,232 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "helpers/memenv/memenv.h" + +#include "db/db_impl.h" +#include "leveldb/db.h" +#include "leveldb/env.h" +#include "util/testharness.h" +#include +#include + +namespace leveldb { + +class MemEnvTest { + public: + Env* env_; + + MemEnvTest() + : env_(NewMemEnv(Env::Default())) { + } + ~MemEnvTest() { + delete env_; + } +}; + +TEST(MemEnvTest, Basics) { + uint64_t file_size; + WritableFile* writable_file; + std::vector children; + + ASSERT_OK(env_->CreateDir("/dir")); + + // Check that the directory is empty. + ASSERT_TRUE(!env_->FileExists("/dir/non_existent")); + ASSERT_TRUE(!env_->GetFileSize("/dir/non_existent", &file_size).ok()); + ASSERT_OK(env_->GetChildren("/dir", &children)); + ASSERT_EQ(0, children.size()); + + // Create a file. + ASSERT_OK(env_->NewWritableFile("/dir/f", &writable_file)); + delete writable_file; + + // Check that the file exists. + ASSERT_TRUE(env_->FileExists("/dir/f")); + ASSERT_OK(env_->GetFileSize("/dir/f", &file_size)); + ASSERT_EQ(0, file_size); + ASSERT_OK(env_->GetChildren("/dir", &children)); + ASSERT_EQ(1, children.size()); + ASSERT_EQ("f", children[0]); + + // Write to the file. + ASSERT_OK(env_->NewWritableFile("/dir/f", &writable_file)); + ASSERT_OK(writable_file->Append("abc")); + delete writable_file; + + // Check for expected size. + ASSERT_OK(env_->GetFileSize("/dir/f", &file_size)); + ASSERT_EQ(3, file_size); + + // Check that renaming works. + ASSERT_TRUE(!env_->RenameFile("/dir/non_existent", "/dir/g").ok()); + ASSERT_OK(env_->RenameFile("/dir/f", "/dir/g")); + ASSERT_TRUE(!env_->FileExists("/dir/f")); + ASSERT_TRUE(env_->FileExists("/dir/g")); + ASSERT_OK(env_->GetFileSize("/dir/g", &file_size)); + ASSERT_EQ(3, file_size); + + // Check that opening non-existent file fails. + SequentialFile* seq_file; + RandomAccessFile* rand_file; + ASSERT_TRUE(!env_->NewSequentialFile("/dir/non_existent", &seq_file).ok()); + ASSERT_TRUE(!seq_file); + ASSERT_TRUE(!env_->NewRandomAccessFile("/dir/non_existent", &rand_file).ok()); + ASSERT_TRUE(!rand_file); + + // Check that deleting works. + ASSERT_TRUE(!env_->DeleteFile("/dir/non_existent").ok()); + ASSERT_OK(env_->DeleteFile("/dir/g")); + ASSERT_TRUE(!env_->FileExists("/dir/g")); + ASSERT_OK(env_->GetChildren("/dir", &children)); + ASSERT_EQ(0, children.size()); + ASSERT_OK(env_->DeleteDir("/dir")); +} + +TEST(MemEnvTest, ReadWrite) { + WritableFile* writable_file; + SequentialFile* seq_file; + RandomAccessFile* rand_file; + Slice result; + char scratch[100]; + + ASSERT_OK(env_->CreateDir("/dir")); + + ASSERT_OK(env_->NewWritableFile("/dir/f", &writable_file)); + ASSERT_OK(writable_file->Append("hello ")); + ASSERT_OK(writable_file->Append("world")); + delete writable_file; + + // Read sequentially. + ASSERT_OK(env_->NewSequentialFile("/dir/f", &seq_file)); + ASSERT_OK(seq_file->Read(5, &result, scratch)); // Read "hello". + ASSERT_EQ(0, result.compare("hello")); + ASSERT_OK(seq_file->Skip(1)); + ASSERT_OK(seq_file->Read(1000, &result, scratch)); // Read "world". + ASSERT_EQ(0, result.compare("world")); + ASSERT_OK(seq_file->Read(1000, &result, scratch)); // Try reading past EOF. + ASSERT_EQ(0, result.size()); + ASSERT_OK(seq_file->Skip(100)); // Try to skip past end of file. + ASSERT_OK(seq_file->Read(1000, &result, scratch)); + ASSERT_EQ(0, result.size()); + delete seq_file; + + // Random reads. + ASSERT_OK(env_->NewRandomAccessFile("/dir/f", &rand_file)); + ASSERT_OK(rand_file->Read(6, 5, &result, scratch)); // Read "world". + ASSERT_EQ(0, result.compare("world")); + ASSERT_OK(rand_file->Read(0, 5, &result, scratch)); // Read "hello". + ASSERT_EQ(0, result.compare("hello")); + ASSERT_OK(rand_file->Read(10, 100, &result, scratch)); // Read "d". + ASSERT_EQ(0, result.compare("d")); + + // Too high offset. + ASSERT_TRUE(!rand_file->Read(1000, 5, &result, scratch).ok()); + delete rand_file; +} + +TEST(MemEnvTest, Locks) { + FileLock* lock; + + // These are no-ops, but we test they return success. + ASSERT_OK(env_->LockFile("some file", &lock)); + ASSERT_OK(env_->UnlockFile(lock)); +} + +TEST(MemEnvTest, Misc) { + std::string test_dir; + ASSERT_OK(env_->GetTestDirectory(&test_dir)); + ASSERT_TRUE(!test_dir.empty()); + + WritableFile* writable_file; + ASSERT_OK(env_->NewWritableFile("/a/b", &writable_file)); + + // These are no-ops, but we test they return success. + ASSERT_OK(writable_file->Sync()); + ASSERT_OK(writable_file->Flush()); + ASSERT_OK(writable_file->Close()); + delete writable_file; +} + +TEST(MemEnvTest, LargeWrite) { + const size_t kWriteSize = 300 * 1024; + char* scratch = new char[kWriteSize * 2]; + + std::string write_data; + for (size_t i = 0; i < kWriteSize; ++i) { + write_data.append(1, static_cast(i)); + } + + WritableFile* writable_file; + ASSERT_OK(env_->NewWritableFile("/dir/f", &writable_file)); + ASSERT_OK(writable_file->Append("foo")); + ASSERT_OK(writable_file->Append(write_data)); + delete writable_file; + + SequentialFile* seq_file; + Slice result; + ASSERT_OK(env_->NewSequentialFile("/dir/f", &seq_file)); + ASSERT_OK(seq_file->Read(3, &result, scratch)); // Read "foo". + ASSERT_EQ(0, result.compare("foo")); + + size_t read = 0; + std::string read_data; + while (read < kWriteSize) { + ASSERT_OK(seq_file->Read(kWriteSize - read, &result, scratch)); + read_data.append(result.data(), result.size()); + read += result.size(); + } + ASSERT_TRUE(write_data == read_data); + delete seq_file; + delete [] scratch; +} + +TEST(MemEnvTest, DBTest) { + Options options; + options.create_if_missing = true; + options.env = env_; + DB* db; + + const Slice keys[] = {Slice("aaa"), Slice("bbb"), Slice("ccc")}; + const Slice vals[] = {Slice("foo"), Slice("bar"), Slice("baz")}; + + ASSERT_OK(DB::Open(options, "/dir/db", &db)); + for (size_t i = 0; i < 3; ++i) { + ASSERT_OK(db->Put(WriteOptions(), keys[i], vals[i])); + } + + for (size_t i = 0; i < 3; ++i) { + std::string res; + ASSERT_OK(db->Get(ReadOptions(), keys[i], &res)); + ASSERT_TRUE(res == vals[i]); + } + + Iterator* iterator = db->NewIterator(ReadOptions()); + iterator->SeekToFirst(); + for (size_t i = 0; i < 3; ++i) { + ASSERT_TRUE(iterator->Valid()); + ASSERT_TRUE(keys[i] == iterator->key()); + ASSERT_TRUE(vals[i] == iterator->value()); + iterator->Next(); + } + ASSERT_TRUE(!iterator->Valid()); + delete iterator; + + DBImpl* dbi = reinterpret_cast(db); + ASSERT_OK(dbi->TEST_CompactMemTable()); + + for (size_t i = 0; i < 3; ++i) { + std::string res; + ASSERT_OK(db->Get(ReadOptions(), keys[i], &res)); + ASSERT_TRUE(res == vals[i]); + } + + delete db; +} + +} // namespace leveldb + +int main(int argc, char** argv) { + return leveldb::test::RunAllTests(); +} diff --git a/src/leveldb/include/leveldb/c.h b/src/leveldb/include/leveldb/c.h new file mode 100644 index 0000000..1048fe3 --- /dev/null +++ b/src/leveldb/include/leveldb/c.h @@ -0,0 +1,290 @@ +/* Copyright (c) 2011 The LevelDB Authors. All rights reserved. + Use of this source code is governed by a BSD-style license that can be + found in the LICENSE file. See the AUTHORS file for names of contributors. + + C bindings for leveldb. May be useful as a stable ABI that can be + used by programs that keep leveldb in a shared library, or for + a JNI api. + + Does not support: + . getters for the option types + . custom comparators that implement key shortening + . custom iter, db, env, cache implementations using just the C bindings + + Some conventions: + + (1) We expose just opaque struct pointers and functions to clients. + This allows us to change internal representations without having to + recompile clients. + + (2) For simplicity, there is no equivalent to the Slice type. Instead, + the caller has to pass the pointer and length as separate + arguments. + + (3) Errors are represented by a null-terminated c string. NULL + means no error. All operations that can raise an error are passed + a "char** errptr" as the last argument. One of the following must + be true on entry: + *errptr == NULL + *errptr points to a malloc()ed null-terminated error message + (On Windows, *errptr must have been malloc()-ed by this library.) + On success, a leveldb routine leaves *errptr unchanged. + On failure, leveldb frees the old value of *errptr and + set *errptr to a malloc()ed error message. + + (4) Bools have the type unsigned char (0 == false; rest == true) + + (5) All of the pointer arguments must be non-NULL. +*/ + +#ifndef STORAGE_LEVELDB_INCLUDE_C_H_ +#define STORAGE_LEVELDB_INCLUDE_C_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include + +/* Exported types */ + +typedef struct leveldb_t leveldb_t; +typedef struct leveldb_cache_t leveldb_cache_t; +typedef struct leveldb_comparator_t leveldb_comparator_t; +typedef struct leveldb_env_t leveldb_env_t; +typedef struct leveldb_filelock_t leveldb_filelock_t; +typedef struct leveldb_filterpolicy_t leveldb_filterpolicy_t; +typedef struct leveldb_iterator_t leveldb_iterator_t; +typedef struct leveldb_logger_t leveldb_logger_t; +typedef struct leveldb_options_t leveldb_options_t; +typedef struct leveldb_randomfile_t leveldb_randomfile_t; +typedef struct leveldb_readoptions_t leveldb_readoptions_t; +typedef struct leveldb_seqfile_t leveldb_seqfile_t; +typedef struct leveldb_snapshot_t leveldb_snapshot_t; +typedef struct leveldb_writablefile_t leveldb_writablefile_t; +typedef struct leveldb_writebatch_t leveldb_writebatch_t; +typedef struct leveldb_writeoptions_t leveldb_writeoptions_t; + +/* DB operations */ + +extern leveldb_t* leveldb_open( + const leveldb_options_t* options, + const char* name, + char** errptr); + +extern void leveldb_close(leveldb_t* db); + +extern void leveldb_put( + leveldb_t* db, + const leveldb_writeoptions_t* options, + const char* key, size_t keylen, + const char* val, size_t vallen, + char** errptr); + +extern void leveldb_delete( + leveldb_t* db, + const leveldb_writeoptions_t* options, + const char* key, size_t keylen, + char** errptr); + +extern void leveldb_write( + leveldb_t* db, + const leveldb_writeoptions_t* options, + leveldb_writebatch_t* batch, + char** errptr); + +/* Returns NULL if not found. A malloc()ed array otherwise. + Stores the length of the array in *vallen. */ +extern char* leveldb_get( + leveldb_t* db, + const leveldb_readoptions_t* options, + const char* key, size_t keylen, + size_t* vallen, + char** errptr); + +extern leveldb_iterator_t* leveldb_create_iterator( + leveldb_t* db, + const leveldb_readoptions_t* options); + +extern const leveldb_snapshot_t* leveldb_create_snapshot( + leveldb_t* db); + +extern void leveldb_release_snapshot( + leveldb_t* db, + const leveldb_snapshot_t* snapshot); + +/* Returns NULL if property name is unknown. + Else returns a pointer to a malloc()-ed null-terminated value. */ +extern char* leveldb_property_value( + leveldb_t* db, + const char* propname); + +extern void leveldb_approximate_sizes( + leveldb_t* db, + int num_ranges, + const char* const* range_start_key, const size_t* range_start_key_len, + const char* const* range_limit_key, const size_t* range_limit_key_len, + uint64_t* sizes); + +extern void leveldb_compact_range( + leveldb_t* db, + const char* start_key, size_t start_key_len, + const char* limit_key, size_t limit_key_len); + +/* Management operations */ + +extern void leveldb_destroy_db( + const leveldb_options_t* options, + const char* name, + char** errptr); + +extern void leveldb_repair_db( + const leveldb_options_t* options, + const char* name, + char** errptr); + +/* Iterator */ + +extern void leveldb_iter_destroy(leveldb_iterator_t*); +extern unsigned char leveldb_iter_valid(const leveldb_iterator_t*); +extern void leveldb_iter_seek_to_first(leveldb_iterator_t*); +extern void leveldb_iter_seek_to_last(leveldb_iterator_t*); +extern void leveldb_iter_seek(leveldb_iterator_t*, const char* k, size_t klen); +extern void leveldb_iter_next(leveldb_iterator_t*); +extern void leveldb_iter_prev(leveldb_iterator_t*); +extern const char* leveldb_iter_key(const leveldb_iterator_t*, size_t* klen); +extern const char* leveldb_iter_value(const leveldb_iterator_t*, size_t* vlen); +extern void leveldb_iter_get_error(const leveldb_iterator_t*, char** errptr); + +/* Write batch */ + +extern leveldb_writebatch_t* leveldb_writebatch_create(); +extern void leveldb_writebatch_destroy(leveldb_writebatch_t*); +extern void leveldb_writebatch_clear(leveldb_writebatch_t*); +extern void leveldb_writebatch_put( + leveldb_writebatch_t*, + const char* key, size_t klen, + const char* val, size_t vlen); +extern void leveldb_writebatch_delete( + leveldb_writebatch_t*, + const char* key, size_t klen); +extern void leveldb_writebatch_iterate( + leveldb_writebatch_t*, + void* state, + void (*put)(void*, const char* k, size_t klen, const char* v, size_t vlen), + void (*deleted)(void*, const char* k, size_t klen)); + +/* Options */ + +extern leveldb_options_t* leveldb_options_create(); +extern void leveldb_options_destroy(leveldb_options_t*); +extern void leveldb_options_set_comparator( + leveldb_options_t*, + leveldb_comparator_t*); +extern void leveldb_options_set_filter_policy( + leveldb_options_t*, + leveldb_filterpolicy_t*); +extern void leveldb_options_set_create_if_missing( + leveldb_options_t*, unsigned char); +extern void leveldb_options_set_error_if_exists( + leveldb_options_t*, unsigned char); +extern void leveldb_options_set_paranoid_checks( + leveldb_options_t*, unsigned char); +extern void leveldb_options_set_env(leveldb_options_t*, leveldb_env_t*); +extern void leveldb_options_set_info_log(leveldb_options_t*, leveldb_logger_t*); +extern void leveldb_options_set_write_buffer_size(leveldb_options_t*, size_t); +extern void leveldb_options_set_max_open_files(leveldb_options_t*, int); +extern void leveldb_options_set_cache(leveldb_options_t*, leveldb_cache_t*); +extern void leveldb_options_set_block_size(leveldb_options_t*, size_t); +extern void leveldb_options_set_block_restart_interval(leveldb_options_t*, int); + +enum { + leveldb_no_compression = 0, + leveldb_snappy_compression = 1 +}; +extern void leveldb_options_set_compression(leveldb_options_t*, int); + +/* Comparator */ + +extern leveldb_comparator_t* leveldb_comparator_create( + void* state, + void (*destructor)(void*), + int (*compare)( + void*, + const char* a, size_t alen, + const char* b, size_t blen), + const char* (*name)(void*)); +extern void leveldb_comparator_destroy(leveldb_comparator_t*); + +/* Filter policy */ + +extern leveldb_filterpolicy_t* leveldb_filterpolicy_create( + void* state, + void (*destructor)(void*), + char* (*create_filter)( + void*, + const char* const* key_array, const size_t* key_length_array, + int num_keys, + size_t* filter_length), + unsigned char (*key_may_match)( + void*, + const char* key, size_t length, + const char* filter, size_t filter_length), + const char* (*name)(void*)); +extern void leveldb_filterpolicy_destroy(leveldb_filterpolicy_t*); + +extern leveldb_filterpolicy_t* leveldb_filterpolicy_create_bloom( + int bits_per_key); + +/* Read options */ + +extern leveldb_readoptions_t* leveldb_readoptions_create(); +extern void leveldb_readoptions_destroy(leveldb_readoptions_t*); +extern void leveldb_readoptions_set_verify_checksums( + leveldb_readoptions_t*, + unsigned char); +extern void leveldb_readoptions_set_fill_cache( + leveldb_readoptions_t*, unsigned char); +extern void leveldb_readoptions_set_snapshot( + leveldb_readoptions_t*, + const leveldb_snapshot_t*); + +/* Write options */ + +extern leveldb_writeoptions_t* leveldb_writeoptions_create(); +extern void leveldb_writeoptions_destroy(leveldb_writeoptions_t*); +extern void leveldb_writeoptions_set_sync( + leveldb_writeoptions_t*, unsigned char); + +/* Cache */ + +extern leveldb_cache_t* leveldb_cache_create_lru(size_t capacity); +extern void leveldb_cache_destroy(leveldb_cache_t* cache); + +/* Env */ + +extern leveldb_env_t* leveldb_create_default_env(); +extern void leveldb_env_destroy(leveldb_env_t*); + +/* Utility */ + +/* Calls free(ptr). + REQUIRES: ptr was malloc()-ed and returned by one of the routines + in this file. Note that in certain cases (typically on Windows), you + may need to call this routine instead of free(ptr) to dispose of + malloc()-ed memory returned by this library. */ +extern void leveldb_free(void* ptr); + +/* Return the major version number for this release. */ +extern int leveldb_major_version(); + +/* Return the minor version number for this release. */ +extern int leveldb_minor_version(); + +#ifdef __cplusplus +} /* end extern "C" */ +#endif + +#endif /* STORAGE_LEVELDB_INCLUDE_C_H_ */ diff --git a/src/leveldb/include/leveldb/cache.h b/src/leveldb/include/leveldb/cache.h new file mode 100644 index 0000000..5e3b476 --- /dev/null +++ b/src/leveldb/include/leveldb/cache.h @@ -0,0 +1,99 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. +// +// A Cache is an interface that maps keys to values. It has internal +// synchronization and may be safely accessed concurrently from +// multiple threads. It may automatically evict entries to make room +// for new entries. Values have a specified charge against the cache +// capacity. For example, a cache where the values are variable +// length strings, may use the length of the string as the charge for +// the string. +// +// A builtin cache implementation with a least-recently-used eviction +// policy is provided. Clients may use their own implementations if +// they want something more sophisticated (like scan-resistance, a +// custom eviction policy, variable cache sizing, etc.) + +#ifndef STORAGE_LEVELDB_INCLUDE_CACHE_H_ +#define STORAGE_LEVELDB_INCLUDE_CACHE_H_ + +#include +#include "leveldb/slice.h" + +namespace leveldb { + +class Cache; + +// Create a new cache with a fixed size capacity. This implementation +// of Cache uses a least-recently-used eviction policy. +extern Cache* NewLRUCache(size_t capacity); + +class Cache { + public: + Cache() { } + + // Destroys all existing entries by calling the "deleter" + // function that was passed to the constructor. + virtual ~Cache(); + + // Opaque handle to an entry stored in the cache. + struct Handle { }; + + // Insert a mapping from key->value into the cache and assign it + // the specified charge against the total cache capacity. + // + // Returns a handle that corresponds to the mapping. The caller + // must call this->Release(handle) when the returned mapping is no + // longer needed. + // + // When the inserted entry is no longer needed, the key and + // value will be passed to "deleter". + virtual Handle* Insert(const Slice& key, void* value, size_t charge, + void (*deleter)(const Slice& key, void* value)) = 0; + + // If the cache has no mapping for "key", returns NULL. + // + // Else return a handle that corresponds to the mapping. The caller + // must call this->Release(handle) when the returned mapping is no + // longer needed. + virtual Handle* Lookup(const Slice& key) = 0; + + // Release a mapping returned by a previous Lookup(). + // REQUIRES: handle must not have been released yet. + // REQUIRES: handle must have been returned by a method on *this. + virtual void Release(Handle* handle) = 0; + + // Return the value encapsulated in a handle returned by a + // successful Lookup(). + // REQUIRES: handle must not have been released yet. + // REQUIRES: handle must have been returned by a method on *this. + virtual void* Value(Handle* handle) = 0; + + // If the cache contains entry for key, erase it. Note that the + // underlying entry will be kept around until all existing handles + // to it have been released. + virtual void Erase(const Slice& key) = 0; + + // Return a new numeric id. May be used by multiple clients who are + // sharing the same cache to partition the key space. Typically the + // client will allocate a new id at startup and prepend the id to + // its cache keys. + virtual uint64_t NewId() = 0; + + private: + void LRU_Remove(Handle* e); + void LRU_Append(Handle* e); + void Unref(Handle* e); + + struct Rep; + Rep* rep_; + + // No copying allowed + Cache(const Cache&); + void operator=(const Cache&); +}; + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_UTIL_CACHE_H_ diff --git a/src/leveldb/include/leveldb/comparator.h b/src/leveldb/include/leveldb/comparator.h new file mode 100644 index 0000000..556b984 --- /dev/null +++ b/src/leveldb/include/leveldb/comparator.h @@ -0,0 +1,63 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#ifndef STORAGE_LEVELDB_INCLUDE_COMPARATOR_H_ +#define STORAGE_LEVELDB_INCLUDE_COMPARATOR_H_ + +#include + +namespace leveldb { + +class Slice; + +// A Comparator object provides a total order across slices that are +// used as keys in an sstable or a database. A Comparator implementation +// must be thread-safe since leveldb may invoke its methods concurrently +// from multiple threads. +class Comparator { + public: + virtual ~Comparator(); + + // Three-way comparison. Returns value: + // < 0 iff "a" < "b", + // == 0 iff "a" == "b", + // > 0 iff "a" > "b" + virtual int Compare(const Slice& a, const Slice& b) const = 0; + + // The name of the comparator. Used to check for comparator + // mismatches (i.e., a DB created with one comparator is + // accessed using a different comparator. + // + // The client of this package should switch to a new name whenever + // the comparator implementation changes in a way that will cause + // the relative ordering of any two keys to change. + // + // Names starting with "leveldb." are reserved and should not be used + // by any clients of this package. + virtual const char* Name() const = 0; + + // Advanced functions: these are used to reduce the space requirements + // for internal data structures like index blocks. + + // If *start < limit, changes *start to a short string in [start,limit). + // Simple comparator implementations may return with *start unchanged, + // i.e., an implementation of this method that does nothing is correct. + virtual void FindShortestSeparator( + std::string* start, + const Slice& limit) const = 0; + + // Changes *key to a short string >= *key. + // Simple comparator implementations may return with *key unchanged, + // i.e., an implementation of this method that does nothing is correct. + virtual void FindShortSuccessor(std::string* key) const = 0; +}; + +// Return a builtin comparator that uses lexicographic byte-wise +// ordering. The result remains the property of this module and +// must not be deleted. +extern const Comparator* BytewiseComparator(); + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_INCLUDE_COMPARATOR_H_ diff --git a/src/leveldb/include/leveldb/db.h b/src/leveldb/include/leveldb/db.h new file mode 100644 index 0000000..40851b2 --- /dev/null +++ b/src/leveldb/include/leveldb/db.h @@ -0,0 +1,161 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#ifndef STORAGE_LEVELDB_INCLUDE_DB_H_ +#define STORAGE_LEVELDB_INCLUDE_DB_H_ + +#include +#include +#include "leveldb/iterator.h" +#include "leveldb/options.h" + +namespace leveldb { + +// Update Makefile if you change these +static const int kMajorVersion = 1; +static const int kMinorVersion = 17; + +struct Options; +struct ReadOptions; +struct WriteOptions; +class WriteBatch; + +// Abstract handle to particular state of a DB. +// A Snapshot is an immutable object and can therefore be safely +// accessed from multiple threads without any external synchronization. +class Snapshot { + protected: + virtual ~Snapshot(); +}; + +// A range of keys +struct Range { + Slice start; // Included in the range + Slice limit; // Not included in the range + + Range() { } + Range(const Slice& s, const Slice& l) : start(s), limit(l) { } +}; + +// A DB is a persistent ordered map from keys to values. +// A DB is safe for concurrent access from multiple threads without +// any external synchronization. +class DB { + public: + // Open the database with the specified "name". + // Stores a pointer to a heap-allocated database in *dbptr and returns + // OK on success. + // Stores NULL in *dbptr and returns a non-OK status on error. + // Caller should delete *dbptr when it is no longer needed. + static Status Open(const Options& options, + const std::string& name, + DB** dbptr); + + DB() { } + virtual ~DB(); + + // Set the database entry for "key" to "value". Returns OK on success, + // and a non-OK status on error. + // Note: consider setting options.sync = true. + virtual Status Put(const WriteOptions& options, + const Slice& key, + const Slice& value) = 0; + + // Remove the database entry (if any) for "key". Returns OK on + // success, and a non-OK status on error. It is not an error if "key" + // did not exist in the database. + // Note: consider setting options.sync = true. + virtual Status Delete(const WriteOptions& options, const Slice& key) = 0; + + // Apply the specified updates to the database. + // Returns OK on success, non-OK on failure. + // Note: consider setting options.sync = true. + virtual Status Write(const WriteOptions& options, WriteBatch* updates) = 0; + + // If the database contains an entry for "key" store the + // corresponding value in *value and return OK. + // + // If there is no entry for "key" leave *value unchanged and return + // a status for which Status::IsNotFound() returns true. + // + // May return some other Status on an error. + virtual Status Get(const ReadOptions& options, + const Slice& key, std::string* value) = 0; + + // Return a heap-allocated iterator over the contents of the database. + // The result of NewIterator() is initially invalid (caller must + // call one of the Seek methods on the iterator before using it). + // + // Caller should delete the iterator when it is no longer needed. + // The returned iterator should be deleted before this db is deleted. + virtual Iterator* NewIterator(const ReadOptions& options) = 0; + + // Return a handle to the current DB state. Iterators created with + // this handle will all observe a stable snapshot of the current DB + // state. The caller must call ReleaseSnapshot(result) when the + // snapshot is no longer needed. + virtual const Snapshot* GetSnapshot() = 0; + + // Release a previously acquired snapshot. The caller must not + // use "snapshot" after this call. + virtual void ReleaseSnapshot(const Snapshot* snapshot) = 0; + + // DB implementations can export properties about their state + // via this method. If "property" is a valid property understood by this + // DB implementation, fills "*value" with its current value and returns + // true. Otherwise returns false. + // + // + // Valid property names include: + // + // "leveldb.num-files-at-level" - return the number of files at level , + // where is an ASCII representation of a level number (e.g. "0"). + // "leveldb.stats" - returns a multi-line string that describes statistics + // about the internal operation of the DB. + // "leveldb.sstables" - returns a multi-line string that describes all + // of the sstables that make up the db contents. + virtual bool GetProperty(const Slice& property, std::string* value) = 0; + + // For each i in [0,n-1], store in "sizes[i]", the approximate + // file system space used by keys in "[range[i].start .. range[i].limit)". + // + // Note that the returned sizes measure file system space usage, so + // if the user data compresses by a factor of ten, the returned + // sizes will be one-tenth the size of the corresponding user data size. + // + // The results may not include the sizes of recently written data. + virtual void GetApproximateSizes(const Range* range, int n, + uint64_t* sizes) = 0; + + // Compact the underlying storage for the key range [*begin,*end]. + // In particular, deleted and overwritten versions are discarded, + // and the data is rearranged to reduce the cost of operations + // needed to access the data. This operation should typically only + // be invoked by users who understand the underlying implementation. + // + // begin==NULL is treated as a key before all keys in the database. + // end==NULL is treated as a key after all keys in the database. + // Therefore the following call will compact the entire database: + // db->CompactRange(NULL, NULL); + virtual void CompactRange(const Slice* begin, const Slice* end) = 0; + + private: + // No copying allowed + DB(const DB&); + void operator=(const DB&); +}; + +// Destroy the contents of the specified database. +// Be very careful using this method. +Status DestroyDB(const std::string& name, const Options& options); + +// If a DB cannot be opened, you may attempt to call this method to +// resurrect as much of the contents of the database as possible. +// Some data may be lost, so be careful when calling this function +// on a database that contains important information. +Status RepairDB(const std::string& dbname, const Options& options); + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_INCLUDE_DB_H_ diff --git a/src/leveldb/include/leveldb/env.h b/src/leveldb/include/leveldb/env.h new file mode 100644 index 0000000..b2072d0 --- /dev/null +++ b/src/leveldb/include/leveldb/env.h @@ -0,0 +1,333 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. +// +// An Env is an interface used by the leveldb implementation to access +// operating system functionality like the filesystem etc. Callers +// may wish to provide a custom Env object when opening a database to +// get fine gain control; e.g., to rate limit file system operations. +// +// All Env implementations are safe for concurrent access from +// multiple threads without any external synchronization. + +#ifndef STORAGE_LEVELDB_INCLUDE_ENV_H_ +#define STORAGE_LEVELDB_INCLUDE_ENV_H_ + +#include +#include +#include +#include +#include "leveldb/status.h" + +namespace leveldb { + +class FileLock; +class Logger; +class RandomAccessFile; +class SequentialFile; +class Slice; +class WritableFile; + +class Env { + public: + Env() { } + virtual ~Env(); + + // Return a default environment suitable for the current operating + // system. Sophisticated users may wish to provide their own Env + // implementation instead of relying on this default environment. + // + // The result of Default() belongs to leveldb and must never be deleted. + static Env* Default(); + + // Create a brand new sequentially-readable file with the specified name. + // On success, stores a pointer to the new file in *result and returns OK. + // On failure stores NULL in *result and returns non-OK. If the file does + // not exist, returns a non-OK status. + // + // The returned file will only be accessed by one thread at a time. + virtual Status NewSequentialFile(const std::string& fname, + SequentialFile** result) = 0; + + // Create a brand new random access read-only file with the + // specified name. On success, stores a pointer to the new file in + // *result and returns OK. On failure stores NULL in *result and + // returns non-OK. If the file does not exist, returns a non-OK + // status. + // + // The returned file may be concurrently accessed by multiple threads. + virtual Status NewRandomAccessFile(const std::string& fname, + RandomAccessFile** result) = 0; + + // Create an object that writes to a new file with the specified + // name. Deletes any existing file with the same name and creates a + // new file. On success, stores a pointer to the new file in + // *result and returns OK. On failure stores NULL in *result and + // returns non-OK. + // + // The returned file will only be accessed by one thread at a time. + virtual Status NewWritableFile(const std::string& fname, + WritableFile** result) = 0; + + // Returns true iff the named file exists. + virtual bool FileExists(const std::string& fname) = 0; + + // Store in *result the names of the children of the specified directory. + // The names are relative to "dir". + // Original contents of *results are dropped. + virtual Status GetChildren(const std::string& dir, + std::vector* result) = 0; + + // Delete the named file. + virtual Status DeleteFile(const std::string& fname) = 0; + + // Create the specified directory. + virtual Status CreateDir(const std::string& dirname) = 0; + + // Delete the specified directory. + virtual Status DeleteDir(const std::string& dirname) = 0; + + // Store the size of fname in *file_size. + virtual Status GetFileSize(const std::string& fname, uint64_t* file_size) = 0; + + // Rename file src to target. + virtual Status RenameFile(const std::string& src, + const std::string& target) = 0; + + // Lock the specified file. Used to prevent concurrent access to + // the same db by multiple processes. On failure, stores NULL in + // *lock and returns non-OK. + // + // On success, stores a pointer to the object that represents the + // acquired lock in *lock and returns OK. The caller should call + // UnlockFile(*lock) to release the lock. If the process exits, + // the lock will be automatically released. + // + // If somebody else already holds the lock, finishes immediately + // with a failure. I.e., this call does not wait for existing locks + // to go away. + // + // May create the named file if it does not already exist. + virtual Status LockFile(const std::string& fname, FileLock** lock) = 0; + + // Release the lock acquired by a previous successful call to LockFile. + // REQUIRES: lock was returned by a successful LockFile() call + // REQUIRES: lock has not already been unlocked. + virtual Status UnlockFile(FileLock* lock) = 0; + + // Arrange to run "(*function)(arg)" once in a background thread. + // + // "function" may run in an unspecified thread. Multiple functions + // added to the same Env may run concurrently in different threads. + // I.e., the caller may not assume that background work items are + // serialized. + virtual void Schedule( + void (*function)(void* arg), + void* arg) = 0; + + // Start a new thread, invoking "function(arg)" within the new thread. + // When "function(arg)" returns, the thread will be destroyed. + virtual void StartThread(void (*function)(void* arg), void* arg) = 0; + + // *path is set to a temporary directory that can be used for testing. It may + // or many not have just been created. The directory may or may not differ + // between runs of the same process, but subsequent calls will return the + // same directory. + virtual Status GetTestDirectory(std::string* path) = 0; + + // Create and return a log file for storing informational messages. + virtual Status NewLogger(const std::string& fname, Logger** result) = 0; + + // Returns the number of micro-seconds since some fixed point in time. Only + // useful for computing deltas of time. + virtual uint64_t NowMicros() = 0; + + // Sleep/delay the thread for the perscribed number of micro-seconds. + virtual void SleepForMicroseconds(int micros) = 0; + + private: + // No copying allowed + Env(const Env&); + void operator=(const Env&); +}; + +// A file abstraction for reading sequentially through a file +class SequentialFile { + public: + SequentialFile() { } + virtual ~SequentialFile(); + + // Read up to "n" bytes from the file. "scratch[0..n-1]" may be + // written by this routine. Sets "*result" to the data that was + // read (including if fewer than "n" bytes were successfully read). + // May set "*result" to point at data in "scratch[0..n-1]", so + // "scratch[0..n-1]" must be live when "*result" is used. + // If an error was encountered, returns a non-OK status. + // + // REQUIRES: External synchronization + virtual Status Read(size_t n, Slice* result, char* scratch) = 0; + + // Skip "n" bytes from the file. This is guaranteed to be no + // slower that reading the same data, but may be faster. + // + // If end of file is reached, skipping will stop at the end of the + // file, and Skip will return OK. + // + // REQUIRES: External synchronization + virtual Status Skip(uint64_t n) = 0; + + private: + // No copying allowed + SequentialFile(const SequentialFile&); + void operator=(const SequentialFile&); +}; + +// A file abstraction for randomly reading the contents of a file. +class RandomAccessFile { + public: + RandomAccessFile() { } + virtual ~RandomAccessFile(); + + // Read up to "n" bytes from the file starting at "offset". + // "scratch[0..n-1]" may be written by this routine. Sets "*result" + // to the data that was read (including if fewer than "n" bytes were + // successfully read). May set "*result" to point at data in + // "scratch[0..n-1]", so "scratch[0..n-1]" must be live when + // "*result" is used. If an error was encountered, returns a non-OK + // status. + // + // Safe for concurrent use by multiple threads. + virtual Status Read(uint64_t offset, size_t n, Slice* result, + char* scratch) const = 0; + + private: + // No copying allowed + RandomAccessFile(const RandomAccessFile&); + void operator=(const RandomAccessFile&); +}; + +// A file abstraction for sequential writing. The implementation +// must provide buffering since callers may append small fragments +// at a time to the file. +class WritableFile { + public: + WritableFile() { } + virtual ~WritableFile(); + + virtual Status Append(const Slice& data) = 0; + virtual Status Close() = 0; + virtual Status Flush() = 0; + virtual Status Sync() = 0; + + private: + // No copying allowed + WritableFile(const WritableFile&); + void operator=(const WritableFile&); +}; + +// An interface for writing log messages. +class Logger { + public: + Logger() { } + virtual ~Logger(); + + // Write an entry to the log file with the specified format. + virtual void Logv(const char* format, va_list ap) = 0; + + private: + // No copying allowed + Logger(const Logger&); + void operator=(const Logger&); +}; + + +// Identifies a locked file. +class FileLock { + public: + FileLock() { } + virtual ~FileLock(); + private: + // No copying allowed + FileLock(const FileLock&); + void operator=(const FileLock&); +}; + +// Log the specified data to *info_log if info_log is non-NULL. +extern void Log(Logger* info_log, const char* format, ...) +# if defined(__GNUC__) || defined(__clang__) + __attribute__((__format__ (__printf__, 2, 3))) +# endif + ; + +// A utility routine: write "data" to the named file. +extern Status WriteStringToFile(Env* env, const Slice& data, + const std::string& fname); + +// A utility routine: read contents of named file into *data +extern Status ReadFileToString(Env* env, const std::string& fname, + std::string* data); + +// An implementation of Env that forwards all calls to another Env. +// May be useful to clients who wish to override just part of the +// functionality of another Env. +class EnvWrapper : public Env { + public: + // Initialize an EnvWrapper that delegates all calls to *t + explicit EnvWrapper(Env* t) : target_(t) { } + virtual ~EnvWrapper(); + + // Return the target to which this Env forwards all calls + Env* target() const { return target_; } + + // The following text is boilerplate that forwards all methods to target() + Status NewSequentialFile(const std::string& f, SequentialFile** r) { + return target_->NewSequentialFile(f, r); + } + Status NewRandomAccessFile(const std::string& f, RandomAccessFile** r) { + return target_->NewRandomAccessFile(f, r); + } + Status NewWritableFile(const std::string& f, WritableFile** r) { + return target_->NewWritableFile(f, r); + } + bool FileExists(const std::string& f) { return target_->FileExists(f); } + Status GetChildren(const std::string& dir, std::vector* r) { + return target_->GetChildren(dir, r); + } + Status DeleteFile(const std::string& f) { return target_->DeleteFile(f); } + Status CreateDir(const std::string& d) { return target_->CreateDir(d); } + Status DeleteDir(const std::string& d) { return target_->DeleteDir(d); } + Status GetFileSize(const std::string& f, uint64_t* s) { + return target_->GetFileSize(f, s); + } + Status RenameFile(const std::string& s, const std::string& t) { + return target_->RenameFile(s, t); + } + Status LockFile(const std::string& f, FileLock** l) { + return target_->LockFile(f, l); + } + Status UnlockFile(FileLock* l) { return target_->UnlockFile(l); } + void Schedule(void (*f)(void*), void* a) { + return target_->Schedule(f, a); + } + void StartThread(void (*f)(void*), void* a) { + return target_->StartThread(f, a); + } + virtual Status GetTestDirectory(std::string* path) { + return target_->GetTestDirectory(path); + } + virtual Status NewLogger(const std::string& fname, Logger** result) { + return target_->NewLogger(fname, result); + } + uint64_t NowMicros() { + return target_->NowMicros(); + } + void SleepForMicroseconds(int micros) { + target_->SleepForMicroseconds(micros); + } + private: + Env* target_; +}; + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_INCLUDE_ENV_H_ diff --git a/src/leveldb/include/leveldb/filter_policy.h b/src/leveldb/include/leveldb/filter_policy.h new file mode 100644 index 0000000..1fba080 --- /dev/null +++ b/src/leveldb/include/leveldb/filter_policy.h @@ -0,0 +1,70 @@ +// Copyright (c) 2012 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. +// +// A database can be configured with a custom FilterPolicy object. +// This object is responsible for creating a small filter from a set +// of keys. These filters are stored in leveldb and are consulted +// automatically by leveldb to decide whether or not to read some +// information from disk. In many cases, a filter can cut down the +// number of disk seeks form a handful to a single disk seek per +// DB::Get() call. +// +// Most people will want to use the builtin bloom filter support (see +// NewBloomFilterPolicy() below). + +#ifndef STORAGE_LEVELDB_INCLUDE_FILTER_POLICY_H_ +#define STORAGE_LEVELDB_INCLUDE_FILTER_POLICY_H_ + +#include + +namespace leveldb { + +class Slice; + +class FilterPolicy { + public: + virtual ~FilterPolicy(); + + // Return the name of this policy. Note that if the filter encoding + // changes in an incompatible way, the name returned by this method + // must be changed. Otherwise, old incompatible filters may be + // passed to methods of this type. + virtual const char* Name() const = 0; + + // keys[0,n-1] contains a list of keys (potentially with duplicates) + // that are ordered according to the user supplied comparator. + // Append a filter that summarizes keys[0,n-1] to *dst. + // + // Warning: do not change the initial contents of *dst. Instead, + // append the newly constructed filter to *dst. + virtual void CreateFilter(const Slice* keys, int n, std::string* dst) + const = 0; + + // "filter" contains the data appended by a preceding call to + // CreateFilter() on this class. This method must return true if + // the key was in the list of keys passed to CreateFilter(). + // This method may return true or false if the key was not on the + // list, but it should aim to return false with a high probability. + virtual bool KeyMayMatch(const Slice& key, const Slice& filter) const = 0; +}; + +// Return a new filter policy that uses a bloom filter with approximately +// the specified number of bits per key. A good value for bits_per_key +// is 10, which yields a filter with ~ 1% false positive rate. +// +// Callers must delete the result after any database that is using the +// result has been closed. +// +// Note: if you are using a custom comparator that ignores some parts +// of the keys being compared, you must not use NewBloomFilterPolicy() +// and must provide your own FilterPolicy that also ignores the +// corresponding parts of the keys. For example, if the comparator +// ignores trailing spaces, it would be incorrect to use a +// FilterPolicy (like NewBloomFilterPolicy) that does not ignore +// trailing spaces in keys. +extern const FilterPolicy* NewBloomFilterPolicy(int bits_per_key); + +} + +#endif // STORAGE_LEVELDB_INCLUDE_FILTER_POLICY_H_ diff --git a/src/leveldb/include/leveldb/iterator.h b/src/leveldb/include/leveldb/iterator.h new file mode 100644 index 0000000..ad543eb --- /dev/null +++ b/src/leveldb/include/leveldb/iterator.h @@ -0,0 +1,100 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. +// +// An iterator yields a sequence of key/value pairs from a source. +// The following class defines the interface. Multiple implementations +// are provided by this library. In particular, iterators are provided +// to access the contents of a Table or a DB. +// +// Multiple threads can invoke const methods on an Iterator without +// external synchronization, but if any of the threads may call a +// non-const method, all threads accessing the same Iterator must use +// external synchronization. + +#ifndef STORAGE_LEVELDB_INCLUDE_ITERATOR_H_ +#define STORAGE_LEVELDB_INCLUDE_ITERATOR_H_ + +#include "leveldb/slice.h" +#include "leveldb/status.h" + +namespace leveldb { + +class Iterator { + public: + Iterator(); + virtual ~Iterator(); + + // An iterator is either positioned at a key/value pair, or + // not valid. This method returns true iff the iterator is valid. + virtual bool Valid() const = 0; + + // Position at the first key in the source. The iterator is Valid() + // after this call iff the source is not empty. + virtual void SeekToFirst() = 0; + + // Position at the last key in the source. The iterator is + // Valid() after this call iff the source is not empty. + virtual void SeekToLast() = 0; + + // Position at the first key in the source that at or past target + // The iterator is Valid() after this call iff the source contains + // an entry that comes at or past target. + virtual void Seek(const Slice& target) = 0; + + // Moves to the next entry in the source. After this call, Valid() is + // true iff the iterator was not positioned at the last entry in the source. + // REQUIRES: Valid() + virtual void Next() = 0; + + // Moves to the previous entry in the source. After this call, Valid() is + // true iff the iterator was not positioned at the first entry in source. + // REQUIRES: Valid() + virtual void Prev() = 0; + + // Return the key for the current entry. The underlying storage for + // the returned slice is valid only until the next modification of + // the iterator. + // REQUIRES: Valid() + virtual Slice key() const = 0; + + // Return the value for the current entry. The underlying storage for + // the returned slice is valid only until the next modification of + // the iterator. + // REQUIRES: !AtEnd() && !AtStart() + virtual Slice value() const = 0; + + // If an error has occurred, return it. Else return an ok status. + virtual Status status() const = 0; + + // Clients are allowed to register function/arg1/arg2 triples that + // will be invoked when this iterator is destroyed. + // + // Note that unlike all of the preceding methods, this method is + // not abstract and therefore clients should not override it. + typedef void (*CleanupFunction)(void* arg1, void* arg2); + void RegisterCleanup(CleanupFunction function, void* arg1, void* arg2); + + private: + struct Cleanup { + CleanupFunction function; + void* arg1; + void* arg2; + Cleanup* next; + }; + Cleanup cleanup_; + + // No copying allowed + Iterator(const Iterator&); + void operator=(const Iterator&); +}; + +// Return an empty iterator (yields nothing). +extern Iterator* NewEmptyIterator(); + +// Return an empty iterator with the specified status. +extern Iterator* NewErrorIterator(const Status& status); + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_INCLUDE_ITERATOR_H_ diff --git a/src/leveldb/include/leveldb/options.h b/src/leveldb/include/leveldb/options.h new file mode 100644 index 0000000..fdda718 --- /dev/null +++ b/src/leveldb/include/leveldb/options.h @@ -0,0 +1,195 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#ifndef STORAGE_LEVELDB_INCLUDE_OPTIONS_H_ +#define STORAGE_LEVELDB_INCLUDE_OPTIONS_H_ + +#include + +namespace leveldb { + +class Cache; +class Comparator; +class Env; +class FilterPolicy; +class Logger; +class Snapshot; + +// DB contents are stored in a set of blocks, each of which holds a +// sequence of key,value pairs. Each block may be compressed before +// being stored in a file. The following enum describes which +// compression method (if any) is used to compress a block. +enum CompressionType { + // NOTE: do not change the values of existing entries, as these are + // part of the persistent format on disk. + kNoCompression = 0x0, + kSnappyCompression = 0x1 +}; + +// Options to control the behavior of a database (passed to DB::Open) +struct Options { + // ------------------- + // Parameters that affect behavior + + // Comparator used to define the order of keys in the table. + // Default: a comparator that uses lexicographic byte-wise ordering + // + // REQUIRES: The client must ensure that the comparator supplied + // here has the same name and orders keys *exactly* the same as the + // comparator provided to previous open calls on the same DB. + const Comparator* comparator; + + // If true, the database will be created if it is missing. + // Default: false + bool create_if_missing; + + // If true, an error is raised if the database already exists. + // Default: false + bool error_if_exists; + + // If true, the implementation will do aggressive checking of the + // data it is processing and will stop early if it detects any + // errors. This may have unforeseen ramifications: for example, a + // corruption of one DB entry may cause a large number of entries to + // become unreadable or for the entire DB to become unopenable. + // Default: false + bool paranoid_checks; + + // Use the specified object to interact with the environment, + // e.g. to read/write files, schedule background work, etc. + // Default: Env::Default() + Env* env; + + // Any internal progress/error information generated by the db will + // be written to info_log if it is non-NULL, or to a file stored + // in the same directory as the DB contents if info_log is NULL. + // Default: NULL + Logger* info_log; + + // ------------------- + // Parameters that affect performance + + // Amount of data to build up in memory (backed by an unsorted log + // on disk) before converting to a sorted on-disk file. + // + // Larger values increase performance, especially during bulk loads. + // Up to two write buffers may be held in memory at the same time, + // so you may wish to adjust this parameter to control memory usage. + // Also, a larger write buffer will result in a longer recovery time + // the next time the database is opened. + // + // Default: 4MB + size_t write_buffer_size; + + // Number of open files that can be used by the DB. You may need to + // increase this if your database has a large working set (budget + // one open file per 2MB of working set). + // + // Default: 1000 + int max_open_files; + + // Control over blocks (user data is stored in a set of blocks, and + // a block is the unit of reading from disk). + + // If non-NULL, use the specified cache for blocks. + // If NULL, leveldb will automatically create and use an 8MB internal cache. + // Default: NULL + Cache* block_cache; + + // Approximate size of user data packed per block. Note that the + // block size specified here corresponds to uncompressed data. The + // actual size of the unit read from disk may be smaller if + // compression is enabled. This parameter can be changed dynamically. + // + // Default: 4K + size_t block_size; + + // Number of keys between restart points for delta encoding of keys. + // This parameter can be changed dynamically. Most clients should + // leave this parameter alone. + // + // Default: 16 + int block_restart_interval; + + // Compress blocks using the specified compression algorithm. This + // parameter can be changed dynamically. + // + // Default: kSnappyCompression, which gives lightweight but fast + // compression. + // + // Typical speeds of kSnappyCompression on an Intel(R) Core(TM)2 2.4GHz: + // ~200-500MB/s compression + // ~400-800MB/s decompression + // Note that these speeds are significantly faster than most + // persistent storage speeds, and therefore it is typically never + // worth switching to kNoCompression. Even if the input data is + // incompressible, the kSnappyCompression implementation will + // efficiently detect that and will switch to uncompressed mode. + CompressionType compression; + + // If non-NULL, use the specified filter policy to reduce disk reads. + // Many applications will benefit from passing the result of + // NewBloomFilterPolicy() here. + // + // Default: NULL + const FilterPolicy* filter_policy; + + // Create an Options object with default values for all fields. + Options(); +}; + +// Options that control read operations +struct ReadOptions { + // If true, all data read from underlying storage will be + // verified against corresponding checksums. + // Default: false + bool verify_checksums; + + // Should the data read for this iteration be cached in memory? + // Callers may wish to set this field to false for bulk scans. + // Default: true + bool fill_cache; + + // If "snapshot" is non-NULL, read as of the supplied snapshot + // (which must belong to the DB that is being read and which must + // not have been released). If "snapshot" is NULL, use an impliicit + // snapshot of the state at the beginning of this read operation. + // Default: NULL + const Snapshot* snapshot; + + ReadOptions() + : verify_checksums(false), + fill_cache(true), + snapshot(NULL) { + } +}; + +// Options that control write operations +struct WriteOptions { + // If true, the write will be flushed from the operating system + // buffer cache (by calling WritableFile::Sync()) before the write + // is considered complete. If this flag is true, writes will be + // slower. + // + // If this flag is false, and the machine crashes, some recent + // writes may be lost. Note that if it is just the process that + // crashes (i.e., the machine does not reboot), no writes will be + // lost even if sync==false. + // + // In other words, a DB write with sync==false has similar + // crash semantics as the "write()" system call. A DB write + // with sync==true has similar crash semantics to a "write()" + // system call followed by "fsync()". + // + // Default: false + bool sync; + + WriteOptions() + : sync(false) { + } +}; + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_INCLUDE_OPTIONS_H_ diff --git a/src/leveldb/include/leveldb/slice.h b/src/leveldb/include/leveldb/slice.h new file mode 100644 index 0000000..bc36798 --- /dev/null +++ b/src/leveldb/include/leveldb/slice.h @@ -0,0 +1,109 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. +// +// Slice is a simple structure containing a pointer into some external +// storage and a size. The user of a Slice must ensure that the slice +// is not used after the corresponding external storage has been +// deallocated. +// +// Multiple threads can invoke const methods on a Slice without +// external synchronization, but if any of the threads may call a +// non-const method, all threads accessing the same Slice must use +// external synchronization. + +#ifndef STORAGE_LEVELDB_INCLUDE_SLICE_H_ +#define STORAGE_LEVELDB_INCLUDE_SLICE_H_ + +#include +#include +#include +#include + +namespace leveldb { + +class Slice { + public: + // Create an empty slice. + Slice() : data_(""), size_(0) { } + + // Create a slice that refers to d[0,n-1]. + Slice(const char* d, size_t n) : data_(d), size_(n) { } + + // Create a slice that refers to the contents of "s" + Slice(const std::string& s) : data_(s.data()), size_(s.size()) { } + + // Create a slice that refers to s[0,strlen(s)-1] + Slice(const char* s) : data_(s), size_(strlen(s)) { } + + // Return a pointer to the beginning of the referenced data + const char* data() const { return data_; } + + // Return the length (in bytes) of the referenced data + size_t size() const { return size_; } + + // Return true iff the length of the referenced data is zero + bool empty() const { return size_ == 0; } + + // Return the ith byte in the referenced data. + // REQUIRES: n < size() + char operator[](size_t n) const { + assert(n < size()); + return data_[n]; + } + + // Change this slice to refer to an empty array + void clear() { data_ = ""; size_ = 0; } + + // Drop the first "n" bytes from this slice. + void remove_prefix(size_t n) { + assert(n <= size()); + data_ += n; + size_ -= n; + } + + // Return a string that contains the copy of the referenced data. + std::string ToString() const { return std::string(data_, size_); } + + // Three-way comparison. Returns value: + // < 0 iff "*this" < "b", + // == 0 iff "*this" == "b", + // > 0 iff "*this" > "b" + int compare(const Slice& b) const; + + // Return true iff "x" is a prefix of "*this" + bool starts_with(const Slice& x) const { + return ((size_ >= x.size_) && + (memcmp(data_, x.data_, x.size_) == 0)); + } + + private: + const char* data_; + size_t size_; + + // Intentionally copyable +}; + +inline bool operator==(const Slice& x, const Slice& y) { + return ((x.size() == y.size()) && + (memcmp(x.data(), y.data(), x.size()) == 0)); +} + +inline bool operator!=(const Slice& x, const Slice& y) { + return !(x == y); +} + +inline int Slice::compare(const Slice& b) const { + const size_t min_len = (size_ < b.size_) ? size_ : b.size_; + int r = memcmp(data_, b.data_, min_len); + if (r == 0) { + if (size_ < b.size_) r = -1; + else if (size_ > b.size_) r = +1; + } + return r; +} + +} // namespace leveldb + + +#endif // STORAGE_LEVELDB_INCLUDE_SLICE_H_ diff --git a/src/leveldb/include/leveldb/status.h b/src/leveldb/include/leveldb/status.h new file mode 100644 index 0000000..11dbd4b --- /dev/null +++ b/src/leveldb/include/leveldb/status.h @@ -0,0 +1,106 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. +// +// A Status encapsulates the result of an operation. It may indicate success, +// or it may indicate an error with an associated error message. +// +// Multiple threads can invoke const methods on a Status without +// external synchronization, but if any of the threads may call a +// non-const method, all threads accessing the same Status must use +// external synchronization. + +#ifndef STORAGE_LEVELDB_INCLUDE_STATUS_H_ +#define STORAGE_LEVELDB_INCLUDE_STATUS_H_ + +#include +#include "leveldb/slice.h" + +namespace leveldb { + +class Status { + public: + // Create a success status. + Status() : state_(NULL) { } + ~Status() { delete[] state_; } + + // Copy the specified status. + Status(const Status& s); + void operator=(const Status& s); + + // Return a success status. + static Status OK() { return Status(); } + + // Return error status of an appropriate type. + static Status NotFound(const Slice& msg, const Slice& msg2 = Slice()) { + return Status(kNotFound, msg, msg2); + } + static Status Corruption(const Slice& msg, const Slice& msg2 = Slice()) { + return Status(kCorruption, msg, msg2); + } + static Status NotSupported(const Slice& msg, const Slice& msg2 = Slice()) { + return Status(kNotSupported, msg, msg2); + } + static Status InvalidArgument(const Slice& msg, const Slice& msg2 = Slice()) { + return Status(kInvalidArgument, msg, msg2); + } + static Status IOError(const Slice& msg, const Slice& msg2 = Slice()) { + return Status(kIOError, msg, msg2); + } + + // Returns true iff the status indicates success. + bool ok() const { return (state_ == NULL); } + + // Returns true iff the status indicates a NotFound error. + bool IsNotFound() const { return code() == kNotFound; } + + // Returns true iff the status indicates a Corruption error. + bool IsCorruption() const { return code() == kCorruption; } + + // Returns true iff the status indicates an IOError. + bool IsIOError() const { return code() == kIOError; } + + // Return a string representation of this status suitable for printing. + // Returns the string "OK" for success. + std::string ToString() const; + + private: + // OK status has a NULL state_. Otherwise, state_ is a new[] array + // of the following form: + // state_[0..3] == length of message + // state_[4] == code + // state_[5..] == message + const char* state_; + + enum Code { + kOk = 0, + kNotFound = 1, + kCorruption = 2, + kNotSupported = 3, + kInvalidArgument = 4, + kIOError = 5 + }; + + Code code() const { + return (state_ == NULL) ? kOk : static_cast(state_[4]); + } + + Status(Code code, const Slice& msg, const Slice& msg2); + static const char* CopyState(const char* s); +}; + +inline Status::Status(const Status& s) { + state_ = (s.state_ == NULL) ? NULL : CopyState(s.state_); +} +inline void Status::operator=(const Status& s) { + // The following condition catches both aliasing (when this == &s), + // and the common case where both s and *this are ok. + if (state_ != s.state_) { + delete[] state_; + state_ = (s.state_ == NULL) ? NULL : CopyState(s.state_); + } +} + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_INCLUDE_STATUS_H_ diff --git a/src/leveldb/include/leveldb/table.h b/src/leveldb/include/leveldb/table.h new file mode 100644 index 0000000..a9746c3 --- /dev/null +++ b/src/leveldb/include/leveldb/table.h @@ -0,0 +1,85 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#ifndef STORAGE_LEVELDB_INCLUDE_TABLE_H_ +#define STORAGE_LEVELDB_INCLUDE_TABLE_H_ + +#include +#include "leveldb/iterator.h" + +namespace leveldb { + +class Block; +class BlockHandle; +class Footer; +struct Options; +class RandomAccessFile; +struct ReadOptions; +class TableCache; + +// A Table is a sorted map from strings to strings. Tables are +// immutable and persistent. A Table may be safely accessed from +// multiple threads without external synchronization. +class Table { + public: + // Attempt to open the table that is stored in bytes [0..file_size) + // of "file", and read the metadata entries necessary to allow + // retrieving data from the table. + // + // If successful, returns ok and sets "*table" to the newly opened + // table. The client should delete "*table" when no longer needed. + // If there was an error while initializing the table, sets "*table" + // to NULL and returns a non-ok status. Does not take ownership of + // "*source", but the client must ensure that "source" remains live + // for the duration of the returned table's lifetime. + // + // *file must remain live while this Table is in use. + static Status Open(const Options& options, + RandomAccessFile* file, + uint64_t file_size, + Table** table); + + ~Table(); + + // Returns a new iterator over the table contents. + // The result of NewIterator() is initially invalid (caller must + // call one of the Seek methods on the iterator before using it). + Iterator* NewIterator(const ReadOptions&) const; + + // Given a key, return an approximate byte offset in the file where + // the data for that key begins (or would begin if the key were + // present in the file). The returned value is in terms of file + // bytes, and so includes effects like compression of the underlying data. + // E.g., the approximate offset of the last key in the table will + // be close to the file length. + uint64_t ApproximateOffsetOf(const Slice& key) const; + + private: + struct Rep; + Rep* rep_; + + explicit Table(Rep* rep) { rep_ = rep; } + static Iterator* BlockReader(void*, const ReadOptions&, const Slice&); + + // Calls (*handle_result)(arg, ...) with the entry found after a call + // to Seek(key). May not make such a call if filter policy says + // that key is not present. + friend class TableCache; + Status InternalGet( + const ReadOptions&, const Slice& key, + void* arg, + void (*handle_result)(void* arg, const Slice& k, const Slice& v)); + + + void ReadMeta(const Footer& footer); + void ReadFilter(const Slice& filter_handle_value); + + // No copying allowed + Table(const Table&); + void operator=(const Table&); +}; + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_INCLUDE_TABLE_H_ diff --git a/src/leveldb/include/leveldb/table_builder.h b/src/leveldb/include/leveldb/table_builder.h new file mode 100644 index 0000000..5fd1dc7 --- /dev/null +++ b/src/leveldb/include/leveldb/table_builder.h @@ -0,0 +1,92 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. +// +// TableBuilder provides the interface used to build a Table +// (an immutable and sorted map from keys to values). +// +// Multiple threads can invoke const methods on a TableBuilder without +// external synchronization, but if any of the threads may call a +// non-const method, all threads accessing the same TableBuilder must use +// external synchronization. + +#ifndef STORAGE_LEVELDB_INCLUDE_TABLE_BUILDER_H_ +#define STORAGE_LEVELDB_INCLUDE_TABLE_BUILDER_H_ + +#include +#include "leveldb/options.h" +#include "leveldb/status.h" + +namespace leveldb { + +class BlockBuilder; +class BlockHandle; +class WritableFile; + +class TableBuilder { + public: + // Create a builder that will store the contents of the table it is + // building in *file. Does not close the file. It is up to the + // caller to close the file after calling Finish(). + TableBuilder(const Options& options, WritableFile* file); + + // REQUIRES: Either Finish() or Abandon() has been called. + ~TableBuilder(); + + // Change the options used by this builder. Note: only some of the + // option fields can be changed after construction. If a field is + // not allowed to change dynamically and its value in the structure + // passed to the constructor is different from its value in the + // structure passed to this method, this method will return an error + // without changing any fields. + Status ChangeOptions(const Options& options); + + // Add key,value to the table being constructed. + // REQUIRES: key is after any previously added key according to comparator. + // REQUIRES: Finish(), Abandon() have not been called + void Add(const Slice& key, const Slice& value); + + // Advanced operation: flush any buffered key/value pairs to file. + // Can be used to ensure that two adjacent entries never live in + // the same data block. Most clients should not need to use this method. + // REQUIRES: Finish(), Abandon() have not been called + void Flush(); + + // Return non-ok iff some error has been detected. + Status status() const; + + // Finish building the table. Stops using the file passed to the + // constructor after this function returns. + // REQUIRES: Finish(), Abandon() have not been called + Status Finish(); + + // Indicate that the contents of this builder should be abandoned. Stops + // using the file passed to the constructor after this function returns. + // If the caller is not going to call Finish(), it must call Abandon() + // before destroying this builder. + // REQUIRES: Finish(), Abandon() have not been called + void Abandon(); + + // Number of calls to Add() so far. + uint64_t NumEntries() const; + + // Size of the file generated so far. If invoked after a successful + // Finish() call, returns the size of the final generated file. + uint64_t FileSize() const; + + private: + bool ok() const { return status().ok(); } + void WriteBlock(BlockBuilder* block, BlockHandle* handle); + void WriteRawBlock(const Slice& data, CompressionType, BlockHandle* handle); + + struct Rep; + Rep* rep_; + + // No copying allowed + TableBuilder(const TableBuilder&); + void operator=(const TableBuilder&); +}; + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_INCLUDE_TABLE_BUILDER_H_ diff --git a/src/leveldb/include/leveldb/write_batch.h b/src/leveldb/include/leveldb/write_batch.h new file mode 100644 index 0000000..ee9aab6 --- /dev/null +++ b/src/leveldb/include/leveldb/write_batch.h @@ -0,0 +1,64 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. +// +// WriteBatch holds a collection of updates to apply atomically to a DB. +// +// The updates are applied in the order in which they are added +// to the WriteBatch. For example, the value of "key" will be "v3" +// after the following batch is written: +// +// batch.Put("key", "v1"); +// batch.Delete("key"); +// batch.Put("key", "v2"); +// batch.Put("key", "v3"); +// +// Multiple threads can invoke const methods on a WriteBatch without +// external synchronization, but if any of the threads may call a +// non-const method, all threads accessing the same WriteBatch must use +// external synchronization. + +#ifndef STORAGE_LEVELDB_INCLUDE_WRITE_BATCH_H_ +#define STORAGE_LEVELDB_INCLUDE_WRITE_BATCH_H_ + +#include +#include "leveldb/status.h" + +namespace leveldb { + +class Slice; + +class WriteBatch { + public: + WriteBatch(); + ~WriteBatch(); + + // Store the mapping "key->value" in the database. + void Put(const Slice& key, const Slice& value); + + // If the database contains a mapping for "key", erase it. Else do nothing. + void Delete(const Slice& key); + + // Clear all updates buffered in this batch. + void Clear(); + + // Support for iterating over the contents of a batch. + class Handler { + public: + virtual ~Handler(); + virtual void Put(const Slice& key, const Slice& value) = 0; + virtual void Delete(const Slice& key) = 0; + }; + Status Iterate(Handler* handler) const; + + private: + friend class WriteBatchInternal; + + std::string rep_; // See comment in write_batch.cc for the format of rep_ + + // Intentionally copyable +}; + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_INCLUDE_WRITE_BATCH_H_ diff --git a/src/leveldb/issues/issue178_test.cc b/src/leveldb/issues/issue178_test.cc new file mode 100644 index 0000000..1b1cf8b --- /dev/null +++ b/src/leveldb/issues/issue178_test.cc @@ -0,0 +1,92 @@ +// Copyright (c) 2013 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +// Test for issue 178: a manual compaction causes deleted data to reappear. +#include +#include +#include + +#include "leveldb/db.h" +#include "leveldb/write_batch.h" +#include "util/testharness.h" + +namespace { + +const int kNumKeys = 1100000; + +std::string Key1(int i) { + char buf[100]; + snprintf(buf, sizeof(buf), "my_key_%d", i); + return buf; +} + +std::string Key2(int i) { + return Key1(i) + "_xxx"; +} + +class Issue178 { }; + +TEST(Issue178, Test) { + // Get rid of any state from an old run. + std::string dbpath = leveldb::test::TmpDir() + "/leveldb_cbug_test"; + DestroyDB(dbpath, leveldb::Options()); + + // Open database. Disable compression since it affects the creation + // of layers and the code below is trying to test against a very + // specific scenario. + leveldb::DB* db; + leveldb::Options db_options; + db_options.create_if_missing = true; + db_options.compression = leveldb::kNoCompression; + ASSERT_OK(leveldb::DB::Open(db_options, dbpath, &db)); + + // create first key range + leveldb::WriteBatch batch; + for (size_t i = 0; i < kNumKeys; i++) { + batch.Put(Key1(i), "value for range 1 key"); + } + ASSERT_OK(db->Write(leveldb::WriteOptions(), &batch)); + + // create second key range + batch.Clear(); + for (size_t i = 0; i < kNumKeys; i++) { + batch.Put(Key2(i), "value for range 2 key"); + } + ASSERT_OK(db->Write(leveldb::WriteOptions(), &batch)); + + // delete second key range + batch.Clear(); + for (size_t i = 0; i < kNumKeys; i++) { + batch.Delete(Key2(i)); + } + ASSERT_OK(db->Write(leveldb::WriteOptions(), &batch)); + + // compact database + std::string start_key = Key1(0); + std::string end_key = Key1(kNumKeys - 1); + leveldb::Slice least(start_key.data(), start_key.size()); + leveldb::Slice greatest(end_key.data(), end_key.size()); + + // commenting out the line below causes the example to work correctly + db->CompactRange(&least, &greatest); + + // count the keys + leveldb::Iterator* iter = db->NewIterator(leveldb::ReadOptions()); + size_t num_keys = 0; + for (iter->SeekToFirst(); iter->Valid(); iter->Next()) { + num_keys++; + } + delete iter; + ASSERT_EQ(kNumKeys, num_keys) << "Bad number of keys"; + + // close database + delete db; + DestroyDB(dbpath, leveldb::Options()); +} + +} // anonymous namespace + +int main(int argc, char** argv) { + return leveldb::test::RunAllTests(); +} diff --git a/src/leveldb/issues/issue200_test.cc b/src/leveldb/issues/issue200_test.cc new file mode 100644 index 0000000..1cec79f --- /dev/null +++ b/src/leveldb/issues/issue200_test.cc @@ -0,0 +1,59 @@ +// Copyright (c) 2013 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +// Test for issue 200: when iterator switches direction from backward +// to forward, the current key can be yielded unexpectedly if a new +// mutation has been added just before the current key. + +#include "leveldb/db.h" +#include "util/testharness.h" + +namespace leveldb { + +class Issue200 { }; + +TEST(Issue200, Test) { + // Get rid of any state from an old run. + std::string dbpath = test::TmpDir() + "/leveldb_issue200_test"; + DestroyDB(dbpath, Options()); + + DB *db; + Options options; + options.create_if_missing = true; + ASSERT_OK(DB::Open(options, dbpath, &db)); + + WriteOptions write_options; + ASSERT_OK(db->Put(write_options, "1", "b")); + ASSERT_OK(db->Put(write_options, "2", "c")); + ASSERT_OK(db->Put(write_options, "3", "d")); + ASSERT_OK(db->Put(write_options, "4", "e")); + ASSERT_OK(db->Put(write_options, "5", "f")); + + ReadOptions read_options; + Iterator *iter = db->NewIterator(read_options); + + // Add an element that should not be reflected in the iterator. + ASSERT_OK(db->Put(write_options, "25", "cd")); + + iter->Seek("5"); + ASSERT_EQ(iter->key().ToString(), "5"); + iter->Prev(); + ASSERT_EQ(iter->key().ToString(), "4"); + iter->Prev(); + ASSERT_EQ(iter->key().ToString(), "3"); + iter->Next(); + ASSERT_EQ(iter->key().ToString(), "4"); + iter->Next(); + ASSERT_EQ(iter->key().ToString(), "5"); + + delete iter; + delete db; + DestroyDB(dbpath, options); +} + +} // namespace leveldb + +int main(int argc, char** argv) { + return leveldb::test::RunAllTests(); +} diff --git a/src/leveldb/port/README b/src/leveldb/port/README new file mode 100644 index 0000000..422563e --- /dev/null +++ b/src/leveldb/port/README @@ -0,0 +1,10 @@ +This directory contains interfaces and implementations that isolate the +rest of the package from platform details. + +Code in the rest of the package includes "port.h" from this directory. +"port.h" in turn includes a platform specific "port_.h" file +that provides the platform specific implementation. + +See port_posix.h for an example of what must be provided in a platform +specific header file. + diff --git a/src/leveldb/port/atomic_pointer.h b/src/leveldb/port/atomic_pointer.h new file mode 100644 index 0000000..a9866b2 --- /dev/null +++ b/src/leveldb/port/atomic_pointer.h @@ -0,0 +1,224 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +// AtomicPointer provides storage for a lock-free pointer. +// Platform-dependent implementation of AtomicPointer: +// - If the platform provides a cheap barrier, we use it with raw pointers +// - If cstdatomic is present (on newer versions of gcc, it is), we use +// a cstdatomic-based AtomicPointer. However we prefer the memory +// barrier based version, because at least on a gcc 4.4 32-bit build +// on linux, we have encountered a buggy +// implementation. Also, some implementations are much +// slower than a memory-barrier based implementation (~16ns for +// based acquire-load vs. ~1ns for a barrier based +// acquire-load). +// This code is based on atomicops-internals-* in Google's perftools: +// http://code.google.com/p/google-perftools/source/browse/#svn%2Ftrunk%2Fsrc%2Fbase + +#ifndef PORT_ATOMIC_POINTER_H_ +#define PORT_ATOMIC_POINTER_H_ + +#include +#ifdef LEVELDB_CSTDATOMIC_PRESENT +#include +#endif +#ifdef OS_WIN +#include +#endif +#ifdef OS_MACOSX +#include +#endif + +#if defined(_M_X64) || defined(__x86_64__) +#define ARCH_CPU_X86_FAMILY 1 +#elif defined(_M_IX86) || defined(__i386__) || defined(__i386) +#define ARCH_CPU_X86_FAMILY 1 +#elif defined(__ARMEL__) +#define ARCH_CPU_ARM_FAMILY 1 +#elif defined(__ppc__) || defined(__powerpc__) || defined(__powerpc64__) +#define ARCH_CPU_PPC_FAMILY 1 +#endif + +namespace leveldb { +namespace port { + +// Define MemoryBarrier() if available +// Windows on x86 +#if defined(OS_WIN) && defined(COMPILER_MSVC) && defined(ARCH_CPU_X86_FAMILY) +// windows.h already provides a MemoryBarrier(void) macro +// http://msdn.microsoft.com/en-us/library/ms684208(v=vs.85).aspx +#define LEVELDB_HAVE_MEMORY_BARRIER + +// Mac OS +#elif defined(OS_MACOSX) +inline void MemoryBarrier() { + OSMemoryBarrier(); +} +#define LEVELDB_HAVE_MEMORY_BARRIER + +// Gcc on x86 +#elif defined(ARCH_CPU_X86_FAMILY) && defined(__GNUC__) +inline void MemoryBarrier() { + // See http://gcc.gnu.org/ml/gcc/2003-04/msg01180.html for a discussion on + // this idiom. Also see http://en.wikipedia.org/wiki/Memory_ordering. + __asm__ __volatile__("" : : : "memory"); +} +#define LEVELDB_HAVE_MEMORY_BARRIER + +// Sun Studio +#elif defined(ARCH_CPU_X86_FAMILY) && defined(__SUNPRO_CC) +inline void MemoryBarrier() { + // See http://gcc.gnu.org/ml/gcc/2003-04/msg01180.html for a discussion on + // this idiom. Also see http://en.wikipedia.org/wiki/Memory_ordering. + asm volatile("" : : : "memory"); +} +#define LEVELDB_HAVE_MEMORY_BARRIER + +// ARM Linux +#elif defined(ARCH_CPU_ARM_FAMILY) && defined(__linux__) +typedef void (*LinuxKernelMemoryBarrierFunc)(void); +// The Linux ARM kernel provides a highly optimized device-specific memory +// barrier function at a fixed memory address that is mapped in every +// user-level process. +// +// This beats using CPU-specific instructions which are, on single-core +// devices, un-necessary and very costly (e.g. ARMv7-A "dmb" takes more +// than 180ns on a Cortex-A8 like the one on a Nexus One). Benchmarking +// shows that the extra function call cost is completely negligible on +// multi-core devices. +// +inline void MemoryBarrier() { + (*(LinuxKernelMemoryBarrierFunc)0xffff0fa0)(); +} +#define LEVELDB_HAVE_MEMORY_BARRIER + +// PPC +#elif defined(ARCH_CPU_PPC_FAMILY) && defined(__GNUC__) +inline void MemoryBarrier() { + // TODO for some powerpc expert: is there a cheaper suitable variant? + // Perhaps by having separate barriers for acquire and release ops. + asm volatile("sync" : : : "memory"); +} +#define LEVELDB_HAVE_MEMORY_BARRIER + +#endif + +// AtomicPointer built using platform-specific MemoryBarrier() +#if defined(LEVELDB_HAVE_MEMORY_BARRIER) +class AtomicPointer { + private: + void* rep_; + public: + AtomicPointer() { } + explicit AtomicPointer(void* p) : rep_(p) {} + inline void* NoBarrier_Load() const { return rep_; } + inline void NoBarrier_Store(void* v) { rep_ = v; } + inline void* Acquire_Load() const { + void* result = rep_; + MemoryBarrier(); + return result; + } + inline void Release_Store(void* v) { + MemoryBarrier(); + rep_ = v; + } +}; + +// AtomicPointer based on +#elif defined(LEVELDB_CSTDATOMIC_PRESENT) +class AtomicPointer { + private: + std::atomic rep_; + public: + AtomicPointer() { } + explicit AtomicPointer(void* v) : rep_(v) { } + inline void* Acquire_Load() const { + return rep_.load(std::memory_order_acquire); + } + inline void Release_Store(void* v) { + rep_.store(v, std::memory_order_release); + } + inline void* NoBarrier_Load() const { + return rep_.load(std::memory_order_relaxed); + } + inline void NoBarrier_Store(void* v) { + rep_.store(v, std::memory_order_relaxed); + } +}; + +// Atomic pointer based on sparc memory barriers +#elif defined(__sparcv9) && defined(__GNUC__) +class AtomicPointer { + private: + void* rep_; + public: + AtomicPointer() { } + explicit AtomicPointer(void* v) : rep_(v) { } + inline void* Acquire_Load() const { + void* val; + __asm__ __volatile__ ( + "ldx [%[rep_]], %[val] \n\t" + "membar #LoadLoad|#LoadStore \n\t" + : [val] "=r" (val) + : [rep_] "r" (&rep_) + : "memory"); + return val; + } + inline void Release_Store(void* v) { + __asm__ __volatile__ ( + "membar #LoadStore|#StoreStore \n\t" + "stx %[v], [%[rep_]] \n\t" + : + : [rep_] "r" (&rep_), [v] "r" (v) + : "memory"); + } + inline void* NoBarrier_Load() const { return rep_; } + inline void NoBarrier_Store(void* v) { rep_ = v; } +}; + +// Atomic pointer based on ia64 acq/rel +#elif defined(__ia64) && defined(__GNUC__) +class AtomicPointer { + private: + void* rep_; + public: + AtomicPointer() { } + explicit AtomicPointer(void* v) : rep_(v) { } + inline void* Acquire_Load() const { + void* val ; + __asm__ __volatile__ ( + "ld8.acq %[val] = [%[rep_]] \n\t" + : [val] "=r" (val) + : [rep_] "r" (&rep_) + : "memory" + ); + return val; + } + inline void Release_Store(void* v) { + __asm__ __volatile__ ( + "st8.rel [%[rep_]] = %[v] \n\t" + : + : [rep_] "r" (&rep_), [v] "r" (v) + : "memory" + ); + } + inline void* NoBarrier_Load() const { return rep_; } + inline void NoBarrier_Store(void* v) { rep_ = v; } +}; + +// We have neither MemoryBarrier(), nor +#else +#error Please implement AtomicPointer for this platform. + +#endif + +#undef LEVELDB_HAVE_MEMORY_BARRIER +#undef ARCH_CPU_X86_FAMILY +#undef ARCH_CPU_ARM_FAMILY +#undef ARCH_CPU_PPC_FAMILY + +} // namespace port +} // namespace leveldb + +#endif // PORT_ATOMIC_POINTER_H_ diff --git a/src/leveldb/port/port.h b/src/leveldb/port/port.h new file mode 100644 index 0000000..4baafa8 --- /dev/null +++ b/src/leveldb/port/port.h @@ -0,0 +1,21 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#ifndef STORAGE_LEVELDB_PORT_PORT_H_ +#define STORAGE_LEVELDB_PORT_PORT_H_ + +#include + +// Include the appropriate platform specific file below. If you are +// porting to a new platform, see "port_example.h" for documentation +// of what the new port_.h file must provide. +#if defined(LEVELDB_PLATFORM_POSIX) +# include "port/port_posix.h" +#elif defined(LEVELDB_PLATFORM_CHROMIUM) +# include "port/port_chromium.h" +#elif defined(LEVELDB_PLATFORM_WINDOWS) +# include "port/port_win.h" +#endif + +#endif // STORAGE_LEVELDB_PORT_PORT_H_ diff --git a/src/leveldb/port/port_example.h b/src/leveldb/port/port_example.h new file mode 100644 index 0000000..ab9e489 --- /dev/null +++ b/src/leveldb/port/port_example.h @@ -0,0 +1,135 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. +// +// This file contains the specification, but not the implementations, +// of the types/operations/etc. that should be defined by a platform +// specific port_.h file. Use this file as a reference for +// how to port this package to a new platform. + +#ifndef STORAGE_LEVELDB_PORT_PORT_EXAMPLE_H_ +#define STORAGE_LEVELDB_PORT_PORT_EXAMPLE_H_ + +namespace leveldb { +namespace port { + +// TODO(jorlow): Many of these belong more in the environment class rather than +// here. We should try moving them and see if it affects perf. + +// The following boolean constant must be true on a little-endian machine +// and false otherwise. +static const bool kLittleEndian = true /* or some other expression */; + +// ------------------ Threading ------------------- + +// A Mutex represents an exclusive lock. +class Mutex { + public: + Mutex(); + ~Mutex(); + + // Lock the mutex. Waits until other lockers have exited. + // Will deadlock if the mutex is already locked by this thread. + void Lock(); + + // Unlock the mutex. + // REQUIRES: This mutex was locked by this thread. + void Unlock(); + + // Optionally crash if this thread does not hold this mutex. + // The implementation must be fast, especially if NDEBUG is + // defined. The implementation is allowed to skip all checks. + void AssertHeld(); +}; + +class CondVar { + public: + explicit CondVar(Mutex* mu); + ~CondVar(); + + // Atomically release *mu and block on this condition variable until + // either a call to SignalAll(), or a call to Signal() that picks + // this thread to wakeup. + // REQUIRES: this thread holds *mu + void Wait(); + + // If there are some threads waiting, wake up at least one of them. + void Signal(); + + // Wake up all waiting threads. + void SignallAll(); +}; + +// Thread-safe initialization. +// Used as follows: +// static port::OnceType init_control = LEVELDB_ONCE_INIT; +// static void Initializer() { ... do something ...; } +// ... +// port::InitOnce(&init_control, &Initializer); +typedef intptr_t OnceType; +#define LEVELDB_ONCE_INIT 0 +extern void InitOnce(port::OnceType*, void (*initializer)()); + +// A type that holds a pointer that can be read or written atomically +// (i.e., without word-tearing.) +class AtomicPointer { + private: + intptr_t rep_; + public: + // Initialize to arbitrary value + AtomicPointer(); + + // Initialize to hold v + explicit AtomicPointer(void* v) : rep_(v) { } + + // Read and return the stored pointer with the guarantee that no + // later memory access (read or write) by this thread can be + // reordered ahead of this read. + void* Acquire_Load() const; + + // Set v as the stored pointer with the guarantee that no earlier + // memory access (read or write) by this thread can be reordered + // after this store. + void Release_Store(void* v); + + // Read the stored pointer with no ordering guarantees. + void* NoBarrier_Load() const; + + // Set va as the stored pointer with no ordering guarantees. + void NoBarrier_Store(void* v); +}; + +// ------------------ Compression ------------------- + +// Store the snappy compression of "input[0,input_length-1]" in *output. +// Returns false if snappy is not supported by this port. +extern bool Snappy_Compress(const char* input, size_t input_length, + std::string* output); + +// If input[0,input_length-1] looks like a valid snappy compressed +// buffer, store the size of the uncompressed data in *result and +// return true. Else return false. +extern bool Snappy_GetUncompressedLength(const char* input, size_t length, + size_t* result); + +// Attempt to snappy uncompress input[0,input_length-1] into *output. +// Returns true if successful, false if the input is invalid lightweight +// compressed data. +// +// REQUIRES: at least the first "n" bytes of output[] must be writable +// where "n" is the result of a successful call to +// Snappy_GetUncompressedLength. +extern bool Snappy_Uncompress(const char* input_data, size_t input_length, + char* output); + +// ------------------ Miscellaneous ------------------- + +// If heap profiling is not supported, returns false. +// Else repeatedly calls (*func)(arg, data, n) and then returns true. +// The concatenation of all "data[0,n-1]" fragments is the heap profile. +extern bool GetHeapProfile(void (*func)(void*, const char*, int), void* arg); + +} // namespace port +} // namespace leveldb + +#endif // STORAGE_LEVELDB_PORT_PORT_EXAMPLE_H_ diff --git a/src/leveldb/port/port_posix.cc b/src/leveldb/port/port_posix.cc new file mode 100644 index 0000000..5ba127a --- /dev/null +++ b/src/leveldb/port/port_posix.cc @@ -0,0 +1,54 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "port/port_posix.h" + +#include +#include +#include +#include "util/logging.h" + +namespace leveldb { +namespace port { + +static void PthreadCall(const char* label, int result) { + if (result != 0) { + fprintf(stderr, "pthread %s: %s\n", label, strerror(result)); + abort(); + } +} + +Mutex::Mutex() { PthreadCall("init mutex", pthread_mutex_init(&mu_, NULL)); } + +Mutex::~Mutex() { PthreadCall("destroy mutex", pthread_mutex_destroy(&mu_)); } + +void Mutex::Lock() { PthreadCall("lock", pthread_mutex_lock(&mu_)); } + +void Mutex::Unlock() { PthreadCall("unlock", pthread_mutex_unlock(&mu_)); } + +CondVar::CondVar(Mutex* mu) + : mu_(mu) { + PthreadCall("init cv", pthread_cond_init(&cv_, NULL)); +} + +CondVar::~CondVar() { PthreadCall("destroy cv", pthread_cond_destroy(&cv_)); } + +void CondVar::Wait() { + PthreadCall("wait", pthread_cond_wait(&cv_, &mu_->mu_)); +} + +void CondVar::Signal() { + PthreadCall("signal", pthread_cond_signal(&cv_)); +} + +void CondVar::SignalAll() { + PthreadCall("broadcast", pthread_cond_broadcast(&cv_)); +} + +void InitOnce(OnceType* once, void (*initializer)()) { + PthreadCall("once", pthread_once(once, initializer)); +} + +} // namespace port +} // namespace leveldb diff --git a/src/leveldb/port/port_posix.h b/src/leveldb/port/port_posix.h new file mode 100644 index 0000000..21c845e --- /dev/null +++ b/src/leveldb/port/port_posix.h @@ -0,0 +1,161 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. +// +// See port_example.h for documentation for the following types/functions. + +#ifndef STORAGE_LEVELDB_PORT_PORT_POSIX_H_ +#define STORAGE_LEVELDB_PORT_PORT_POSIX_H_ + +#undef PLATFORM_IS_LITTLE_ENDIAN +#if defined(OS_MACOSX) + #include + #if defined(__DARWIN_LITTLE_ENDIAN) && defined(__DARWIN_BYTE_ORDER) + #define PLATFORM_IS_LITTLE_ENDIAN \ + (__DARWIN_BYTE_ORDER == __DARWIN_LITTLE_ENDIAN) + #endif +#elif defined(OS_SOLARIS) + #include + #ifdef _LITTLE_ENDIAN + #define PLATFORM_IS_LITTLE_ENDIAN true + #else + #define PLATFORM_IS_LITTLE_ENDIAN false + #endif +#elif defined(OS_FREEBSD) + #include + #include + #define PLATFORM_IS_LITTLE_ENDIAN (_BYTE_ORDER == _LITTLE_ENDIAN) +#elif defined(OS_OPENBSD) || defined(OS_NETBSD) ||\ + defined(OS_DRAGONFLYBSD) + #include + #include +#elif defined(OS_HPUX) + #define PLATFORM_IS_LITTLE_ENDIAN false +#elif defined(OS_ANDROID) + // Due to a bug in the NDK x86 definition, + // _BYTE_ORDER must be used instead of __BYTE_ORDER on Android. + // See http://code.google.com/p/android/issues/detail?id=39824 + #include + #define PLATFORM_IS_LITTLE_ENDIAN (_BYTE_ORDER == _LITTLE_ENDIAN) +#else + #include +#endif + +#include +#ifdef SNAPPY +#include +#endif +#include +#include +#include "port/atomic_pointer.h" + +#ifndef PLATFORM_IS_LITTLE_ENDIAN +#define PLATFORM_IS_LITTLE_ENDIAN (__BYTE_ORDER == __LITTLE_ENDIAN) +#endif + +#if defined(OS_MACOSX) || defined(OS_SOLARIS) || defined(OS_FREEBSD) ||\ + defined(OS_NETBSD) || defined(OS_OPENBSD) || defined(OS_DRAGONFLYBSD) ||\ + defined(OS_ANDROID) || defined(OS_HPUX) +// Use fread/fwrite/fflush on platforms without _unlocked variants +#define fread_unlocked fread +#define fwrite_unlocked fwrite +#define fflush_unlocked fflush +#endif + +#if defined(OS_FREEBSD) ||\ + defined(OS_OPENBSD) || defined(OS_DRAGONFLYBSD) +// Use fsync() on platforms without fdatasync() +#define fdatasync fsync +#endif + +#if defined(OS_MACOSX) +#define fdatasync(fd) fcntl(fd, F_FULLFSYNC, 0) +#endif + +#if defined(OS_ANDROID) && __ANDROID_API__ < 9 +// fdatasync() was only introduced in API level 9 on Android. Use fsync() +// when targetting older platforms. +#define fdatasync fsync +#endif + +namespace leveldb { +namespace port { + +static const bool kLittleEndian = PLATFORM_IS_LITTLE_ENDIAN; +#undef PLATFORM_IS_LITTLE_ENDIAN + +class CondVar; + +class Mutex { + public: + Mutex(); + ~Mutex(); + + void Lock(); + void Unlock(); + void AssertHeld() { } + + private: + friend class CondVar; + pthread_mutex_t mu_; + + // No copying + Mutex(const Mutex&); + void operator=(const Mutex&); +}; + +class CondVar { + public: + explicit CondVar(Mutex* mu); + ~CondVar(); + void Wait(); + void Signal(); + void SignalAll(); + private: + pthread_cond_t cv_; + Mutex* mu_; +}; + +typedef pthread_once_t OnceType; +#define LEVELDB_ONCE_INIT PTHREAD_ONCE_INIT +extern void InitOnce(OnceType* once, void (*initializer)()); + +inline bool Snappy_Compress(const char* input, size_t length, + ::std::string* output) { +#ifdef SNAPPY + output->resize(snappy::MaxCompressedLength(length)); + size_t outlen; + snappy::RawCompress(input, length, &(*output)[0], &outlen); + output->resize(outlen); + return true; +#endif + + return false; +} + +inline bool Snappy_GetUncompressedLength(const char* input, size_t length, + size_t* result) { +#ifdef SNAPPY + return snappy::GetUncompressedLength(input, length, result); +#else + return false; +#endif +} + +inline bool Snappy_Uncompress(const char* input, size_t length, + char* output) { +#ifdef SNAPPY + return snappy::RawUncompress(input, length, output); +#else + return false; +#endif +} + +inline bool GetHeapProfile(void (*func)(void*, const char*, int), void* arg) { + return false; +} + +} // namespace port +} // namespace leveldb + +#endif // STORAGE_LEVELDB_PORT_PORT_POSIX_H_ diff --git a/src/leveldb/port/port_win.cc b/src/leveldb/port/port_win.cc new file mode 100644 index 0000000..1b0f060 --- /dev/null +++ b/src/leveldb/port/port_win.cc @@ -0,0 +1,147 @@ +// LevelDB Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. +// +// See port_example.h for documentation for the following types/functions. + +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of the University of California, Berkeley nor the +// names of its contributors may be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY +// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// + +#include "port/port_win.h" + +#include +#include + +namespace leveldb { +namespace port { + +Mutex::Mutex() : + cs_(NULL) { + assert(!cs_); + cs_ = static_cast(new CRITICAL_SECTION()); + ::InitializeCriticalSection(static_cast(cs_)); + assert(cs_); +} + +Mutex::~Mutex() { + assert(cs_); + ::DeleteCriticalSection(static_cast(cs_)); + delete static_cast(cs_); + cs_ = NULL; + assert(!cs_); +} + +void Mutex::Lock() { + assert(cs_); + ::EnterCriticalSection(static_cast(cs_)); +} + +void Mutex::Unlock() { + assert(cs_); + ::LeaveCriticalSection(static_cast(cs_)); +} + +void Mutex::AssertHeld() { + assert(cs_); + assert(1); +} + +CondVar::CondVar(Mutex* mu) : + waiting_(0), + mu_(mu), + sem1_(::CreateSemaphore(NULL, 0, 10000, NULL)), + sem2_(::CreateSemaphore(NULL, 0, 10000, NULL)) { + assert(mu_); +} + +CondVar::~CondVar() { + ::CloseHandle(sem1_); + ::CloseHandle(sem2_); +} + +void CondVar::Wait() { + mu_->AssertHeld(); + + wait_mtx_.Lock(); + ++waiting_; + wait_mtx_.Unlock(); + + mu_->Unlock(); + + // initiate handshake + ::WaitForSingleObject(sem1_, INFINITE); + ::ReleaseSemaphore(sem2_, 1, NULL); + mu_->Lock(); +} + +void CondVar::Signal() { + wait_mtx_.Lock(); + if (waiting_ > 0) { + --waiting_; + + // finalize handshake + ::ReleaseSemaphore(sem1_, 1, NULL); + ::WaitForSingleObject(sem2_, INFINITE); + } + wait_mtx_.Unlock(); +} + +void CondVar::SignalAll() { + wait_mtx_.Lock(); + ::ReleaseSemaphore(sem1_, waiting_, NULL); + while(waiting_ > 0) { + --waiting_; + ::WaitForSingleObject(sem2_, INFINITE); + } + wait_mtx_.Unlock(); +} + +AtomicPointer::AtomicPointer(void* v) { + Release_Store(v); +} + +void InitOnce(OnceType* once, void (*initializer)()) { + once->InitOnce(initializer); +} + +void* AtomicPointer::Acquire_Load() const { + void * p = NULL; + InterlockedExchangePointer(&p, rep_); + return p; +} + +void AtomicPointer::Release_Store(void* v) { + InterlockedExchangePointer(&rep_, v); +} + +void* AtomicPointer::NoBarrier_Load() const { + return rep_; +} + +void AtomicPointer::NoBarrier_Store(void* v) { + rep_ = v; +} + +} +} diff --git a/src/leveldb/port/port_win.h b/src/leveldb/port/port_win.h new file mode 100644 index 0000000..45bf2f0 --- /dev/null +++ b/src/leveldb/port/port_win.h @@ -0,0 +1,174 @@ +// LevelDB Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. +// +// See port_example.h for documentation for the following types/functions. + +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of the University of California, Berkeley nor the +// names of its contributors may be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY +// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// + +#ifndef STORAGE_LEVELDB_PORT_PORT_WIN_H_ +#define STORAGE_LEVELDB_PORT_PORT_WIN_H_ + +#ifdef _MSC_VER +#define snprintf _snprintf +#define close _close +#define fread_unlocked _fread_nolock +#endif + +#include +#include +#ifdef SNAPPY +#include +#endif + +namespace leveldb { +namespace port { + +// Windows is little endian (for now :p) +static const bool kLittleEndian = true; + +class CondVar; + +class Mutex { + public: + Mutex(); + ~Mutex(); + + void Lock(); + void Unlock(); + void AssertHeld(); + + private: + friend class CondVar; + // critical sections are more efficient than mutexes + // but they are not recursive and can only be used to synchronize threads within the same process + // we use opaque void * to avoid including windows.h in port_win.h + void * cs_; + + // No copying + Mutex(const Mutex&); + void operator=(const Mutex&); +}; + +// the Win32 API offers a dependable condition variable mechanism, but only starting with +// Windows 2008 and Vista +// no matter what we will implement our own condition variable with a semaphore +// implementation as described in a paper written by Andrew D. Birrell in 2003 +class CondVar { + public: + explicit CondVar(Mutex* mu); + ~CondVar(); + void Wait(); + void Signal(); + void SignalAll(); + private: + Mutex* mu_; + + Mutex wait_mtx_; + long waiting_; + + void * sem1_; + void * sem2_; + + +}; + +class OnceType { +public: +// OnceType() : init_(false) {} + OnceType(const OnceType &once) : init_(once.init_) {} + OnceType(bool f) : init_(f) {} + void InitOnce(void (*initializer)()) { + mutex_.Lock(); + if (!init_) { + init_ = true; + initializer(); + } + mutex_.Unlock(); + } + +private: + bool init_; + Mutex mutex_; +}; + +#define LEVELDB_ONCE_INIT false +extern void InitOnce(port::OnceType*, void (*initializer)()); + +// Storage for a lock-free pointer +class AtomicPointer { + private: + void * rep_; + public: + AtomicPointer() : rep_(NULL) { } + explicit AtomicPointer(void* v); + void* Acquire_Load() const; + + void Release_Store(void* v); + + void* NoBarrier_Load() const; + + void NoBarrier_Store(void* v); +}; + +inline bool Snappy_Compress(const char* input, size_t length, + ::std::string* output) { +#ifdef SNAPPY + output->resize(snappy::MaxCompressedLength(length)); + size_t outlen; + snappy::RawCompress(input, length, &(*output)[0], &outlen); + output->resize(outlen); + return true; +#endif + + return false; +} + +inline bool Snappy_GetUncompressedLength(const char* input, size_t length, + size_t* result) { +#ifdef SNAPPY + return snappy::GetUncompressedLength(input, length, result); +#else + return false; +#endif +} + +inline bool Snappy_Uncompress(const char* input, size_t length, + char* output) { +#ifdef SNAPPY + return snappy::RawUncompress(input, length, output); +#else + return false; +#endif +} + +inline bool GetHeapProfile(void (*func)(void*, const char*, int), void* arg) { + return false; +} + +} +} + +#endif // STORAGE_LEVELDB_PORT_PORT_WIN_H_ diff --git a/src/leveldb/port/thread_annotations.h b/src/leveldb/port/thread_annotations.h new file mode 100644 index 0000000..6f9b6a7 --- /dev/null +++ b/src/leveldb/port/thread_annotations.h @@ -0,0 +1,59 @@ +// Copyright (c) 2012 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#ifndef STORAGE_LEVELDB_PORT_THREAD_ANNOTATIONS_H + +// Some environments provide custom macros to aid in static thread-safety +// analysis. Provide empty definitions of such macros unless they are already +// defined. + +#ifndef EXCLUSIVE_LOCKS_REQUIRED +#define EXCLUSIVE_LOCKS_REQUIRED(...) +#endif + +#ifndef SHARED_LOCKS_REQUIRED +#define SHARED_LOCKS_REQUIRED(...) +#endif + +#ifndef LOCKS_EXCLUDED +#define LOCKS_EXCLUDED(...) +#endif + +#ifndef LOCK_RETURNED +#define LOCK_RETURNED(x) +#endif + +#ifndef LOCKABLE +#define LOCKABLE +#endif + +#ifndef SCOPED_LOCKABLE +#define SCOPED_LOCKABLE +#endif + +#ifndef EXCLUSIVE_LOCK_FUNCTION +#define EXCLUSIVE_LOCK_FUNCTION(...) +#endif + +#ifndef SHARED_LOCK_FUNCTION +#define SHARED_LOCK_FUNCTION(...) +#endif + +#ifndef EXCLUSIVE_TRYLOCK_FUNCTION +#define EXCLUSIVE_TRYLOCK_FUNCTION(...) +#endif + +#ifndef SHARED_TRYLOCK_FUNCTION +#define SHARED_TRYLOCK_FUNCTION(...) +#endif + +#ifndef UNLOCK_FUNCTION +#define UNLOCK_FUNCTION(...) +#endif + +#ifndef NO_THREAD_SAFETY_ANALYSIS +#define NO_THREAD_SAFETY_ANALYSIS +#endif + +#endif // STORAGE_LEVELDB_PORT_THREAD_ANNOTATIONS_H diff --git a/src/leveldb/port/win/stdint.h b/src/leveldb/port/win/stdint.h new file mode 100644 index 0000000..39edd0d --- /dev/null +++ b/src/leveldb/port/win/stdint.h @@ -0,0 +1,24 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +// MSVC didn't ship with this file until the 2010 version. + +#ifndef STORAGE_LEVELDB_PORT_WIN_STDINT_H_ +#define STORAGE_LEVELDB_PORT_WIN_STDINT_H_ + +#if !defined(_MSC_VER) +#error This file should only be included when compiling with MSVC. +#endif + +// Define C99 equivalent types. +typedef signed char int8_t; +typedef signed short int16_t; +typedef signed int int32_t; +typedef signed long long int64_t; +typedef unsigned char uint8_t; +typedef unsigned short uint16_t; +typedef unsigned int uint32_t; +typedef unsigned long long uint64_t; + +#endif // STORAGE_LEVELDB_PORT_WIN_STDINT_H_ diff --git a/src/leveldb/table/block.cc b/src/leveldb/table/block.cc new file mode 100644 index 0000000..79ea9d9 --- /dev/null +++ b/src/leveldb/table/block.cc @@ -0,0 +1,268 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. +// +// Decodes the blocks generated by block_builder.cc. + +#include "table/block.h" + +#include +#include +#include "leveldb/comparator.h" +#include "table/format.h" +#include "util/coding.h" +#include "util/logging.h" + +namespace leveldb { + +inline uint32_t Block::NumRestarts() const { + assert(size_ >= sizeof(uint32_t)); + return DecodeFixed32(data_ + size_ - sizeof(uint32_t)); +} + +Block::Block(const BlockContents& contents) + : data_(contents.data.data()), + size_(contents.data.size()), + owned_(contents.heap_allocated) { + if (size_ < sizeof(uint32_t)) { + size_ = 0; // Error marker + } else { + size_t max_restarts_allowed = (size_-sizeof(uint32_t)) / sizeof(uint32_t); + if (NumRestarts() > max_restarts_allowed) { + // The size is too small for NumRestarts() + size_ = 0; + } else { + restart_offset_ = size_ - (1 + NumRestarts()) * sizeof(uint32_t); + } + } +} + +Block::~Block() { + if (owned_) { + delete[] data_; + } +} + +// Helper routine: decode the next block entry starting at "p", +// storing the number of shared key bytes, non_shared key bytes, +// and the length of the value in "*shared", "*non_shared", and +// "*value_length", respectively. Will not derefence past "limit". +// +// If any errors are detected, returns NULL. Otherwise, returns a +// pointer to the key delta (just past the three decoded values). +static inline const char* DecodeEntry(const char* p, const char* limit, + uint32_t* shared, + uint32_t* non_shared, + uint32_t* value_length) { + if (limit - p < 3) return NULL; + *shared = reinterpret_cast(p)[0]; + *non_shared = reinterpret_cast(p)[1]; + *value_length = reinterpret_cast(p)[2]; + if ((*shared | *non_shared | *value_length) < 128) { + // Fast path: all three values are encoded in one byte each + p += 3; + } else { + if ((p = GetVarint32Ptr(p, limit, shared)) == NULL) return NULL; + if ((p = GetVarint32Ptr(p, limit, non_shared)) == NULL) return NULL; + if ((p = GetVarint32Ptr(p, limit, value_length)) == NULL) return NULL; + } + + if (static_cast(limit - p) < (*non_shared + *value_length)) { + return NULL; + } + return p; +} + +class Block::Iter : public Iterator { + private: + const Comparator* const comparator_; + const char* const data_; // underlying block contents + uint32_t const restarts_; // Offset of restart array (list of fixed32) + uint32_t const num_restarts_; // Number of uint32_t entries in restart array + + // current_ is offset in data_ of current entry. >= restarts_ if !Valid + uint32_t current_; + uint32_t restart_index_; // Index of restart block in which current_ falls + std::string key_; + Slice value_; + Status status_; + + inline int Compare(const Slice& a, const Slice& b) const { + return comparator_->Compare(a, b); + } + + // Return the offset in data_ just past the end of the current entry. + inline uint32_t NextEntryOffset() const { + return (value_.data() + value_.size()) - data_; + } + + uint32_t GetRestartPoint(uint32_t index) { + assert(index < num_restarts_); + return DecodeFixed32(data_ + restarts_ + index * sizeof(uint32_t)); + } + + void SeekToRestartPoint(uint32_t index) { + key_.clear(); + restart_index_ = index; + // current_ will be fixed by ParseNextKey(); + + // ParseNextKey() starts at the end of value_, so set value_ accordingly + uint32_t offset = GetRestartPoint(index); + value_ = Slice(data_ + offset, 0); + } + + public: + Iter(const Comparator* comparator, + const char* data, + uint32_t restarts, + uint32_t num_restarts) + : comparator_(comparator), + data_(data), + restarts_(restarts), + num_restarts_(num_restarts), + current_(restarts_), + restart_index_(num_restarts_) { + assert(num_restarts_ > 0); + } + + virtual bool Valid() const { return current_ < restarts_; } + virtual Status status() const { return status_; } + virtual Slice key() const { + assert(Valid()); + return key_; + } + virtual Slice value() const { + assert(Valid()); + return value_; + } + + virtual void Next() { + assert(Valid()); + ParseNextKey(); + } + + virtual void Prev() { + assert(Valid()); + + // Scan backwards to a restart point before current_ + const uint32_t original = current_; + while (GetRestartPoint(restart_index_) >= original) { + if (restart_index_ == 0) { + // No more entries + current_ = restarts_; + restart_index_ = num_restarts_; + return; + } + restart_index_--; + } + + SeekToRestartPoint(restart_index_); + do { + // Loop until end of current entry hits the start of original entry + } while (ParseNextKey() && NextEntryOffset() < original); + } + + virtual void Seek(const Slice& target) { + // Binary search in restart array to find the last restart point + // with a key < target + uint32_t left = 0; + uint32_t right = num_restarts_ - 1; + while (left < right) { + uint32_t mid = (left + right + 1) / 2; + uint32_t region_offset = GetRestartPoint(mid); + uint32_t shared, non_shared, value_length; + const char* key_ptr = DecodeEntry(data_ + region_offset, + data_ + restarts_, + &shared, &non_shared, &value_length); + if (key_ptr == NULL || (shared != 0)) { + CorruptionError(); + return; + } + Slice mid_key(key_ptr, non_shared); + if (Compare(mid_key, target) < 0) { + // Key at "mid" is smaller than "target". Therefore all + // blocks before "mid" are uninteresting. + left = mid; + } else { + // Key at "mid" is >= "target". Therefore all blocks at or + // after "mid" are uninteresting. + right = mid - 1; + } + } + + // Linear search (within restart block) for first key >= target + SeekToRestartPoint(left); + while (true) { + if (!ParseNextKey()) { + return; + } + if (Compare(key_, target) >= 0) { + return; + } + } + } + + virtual void SeekToFirst() { + SeekToRestartPoint(0); + ParseNextKey(); + } + + virtual void SeekToLast() { + SeekToRestartPoint(num_restarts_ - 1); + while (ParseNextKey() && NextEntryOffset() < restarts_) { + // Keep skipping + } + } + + private: + void CorruptionError() { + current_ = restarts_; + restart_index_ = num_restarts_; + status_ = Status::Corruption("bad entry in block"); + key_.clear(); + value_.clear(); + } + + bool ParseNextKey() { + current_ = NextEntryOffset(); + const char* p = data_ + current_; + const char* limit = data_ + restarts_; // Restarts come right after data + if (p >= limit) { + // No more entries to return. Mark as invalid. + current_ = restarts_; + restart_index_ = num_restarts_; + return false; + } + + // Decode next entry + uint32_t shared, non_shared, value_length; + p = DecodeEntry(p, limit, &shared, &non_shared, &value_length); + if (p == NULL || key_.size() < shared) { + CorruptionError(); + return false; + } else { + key_.resize(shared); + key_.append(p, non_shared); + value_ = Slice(p + non_shared, value_length); + while (restart_index_ + 1 < num_restarts_ && + GetRestartPoint(restart_index_ + 1) < current_) { + ++restart_index_; + } + return true; + } + } +}; + +Iterator* Block::NewIterator(const Comparator* cmp) { + if (size_ < sizeof(uint32_t)) { + return NewErrorIterator(Status::Corruption("bad block contents")); + } + const uint32_t num_restarts = NumRestarts(); + if (num_restarts == 0) { + return NewEmptyIterator(); + } else { + return new Iter(cmp, data_, restart_offset_, num_restarts); + } +} + +} // namespace leveldb diff --git a/src/leveldb/table/block.h b/src/leveldb/table/block.h new file mode 100644 index 0000000..2493eb9 --- /dev/null +++ b/src/leveldb/table/block.h @@ -0,0 +1,44 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#ifndef STORAGE_LEVELDB_TABLE_BLOCK_H_ +#define STORAGE_LEVELDB_TABLE_BLOCK_H_ + +#include +#include +#include "leveldb/iterator.h" + +namespace leveldb { + +struct BlockContents; +class Comparator; + +class Block { + public: + // Initialize the block with the specified contents. + explicit Block(const BlockContents& contents); + + ~Block(); + + size_t size() const { return size_; } + Iterator* NewIterator(const Comparator* comparator); + + private: + uint32_t NumRestarts() const; + + const char* data_; + size_t size_; + uint32_t restart_offset_; // Offset in data_ of restart array + bool owned_; // Block owns data_[] + + // No copying allowed + Block(const Block&); + void operator=(const Block&); + + class Iter; +}; + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_TABLE_BLOCK_H_ diff --git a/src/leveldb/table/block_builder.cc b/src/leveldb/table/block_builder.cc new file mode 100644 index 0000000..db660cd --- /dev/null +++ b/src/leveldb/table/block_builder.cc @@ -0,0 +1,109 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. +// +// BlockBuilder generates blocks where keys are prefix-compressed: +// +// When we store a key, we drop the prefix shared with the previous +// string. This helps reduce the space requirement significantly. +// Furthermore, once every K keys, we do not apply the prefix +// compression and store the entire key. We call this a "restart +// point". The tail end of the block stores the offsets of all of the +// restart points, and can be used to do a binary search when looking +// for a particular key. Values are stored as-is (without compression) +// immediately following the corresponding key. +// +// An entry for a particular key-value pair has the form: +// shared_bytes: varint32 +// unshared_bytes: varint32 +// value_length: varint32 +// key_delta: char[unshared_bytes] +// value: char[value_length] +// shared_bytes == 0 for restart points. +// +// The trailer of the block has the form: +// restarts: uint32[num_restarts] +// num_restarts: uint32 +// restarts[i] contains the offset within the block of the ith restart point. + +#include "table/block_builder.h" + +#include +#include +#include "leveldb/comparator.h" +#include "leveldb/table_builder.h" +#include "util/coding.h" + +namespace leveldb { + +BlockBuilder::BlockBuilder(const Options* options) + : options_(options), + restarts_(), + counter_(0), + finished_(false) { + assert(options->block_restart_interval >= 1); + restarts_.push_back(0); // First restart point is at offset 0 +} + +void BlockBuilder::Reset() { + buffer_.clear(); + restarts_.clear(); + restarts_.push_back(0); // First restart point is at offset 0 + counter_ = 0; + finished_ = false; + last_key_.clear(); +} + +size_t BlockBuilder::CurrentSizeEstimate() const { + return (buffer_.size() + // Raw data buffer + restarts_.size() * sizeof(uint32_t) + // Restart array + sizeof(uint32_t)); // Restart array length +} + +Slice BlockBuilder::Finish() { + // Append restart array + for (size_t i = 0; i < restarts_.size(); i++) { + PutFixed32(&buffer_, restarts_[i]); + } + PutFixed32(&buffer_, restarts_.size()); + finished_ = true; + return Slice(buffer_); +} + +void BlockBuilder::Add(const Slice& key, const Slice& value) { + Slice last_key_piece(last_key_); + assert(!finished_); + assert(counter_ <= options_->block_restart_interval); + assert(buffer_.empty() // No values yet? + || options_->comparator->Compare(key, last_key_piece) > 0); + size_t shared = 0; + if (counter_ < options_->block_restart_interval) { + // See how much sharing to do with previous string + const size_t min_length = std::min(last_key_piece.size(), key.size()); + while ((shared < min_length) && (last_key_piece[shared] == key[shared])) { + shared++; + } + } else { + // Restart compression + restarts_.push_back(buffer_.size()); + counter_ = 0; + } + const size_t non_shared = key.size() - shared; + + // Add "" to buffer_ + PutVarint32(&buffer_, shared); + PutVarint32(&buffer_, non_shared); + PutVarint32(&buffer_, value.size()); + + // Add string delta to buffer_ followed by value + buffer_.append(key.data() + shared, non_shared); + buffer_.append(value.data(), value.size()); + + // Update state + last_key_.resize(shared); + last_key_.append(key.data() + shared, non_shared); + assert(Slice(last_key_) == key); + counter_++; +} + +} // namespace leveldb diff --git a/src/leveldb/table/block_builder.h b/src/leveldb/table/block_builder.h new file mode 100644 index 0000000..5b545bd --- /dev/null +++ b/src/leveldb/table/block_builder.h @@ -0,0 +1,57 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#ifndef STORAGE_LEVELDB_TABLE_BLOCK_BUILDER_H_ +#define STORAGE_LEVELDB_TABLE_BLOCK_BUILDER_H_ + +#include + +#include +#include "leveldb/slice.h" + +namespace leveldb { + +struct Options; + +class BlockBuilder { + public: + explicit BlockBuilder(const Options* options); + + // Reset the contents as if the BlockBuilder was just constructed. + void Reset(); + + // REQUIRES: Finish() has not been callled since the last call to Reset(). + // REQUIRES: key is larger than any previously added key + void Add(const Slice& key, const Slice& value); + + // Finish building the block and return a slice that refers to the + // block contents. The returned slice will remain valid for the + // lifetime of this builder or until Reset() is called. + Slice Finish(); + + // Returns an estimate of the current (uncompressed) size of the block + // we are building. + size_t CurrentSizeEstimate() const; + + // Return true iff no entries have been added since the last Reset() + bool empty() const { + return buffer_.empty(); + } + + private: + const Options* options_; + std::string buffer_; // Destination buffer + std::vector restarts_; // Restart points + int counter_; // Number of entries emitted since restart + bool finished_; // Has Finish() been called? + std::string last_key_; + + // No copying allowed + BlockBuilder(const BlockBuilder&); + void operator=(const BlockBuilder&); +}; + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_TABLE_BLOCK_BUILDER_H_ diff --git a/src/leveldb/table/filter_block.cc b/src/leveldb/table/filter_block.cc new file mode 100644 index 0000000..203e15c --- /dev/null +++ b/src/leveldb/table/filter_block.cc @@ -0,0 +1,111 @@ +// Copyright (c) 2012 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "table/filter_block.h" + +#include "leveldb/filter_policy.h" +#include "util/coding.h" + +namespace leveldb { + +// See doc/table_format.txt for an explanation of the filter block format. + +// Generate new filter every 2KB of data +static const size_t kFilterBaseLg = 11; +static const size_t kFilterBase = 1 << kFilterBaseLg; + +FilterBlockBuilder::FilterBlockBuilder(const FilterPolicy* policy) + : policy_(policy) { +} + +void FilterBlockBuilder::StartBlock(uint64_t block_offset) { + uint64_t filter_index = (block_offset / kFilterBase); + assert(filter_index >= filter_offsets_.size()); + while (filter_index > filter_offsets_.size()) { + GenerateFilter(); + } +} + +void FilterBlockBuilder::AddKey(const Slice& key) { + Slice k = key; + start_.push_back(keys_.size()); + keys_.append(k.data(), k.size()); +} + +Slice FilterBlockBuilder::Finish() { + if (!start_.empty()) { + GenerateFilter(); + } + + // Append array of per-filter offsets + const uint32_t array_offset = result_.size(); + for (size_t i = 0; i < filter_offsets_.size(); i++) { + PutFixed32(&result_, filter_offsets_[i]); + } + + PutFixed32(&result_, array_offset); + result_.push_back(kFilterBaseLg); // Save encoding parameter in result + return Slice(result_); +} + +void FilterBlockBuilder::GenerateFilter() { + const size_t num_keys = start_.size(); + if (num_keys == 0) { + // Fast path if there are no keys for this filter + filter_offsets_.push_back(result_.size()); + return; + } + + // Make list of keys from flattened key structure + start_.push_back(keys_.size()); // Simplify length computation + tmp_keys_.resize(num_keys); + for (size_t i = 0; i < num_keys; i++) { + const char* base = keys_.data() + start_[i]; + size_t length = start_[i+1] - start_[i]; + tmp_keys_[i] = Slice(base, length); + } + + // Generate filter for current set of keys and append to result_. + filter_offsets_.push_back(result_.size()); + policy_->CreateFilter(&tmp_keys_[0], num_keys, &result_); + + tmp_keys_.clear(); + keys_.clear(); + start_.clear(); +} + +FilterBlockReader::FilterBlockReader(const FilterPolicy* policy, + const Slice& contents) + : policy_(policy), + data_(NULL), + offset_(NULL), + num_(0), + base_lg_(0) { + size_t n = contents.size(); + if (n < 5) return; // 1 byte for base_lg_ and 4 for start of offset array + base_lg_ = contents[n-1]; + uint32_t last_word = DecodeFixed32(contents.data() + n - 5); + if (last_word > n - 5) return; + data_ = contents.data(); + offset_ = data_ + last_word; + num_ = (n - 5 - last_word) / 4; +} + +bool FilterBlockReader::KeyMayMatch(uint64_t block_offset, const Slice& key) { + uint64_t index = block_offset >> base_lg_; + if (index < num_) { + uint32_t start = DecodeFixed32(offset_ + index*4); + uint32_t limit = DecodeFixed32(offset_ + index*4 + 4); + if (start <= limit && limit <= (offset_ - data_)) { + Slice filter = Slice(data_ + start, limit - start); + return policy_->KeyMayMatch(key, filter); + } else if (start == limit) { + // Empty filters do not match any keys + return false; + } + } + return true; // Errors are treated as potential matches +} + +} diff --git a/src/leveldb/table/filter_block.h b/src/leveldb/table/filter_block.h new file mode 100644 index 0000000..c67d010 --- /dev/null +++ b/src/leveldb/table/filter_block.h @@ -0,0 +1,68 @@ +// Copyright (c) 2012 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. +// +// A filter block is stored near the end of a Table file. It contains +// filters (e.g., bloom filters) for all data blocks in the table combined +// into a single filter block. + +#ifndef STORAGE_LEVELDB_TABLE_FILTER_BLOCK_H_ +#define STORAGE_LEVELDB_TABLE_FILTER_BLOCK_H_ + +#include +#include +#include +#include +#include "leveldb/slice.h" +#include "util/hash.h" + +namespace leveldb { + +class FilterPolicy; + +// A FilterBlockBuilder is used to construct all of the filters for a +// particular Table. It generates a single string which is stored as +// a special block in the Table. +// +// The sequence of calls to FilterBlockBuilder must match the regexp: +// (StartBlock AddKey*)* Finish +class FilterBlockBuilder { + public: + explicit FilterBlockBuilder(const FilterPolicy*); + + void StartBlock(uint64_t block_offset); + void AddKey(const Slice& key); + Slice Finish(); + + private: + void GenerateFilter(); + + const FilterPolicy* policy_; + std::string keys_; // Flattened key contents + std::vector start_; // Starting index in keys_ of each key + std::string result_; // Filter data computed so far + std::vector tmp_keys_; // policy_->CreateFilter() argument + std::vector filter_offsets_; + + // No copying allowed + FilterBlockBuilder(const FilterBlockBuilder&); + void operator=(const FilterBlockBuilder&); +}; + +class FilterBlockReader { + public: + // REQUIRES: "contents" and *policy must stay live while *this is live. + FilterBlockReader(const FilterPolicy* policy, const Slice& contents); + bool KeyMayMatch(uint64_t block_offset, const Slice& key); + + private: + const FilterPolicy* policy_; + const char* data_; // Pointer to filter data (at block-start) + const char* offset_; // Pointer to beginning of offset array (at block-end) + size_t num_; // Number of entries in offset array + size_t base_lg_; // Encoding parameter (see kFilterBaseLg in .cc file) +}; + +} + +#endif // STORAGE_LEVELDB_TABLE_FILTER_BLOCK_H_ diff --git a/src/leveldb/table/filter_block_test.cc b/src/leveldb/table/filter_block_test.cc new file mode 100644 index 0000000..8c4a474 --- /dev/null +++ b/src/leveldb/table/filter_block_test.cc @@ -0,0 +1,128 @@ +// Copyright (c) 2012 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "table/filter_block.h" + +#include "leveldb/filter_policy.h" +#include "util/coding.h" +#include "util/hash.h" +#include "util/logging.h" +#include "util/testharness.h" +#include "util/testutil.h" + +namespace leveldb { + +// For testing: emit an array with one hash value per key +class TestHashFilter : public FilterPolicy { + public: + virtual const char* Name() const { + return "TestHashFilter"; + } + + virtual void CreateFilter(const Slice* keys, int n, std::string* dst) const { + for (int i = 0; i < n; i++) { + uint32_t h = Hash(keys[i].data(), keys[i].size(), 1); + PutFixed32(dst, h); + } + } + + virtual bool KeyMayMatch(const Slice& key, const Slice& filter) const { + uint32_t h = Hash(key.data(), key.size(), 1); + for (size_t i = 0; i + 4 <= filter.size(); i += 4) { + if (h == DecodeFixed32(filter.data() + i)) { + return true; + } + } + return false; + } +}; + +class FilterBlockTest { + public: + TestHashFilter policy_; +}; + +TEST(FilterBlockTest, EmptyBuilder) { + FilterBlockBuilder builder(&policy_); + Slice block = builder.Finish(); + ASSERT_EQ("\\x00\\x00\\x00\\x00\\x0b", EscapeString(block)); + FilterBlockReader reader(&policy_, block); + ASSERT_TRUE(reader.KeyMayMatch(0, "foo")); + ASSERT_TRUE(reader.KeyMayMatch(100000, "foo")); +} + +TEST(FilterBlockTest, SingleChunk) { + FilterBlockBuilder builder(&policy_); + builder.StartBlock(100); + builder.AddKey("foo"); + builder.AddKey("bar"); + builder.AddKey("box"); + builder.StartBlock(200); + builder.AddKey("box"); + builder.StartBlock(300); + builder.AddKey("hello"); + Slice block = builder.Finish(); + FilterBlockReader reader(&policy_, block); + ASSERT_TRUE(reader.KeyMayMatch(100, "foo")); + ASSERT_TRUE(reader.KeyMayMatch(100, "bar")); + ASSERT_TRUE(reader.KeyMayMatch(100, "box")); + ASSERT_TRUE(reader.KeyMayMatch(100, "hello")); + ASSERT_TRUE(reader.KeyMayMatch(100, "foo")); + ASSERT_TRUE(! reader.KeyMayMatch(100, "missing")); + ASSERT_TRUE(! reader.KeyMayMatch(100, "other")); +} + +TEST(FilterBlockTest, MultiChunk) { + FilterBlockBuilder builder(&policy_); + + // First filter + builder.StartBlock(0); + builder.AddKey("foo"); + builder.StartBlock(2000); + builder.AddKey("bar"); + + // Second filter + builder.StartBlock(3100); + builder.AddKey("box"); + + // Third filter is empty + + // Last filter + builder.StartBlock(9000); + builder.AddKey("box"); + builder.AddKey("hello"); + + Slice block = builder.Finish(); + FilterBlockReader reader(&policy_, block); + + // Check first filter + ASSERT_TRUE(reader.KeyMayMatch(0, "foo")); + ASSERT_TRUE(reader.KeyMayMatch(2000, "bar")); + ASSERT_TRUE(! reader.KeyMayMatch(0, "box")); + ASSERT_TRUE(! reader.KeyMayMatch(0, "hello")); + + // Check second filter + ASSERT_TRUE(reader.KeyMayMatch(3100, "box")); + ASSERT_TRUE(! reader.KeyMayMatch(3100, "foo")); + ASSERT_TRUE(! reader.KeyMayMatch(3100, "bar")); + ASSERT_TRUE(! reader.KeyMayMatch(3100, "hello")); + + // Check third filter (empty) + ASSERT_TRUE(! reader.KeyMayMatch(4100, "foo")); + ASSERT_TRUE(! reader.KeyMayMatch(4100, "bar")); + ASSERT_TRUE(! reader.KeyMayMatch(4100, "box")); + ASSERT_TRUE(! reader.KeyMayMatch(4100, "hello")); + + // Check last filter + ASSERT_TRUE(reader.KeyMayMatch(9000, "box")); + ASSERT_TRUE(reader.KeyMayMatch(9000, "hello")); + ASSERT_TRUE(! reader.KeyMayMatch(9000, "foo")); + ASSERT_TRUE(! reader.KeyMayMatch(9000, "bar")); +} + +} // namespace leveldb + +int main(int argc, char** argv) { + return leveldb::test::RunAllTests(); +} diff --git a/src/leveldb/table/format.cc b/src/leveldb/table/format.cc new file mode 100644 index 0000000..cda1dec --- /dev/null +++ b/src/leveldb/table/format.cc @@ -0,0 +1,145 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "table/format.h" + +#include "leveldb/env.h" +#include "port/port.h" +#include "table/block.h" +#include "util/coding.h" +#include "util/crc32c.h" + +namespace leveldb { + +void BlockHandle::EncodeTo(std::string* dst) const { + // Sanity check that all fields have been set + assert(offset_ != ~static_cast(0)); + assert(size_ != ~static_cast(0)); + PutVarint64(dst, offset_); + PutVarint64(dst, size_); +} + +Status BlockHandle::DecodeFrom(Slice* input) { + if (GetVarint64(input, &offset_) && + GetVarint64(input, &size_)) { + return Status::OK(); + } else { + return Status::Corruption("bad block handle"); + } +} + +void Footer::EncodeTo(std::string* dst) const { +#ifndef NDEBUG + const size_t original_size = dst->size(); +#endif + metaindex_handle_.EncodeTo(dst); + index_handle_.EncodeTo(dst); + dst->resize(2 * BlockHandle::kMaxEncodedLength); // Padding + PutFixed32(dst, static_cast(kTableMagicNumber & 0xffffffffu)); + PutFixed32(dst, static_cast(kTableMagicNumber >> 32)); + assert(dst->size() == original_size + kEncodedLength); +} + +Status Footer::DecodeFrom(Slice* input) { + const char* magic_ptr = input->data() + kEncodedLength - 8; + const uint32_t magic_lo = DecodeFixed32(magic_ptr); + const uint32_t magic_hi = DecodeFixed32(magic_ptr + 4); + const uint64_t magic = ((static_cast(magic_hi) << 32) | + (static_cast(magic_lo))); + if (magic != kTableMagicNumber) { + return Status::InvalidArgument("not an sstable (bad magic number)"); + } + + Status result = metaindex_handle_.DecodeFrom(input); + if (result.ok()) { + result = index_handle_.DecodeFrom(input); + } + if (result.ok()) { + // We skip over any leftover data (just padding for now) in "input" + const char* end = magic_ptr + 8; + *input = Slice(end, input->data() + input->size() - end); + } + return result; +} + +Status ReadBlock(RandomAccessFile* file, + const ReadOptions& options, + const BlockHandle& handle, + BlockContents* result) { + result->data = Slice(); + result->cachable = false; + result->heap_allocated = false; + + // Read the block contents as well as the type/crc footer. + // See table_builder.cc for the code that built this structure. + size_t n = static_cast(handle.size()); + char* buf = new char[n + kBlockTrailerSize]; + Slice contents; + Status s = file->Read(handle.offset(), n + kBlockTrailerSize, &contents, buf); + if (!s.ok()) { + delete[] buf; + return s; + } + if (contents.size() != n + kBlockTrailerSize) { + delete[] buf; + return Status::Corruption("truncated block read"); + } + + // Check the crc of the type and the block contents + const char* data = contents.data(); // Pointer to where Read put the data + if (options.verify_checksums) { + const uint32_t crc = crc32c::Unmask(DecodeFixed32(data + n + 1)); + const uint32_t actual = crc32c::Value(data, n + 1); + if (actual != crc) { + delete[] buf; + s = Status::Corruption("block checksum mismatch"); + return s; + } + } + + switch (data[n]) { + case kNoCompression: + if (data != buf) { + // File implementation gave us pointer to some other data. + // Use it directly under the assumption that it will be live + // while the file is open. + delete[] buf; + result->data = Slice(data, n); + result->heap_allocated = false; + result->cachable = false; // Do not double-cache + } else { + result->data = Slice(buf, n); + result->heap_allocated = true; + result->cachable = true; + } + + // Ok + break; + case kSnappyCompression: { + size_t ulength = 0; + if (!port::Snappy_GetUncompressedLength(data, n, &ulength)) { + delete[] buf; + return Status::Corruption("corrupted compressed block contents"); + } + char* ubuf = new char[ulength]; + if (!port::Snappy_Uncompress(data, n, ubuf)) { + delete[] buf; + delete[] ubuf; + return Status::Corruption("corrupted compressed block contents"); + } + delete[] buf; + result->data = Slice(ubuf, ulength); + result->heap_allocated = true; + result->cachable = true; + break; + } + default: + delete[] buf; + return Status::Corruption("bad block type"); + } + + return Status::OK(); +} + +} // namespace leveldb diff --git a/src/leveldb/table/format.h b/src/leveldb/table/format.h new file mode 100644 index 0000000..6c0b80c --- /dev/null +++ b/src/leveldb/table/format.h @@ -0,0 +1,108 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#ifndef STORAGE_LEVELDB_TABLE_FORMAT_H_ +#define STORAGE_LEVELDB_TABLE_FORMAT_H_ + +#include +#include +#include "leveldb/slice.h" +#include "leveldb/status.h" +#include "leveldb/table_builder.h" + +namespace leveldb { + +class Block; +class RandomAccessFile; +struct ReadOptions; + +// BlockHandle is a pointer to the extent of a file that stores a data +// block or a meta block. +class BlockHandle { + public: + BlockHandle(); + + // The offset of the block in the file. + uint64_t offset() const { return offset_; } + void set_offset(uint64_t offset) { offset_ = offset; } + + // The size of the stored block + uint64_t size() const { return size_; } + void set_size(uint64_t size) { size_ = size; } + + void EncodeTo(std::string* dst) const; + Status DecodeFrom(Slice* input); + + // Maximum encoding length of a BlockHandle + enum { kMaxEncodedLength = 10 + 10 }; + + private: + uint64_t offset_; + uint64_t size_; +}; + +// Footer encapsulates the fixed information stored at the tail +// end of every table file. +class Footer { + public: + Footer() { } + + // The block handle for the metaindex block of the table + const BlockHandle& metaindex_handle() const { return metaindex_handle_; } + void set_metaindex_handle(const BlockHandle& h) { metaindex_handle_ = h; } + + // The block handle for the index block of the table + const BlockHandle& index_handle() const { + return index_handle_; + } + void set_index_handle(const BlockHandle& h) { + index_handle_ = h; + } + + void EncodeTo(std::string* dst) const; + Status DecodeFrom(Slice* input); + + // Encoded length of a Footer. Note that the serialization of a + // Footer will always occupy exactly this many bytes. It consists + // of two block handles and a magic number. + enum { + kEncodedLength = 2*BlockHandle::kMaxEncodedLength + 8 + }; + + private: + BlockHandle metaindex_handle_; + BlockHandle index_handle_; +}; + +// kTableMagicNumber was picked by running +// echo http://code.google.com/p/leveldb/ | sha1sum +// and taking the leading 64 bits. +static const uint64_t kTableMagicNumber = 0xdb4775248b80fb57ull; + +// 1-byte type + 32-bit crc +static const size_t kBlockTrailerSize = 5; + +struct BlockContents { + Slice data; // Actual contents of data + bool cachable; // True iff data can be cached + bool heap_allocated; // True iff caller should delete[] data.data() +}; + +// Read the block identified by "handle" from "file". On failure +// return non-OK. On success fill *result and return OK. +extern Status ReadBlock(RandomAccessFile* file, + const ReadOptions& options, + const BlockHandle& handle, + BlockContents* result); + +// Implementation details follow. Clients should ignore, + +inline BlockHandle::BlockHandle() + : offset_(~static_cast(0)), + size_(~static_cast(0)) { +} + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_TABLE_FORMAT_H_ diff --git a/src/leveldb/table/iterator.cc b/src/leveldb/table/iterator.cc new file mode 100644 index 0000000..3d1c87f --- /dev/null +++ b/src/leveldb/table/iterator.cc @@ -0,0 +1,67 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "leveldb/iterator.h" + +namespace leveldb { + +Iterator::Iterator() { + cleanup_.function = NULL; + cleanup_.next = NULL; +} + +Iterator::~Iterator() { + if (cleanup_.function != NULL) { + (*cleanup_.function)(cleanup_.arg1, cleanup_.arg2); + for (Cleanup* c = cleanup_.next; c != NULL; ) { + (*c->function)(c->arg1, c->arg2); + Cleanup* next = c->next; + delete c; + c = next; + } + } +} + +void Iterator::RegisterCleanup(CleanupFunction func, void* arg1, void* arg2) { + assert(func != NULL); + Cleanup* c; + if (cleanup_.function == NULL) { + c = &cleanup_; + } else { + c = new Cleanup; + c->next = cleanup_.next; + cleanup_.next = c; + } + c->function = func; + c->arg1 = arg1; + c->arg2 = arg2; +} + +namespace { +class EmptyIterator : public Iterator { + public: + EmptyIterator(const Status& s) : status_(s) { } + virtual bool Valid() const { return false; } + virtual void Seek(const Slice& target) { } + virtual void SeekToFirst() { } + virtual void SeekToLast() { } + virtual void Next() { assert(false); } + virtual void Prev() { assert(false); } + Slice key() const { assert(false); return Slice(); } + Slice value() const { assert(false); return Slice(); } + virtual Status status() const { return status_; } + private: + Status status_; +}; +} // namespace + +Iterator* NewEmptyIterator() { + return new EmptyIterator(Status::OK()); +} + +Iterator* NewErrorIterator(const Status& status) { + return new EmptyIterator(status); +} + +} // namespace leveldb diff --git a/src/leveldb/table/iterator_wrapper.h b/src/leveldb/table/iterator_wrapper.h new file mode 100644 index 0000000..9e16b3d --- /dev/null +++ b/src/leveldb/table/iterator_wrapper.h @@ -0,0 +1,63 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#ifndef STORAGE_LEVELDB_TABLE_ITERATOR_WRAPPER_H_ +#define STORAGE_LEVELDB_TABLE_ITERATOR_WRAPPER_H_ + +namespace leveldb { + +// A internal wrapper class with an interface similar to Iterator that +// caches the valid() and key() results for an underlying iterator. +// This can help avoid virtual function calls and also gives better +// cache locality. +class IteratorWrapper { + public: + IteratorWrapper(): iter_(NULL), valid_(false) { } + explicit IteratorWrapper(Iterator* iter): iter_(NULL) { + Set(iter); + } + ~IteratorWrapper() { delete iter_; } + Iterator* iter() const { return iter_; } + + // Takes ownership of "iter" and will delete it when destroyed, or + // when Set() is invoked again. + void Set(Iterator* iter) { + delete iter_; + iter_ = iter; + if (iter_ == NULL) { + valid_ = false; + } else { + Update(); + } + } + + + // Iterator interface methods + bool Valid() const { return valid_; } + Slice key() const { assert(Valid()); return key_; } + Slice value() const { assert(Valid()); return iter_->value(); } + // Methods below require iter() != NULL + Status status() const { assert(iter_); return iter_->status(); } + void Next() { assert(iter_); iter_->Next(); Update(); } + void Prev() { assert(iter_); iter_->Prev(); Update(); } + void Seek(const Slice& k) { assert(iter_); iter_->Seek(k); Update(); } + void SeekToFirst() { assert(iter_); iter_->SeekToFirst(); Update(); } + void SeekToLast() { assert(iter_); iter_->SeekToLast(); Update(); } + + private: + void Update() { + valid_ = iter_->Valid(); + if (valid_) { + key_ = iter_->key(); + } + } + + Iterator* iter_; + bool valid_; + Slice key_; +}; + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_TABLE_ITERATOR_WRAPPER_H_ diff --git a/src/leveldb/table/merger.cc b/src/leveldb/table/merger.cc new file mode 100644 index 0000000..2dde4dc --- /dev/null +++ b/src/leveldb/table/merger.cc @@ -0,0 +1,197 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "table/merger.h" + +#include "leveldb/comparator.h" +#include "leveldb/iterator.h" +#include "table/iterator_wrapper.h" + +namespace leveldb { + +namespace { +class MergingIterator : public Iterator { + public: + MergingIterator(const Comparator* comparator, Iterator** children, int n) + : comparator_(comparator), + children_(new IteratorWrapper[n]), + n_(n), + current_(NULL), + direction_(kForward) { + for (int i = 0; i < n; i++) { + children_[i].Set(children[i]); + } + } + + virtual ~MergingIterator() { + delete[] children_; + } + + virtual bool Valid() const { + return (current_ != NULL); + } + + virtual void SeekToFirst() { + for (int i = 0; i < n_; i++) { + children_[i].SeekToFirst(); + } + FindSmallest(); + direction_ = kForward; + } + + virtual void SeekToLast() { + for (int i = 0; i < n_; i++) { + children_[i].SeekToLast(); + } + FindLargest(); + direction_ = kReverse; + } + + virtual void Seek(const Slice& target) { + for (int i = 0; i < n_; i++) { + children_[i].Seek(target); + } + FindSmallest(); + direction_ = kForward; + } + + virtual void Next() { + assert(Valid()); + + // Ensure that all children are positioned after key(). + // If we are moving in the forward direction, it is already + // true for all of the non-current_ children since current_ is + // the smallest child and key() == current_->key(). Otherwise, + // we explicitly position the non-current_ children. + if (direction_ != kForward) { + for (int i = 0; i < n_; i++) { + IteratorWrapper* child = &children_[i]; + if (child != current_) { + child->Seek(key()); + if (child->Valid() && + comparator_->Compare(key(), child->key()) == 0) { + child->Next(); + } + } + } + direction_ = kForward; + } + + current_->Next(); + FindSmallest(); + } + + virtual void Prev() { + assert(Valid()); + + // Ensure that all children are positioned before key(). + // If we are moving in the reverse direction, it is already + // true for all of the non-current_ children since current_ is + // the largest child and key() == current_->key(). Otherwise, + // we explicitly position the non-current_ children. + if (direction_ != kReverse) { + for (int i = 0; i < n_; i++) { + IteratorWrapper* child = &children_[i]; + if (child != current_) { + child->Seek(key()); + if (child->Valid()) { + // Child is at first entry >= key(). Step back one to be < key() + child->Prev(); + } else { + // Child has no entries >= key(). Position at last entry. + child->SeekToLast(); + } + } + } + direction_ = kReverse; + } + + current_->Prev(); + FindLargest(); + } + + virtual Slice key() const { + assert(Valid()); + return current_->key(); + } + + virtual Slice value() const { + assert(Valid()); + return current_->value(); + } + + virtual Status status() const { + Status status; + for (int i = 0; i < n_; i++) { + status = children_[i].status(); + if (!status.ok()) { + break; + } + } + return status; + } + + private: + void FindSmallest(); + void FindLargest(); + + // We might want to use a heap in case there are lots of children. + // For now we use a simple array since we expect a very small number + // of children in leveldb. + const Comparator* comparator_; + IteratorWrapper* children_; + int n_; + IteratorWrapper* current_; + + // Which direction is the iterator moving? + enum Direction { + kForward, + kReverse + }; + Direction direction_; +}; + +void MergingIterator::FindSmallest() { + IteratorWrapper* smallest = NULL; + for (int i = 0; i < n_; i++) { + IteratorWrapper* child = &children_[i]; + if (child->Valid()) { + if (smallest == NULL) { + smallest = child; + } else if (comparator_->Compare(child->key(), smallest->key()) < 0) { + smallest = child; + } + } + } + current_ = smallest; +} + +void MergingIterator::FindLargest() { + IteratorWrapper* largest = NULL; + for (int i = n_-1; i >= 0; i--) { + IteratorWrapper* child = &children_[i]; + if (child->Valid()) { + if (largest == NULL) { + largest = child; + } else if (comparator_->Compare(child->key(), largest->key()) > 0) { + largest = child; + } + } + } + current_ = largest; +} +} // namespace + +Iterator* NewMergingIterator(const Comparator* cmp, Iterator** list, int n) { + assert(n >= 0); + if (n == 0) { + return NewEmptyIterator(); + } else if (n == 1) { + return list[0]; + } else { + return new MergingIterator(cmp, list, n); + } +} + +} // namespace leveldb diff --git a/src/leveldb/table/merger.h b/src/leveldb/table/merger.h new file mode 100644 index 0000000..91ddd80 --- /dev/null +++ b/src/leveldb/table/merger.h @@ -0,0 +1,26 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#ifndef STORAGE_LEVELDB_TABLE_MERGER_H_ +#define STORAGE_LEVELDB_TABLE_MERGER_H_ + +namespace leveldb { + +class Comparator; +class Iterator; + +// Return an iterator that provided the union of the data in +// children[0,n-1]. Takes ownership of the child iterators and +// will delete them when the result iterator is deleted. +// +// The result does no duplicate suppression. I.e., if a particular +// key is present in K child iterators, it will be yielded K times. +// +// REQUIRES: n >= 0 +extern Iterator* NewMergingIterator( + const Comparator* comparator, Iterator** children, int n); + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_TABLE_MERGER_H_ diff --git a/src/leveldb/table/table.cc b/src/leveldb/table/table.cc new file mode 100644 index 0000000..71c1756 --- /dev/null +++ b/src/leveldb/table/table.cc @@ -0,0 +1,275 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "leveldb/table.h" + +#include "leveldb/cache.h" +#include "leveldb/comparator.h" +#include "leveldb/env.h" +#include "leveldb/filter_policy.h" +#include "leveldb/options.h" +#include "table/block.h" +#include "table/filter_block.h" +#include "table/format.h" +#include "table/two_level_iterator.h" +#include "util/coding.h" + +namespace leveldb { + +struct Table::Rep { + ~Rep() { + delete filter; + delete [] filter_data; + delete index_block; + } + + Options options; + Status status; + RandomAccessFile* file; + uint64_t cache_id; + FilterBlockReader* filter; + const char* filter_data; + + BlockHandle metaindex_handle; // Handle to metaindex_block: saved from footer + Block* index_block; +}; + +Status Table::Open(const Options& options, + RandomAccessFile* file, + uint64_t size, + Table** table) { + *table = NULL; + if (size < Footer::kEncodedLength) { + return Status::InvalidArgument("file is too short to be an sstable"); + } + + char footer_space[Footer::kEncodedLength]; + Slice footer_input; + Status s = file->Read(size - Footer::kEncodedLength, Footer::kEncodedLength, + &footer_input, footer_space); + if (!s.ok()) return s; + + Footer footer; + s = footer.DecodeFrom(&footer_input); + if (!s.ok()) return s; + + // Read the index block + BlockContents contents; + Block* index_block = NULL; + if (s.ok()) { + s = ReadBlock(file, ReadOptions(), footer.index_handle(), &contents); + if (s.ok()) { + index_block = new Block(contents); + } + } + + if (s.ok()) { + // We've successfully read the footer and the index block: we're + // ready to serve requests. + Rep* rep = new Table::Rep; + rep->options = options; + rep->file = file; + rep->metaindex_handle = footer.metaindex_handle(); + rep->index_block = index_block; + rep->cache_id = (options.block_cache ? options.block_cache->NewId() : 0); + rep->filter_data = NULL; + rep->filter = NULL; + *table = new Table(rep); + (*table)->ReadMeta(footer); + } else { + if (index_block) delete index_block; + } + + return s; +} + +void Table::ReadMeta(const Footer& footer) { + if (rep_->options.filter_policy == NULL) { + return; // Do not need any metadata + } + + // TODO(sanjay): Skip this if footer.metaindex_handle() size indicates + // it is an empty block. + ReadOptions opt; + BlockContents contents; + if (!ReadBlock(rep_->file, opt, footer.metaindex_handle(), &contents).ok()) { + // Do not propagate errors since meta info is not needed for operation + return; + } + Block* meta = new Block(contents); + + Iterator* iter = meta->NewIterator(BytewiseComparator()); + std::string key = "filter."; + key.append(rep_->options.filter_policy->Name()); + iter->Seek(key); + if (iter->Valid() && iter->key() == Slice(key)) { + ReadFilter(iter->value()); + } + delete iter; + delete meta; +} + +void Table::ReadFilter(const Slice& filter_handle_value) { + Slice v = filter_handle_value; + BlockHandle filter_handle; + if (!filter_handle.DecodeFrom(&v).ok()) { + return; + } + + // We might want to unify with ReadBlock() if we start + // requiring checksum verification in Table::Open. + ReadOptions opt; + BlockContents block; + if (!ReadBlock(rep_->file, opt, filter_handle, &block).ok()) { + return; + } + if (block.heap_allocated) { + rep_->filter_data = block.data.data(); // Will need to delete later + } + rep_->filter = new FilterBlockReader(rep_->options.filter_policy, block.data); +} + +Table::~Table() { + delete rep_; +} + +static void DeleteBlock(void* arg, void* ignored) { + delete reinterpret_cast(arg); +} + +static void DeleteCachedBlock(const Slice& key, void* value) { + Block* block = reinterpret_cast(value); + delete block; +} + +static void ReleaseBlock(void* arg, void* h) { + Cache* cache = reinterpret_cast(arg); + Cache::Handle* handle = reinterpret_cast(h); + cache->Release(handle); +} + +// Convert an index iterator value (i.e., an encoded BlockHandle) +// into an iterator over the contents of the corresponding block. +Iterator* Table::BlockReader(void* arg, + const ReadOptions& options, + const Slice& index_value) { + Table* table = reinterpret_cast(arg); + Cache* block_cache = table->rep_->options.block_cache; + Block* block = NULL; + Cache::Handle* cache_handle = NULL; + + BlockHandle handle; + Slice input = index_value; + Status s = handle.DecodeFrom(&input); + // We intentionally allow extra stuff in index_value so that we + // can add more features in the future. + + if (s.ok()) { + BlockContents contents; + if (block_cache != NULL) { + char cache_key_buffer[16]; + EncodeFixed64(cache_key_buffer, table->rep_->cache_id); + EncodeFixed64(cache_key_buffer+8, handle.offset()); + Slice key(cache_key_buffer, sizeof(cache_key_buffer)); + cache_handle = block_cache->Lookup(key); + if (cache_handle != NULL) { + block = reinterpret_cast(block_cache->Value(cache_handle)); + } else { + s = ReadBlock(table->rep_->file, options, handle, &contents); + if (s.ok()) { + block = new Block(contents); + if (contents.cachable && options.fill_cache) { + cache_handle = block_cache->Insert( + key, block, block->size(), &DeleteCachedBlock); + } + } + } + } else { + s = ReadBlock(table->rep_->file, options, handle, &contents); + if (s.ok()) { + block = new Block(contents); + } + } + } + + Iterator* iter; + if (block != NULL) { + iter = block->NewIterator(table->rep_->options.comparator); + if (cache_handle == NULL) { + iter->RegisterCleanup(&DeleteBlock, block, NULL); + } else { + iter->RegisterCleanup(&ReleaseBlock, block_cache, cache_handle); + } + } else { + iter = NewErrorIterator(s); + } + return iter; +} + +Iterator* Table::NewIterator(const ReadOptions& options) const { + return NewTwoLevelIterator( + rep_->index_block->NewIterator(rep_->options.comparator), + &Table::BlockReader, const_cast(this), options); +} + +Status Table::InternalGet(const ReadOptions& options, const Slice& k, + void* arg, + void (*saver)(void*, const Slice&, const Slice&)) { + Status s; + Iterator* iiter = rep_->index_block->NewIterator(rep_->options.comparator); + iiter->Seek(k); + if (iiter->Valid()) { + Slice handle_value = iiter->value(); + FilterBlockReader* filter = rep_->filter; + BlockHandle handle; + if (filter != NULL && + handle.DecodeFrom(&handle_value).ok() && + !filter->KeyMayMatch(handle.offset(), k)) { + // Not found + } else { + Iterator* block_iter = BlockReader(this, options, iiter->value()); + block_iter->Seek(k); + if (block_iter->Valid()) { + (*saver)(arg, block_iter->key(), block_iter->value()); + } + s = block_iter->status(); + delete block_iter; + } + } + if (s.ok()) { + s = iiter->status(); + } + delete iiter; + return s; +} + + +uint64_t Table::ApproximateOffsetOf(const Slice& key) const { + Iterator* index_iter = + rep_->index_block->NewIterator(rep_->options.comparator); + index_iter->Seek(key); + uint64_t result; + if (index_iter->Valid()) { + BlockHandle handle; + Slice input = index_iter->value(); + Status s = handle.DecodeFrom(&input); + if (s.ok()) { + result = handle.offset(); + } else { + // Strange: we can't decode the block handle in the index block. + // We'll just return the offset of the metaindex block, which is + // close to the whole file size for this case. + result = rep_->metaindex_handle.offset(); + } + } else { + // key is past the last key in the file. Approximate the offset + // by returning the offset of the metaindex block (which is + // right near the end of the file). + result = rep_->metaindex_handle.offset(); + } + delete index_iter; + return result; +} + +} // namespace leveldb diff --git a/src/leveldb/table/table_builder.cc b/src/leveldb/table/table_builder.cc new file mode 100644 index 0000000..62002c8 --- /dev/null +++ b/src/leveldb/table/table_builder.cc @@ -0,0 +1,270 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "leveldb/table_builder.h" + +#include +#include "leveldb/comparator.h" +#include "leveldb/env.h" +#include "leveldb/filter_policy.h" +#include "leveldb/options.h" +#include "table/block_builder.h" +#include "table/filter_block.h" +#include "table/format.h" +#include "util/coding.h" +#include "util/crc32c.h" + +namespace leveldb { + +struct TableBuilder::Rep { + Options options; + Options index_block_options; + WritableFile* file; + uint64_t offset; + Status status; + BlockBuilder data_block; + BlockBuilder index_block; + std::string last_key; + int64_t num_entries; + bool closed; // Either Finish() or Abandon() has been called. + FilterBlockBuilder* filter_block; + + // We do not emit the index entry for a block until we have seen the + // first key for the next data block. This allows us to use shorter + // keys in the index block. For example, consider a block boundary + // between the keys "the quick brown fox" and "the who". We can use + // "the r" as the key for the index block entry since it is >= all + // entries in the first block and < all entries in subsequent + // blocks. + // + // Invariant: r->pending_index_entry is true only if data_block is empty. + bool pending_index_entry; + BlockHandle pending_handle; // Handle to add to index block + + std::string compressed_output; + + Rep(const Options& opt, WritableFile* f) + : options(opt), + index_block_options(opt), + file(f), + offset(0), + data_block(&options), + index_block(&index_block_options), + num_entries(0), + closed(false), + filter_block(opt.filter_policy == NULL ? NULL + : new FilterBlockBuilder(opt.filter_policy)), + pending_index_entry(false) { + index_block_options.block_restart_interval = 1; + } +}; + +TableBuilder::TableBuilder(const Options& options, WritableFile* file) + : rep_(new Rep(options, file)) { + if (rep_->filter_block != NULL) { + rep_->filter_block->StartBlock(0); + } +} + +TableBuilder::~TableBuilder() { + assert(rep_->closed); // Catch errors where caller forgot to call Finish() + delete rep_->filter_block; + delete rep_; +} + +Status TableBuilder::ChangeOptions(const Options& options) { + // Note: if more fields are added to Options, update + // this function to catch changes that should not be allowed to + // change in the middle of building a Table. + if (options.comparator != rep_->options.comparator) { + return Status::InvalidArgument("changing comparator while building table"); + } + + // Note that any live BlockBuilders point to rep_->options and therefore + // will automatically pick up the updated options. + rep_->options = options; + rep_->index_block_options = options; + rep_->index_block_options.block_restart_interval = 1; + return Status::OK(); +} + +void TableBuilder::Add(const Slice& key, const Slice& value) { + Rep* r = rep_; + assert(!r->closed); + if (!ok()) return; + if (r->num_entries > 0) { + assert(r->options.comparator->Compare(key, Slice(r->last_key)) > 0); + } + + if (r->pending_index_entry) { + assert(r->data_block.empty()); + r->options.comparator->FindShortestSeparator(&r->last_key, key); + std::string handle_encoding; + r->pending_handle.EncodeTo(&handle_encoding); + r->index_block.Add(r->last_key, Slice(handle_encoding)); + r->pending_index_entry = false; + } + + if (r->filter_block != NULL) { + r->filter_block->AddKey(key); + } + + r->last_key.assign(key.data(), key.size()); + r->num_entries++; + r->data_block.Add(key, value); + + const size_t estimated_block_size = r->data_block.CurrentSizeEstimate(); + if (estimated_block_size >= r->options.block_size) { + Flush(); + } +} + +void TableBuilder::Flush() { + Rep* r = rep_; + assert(!r->closed); + if (!ok()) return; + if (r->data_block.empty()) return; + assert(!r->pending_index_entry); + WriteBlock(&r->data_block, &r->pending_handle); + if (ok()) { + r->pending_index_entry = true; + r->status = r->file->Flush(); + } + if (r->filter_block != NULL) { + r->filter_block->StartBlock(r->offset); + } +} + +void TableBuilder::WriteBlock(BlockBuilder* block, BlockHandle* handle) { + // File format contains a sequence of blocks where each block has: + // block_data: uint8[n] + // type: uint8 + // crc: uint32 + assert(ok()); + Rep* r = rep_; + Slice raw = block->Finish(); + + Slice block_contents; + CompressionType type = r->options.compression; + // TODO(postrelease): Support more compression options: zlib? + switch (type) { + case kNoCompression: + block_contents = raw; + break; + + case kSnappyCompression: { + std::string* compressed = &r->compressed_output; + if (port::Snappy_Compress(raw.data(), raw.size(), compressed) && + compressed->size() < raw.size() - (raw.size() / 8u)) { + block_contents = *compressed; + } else { + // Snappy not supported, or compressed less than 12.5%, so just + // store uncompressed form + block_contents = raw; + type = kNoCompression; + } + break; + } + } + WriteRawBlock(block_contents, type, handle); + r->compressed_output.clear(); + block->Reset(); +} + +void TableBuilder::WriteRawBlock(const Slice& block_contents, + CompressionType type, + BlockHandle* handle) { + Rep* r = rep_; + handle->set_offset(r->offset); + handle->set_size(block_contents.size()); + r->status = r->file->Append(block_contents); + if (r->status.ok()) { + char trailer[kBlockTrailerSize]; + trailer[0] = type; + uint32_t crc = crc32c::Value(block_contents.data(), block_contents.size()); + crc = crc32c::Extend(crc, trailer, 1); // Extend crc to cover block type + EncodeFixed32(trailer+1, crc32c::Mask(crc)); + r->status = r->file->Append(Slice(trailer, kBlockTrailerSize)); + if (r->status.ok()) { + r->offset += block_contents.size() + kBlockTrailerSize; + } + } +} + +Status TableBuilder::status() const { + return rep_->status; +} + +Status TableBuilder::Finish() { + Rep* r = rep_; + Flush(); + assert(!r->closed); + r->closed = true; + + BlockHandle filter_block_handle, metaindex_block_handle, index_block_handle; + + // Write filter block + if (ok() && r->filter_block != NULL) { + WriteRawBlock(r->filter_block->Finish(), kNoCompression, + &filter_block_handle); + } + + // Write metaindex block + if (ok()) { + BlockBuilder meta_index_block(&r->options); + if (r->filter_block != NULL) { + // Add mapping from "filter.Name" to location of filter data + std::string key = "filter."; + key.append(r->options.filter_policy->Name()); + std::string handle_encoding; + filter_block_handle.EncodeTo(&handle_encoding); + meta_index_block.Add(key, handle_encoding); + } + + // TODO(postrelease): Add stats and other meta blocks + WriteBlock(&meta_index_block, &metaindex_block_handle); + } + + // Write index block + if (ok()) { + if (r->pending_index_entry) { + r->options.comparator->FindShortSuccessor(&r->last_key); + std::string handle_encoding; + r->pending_handle.EncodeTo(&handle_encoding); + r->index_block.Add(r->last_key, Slice(handle_encoding)); + r->pending_index_entry = false; + } + WriteBlock(&r->index_block, &index_block_handle); + } + + // Write footer + if (ok()) { + Footer footer; + footer.set_metaindex_handle(metaindex_block_handle); + footer.set_index_handle(index_block_handle); + std::string footer_encoding; + footer.EncodeTo(&footer_encoding); + r->status = r->file->Append(footer_encoding); + if (r->status.ok()) { + r->offset += footer_encoding.size(); + } + } + return r->status; +} + +void TableBuilder::Abandon() { + Rep* r = rep_; + assert(!r->closed); + r->closed = true; +} + +uint64_t TableBuilder::NumEntries() const { + return rep_->num_entries; +} + +uint64_t TableBuilder::FileSize() const { + return rep_->offset; +} + +} // namespace leveldb diff --git a/src/leveldb/table/table_test.cc b/src/leveldb/table/table_test.cc new file mode 100644 index 0000000..c723bf8 --- /dev/null +++ b/src/leveldb/table/table_test.cc @@ -0,0 +1,868 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "leveldb/table.h" + +#include +#include +#include "db/dbformat.h" +#include "db/memtable.h" +#include "db/write_batch_internal.h" +#include "leveldb/db.h" +#include "leveldb/env.h" +#include "leveldb/iterator.h" +#include "leveldb/table_builder.h" +#include "table/block.h" +#include "table/block_builder.h" +#include "table/format.h" +#include "util/random.h" +#include "util/testharness.h" +#include "util/testutil.h" + +namespace leveldb { + +// Return reverse of "key". +// Used to test non-lexicographic comparators. +static std::string Reverse(const Slice& key) { + std::string str(key.ToString()); + std::string rev(""); + for (std::string::reverse_iterator rit = str.rbegin(); + rit != str.rend(); ++rit) { + rev.push_back(*rit); + } + return rev; +} + +namespace { +class ReverseKeyComparator : public Comparator { + public: + virtual const char* Name() const { + return "leveldb.ReverseBytewiseComparator"; + } + + virtual int Compare(const Slice& a, const Slice& b) const { + return BytewiseComparator()->Compare(Reverse(a), Reverse(b)); + } + + virtual void FindShortestSeparator( + std::string* start, + const Slice& limit) const { + std::string s = Reverse(*start); + std::string l = Reverse(limit); + BytewiseComparator()->FindShortestSeparator(&s, l); + *start = Reverse(s); + } + + virtual void FindShortSuccessor(std::string* key) const { + std::string s = Reverse(*key); + BytewiseComparator()->FindShortSuccessor(&s); + *key = Reverse(s); + } +}; +} // namespace +static ReverseKeyComparator reverse_key_comparator; + +static void Increment(const Comparator* cmp, std::string* key) { + if (cmp == BytewiseComparator()) { + key->push_back('\0'); + } else { + assert(cmp == &reverse_key_comparator); + std::string rev = Reverse(*key); + rev.push_back('\0'); + *key = Reverse(rev); + } +} + +// An STL comparator that uses a Comparator +namespace { +struct STLLessThan { + const Comparator* cmp; + + STLLessThan() : cmp(BytewiseComparator()) { } + STLLessThan(const Comparator* c) : cmp(c) { } + bool operator()(const std::string& a, const std::string& b) const { + return cmp->Compare(Slice(a), Slice(b)) < 0; + } +}; +} // namespace + +class StringSink: public WritableFile { + public: + ~StringSink() { } + + const std::string& contents() const { return contents_; } + + virtual Status Close() { return Status::OK(); } + virtual Status Flush() { return Status::OK(); } + virtual Status Sync() { return Status::OK(); } + + virtual Status Append(const Slice& data) { + contents_.append(data.data(), data.size()); + return Status::OK(); + } + + private: + std::string contents_; +}; + + +class StringSource: public RandomAccessFile { + public: + StringSource(const Slice& contents) + : contents_(contents.data(), contents.size()) { + } + + virtual ~StringSource() { } + + uint64_t Size() const { return contents_.size(); } + + virtual Status Read(uint64_t offset, size_t n, Slice* result, + char* scratch) const { + if (offset > contents_.size()) { + return Status::InvalidArgument("invalid Read offset"); + } + if (offset + n > contents_.size()) { + n = contents_.size() - offset; + } + memcpy(scratch, &contents_[offset], n); + *result = Slice(scratch, n); + return Status::OK(); + } + + private: + std::string contents_; +}; + +typedef std::map KVMap; + +// Helper class for tests to unify the interface between +// BlockBuilder/TableBuilder and Block/Table. +class Constructor { + public: + explicit Constructor(const Comparator* cmp) : data_(STLLessThan(cmp)) { } + virtual ~Constructor() { } + + void Add(const std::string& key, const Slice& value) { + data_[key] = value.ToString(); + } + + // Finish constructing the data structure with all the keys that have + // been added so far. Returns the keys in sorted order in "*keys" + // and stores the key/value pairs in "*kvmap" + void Finish(const Options& options, + std::vector* keys, + KVMap* kvmap) { + *kvmap = data_; + keys->clear(); + for (KVMap::const_iterator it = data_.begin(); + it != data_.end(); + ++it) { + keys->push_back(it->first); + } + data_.clear(); + Status s = FinishImpl(options, *kvmap); + ASSERT_TRUE(s.ok()) << s.ToString(); + } + + // Construct the data structure from the data in "data" + virtual Status FinishImpl(const Options& options, const KVMap& data) = 0; + + virtual Iterator* NewIterator() const = 0; + + virtual const KVMap& data() { return data_; } + + virtual DB* db() const { return NULL; } // Overridden in DBConstructor + + private: + KVMap data_; +}; + +class BlockConstructor: public Constructor { + public: + explicit BlockConstructor(const Comparator* cmp) + : Constructor(cmp), + comparator_(cmp), + block_(NULL) { } + ~BlockConstructor() { + delete block_; + } + virtual Status FinishImpl(const Options& options, const KVMap& data) { + delete block_; + block_ = NULL; + BlockBuilder builder(&options); + + for (KVMap::const_iterator it = data.begin(); + it != data.end(); + ++it) { + builder.Add(it->first, it->second); + } + // Open the block + data_ = builder.Finish().ToString(); + BlockContents contents; + contents.data = data_; + contents.cachable = false; + contents.heap_allocated = false; + block_ = new Block(contents); + return Status::OK(); + } + virtual Iterator* NewIterator() const { + return block_->NewIterator(comparator_); + } + + private: + const Comparator* comparator_; + std::string data_; + Block* block_; + + BlockConstructor(); +}; + +class TableConstructor: public Constructor { + public: + TableConstructor(const Comparator* cmp) + : Constructor(cmp), + source_(NULL), table_(NULL) { + } + ~TableConstructor() { + Reset(); + } + virtual Status FinishImpl(const Options& options, const KVMap& data) { + Reset(); + StringSink sink; + TableBuilder builder(options, &sink); + + for (KVMap::const_iterator it = data.begin(); + it != data.end(); + ++it) { + builder.Add(it->first, it->second); + ASSERT_TRUE(builder.status().ok()); + } + Status s = builder.Finish(); + ASSERT_TRUE(s.ok()) << s.ToString(); + + ASSERT_EQ(sink.contents().size(), builder.FileSize()); + + // Open the table + source_ = new StringSource(sink.contents()); + Options table_options; + table_options.comparator = options.comparator; + return Table::Open(table_options, source_, sink.contents().size(), &table_); + } + + virtual Iterator* NewIterator() const { + return table_->NewIterator(ReadOptions()); + } + + uint64_t ApproximateOffsetOf(const Slice& key) const { + return table_->ApproximateOffsetOf(key); + } + + private: + void Reset() { + delete table_; + delete source_; + table_ = NULL; + source_ = NULL; + } + + StringSource* source_; + Table* table_; + + TableConstructor(); +}; + +// A helper class that converts internal format keys into user keys +class KeyConvertingIterator: public Iterator { + public: + explicit KeyConvertingIterator(Iterator* iter) : iter_(iter) { } + virtual ~KeyConvertingIterator() { delete iter_; } + virtual bool Valid() const { return iter_->Valid(); } + virtual void Seek(const Slice& target) { + ParsedInternalKey ikey(target, kMaxSequenceNumber, kTypeValue); + std::string encoded; + AppendInternalKey(&encoded, ikey); + iter_->Seek(encoded); + } + virtual void SeekToFirst() { iter_->SeekToFirst(); } + virtual void SeekToLast() { iter_->SeekToLast(); } + virtual void Next() { iter_->Next(); } + virtual void Prev() { iter_->Prev(); } + + virtual Slice key() const { + assert(Valid()); + ParsedInternalKey key; + if (!ParseInternalKey(iter_->key(), &key)) { + status_ = Status::Corruption("malformed internal key"); + return Slice("corrupted key"); + } + return key.user_key; + } + + virtual Slice value() const { return iter_->value(); } + virtual Status status() const { + return status_.ok() ? iter_->status() : status_; + } + + private: + mutable Status status_; + Iterator* iter_; + + // No copying allowed + KeyConvertingIterator(const KeyConvertingIterator&); + void operator=(const KeyConvertingIterator&); +}; + +class MemTableConstructor: public Constructor { + public: + explicit MemTableConstructor(const Comparator* cmp) + : Constructor(cmp), + internal_comparator_(cmp) { + memtable_ = new MemTable(internal_comparator_); + memtable_->Ref(); + } + ~MemTableConstructor() { + memtable_->Unref(); + } + virtual Status FinishImpl(const Options& options, const KVMap& data) { + memtable_->Unref(); + memtable_ = new MemTable(internal_comparator_); + memtable_->Ref(); + int seq = 1; + for (KVMap::const_iterator it = data.begin(); + it != data.end(); + ++it) { + memtable_->Add(seq, kTypeValue, it->first, it->second); + seq++; + } + return Status::OK(); + } + virtual Iterator* NewIterator() const { + return new KeyConvertingIterator(memtable_->NewIterator()); + } + + private: + InternalKeyComparator internal_comparator_; + MemTable* memtable_; +}; + +class DBConstructor: public Constructor { + public: + explicit DBConstructor(const Comparator* cmp) + : Constructor(cmp), + comparator_(cmp) { + db_ = NULL; + NewDB(); + } + ~DBConstructor() { + delete db_; + } + virtual Status FinishImpl(const Options& options, const KVMap& data) { + delete db_; + db_ = NULL; + NewDB(); + for (KVMap::const_iterator it = data.begin(); + it != data.end(); + ++it) { + WriteBatch batch; + batch.Put(it->first, it->second); + ASSERT_TRUE(db_->Write(WriteOptions(), &batch).ok()); + } + return Status::OK(); + } + virtual Iterator* NewIterator() const { + return db_->NewIterator(ReadOptions()); + } + + virtual DB* db() const { return db_; } + + private: + void NewDB() { + std::string name = test::TmpDir() + "/table_testdb"; + + Options options; + options.comparator = comparator_; + Status status = DestroyDB(name, options); + ASSERT_TRUE(status.ok()) << status.ToString(); + + options.create_if_missing = true; + options.error_if_exists = true; + options.write_buffer_size = 10000; // Something small to force merging + status = DB::Open(options, name, &db_); + ASSERT_TRUE(status.ok()) << status.ToString(); + } + + const Comparator* comparator_; + DB* db_; +}; + +enum TestType { + TABLE_TEST, + BLOCK_TEST, + MEMTABLE_TEST, + DB_TEST +}; + +struct TestArgs { + TestType type; + bool reverse_compare; + int restart_interval; +}; + +static const TestArgs kTestArgList[] = { + { TABLE_TEST, false, 16 }, + { TABLE_TEST, false, 1 }, + { TABLE_TEST, false, 1024 }, + { TABLE_TEST, true, 16 }, + { TABLE_TEST, true, 1 }, + { TABLE_TEST, true, 1024 }, + + { BLOCK_TEST, false, 16 }, + { BLOCK_TEST, false, 1 }, + { BLOCK_TEST, false, 1024 }, + { BLOCK_TEST, true, 16 }, + { BLOCK_TEST, true, 1 }, + { BLOCK_TEST, true, 1024 }, + + // Restart interval does not matter for memtables + { MEMTABLE_TEST, false, 16 }, + { MEMTABLE_TEST, true, 16 }, + + // Do not bother with restart interval variations for DB + { DB_TEST, false, 16 }, + { DB_TEST, true, 16 }, +}; +static const int kNumTestArgs = sizeof(kTestArgList) / sizeof(kTestArgList[0]); + +class Harness { + public: + Harness() : constructor_(NULL) { } + + void Init(const TestArgs& args) { + delete constructor_; + constructor_ = NULL; + options_ = Options(); + + options_.block_restart_interval = args.restart_interval; + // Use shorter block size for tests to exercise block boundary + // conditions more. + options_.block_size = 256; + if (args.reverse_compare) { + options_.comparator = &reverse_key_comparator; + } + switch (args.type) { + case TABLE_TEST: + constructor_ = new TableConstructor(options_.comparator); + break; + case BLOCK_TEST: + constructor_ = new BlockConstructor(options_.comparator); + break; + case MEMTABLE_TEST: + constructor_ = new MemTableConstructor(options_.comparator); + break; + case DB_TEST: + constructor_ = new DBConstructor(options_.comparator); + break; + } + } + + ~Harness() { + delete constructor_; + } + + void Add(const std::string& key, const std::string& value) { + constructor_->Add(key, value); + } + + void Test(Random* rnd) { + std::vector keys; + KVMap data; + constructor_->Finish(options_, &keys, &data); + + TestForwardScan(keys, data); + TestBackwardScan(keys, data); + TestRandomAccess(rnd, keys, data); + } + + void TestForwardScan(const std::vector& keys, + const KVMap& data) { + Iterator* iter = constructor_->NewIterator(); + ASSERT_TRUE(!iter->Valid()); + iter->SeekToFirst(); + for (KVMap::const_iterator model_iter = data.begin(); + model_iter != data.end(); + ++model_iter) { + ASSERT_EQ(ToString(data, model_iter), ToString(iter)); + iter->Next(); + } + ASSERT_TRUE(!iter->Valid()); + delete iter; + } + + void TestBackwardScan(const std::vector& keys, + const KVMap& data) { + Iterator* iter = constructor_->NewIterator(); + ASSERT_TRUE(!iter->Valid()); + iter->SeekToLast(); + for (KVMap::const_reverse_iterator model_iter = data.rbegin(); + model_iter != data.rend(); + ++model_iter) { + ASSERT_EQ(ToString(data, model_iter), ToString(iter)); + iter->Prev(); + } + ASSERT_TRUE(!iter->Valid()); + delete iter; + } + + void TestRandomAccess(Random* rnd, + const std::vector& keys, + const KVMap& data) { + static const bool kVerbose = false; + Iterator* iter = constructor_->NewIterator(); + ASSERT_TRUE(!iter->Valid()); + KVMap::const_iterator model_iter = data.begin(); + if (kVerbose) fprintf(stderr, "---\n"); + for (int i = 0; i < 200; i++) { + const int toss = rnd->Uniform(5); + switch (toss) { + case 0: { + if (iter->Valid()) { + if (kVerbose) fprintf(stderr, "Next\n"); + iter->Next(); + ++model_iter; + ASSERT_EQ(ToString(data, model_iter), ToString(iter)); + } + break; + } + + case 1: { + if (kVerbose) fprintf(stderr, "SeekToFirst\n"); + iter->SeekToFirst(); + model_iter = data.begin(); + ASSERT_EQ(ToString(data, model_iter), ToString(iter)); + break; + } + + case 2: { + std::string key = PickRandomKey(rnd, keys); + model_iter = data.lower_bound(key); + if (kVerbose) fprintf(stderr, "Seek '%s'\n", + EscapeString(key).c_str()); + iter->Seek(Slice(key)); + ASSERT_EQ(ToString(data, model_iter), ToString(iter)); + break; + } + + case 3: { + if (iter->Valid()) { + if (kVerbose) fprintf(stderr, "Prev\n"); + iter->Prev(); + if (model_iter == data.begin()) { + model_iter = data.end(); // Wrap around to invalid value + } else { + --model_iter; + } + ASSERT_EQ(ToString(data, model_iter), ToString(iter)); + } + break; + } + + case 4: { + if (kVerbose) fprintf(stderr, "SeekToLast\n"); + iter->SeekToLast(); + if (keys.empty()) { + model_iter = data.end(); + } else { + std::string last = data.rbegin()->first; + model_iter = data.lower_bound(last); + } + ASSERT_EQ(ToString(data, model_iter), ToString(iter)); + break; + } + } + } + delete iter; + } + + std::string ToString(const KVMap& data, const KVMap::const_iterator& it) { + if (it == data.end()) { + return "END"; + } else { + return "'" + it->first + "->" + it->second + "'"; + } + } + + std::string ToString(const KVMap& data, + const KVMap::const_reverse_iterator& it) { + if (it == data.rend()) { + return "END"; + } else { + return "'" + it->first + "->" + it->second + "'"; + } + } + + std::string ToString(const Iterator* it) { + if (!it->Valid()) { + return "END"; + } else { + return "'" + it->key().ToString() + "->" + it->value().ToString() + "'"; + } + } + + std::string PickRandomKey(Random* rnd, const std::vector& keys) { + if (keys.empty()) { + return "foo"; + } else { + const int index = rnd->Uniform(keys.size()); + std::string result = keys[index]; + switch (rnd->Uniform(3)) { + case 0: + // Return an existing key + break; + case 1: { + // Attempt to return something smaller than an existing key + if (result.size() > 0 && result[result.size()-1] > '\0') { + result[result.size()-1]--; + } + break; + } + case 2: { + // Return something larger than an existing key + Increment(options_.comparator, &result); + break; + } + } + return result; + } + } + + // Returns NULL if not running against a DB + DB* db() const { return constructor_->db(); } + + private: + Options options_; + Constructor* constructor_; +}; + +// Test empty table/block. +TEST(Harness, Empty) { + for (int i = 0; i < kNumTestArgs; i++) { + Init(kTestArgList[i]); + Random rnd(test::RandomSeed() + 1); + Test(&rnd); + } +} + +// Special test for a block with no restart entries. The C++ leveldb +// code never generates such blocks, but the Java version of leveldb +// seems to. +TEST(Harness, ZeroRestartPointsInBlock) { + char data[sizeof(uint32_t)]; + memset(data, 0, sizeof(data)); + BlockContents contents; + contents.data = Slice(data, sizeof(data)); + contents.cachable = false; + contents.heap_allocated = false; + Block block(contents); + Iterator* iter = block.NewIterator(BytewiseComparator()); + iter->SeekToFirst(); + ASSERT_TRUE(!iter->Valid()); + iter->SeekToLast(); + ASSERT_TRUE(!iter->Valid()); + iter->Seek("foo"); + ASSERT_TRUE(!iter->Valid()); + delete iter; +} + +// Test the empty key +TEST(Harness, SimpleEmptyKey) { + for (int i = 0; i < kNumTestArgs; i++) { + Init(kTestArgList[i]); + Random rnd(test::RandomSeed() + 1); + Add("", "v"); + Test(&rnd); + } +} + +TEST(Harness, SimpleSingle) { + for (int i = 0; i < kNumTestArgs; i++) { + Init(kTestArgList[i]); + Random rnd(test::RandomSeed() + 2); + Add("abc", "v"); + Test(&rnd); + } +} + +TEST(Harness, SimpleMulti) { + for (int i = 0; i < kNumTestArgs; i++) { + Init(kTestArgList[i]); + Random rnd(test::RandomSeed() + 3); + Add("abc", "v"); + Add("abcd", "v"); + Add("ac", "v2"); + Test(&rnd); + } +} + +TEST(Harness, SimpleSpecialKey) { + for (int i = 0; i < kNumTestArgs; i++) { + Init(kTestArgList[i]); + Random rnd(test::RandomSeed() + 4); + Add("\xff\xff", "v3"); + Test(&rnd); + } +} + +TEST(Harness, Randomized) { + for (int i = 0; i < kNumTestArgs; i++) { + Init(kTestArgList[i]); + Random rnd(test::RandomSeed() + 5); + for (int num_entries = 0; num_entries < 2000; + num_entries += (num_entries < 50 ? 1 : 200)) { + if ((num_entries % 10) == 0) { + fprintf(stderr, "case %d of %d: num_entries = %d\n", + (i + 1), int(kNumTestArgs), num_entries); + } + for (int e = 0; e < num_entries; e++) { + std::string v; + Add(test::RandomKey(&rnd, rnd.Skewed(4)), + test::RandomString(&rnd, rnd.Skewed(5), &v).ToString()); + } + Test(&rnd); + } + } +} + +TEST(Harness, RandomizedLongDB) { + Random rnd(test::RandomSeed()); + TestArgs args = { DB_TEST, false, 16 }; + Init(args); + int num_entries = 100000; + for (int e = 0; e < num_entries; e++) { + std::string v; + Add(test::RandomKey(&rnd, rnd.Skewed(4)), + test::RandomString(&rnd, rnd.Skewed(5), &v).ToString()); + } + Test(&rnd); + + // We must have created enough data to force merging + int files = 0; + for (int level = 0; level < config::kNumLevels; level++) { + std::string value; + char name[100]; + snprintf(name, sizeof(name), "leveldb.num-files-at-level%d", level); + ASSERT_TRUE(db()->GetProperty(name, &value)); + files += atoi(value.c_str()); + } + ASSERT_GT(files, 0); +} + +class MemTableTest { }; + +TEST(MemTableTest, Simple) { + InternalKeyComparator cmp(BytewiseComparator()); + MemTable* memtable = new MemTable(cmp); + memtable->Ref(); + WriteBatch batch; + WriteBatchInternal::SetSequence(&batch, 100); + batch.Put(std::string("k1"), std::string("v1")); + batch.Put(std::string("k2"), std::string("v2")); + batch.Put(std::string("k3"), std::string("v3")); + batch.Put(std::string("largekey"), std::string("vlarge")); + ASSERT_TRUE(WriteBatchInternal::InsertInto(&batch, memtable).ok()); + + Iterator* iter = memtable->NewIterator(); + iter->SeekToFirst(); + while (iter->Valid()) { + fprintf(stderr, "key: '%s' -> '%s'\n", + iter->key().ToString().c_str(), + iter->value().ToString().c_str()); + iter->Next(); + } + + delete iter; + memtable->Unref(); +} + +static bool Between(uint64_t val, uint64_t low, uint64_t high) { + bool result = (val >= low) && (val <= high); + if (!result) { + fprintf(stderr, "Value %llu is not in range [%llu, %llu]\n", + (unsigned long long)(val), + (unsigned long long)(low), + (unsigned long long)(high)); + } + return result; +} + +class TableTest { }; + +TEST(TableTest, ApproximateOffsetOfPlain) { + TableConstructor c(BytewiseComparator()); + c.Add("k01", "hello"); + c.Add("k02", "hello2"); + c.Add("k03", std::string(10000, 'x')); + c.Add("k04", std::string(200000, 'x')); + c.Add("k05", std::string(300000, 'x')); + c.Add("k06", "hello3"); + c.Add("k07", std::string(100000, 'x')); + std::vector keys; + KVMap kvmap; + Options options; + options.block_size = 1024; + options.compression = kNoCompression; + c.Finish(options, &keys, &kvmap); + + ASSERT_TRUE(Between(c.ApproximateOffsetOf("abc"), 0, 0)); + ASSERT_TRUE(Between(c.ApproximateOffsetOf("k01"), 0, 0)); + ASSERT_TRUE(Between(c.ApproximateOffsetOf("k01a"), 0, 0)); + ASSERT_TRUE(Between(c.ApproximateOffsetOf("k02"), 0, 0)); + ASSERT_TRUE(Between(c.ApproximateOffsetOf("k03"), 0, 0)); + ASSERT_TRUE(Between(c.ApproximateOffsetOf("k04"), 10000, 11000)); + ASSERT_TRUE(Between(c.ApproximateOffsetOf("k04a"), 210000, 211000)); + ASSERT_TRUE(Between(c.ApproximateOffsetOf("k05"), 210000, 211000)); + ASSERT_TRUE(Between(c.ApproximateOffsetOf("k06"), 510000, 511000)); + ASSERT_TRUE(Between(c.ApproximateOffsetOf("k07"), 510000, 511000)); + ASSERT_TRUE(Between(c.ApproximateOffsetOf("xyz"), 610000, 612000)); + +} + +static bool SnappyCompressionSupported() { + std::string out; + Slice in = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; + return port::Snappy_Compress(in.data(), in.size(), &out); +} + +TEST(TableTest, ApproximateOffsetOfCompressed) { + if (!SnappyCompressionSupported()) { + fprintf(stderr, "skipping compression tests\n"); + return; + } + + Random rnd(301); + TableConstructor c(BytewiseComparator()); + std::string tmp; + c.Add("k01", "hello"); + c.Add("k02", test::CompressibleString(&rnd, 0.25, 10000, &tmp)); + c.Add("k03", "hello3"); + c.Add("k04", test::CompressibleString(&rnd, 0.25, 10000, &tmp)); + std::vector keys; + KVMap kvmap; + Options options; + options.block_size = 1024; + options.compression = kSnappyCompression; + c.Finish(options, &keys, &kvmap); + + ASSERT_TRUE(Between(c.ApproximateOffsetOf("abc"), 0, 0)); + ASSERT_TRUE(Between(c.ApproximateOffsetOf("k01"), 0, 0)); + ASSERT_TRUE(Between(c.ApproximateOffsetOf("k02"), 0, 0)); + ASSERT_TRUE(Between(c.ApproximateOffsetOf("k03"), 2000, 3000)); + ASSERT_TRUE(Between(c.ApproximateOffsetOf("k04"), 2000, 3000)); + ASSERT_TRUE(Between(c.ApproximateOffsetOf("xyz"), 4000, 6000)); +} + +} // namespace leveldb + +int main(int argc, char** argv) { + return leveldb::test::RunAllTests(); +} diff --git a/src/leveldb/table/two_level_iterator.cc b/src/leveldb/table/two_level_iterator.cc new file mode 100644 index 0000000..7822eba --- /dev/null +++ b/src/leveldb/table/two_level_iterator.cc @@ -0,0 +1,182 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "table/two_level_iterator.h" + +#include "leveldb/table.h" +#include "table/block.h" +#include "table/format.h" +#include "table/iterator_wrapper.h" + +namespace leveldb { + +namespace { + +typedef Iterator* (*BlockFunction)(void*, const ReadOptions&, const Slice&); + +class TwoLevelIterator: public Iterator { + public: + TwoLevelIterator( + Iterator* index_iter, + BlockFunction block_function, + void* arg, + const ReadOptions& options); + + virtual ~TwoLevelIterator(); + + virtual void Seek(const Slice& target); + virtual void SeekToFirst(); + virtual void SeekToLast(); + virtual void Next(); + virtual void Prev(); + + virtual bool Valid() const { + return data_iter_.Valid(); + } + virtual Slice key() const { + assert(Valid()); + return data_iter_.key(); + } + virtual Slice value() const { + assert(Valid()); + return data_iter_.value(); + } + virtual Status status() const { + // It'd be nice if status() returned a const Status& instead of a Status + if (!index_iter_.status().ok()) { + return index_iter_.status(); + } else if (data_iter_.iter() != NULL && !data_iter_.status().ok()) { + return data_iter_.status(); + } else { + return status_; + } + } + + private: + void SaveError(const Status& s) { + if (status_.ok() && !s.ok()) status_ = s; + } + void SkipEmptyDataBlocksForward(); + void SkipEmptyDataBlocksBackward(); + void SetDataIterator(Iterator* data_iter); + void InitDataBlock(); + + BlockFunction block_function_; + void* arg_; + const ReadOptions options_; + Status status_; + IteratorWrapper index_iter_; + IteratorWrapper data_iter_; // May be NULL + // If data_iter_ is non-NULL, then "data_block_handle_" holds the + // "index_value" passed to block_function_ to create the data_iter_. + std::string data_block_handle_; +}; + +TwoLevelIterator::TwoLevelIterator( + Iterator* index_iter, + BlockFunction block_function, + void* arg, + const ReadOptions& options) + : block_function_(block_function), + arg_(arg), + options_(options), + index_iter_(index_iter), + data_iter_(NULL) { +} + +TwoLevelIterator::~TwoLevelIterator() { +} + +void TwoLevelIterator::Seek(const Slice& target) { + index_iter_.Seek(target); + InitDataBlock(); + if (data_iter_.iter() != NULL) data_iter_.Seek(target); + SkipEmptyDataBlocksForward(); +} + +void TwoLevelIterator::SeekToFirst() { + index_iter_.SeekToFirst(); + InitDataBlock(); + if (data_iter_.iter() != NULL) data_iter_.SeekToFirst(); + SkipEmptyDataBlocksForward(); +} + +void TwoLevelIterator::SeekToLast() { + index_iter_.SeekToLast(); + InitDataBlock(); + if (data_iter_.iter() != NULL) data_iter_.SeekToLast(); + SkipEmptyDataBlocksBackward(); +} + +void TwoLevelIterator::Next() { + assert(Valid()); + data_iter_.Next(); + SkipEmptyDataBlocksForward(); +} + +void TwoLevelIterator::Prev() { + assert(Valid()); + data_iter_.Prev(); + SkipEmptyDataBlocksBackward(); +} + + +void TwoLevelIterator::SkipEmptyDataBlocksForward() { + while (data_iter_.iter() == NULL || !data_iter_.Valid()) { + // Move to next block + if (!index_iter_.Valid()) { + SetDataIterator(NULL); + return; + } + index_iter_.Next(); + InitDataBlock(); + if (data_iter_.iter() != NULL) data_iter_.SeekToFirst(); + } +} + +void TwoLevelIterator::SkipEmptyDataBlocksBackward() { + while (data_iter_.iter() == NULL || !data_iter_.Valid()) { + // Move to next block + if (!index_iter_.Valid()) { + SetDataIterator(NULL); + return; + } + index_iter_.Prev(); + InitDataBlock(); + if (data_iter_.iter() != NULL) data_iter_.SeekToLast(); + } +} + +void TwoLevelIterator::SetDataIterator(Iterator* data_iter) { + if (data_iter_.iter() != NULL) SaveError(data_iter_.status()); + data_iter_.Set(data_iter); +} + +void TwoLevelIterator::InitDataBlock() { + if (!index_iter_.Valid()) { + SetDataIterator(NULL); + } else { + Slice handle = index_iter_.value(); + if (data_iter_.iter() != NULL && handle.compare(data_block_handle_) == 0) { + // data_iter_ is already constructed with this iterator, so + // no need to change anything + } else { + Iterator* iter = (*block_function_)(arg_, options_, handle); + data_block_handle_.assign(handle.data(), handle.size()); + SetDataIterator(iter); + } + } +} + +} // namespace + +Iterator* NewTwoLevelIterator( + Iterator* index_iter, + BlockFunction block_function, + void* arg, + const ReadOptions& options) { + return new TwoLevelIterator(index_iter, block_function, arg, options); +} + +} // namespace leveldb diff --git a/src/leveldb/table/two_level_iterator.h b/src/leveldb/table/two_level_iterator.h new file mode 100644 index 0000000..629ca34 --- /dev/null +++ b/src/leveldb/table/two_level_iterator.h @@ -0,0 +1,34 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#ifndef STORAGE_LEVELDB_TABLE_TWO_LEVEL_ITERATOR_H_ +#define STORAGE_LEVELDB_TABLE_TWO_LEVEL_ITERATOR_H_ + +#include "leveldb/iterator.h" + +namespace leveldb { + +struct ReadOptions; + +// Return a new two level iterator. A two-level iterator contains an +// index iterator whose values point to a sequence of blocks where +// each block is itself a sequence of key,value pairs. The returned +// two-level iterator yields the concatenation of all key/value pairs +// in the sequence of blocks. Takes ownership of "index_iter" and +// will delete it when no longer needed. +// +// Uses a supplied function to convert an index_iter value into +// an iterator over the contents of the corresponding block. +extern Iterator* NewTwoLevelIterator( + Iterator* index_iter, + Iterator* (*block_function)( + void* arg, + const ReadOptions& options, + const Slice& index_value), + void* arg, + const ReadOptions& options); + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_TABLE_TWO_LEVEL_ITERATOR_H_ diff --git a/src/leveldb/util/arena.cc b/src/leveldb/util/arena.cc new file mode 100644 index 0000000..9367f71 --- /dev/null +++ b/src/leveldb/util/arena.cc @@ -0,0 +1,68 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "util/arena.h" +#include + +namespace leveldb { + +static const int kBlockSize = 4096; + +Arena::Arena() { + blocks_memory_ = 0; + alloc_ptr_ = NULL; // First allocation will allocate a block + alloc_bytes_remaining_ = 0; +} + +Arena::~Arena() { + for (size_t i = 0; i < blocks_.size(); i++) { + delete[] blocks_[i]; + } +} + +char* Arena::AllocateFallback(size_t bytes) { + if (bytes > kBlockSize / 4) { + // Object is more than a quarter of our block size. Allocate it separately + // to avoid wasting too much space in leftover bytes. + char* result = AllocateNewBlock(bytes); + return result; + } + + // We waste the remaining space in the current block. + alloc_ptr_ = AllocateNewBlock(kBlockSize); + alloc_bytes_remaining_ = kBlockSize; + + char* result = alloc_ptr_; + alloc_ptr_ += bytes; + alloc_bytes_remaining_ -= bytes; + return result; +} + +char* Arena::AllocateAligned(size_t bytes) { + const int align = (sizeof(void*) > 8) ? sizeof(void*) : 8; + assert((align & (align-1)) == 0); // Pointer size should be a power of 2 + size_t current_mod = reinterpret_cast(alloc_ptr_) & (align-1); + size_t slop = (current_mod == 0 ? 0 : align - current_mod); + size_t needed = bytes + slop; + char* result; + if (needed <= alloc_bytes_remaining_) { + result = alloc_ptr_ + slop; + alloc_ptr_ += needed; + alloc_bytes_remaining_ -= needed; + } else { + // AllocateFallback always returned aligned memory + result = AllocateFallback(bytes); + } + assert((reinterpret_cast(result) & (align-1)) == 0); + return result; +} + +char* Arena::AllocateNewBlock(size_t block_bytes) { + char* result = new char[block_bytes]; + blocks_memory_ += block_bytes; + blocks_.push_back(result); + return result; +} + +} // namespace leveldb diff --git a/src/leveldb/util/arena.h b/src/leveldb/util/arena.h new file mode 100644 index 0000000..73bbf1c --- /dev/null +++ b/src/leveldb/util/arena.h @@ -0,0 +1,68 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#ifndef STORAGE_LEVELDB_UTIL_ARENA_H_ +#define STORAGE_LEVELDB_UTIL_ARENA_H_ + +#include +#include +#include +#include + +namespace leveldb { + +class Arena { + public: + Arena(); + ~Arena(); + + // Return a pointer to a newly allocated memory block of "bytes" bytes. + char* Allocate(size_t bytes); + + // Allocate memory with the normal alignment guarantees provided by malloc + char* AllocateAligned(size_t bytes); + + // Returns an estimate of the total memory usage of data allocated + // by the arena (including space allocated but not yet used for user + // allocations). + size_t MemoryUsage() const { + return blocks_memory_ + blocks_.capacity() * sizeof(char*); + } + + private: + char* AllocateFallback(size_t bytes); + char* AllocateNewBlock(size_t block_bytes); + + // Allocation state + char* alloc_ptr_; + size_t alloc_bytes_remaining_; + + // Array of new[] allocated memory blocks + std::vector blocks_; + + // Bytes of memory in blocks allocated so far + size_t blocks_memory_; + + // No copying allowed + Arena(const Arena&); + void operator=(const Arena&); +}; + +inline char* Arena::Allocate(size_t bytes) { + // The semantics of what to return are a bit messy if we allow + // 0-byte allocations, so we disallow them here (we don't need + // them for our internal use). + assert(bytes > 0); + if (bytes <= alloc_bytes_remaining_) { + char* result = alloc_ptr_; + alloc_ptr_ += bytes; + alloc_bytes_remaining_ -= bytes; + return result; + } + return AllocateFallback(bytes); +} + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_UTIL_ARENA_H_ diff --git a/src/leveldb/util/arena_test.cc b/src/leveldb/util/arena_test.cc new file mode 100644 index 0000000..58e870e --- /dev/null +++ b/src/leveldb/util/arena_test.cc @@ -0,0 +1,68 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "util/arena.h" + +#include "util/random.h" +#include "util/testharness.h" + +namespace leveldb { + +class ArenaTest { }; + +TEST(ArenaTest, Empty) { + Arena arena; +} + +TEST(ArenaTest, Simple) { + std::vector > allocated; + Arena arena; + const int N = 100000; + size_t bytes = 0; + Random rnd(301); + for (int i = 0; i < N; i++) { + size_t s; + if (i % (N / 10) == 0) { + s = i; + } else { + s = rnd.OneIn(4000) ? rnd.Uniform(6000) : + (rnd.OneIn(10) ? rnd.Uniform(100) : rnd.Uniform(20)); + } + if (s == 0) { + // Our arena disallows size 0 allocations. + s = 1; + } + char* r; + if (rnd.OneIn(10)) { + r = arena.AllocateAligned(s); + } else { + r = arena.Allocate(s); + } + + for (size_t b = 0; b < s; b++) { + // Fill the "i"th allocation with a known bit pattern + r[b] = i % 256; + } + bytes += s; + allocated.push_back(std::make_pair(s, r)); + ASSERT_GE(arena.MemoryUsage(), bytes); + if (i > N/10) { + ASSERT_LE(arena.MemoryUsage(), bytes * 1.10); + } + } + for (size_t i = 0; i < allocated.size(); i++) { + size_t num_bytes = allocated[i].first; + const char* p = allocated[i].second; + for (size_t b = 0; b < num_bytes; b++) { + // Check the "i"th allocation for the known bit pattern + ASSERT_EQ(int(p[b]) & 0xff, i % 256); + } + } +} + +} // namespace leveldb + +int main(int argc, char** argv) { + return leveldb::test::RunAllTests(); +} diff --git a/src/leveldb/util/bloom.cc b/src/leveldb/util/bloom.cc new file mode 100644 index 0000000..d7941cd --- /dev/null +++ b/src/leveldb/util/bloom.cc @@ -0,0 +1,95 @@ +// Copyright (c) 2012 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "leveldb/filter_policy.h" + +#include "leveldb/slice.h" +#include "util/hash.h" + +namespace leveldb { + +namespace { +static uint32_t BloomHash(const Slice& key) { + return Hash(key.data(), key.size(), 0xbc9f1d34); +} + +class BloomFilterPolicy : public FilterPolicy { + private: + size_t bits_per_key_; + size_t k_; + + public: + explicit BloomFilterPolicy(int bits_per_key) + : bits_per_key_(bits_per_key) { + // We intentionally round down to reduce probing cost a little bit + k_ = static_cast(bits_per_key * 0.69); // 0.69 =~ ln(2) + if (k_ < 1) k_ = 1; + if (k_ > 30) k_ = 30; + } + + virtual const char* Name() const { + return "leveldb.BuiltinBloomFilter"; + } + + virtual void CreateFilter(const Slice* keys, int n, std::string* dst) const { + // Compute bloom filter size (in both bits and bytes) + size_t bits = n * bits_per_key_; + + // For small n, we can see a very high false positive rate. Fix it + // by enforcing a minimum bloom filter length. + if (bits < 64) bits = 64; + + size_t bytes = (bits + 7) / 8; + bits = bytes * 8; + + const size_t init_size = dst->size(); + dst->resize(init_size + bytes, 0); + dst->push_back(static_cast(k_)); // Remember # of probes in filter + char* array = &(*dst)[init_size]; + for (size_t i = 0; i < n; i++) { + // Use double-hashing to generate a sequence of hash values. + // See analysis in [Kirsch,Mitzenmacher 2006]. + uint32_t h = BloomHash(keys[i]); + const uint32_t delta = (h >> 17) | (h << 15); // Rotate right 17 bits + for (size_t j = 0; j < k_; j++) { + const uint32_t bitpos = h % bits; + array[bitpos/8] |= (1 << (bitpos % 8)); + h += delta; + } + } + } + + virtual bool KeyMayMatch(const Slice& key, const Slice& bloom_filter) const { + const size_t len = bloom_filter.size(); + if (len < 2) return false; + + const char* array = bloom_filter.data(); + const size_t bits = (len - 1) * 8; + + // Use the encoded k so that we can read filters generated by + // bloom filters created using different parameters. + const size_t k = array[len-1]; + if (k > 30) { + // Reserved for potentially new encodings for short bloom filters. + // Consider it a match. + return true; + } + + uint32_t h = BloomHash(key); + const uint32_t delta = (h >> 17) | (h << 15); // Rotate right 17 bits + for (size_t j = 0; j < k; j++) { + const uint32_t bitpos = h % bits; + if ((array[bitpos/8] & (1 << (bitpos % 8))) == 0) return false; + h += delta; + } + return true; + } +}; +} + +const FilterPolicy* NewBloomFilterPolicy(int bits_per_key) { + return new BloomFilterPolicy(bits_per_key); +} + +} // namespace leveldb diff --git a/src/leveldb/util/bloom_test.cc b/src/leveldb/util/bloom_test.cc new file mode 100644 index 0000000..77fb1b3 --- /dev/null +++ b/src/leveldb/util/bloom_test.cc @@ -0,0 +1,161 @@ +// Copyright (c) 2012 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "leveldb/filter_policy.h" + +#include "util/coding.h" +#include "util/logging.h" +#include "util/testharness.h" +#include "util/testutil.h" + +namespace leveldb { + +static const int kVerbose = 1; + +static Slice Key(int i, char* buffer) { + EncodeFixed32(buffer, i); + return Slice(buffer, sizeof(uint32_t)); +} + +class BloomTest { + private: + const FilterPolicy* policy_; + std::string filter_; + std::vector keys_; + + public: + BloomTest() : policy_(NewBloomFilterPolicy(10)) { } + + ~BloomTest() { + delete policy_; + } + + void Reset() { + keys_.clear(); + filter_.clear(); + } + + void Add(const Slice& s) { + keys_.push_back(s.ToString()); + } + + void Build() { + std::vector key_slices; + for (size_t i = 0; i < keys_.size(); i++) { + key_slices.push_back(Slice(keys_[i])); + } + filter_.clear(); + policy_->CreateFilter(&key_slices[0], key_slices.size(), &filter_); + keys_.clear(); + if (kVerbose >= 2) DumpFilter(); + } + + size_t FilterSize() const { + return filter_.size(); + } + + void DumpFilter() { + fprintf(stderr, "F("); + for (size_t i = 0; i+1 < filter_.size(); i++) { + const unsigned int c = static_cast(filter_[i]); + for (int j = 0; j < 8; j++) { + fprintf(stderr, "%c", (c & (1 <KeyMayMatch(s, filter_); + } + + double FalsePositiveRate() { + char buffer[sizeof(int)]; + int result = 0; + for (int i = 0; i < 10000; i++) { + if (Matches(Key(i + 1000000000, buffer))) { + result++; + } + } + return result / 10000.0; + } +}; + +TEST(BloomTest, EmptyFilter) { + ASSERT_TRUE(! Matches("hello")); + ASSERT_TRUE(! Matches("world")); +} + +TEST(BloomTest, Small) { + Add("hello"); + Add("world"); + ASSERT_TRUE(Matches("hello")); + ASSERT_TRUE(Matches("world")); + ASSERT_TRUE(! Matches("x")); + ASSERT_TRUE(! Matches("foo")); +} + +static int NextLength(int length) { + if (length < 10) { + length += 1; + } else if (length < 100) { + length += 10; + } else if (length < 1000) { + length += 100; + } else { + length += 1000; + } + return length; +} + +TEST(BloomTest, VaryingLengths) { + char buffer[sizeof(int)]; + + // Count number of filters that significantly exceed the false positive rate + int mediocre_filters = 0; + int good_filters = 0; + + for (int length = 1; length <= 10000; length = NextLength(length)) { + Reset(); + for (int i = 0; i < length; i++) { + Add(Key(i, buffer)); + } + Build(); + + ASSERT_LE(FilterSize(), static_cast((length * 10 / 8) + 40)) + << length; + + // All added keys must match + for (int i = 0; i < length; i++) { + ASSERT_TRUE(Matches(Key(i, buffer))) + << "Length " << length << "; key " << i; + } + + // Check false positive rate + double rate = FalsePositiveRate(); + if (kVerbose >= 1) { + fprintf(stderr, "False positives: %5.2f%% @ length = %6d ; bytes = %6d\n", + rate*100.0, length, static_cast(FilterSize())); + } + ASSERT_LE(rate, 0.02); // Must not be over 2% + if (rate > 0.0125) mediocre_filters++; // Allowed, but not too often + else good_filters++; + } + if (kVerbose >= 1) { + fprintf(stderr, "Filters: %d good, %d mediocre\n", + good_filters, mediocre_filters); + } + ASSERT_LE(mediocre_filters, good_filters/5); +} + +// Different bits-per-byte + +} // namespace leveldb + +int main(int argc, char** argv) { + return leveldb::test::RunAllTests(); +} diff --git a/src/leveldb/util/cache.cc b/src/leveldb/util/cache.cc new file mode 100644 index 0000000..8b197bc --- /dev/null +++ b/src/leveldb/util/cache.cc @@ -0,0 +1,325 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include +#include +#include + +#include "leveldb/cache.h" +#include "port/port.h" +#include "util/hash.h" +#include "util/mutexlock.h" + +namespace leveldb { + +Cache::~Cache() { +} + +namespace { + +// LRU cache implementation + +// An entry is a variable length heap-allocated structure. Entries +// are kept in a circular doubly linked list ordered by access time. +struct LRUHandle { + void* value; + void (*deleter)(const Slice&, void* value); + LRUHandle* next_hash; + LRUHandle* next; + LRUHandle* prev; + size_t charge; // TODO(opt): Only allow uint32_t? + size_t key_length; + uint32_t refs; + uint32_t hash; // Hash of key(); used for fast sharding and comparisons + char key_data[1]; // Beginning of key + + Slice key() const { + // For cheaper lookups, we allow a temporary Handle object + // to store a pointer to a key in "value". + if (next == this) { + return *(reinterpret_cast(value)); + } else { + return Slice(key_data, key_length); + } + } +}; + +// We provide our own simple hash table since it removes a whole bunch +// of porting hacks and is also faster than some of the built-in hash +// table implementations in some of the compiler/runtime combinations +// we have tested. E.g., readrandom speeds up by ~5% over the g++ +// 4.4.3's builtin hashtable. +class HandleTable { + public: + HandleTable() : length_(0), elems_(0), list_(NULL) { Resize(); } + ~HandleTable() { delete[] list_; } + + LRUHandle* Lookup(const Slice& key, uint32_t hash) { + return *FindPointer(key, hash); + } + + LRUHandle* Insert(LRUHandle* h) { + LRUHandle** ptr = FindPointer(h->key(), h->hash); + LRUHandle* old = *ptr; + h->next_hash = (old == NULL ? NULL : old->next_hash); + *ptr = h; + if (old == NULL) { + ++elems_; + if (elems_ > length_) { + // Since each cache entry is fairly large, we aim for a small + // average linked list length (<= 1). + Resize(); + } + } + return old; + } + + LRUHandle* Remove(const Slice& key, uint32_t hash) { + LRUHandle** ptr = FindPointer(key, hash); + LRUHandle* result = *ptr; + if (result != NULL) { + *ptr = result->next_hash; + --elems_; + } + return result; + } + + private: + // The table consists of an array of buckets where each bucket is + // a linked list of cache entries that hash into the bucket. + uint32_t length_; + uint32_t elems_; + LRUHandle** list_; + + // Return a pointer to slot that points to a cache entry that + // matches key/hash. If there is no such cache entry, return a + // pointer to the trailing slot in the corresponding linked list. + LRUHandle** FindPointer(const Slice& key, uint32_t hash) { + LRUHandle** ptr = &list_[hash & (length_ - 1)]; + while (*ptr != NULL && + ((*ptr)->hash != hash || key != (*ptr)->key())) { + ptr = &(*ptr)->next_hash; + } + return ptr; + } + + void Resize() { + uint32_t new_length = 4; + while (new_length < elems_) { + new_length *= 2; + } + LRUHandle** new_list = new LRUHandle*[new_length]; + memset(new_list, 0, sizeof(new_list[0]) * new_length); + uint32_t count = 0; + for (uint32_t i = 0; i < length_; i++) { + LRUHandle* h = list_[i]; + while (h != NULL) { + LRUHandle* next = h->next_hash; + uint32_t hash = h->hash; + LRUHandle** ptr = &new_list[hash & (new_length - 1)]; + h->next_hash = *ptr; + *ptr = h; + h = next; + count++; + } + } + assert(elems_ == count); + delete[] list_; + list_ = new_list; + length_ = new_length; + } +}; + +// A single shard of sharded cache. +class LRUCache { + public: + LRUCache(); + ~LRUCache(); + + // Separate from constructor so caller can easily make an array of LRUCache + void SetCapacity(size_t capacity) { capacity_ = capacity; } + + // Like Cache methods, but with an extra "hash" parameter. + Cache::Handle* Insert(const Slice& key, uint32_t hash, + void* value, size_t charge, + void (*deleter)(const Slice& key, void* value)); + Cache::Handle* Lookup(const Slice& key, uint32_t hash); + void Release(Cache::Handle* handle); + void Erase(const Slice& key, uint32_t hash); + + private: + void LRU_Remove(LRUHandle* e); + void LRU_Append(LRUHandle* e); + void Unref(LRUHandle* e); + + // Initialized before use. + size_t capacity_; + + // mutex_ protects the following state. + port::Mutex mutex_; + size_t usage_; + + // Dummy head of LRU list. + // lru.prev is newest entry, lru.next is oldest entry. + LRUHandle lru_; + + HandleTable table_; +}; + +LRUCache::LRUCache() + : usage_(0) { + // Make empty circular linked list + lru_.next = &lru_; + lru_.prev = &lru_; +} + +LRUCache::~LRUCache() { + for (LRUHandle* e = lru_.next; e != &lru_; ) { + LRUHandle* next = e->next; + assert(e->refs == 1); // Error if caller has an unreleased handle + Unref(e); + e = next; + } +} + +void LRUCache::Unref(LRUHandle* e) { + assert(e->refs > 0); + e->refs--; + if (e->refs <= 0) { + usage_ -= e->charge; + (*e->deleter)(e->key(), e->value); + free(e); + } +} + +void LRUCache::LRU_Remove(LRUHandle* e) { + e->next->prev = e->prev; + e->prev->next = e->next; +} + +void LRUCache::LRU_Append(LRUHandle* e) { + // Make "e" newest entry by inserting just before lru_ + e->next = &lru_; + e->prev = lru_.prev; + e->prev->next = e; + e->next->prev = e; +} + +Cache::Handle* LRUCache::Lookup(const Slice& key, uint32_t hash) { + MutexLock l(&mutex_); + LRUHandle* e = table_.Lookup(key, hash); + if (e != NULL) { + e->refs++; + LRU_Remove(e); + LRU_Append(e); + } + return reinterpret_cast(e); +} + +void LRUCache::Release(Cache::Handle* handle) { + MutexLock l(&mutex_); + Unref(reinterpret_cast(handle)); +} + +Cache::Handle* LRUCache::Insert( + const Slice& key, uint32_t hash, void* value, size_t charge, + void (*deleter)(const Slice& key, void* value)) { + MutexLock l(&mutex_); + + LRUHandle* e = reinterpret_cast( + malloc(sizeof(LRUHandle)-1 + key.size())); + e->value = value; + e->deleter = deleter; + e->charge = charge; + e->key_length = key.size(); + e->hash = hash; + e->refs = 2; // One from LRUCache, one for the returned handle + memcpy(e->key_data, key.data(), key.size()); + LRU_Append(e); + usage_ += charge; + + LRUHandle* old = table_.Insert(e); + if (old != NULL) { + LRU_Remove(old); + Unref(old); + } + + while (usage_ > capacity_ && lru_.next != &lru_) { + LRUHandle* old = lru_.next; + LRU_Remove(old); + table_.Remove(old->key(), old->hash); + Unref(old); + } + + return reinterpret_cast(e); +} + +void LRUCache::Erase(const Slice& key, uint32_t hash) { + MutexLock l(&mutex_); + LRUHandle* e = table_.Remove(key, hash); + if (e != NULL) { + LRU_Remove(e); + Unref(e); + } +} + +static const int kNumShardBits = 4; +static const int kNumShards = 1 << kNumShardBits; + +class ShardedLRUCache : public Cache { + private: + LRUCache shard_[kNumShards]; + port::Mutex id_mutex_; + uint64_t last_id_; + + static inline uint32_t HashSlice(const Slice& s) { + return Hash(s.data(), s.size(), 0); + } + + static uint32_t Shard(uint32_t hash) { + return hash >> (32 - kNumShardBits); + } + + public: + explicit ShardedLRUCache(size_t capacity) + : last_id_(0) { + const size_t per_shard = (capacity + (kNumShards - 1)) / kNumShards; + for (int s = 0; s < kNumShards; s++) { + shard_[s].SetCapacity(per_shard); + } + } + virtual ~ShardedLRUCache() { } + virtual Handle* Insert(const Slice& key, void* value, size_t charge, + void (*deleter)(const Slice& key, void* value)) { + const uint32_t hash = HashSlice(key); + return shard_[Shard(hash)].Insert(key, hash, value, charge, deleter); + } + virtual Handle* Lookup(const Slice& key) { + const uint32_t hash = HashSlice(key); + return shard_[Shard(hash)].Lookup(key, hash); + } + virtual void Release(Handle* handle) { + LRUHandle* h = reinterpret_cast(handle); + shard_[Shard(h->hash)].Release(handle); + } + virtual void Erase(const Slice& key) { + const uint32_t hash = HashSlice(key); + shard_[Shard(hash)].Erase(key, hash); + } + virtual void* Value(Handle* handle) { + return reinterpret_cast(handle)->value; + } + virtual uint64_t NewId() { + MutexLock l(&id_mutex_); + return ++(last_id_); + } +}; + +} // end anonymous namespace + +Cache* NewLRUCache(size_t capacity) { + return new ShardedLRUCache(capacity); +} + +} // namespace leveldb diff --git a/src/leveldb/util/cache_test.cc b/src/leveldb/util/cache_test.cc new file mode 100644 index 0000000..4371671 --- /dev/null +++ b/src/leveldb/util/cache_test.cc @@ -0,0 +1,186 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "leveldb/cache.h" + +#include +#include "util/coding.h" +#include "util/testharness.h" + +namespace leveldb { + +// Conversions between numeric keys/values and the types expected by Cache. +static std::string EncodeKey(int k) { + std::string result; + PutFixed32(&result, k); + return result; +} +static int DecodeKey(const Slice& k) { + assert(k.size() == 4); + return DecodeFixed32(k.data()); +} +static void* EncodeValue(uintptr_t v) { return reinterpret_cast(v); } +static int DecodeValue(void* v) { return reinterpret_cast(v); } + +class CacheTest { + public: + static CacheTest* current_; + + static void Deleter(const Slice& key, void* v) { + current_->deleted_keys_.push_back(DecodeKey(key)); + current_->deleted_values_.push_back(DecodeValue(v)); + } + + static const int kCacheSize = 1000; + std::vector deleted_keys_; + std::vector deleted_values_; + Cache* cache_; + + CacheTest() : cache_(NewLRUCache(kCacheSize)) { + current_ = this; + } + + ~CacheTest() { + delete cache_; + } + + int Lookup(int key) { + Cache::Handle* handle = cache_->Lookup(EncodeKey(key)); + const int r = (handle == NULL) ? -1 : DecodeValue(cache_->Value(handle)); + if (handle != NULL) { + cache_->Release(handle); + } + return r; + } + + void Insert(int key, int value, int charge = 1) { + cache_->Release(cache_->Insert(EncodeKey(key), EncodeValue(value), charge, + &CacheTest::Deleter)); + } + + void Erase(int key) { + cache_->Erase(EncodeKey(key)); + } +}; +CacheTest* CacheTest::current_; + +TEST(CacheTest, HitAndMiss) { + ASSERT_EQ(-1, Lookup(100)); + + Insert(100, 101); + ASSERT_EQ(101, Lookup(100)); + ASSERT_EQ(-1, Lookup(200)); + ASSERT_EQ(-1, Lookup(300)); + + Insert(200, 201); + ASSERT_EQ(101, Lookup(100)); + ASSERT_EQ(201, Lookup(200)); + ASSERT_EQ(-1, Lookup(300)); + + Insert(100, 102); + ASSERT_EQ(102, Lookup(100)); + ASSERT_EQ(201, Lookup(200)); + ASSERT_EQ(-1, Lookup(300)); + + ASSERT_EQ(1, deleted_keys_.size()); + ASSERT_EQ(100, deleted_keys_[0]); + ASSERT_EQ(101, deleted_values_[0]); +} + +TEST(CacheTest, Erase) { + Erase(200); + ASSERT_EQ(0, deleted_keys_.size()); + + Insert(100, 101); + Insert(200, 201); + Erase(100); + ASSERT_EQ(-1, Lookup(100)); + ASSERT_EQ(201, Lookup(200)); + ASSERT_EQ(1, deleted_keys_.size()); + ASSERT_EQ(100, deleted_keys_[0]); + ASSERT_EQ(101, deleted_values_[0]); + + Erase(100); + ASSERT_EQ(-1, Lookup(100)); + ASSERT_EQ(201, Lookup(200)); + ASSERT_EQ(1, deleted_keys_.size()); +} + +TEST(CacheTest, EntriesArePinned) { + Insert(100, 101); + Cache::Handle* h1 = cache_->Lookup(EncodeKey(100)); + ASSERT_EQ(101, DecodeValue(cache_->Value(h1))); + + Insert(100, 102); + Cache::Handle* h2 = cache_->Lookup(EncodeKey(100)); + ASSERT_EQ(102, DecodeValue(cache_->Value(h2))); + ASSERT_EQ(0, deleted_keys_.size()); + + cache_->Release(h1); + ASSERT_EQ(1, deleted_keys_.size()); + ASSERT_EQ(100, deleted_keys_[0]); + ASSERT_EQ(101, deleted_values_[0]); + + Erase(100); + ASSERT_EQ(-1, Lookup(100)); + ASSERT_EQ(1, deleted_keys_.size()); + + cache_->Release(h2); + ASSERT_EQ(2, deleted_keys_.size()); + ASSERT_EQ(100, deleted_keys_[1]); + ASSERT_EQ(102, deleted_values_[1]); +} + +TEST(CacheTest, EvictionPolicy) { + Insert(100, 101); + Insert(200, 201); + + // Frequently used entry must be kept around + for (int i = 0; i < kCacheSize + 100; i++) { + Insert(1000+i, 2000+i); + ASSERT_EQ(2000+i, Lookup(1000+i)); + ASSERT_EQ(101, Lookup(100)); + } + ASSERT_EQ(101, Lookup(100)); + ASSERT_EQ(-1, Lookup(200)); +} + +TEST(CacheTest, HeavyEntries) { + // Add a bunch of light and heavy entries and then count the combined + // size of items still in the cache, which must be approximately the + // same as the total capacity. + const int kLight = 1; + const int kHeavy = 10; + int added = 0; + int index = 0; + while (added < 2*kCacheSize) { + const int weight = (index & 1) ? kLight : kHeavy; + Insert(index, 1000+index, weight); + added += weight; + index++; + } + + int cached_weight = 0; + for (int i = 0; i < index; i++) { + const int weight = (i & 1 ? kLight : kHeavy); + int r = Lookup(i); + if (r >= 0) { + cached_weight += weight; + ASSERT_EQ(1000+i, r); + } + } + ASSERT_LE(cached_weight, kCacheSize + kCacheSize/10); +} + +TEST(CacheTest, NewId) { + uint64_t a = cache_->NewId(); + uint64_t b = cache_->NewId(); + ASSERT_NE(a, b); +} + +} // namespace leveldb + +int main(int argc, char** argv) { + return leveldb::test::RunAllTests(); +} diff --git a/src/leveldb/util/coding.cc b/src/leveldb/util/coding.cc new file mode 100644 index 0000000..21e3186 --- /dev/null +++ b/src/leveldb/util/coding.cc @@ -0,0 +1,194 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "util/coding.h" + +namespace leveldb { + +void EncodeFixed32(char* buf, uint32_t value) { + if (port::kLittleEndian) { + memcpy(buf, &value, sizeof(value)); + } else { + buf[0] = value & 0xff; + buf[1] = (value >> 8) & 0xff; + buf[2] = (value >> 16) & 0xff; + buf[3] = (value >> 24) & 0xff; + } +} + +void EncodeFixed64(char* buf, uint64_t value) { + if (port::kLittleEndian) { + memcpy(buf, &value, sizeof(value)); + } else { + buf[0] = value & 0xff; + buf[1] = (value >> 8) & 0xff; + buf[2] = (value >> 16) & 0xff; + buf[3] = (value >> 24) & 0xff; + buf[4] = (value >> 32) & 0xff; + buf[5] = (value >> 40) & 0xff; + buf[6] = (value >> 48) & 0xff; + buf[7] = (value >> 56) & 0xff; + } +} + +void PutFixed32(std::string* dst, uint32_t value) { + char buf[sizeof(value)]; + EncodeFixed32(buf, value); + dst->append(buf, sizeof(buf)); +} + +void PutFixed64(std::string* dst, uint64_t value) { + char buf[sizeof(value)]; + EncodeFixed64(buf, value); + dst->append(buf, sizeof(buf)); +} + +char* EncodeVarint32(char* dst, uint32_t v) { + // Operate on characters as unsigneds + unsigned char* ptr = reinterpret_cast(dst); + static const int B = 128; + if (v < (1<<7)) { + *(ptr++) = v; + } else if (v < (1<<14)) { + *(ptr++) = v | B; + *(ptr++) = v>>7; + } else if (v < (1<<21)) { + *(ptr++) = v | B; + *(ptr++) = (v>>7) | B; + *(ptr++) = v>>14; + } else if (v < (1<<28)) { + *(ptr++) = v | B; + *(ptr++) = (v>>7) | B; + *(ptr++) = (v>>14) | B; + *(ptr++) = v>>21; + } else { + *(ptr++) = v | B; + *(ptr++) = (v>>7) | B; + *(ptr++) = (v>>14) | B; + *(ptr++) = (v>>21) | B; + *(ptr++) = v>>28; + } + return reinterpret_cast(ptr); +} + +void PutVarint32(std::string* dst, uint32_t v) { + char buf[5]; + char* ptr = EncodeVarint32(buf, v); + dst->append(buf, ptr - buf); +} + +char* EncodeVarint64(char* dst, uint64_t v) { + static const int B = 128; + unsigned char* ptr = reinterpret_cast(dst); + while (v >= B) { + *(ptr++) = (v & (B-1)) | B; + v >>= 7; + } + *(ptr++) = static_cast(v); + return reinterpret_cast(ptr); +} + +void PutVarint64(std::string* dst, uint64_t v) { + char buf[10]; + char* ptr = EncodeVarint64(buf, v); + dst->append(buf, ptr - buf); +} + +void PutLengthPrefixedSlice(std::string* dst, const Slice& value) { + PutVarint32(dst, value.size()); + dst->append(value.data(), value.size()); +} + +int VarintLength(uint64_t v) { + int len = 1; + while (v >= 128) { + v >>= 7; + len++; + } + return len; +} + +const char* GetVarint32PtrFallback(const char* p, + const char* limit, + uint32_t* value) { + uint32_t result = 0; + for (uint32_t shift = 0; shift <= 28 && p < limit; shift += 7) { + uint32_t byte = *(reinterpret_cast(p)); + p++; + if (byte & 128) { + // More bytes are present + result |= ((byte & 127) << shift); + } else { + result |= (byte << shift); + *value = result; + return reinterpret_cast(p); + } + } + return NULL; +} + +bool GetVarint32(Slice* input, uint32_t* value) { + const char* p = input->data(); + const char* limit = p + input->size(); + const char* q = GetVarint32Ptr(p, limit, value); + if (q == NULL) { + return false; + } else { + *input = Slice(q, limit - q); + return true; + } +} + +const char* GetVarint64Ptr(const char* p, const char* limit, uint64_t* value) { + uint64_t result = 0; + for (uint32_t shift = 0; shift <= 63 && p < limit; shift += 7) { + uint64_t byte = *(reinterpret_cast(p)); + p++; + if (byte & 128) { + // More bytes are present + result |= ((byte & 127) << shift); + } else { + result |= (byte << shift); + *value = result; + return reinterpret_cast(p); + } + } + return NULL; +} + +bool GetVarint64(Slice* input, uint64_t* value) { + const char* p = input->data(); + const char* limit = p + input->size(); + const char* q = GetVarint64Ptr(p, limit, value); + if (q == NULL) { + return false; + } else { + *input = Slice(q, limit - q); + return true; + } +} + +const char* GetLengthPrefixedSlice(const char* p, const char* limit, + Slice* result) { + uint32_t len; + p = GetVarint32Ptr(p, limit, &len); + if (p == NULL) return NULL; + if (p + len > limit) return NULL; + *result = Slice(p, len); + return p + len; +} + +bool GetLengthPrefixedSlice(Slice* input, Slice* result) { + uint32_t len; + if (GetVarint32(input, &len) && + input->size() >= len) { + *result = Slice(input->data(), len); + input->remove_prefix(len); + return true; + } else { + return false; + } +} + +} // namespace leveldb diff --git a/src/leveldb/util/coding.h b/src/leveldb/util/coding.h new file mode 100644 index 0000000..3993c4a --- /dev/null +++ b/src/leveldb/util/coding.h @@ -0,0 +1,104 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. +// +// Endian-neutral encoding: +// * Fixed-length numbers are encoded with least-significant byte first +// * In addition we support variable length "varint" encoding +// * Strings are encoded prefixed by their length in varint format + +#ifndef STORAGE_LEVELDB_UTIL_CODING_H_ +#define STORAGE_LEVELDB_UTIL_CODING_H_ + +#include +#include +#include +#include "leveldb/slice.h" +#include "port/port.h" + +namespace leveldb { + +// Standard Put... routines append to a string +extern void PutFixed32(std::string* dst, uint32_t value); +extern void PutFixed64(std::string* dst, uint64_t value); +extern void PutVarint32(std::string* dst, uint32_t value); +extern void PutVarint64(std::string* dst, uint64_t value); +extern void PutLengthPrefixedSlice(std::string* dst, const Slice& value); + +// Standard Get... routines parse a value from the beginning of a Slice +// and advance the slice past the parsed value. +extern bool GetVarint32(Slice* input, uint32_t* value); +extern bool GetVarint64(Slice* input, uint64_t* value); +extern bool GetLengthPrefixedSlice(Slice* input, Slice* result); + +// Pointer-based variants of GetVarint... These either store a value +// in *v and return a pointer just past the parsed value, or return +// NULL on error. These routines only look at bytes in the range +// [p..limit-1] +extern const char* GetVarint32Ptr(const char* p,const char* limit, uint32_t* v); +extern const char* GetVarint64Ptr(const char* p,const char* limit, uint64_t* v); + +// Returns the length of the varint32 or varint64 encoding of "v" +extern int VarintLength(uint64_t v); + +// Lower-level versions of Put... that write directly into a character buffer +// REQUIRES: dst has enough space for the value being written +extern void EncodeFixed32(char* dst, uint32_t value); +extern void EncodeFixed64(char* dst, uint64_t value); + +// Lower-level versions of Put... that write directly into a character buffer +// and return a pointer just past the last byte written. +// REQUIRES: dst has enough space for the value being written +extern char* EncodeVarint32(char* dst, uint32_t value); +extern char* EncodeVarint64(char* dst, uint64_t value); + +// Lower-level versions of Get... that read directly from a character buffer +// without any bounds checking. + +inline uint32_t DecodeFixed32(const char* ptr) { + if (port::kLittleEndian) { + // Load the raw bytes + uint32_t result; + memcpy(&result, ptr, sizeof(result)); // gcc optimizes this to a plain load + return result; + } else { + return ((static_cast(static_cast(ptr[0]))) + | (static_cast(static_cast(ptr[1])) << 8) + | (static_cast(static_cast(ptr[2])) << 16) + | (static_cast(static_cast(ptr[3])) << 24)); + } +} + +inline uint64_t DecodeFixed64(const char* ptr) { + if (port::kLittleEndian) { + // Load the raw bytes + uint64_t result; + memcpy(&result, ptr, sizeof(result)); // gcc optimizes this to a plain load + return result; + } else { + uint64_t lo = DecodeFixed32(ptr); + uint64_t hi = DecodeFixed32(ptr + 4); + return (hi << 32) | lo; + } +} + +// Internal routine for use by fallback path of GetVarint32Ptr +extern const char* GetVarint32PtrFallback(const char* p, + const char* limit, + uint32_t* value); +inline const char* GetVarint32Ptr(const char* p, + const char* limit, + uint32_t* value) { + if (p < limit) { + uint32_t result = *(reinterpret_cast(p)); + if ((result & 128) == 0) { + *value = result; + return p + 1; + } + } + return GetVarint32PtrFallback(p, limit, value); +} + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_UTIL_CODING_H_ diff --git a/src/leveldb/util/coding_test.cc b/src/leveldb/util/coding_test.cc new file mode 100644 index 0000000..521541e --- /dev/null +++ b/src/leveldb/util/coding_test.cc @@ -0,0 +1,196 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "util/coding.h" + +#include "util/testharness.h" + +namespace leveldb { + +class Coding { }; + +TEST(Coding, Fixed32) { + std::string s; + for (uint32_t v = 0; v < 100000; v++) { + PutFixed32(&s, v); + } + + const char* p = s.data(); + for (uint32_t v = 0; v < 100000; v++) { + uint32_t actual = DecodeFixed32(p); + ASSERT_EQ(v, actual); + p += sizeof(uint32_t); + } +} + +TEST(Coding, Fixed64) { + std::string s; + for (int power = 0; power <= 63; power++) { + uint64_t v = static_cast(1) << power; + PutFixed64(&s, v - 1); + PutFixed64(&s, v + 0); + PutFixed64(&s, v + 1); + } + + const char* p = s.data(); + for (int power = 0; power <= 63; power++) { + uint64_t v = static_cast(1) << power; + uint64_t actual; + actual = DecodeFixed64(p); + ASSERT_EQ(v-1, actual); + p += sizeof(uint64_t); + + actual = DecodeFixed64(p); + ASSERT_EQ(v+0, actual); + p += sizeof(uint64_t); + + actual = DecodeFixed64(p); + ASSERT_EQ(v+1, actual); + p += sizeof(uint64_t); + } +} + +// Test that encoding routines generate little-endian encodings +TEST(Coding, EncodingOutput) { + std::string dst; + PutFixed32(&dst, 0x04030201); + ASSERT_EQ(4, dst.size()); + ASSERT_EQ(0x01, static_cast(dst[0])); + ASSERT_EQ(0x02, static_cast(dst[1])); + ASSERT_EQ(0x03, static_cast(dst[2])); + ASSERT_EQ(0x04, static_cast(dst[3])); + + dst.clear(); + PutFixed64(&dst, 0x0807060504030201ull); + ASSERT_EQ(8, dst.size()); + ASSERT_EQ(0x01, static_cast(dst[0])); + ASSERT_EQ(0x02, static_cast(dst[1])); + ASSERT_EQ(0x03, static_cast(dst[2])); + ASSERT_EQ(0x04, static_cast(dst[3])); + ASSERT_EQ(0x05, static_cast(dst[4])); + ASSERT_EQ(0x06, static_cast(dst[5])); + ASSERT_EQ(0x07, static_cast(dst[6])); + ASSERT_EQ(0x08, static_cast(dst[7])); +} + +TEST(Coding, Varint32) { + std::string s; + for (uint32_t i = 0; i < (32 * 32); i++) { + uint32_t v = (i / 32) << (i % 32); + PutVarint32(&s, v); + } + + const char* p = s.data(); + const char* limit = p + s.size(); + for (uint32_t i = 0; i < (32 * 32); i++) { + uint32_t expected = (i / 32) << (i % 32); + uint32_t actual; + const char* start = p; + p = GetVarint32Ptr(p, limit, &actual); + ASSERT_TRUE(p != NULL); + ASSERT_EQ(expected, actual); + ASSERT_EQ(VarintLength(actual), p - start); + } + ASSERT_EQ(p, s.data() + s.size()); +} + +TEST(Coding, Varint64) { + // Construct the list of values to check + std::vector values; + // Some special values + values.push_back(0); + values.push_back(100); + values.push_back(~static_cast(0)); + values.push_back(~static_cast(0) - 1); + for (uint32_t k = 0; k < 64; k++) { + // Test values near powers of two + const uint64_t power = 1ull << k; + values.push_back(power); + values.push_back(power-1); + values.push_back(power+1); + } + + std::string s; + for (size_t i = 0; i < values.size(); i++) { + PutVarint64(&s, values[i]); + } + + const char* p = s.data(); + const char* limit = p + s.size(); + for (size_t i = 0; i < values.size(); i++) { + ASSERT_TRUE(p < limit); + uint64_t actual; + const char* start = p; + p = GetVarint64Ptr(p, limit, &actual); + ASSERT_TRUE(p != NULL); + ASSERT_EQ(values[i], actual); + ASSERT_EQ(VarintLength(actual), p - start); + } + ASSERT_EQ(p, limit); + +} + +TEST(Coding, Varint32Overflow) { + uint32_t result; + std::string input("\x81\x82\x83\x84\x85\x11"); + ASSERT_TRUE(GetVarint32Ptr(input.data(), input.data() + input.size(), &result) + == NULL); +} + +TEST(Coding, Varint32Truncation) { + uint32_t large_value = (1u << 31) + 100; + std::string s; + PutVarint32(&s, large_value); + uint32_t result; + for (size_t len = 0; len < s.size() - 1; len++) { + ASSERT_TRUE(GetVarint32Ptr(s.data(), s.data() + len, &result) == NULL); + } + ASSERT_TRUE(GetVarint32Ptr(s.data(), s.data() + s.size(), &result) != NULL); + ASSERT_EQ(large_value, result); +} + +TEST(Coding, Varint64Overflow) { + uint64_t result; + std::string input("\x81\x82\x83\x84\x85\x81\x82\x83\x84\x85\x11"); + ASSERT_TRUE(GetVarint64Ptr(input.data(), input.data() + input.size(), &result) + == NULL); +} + +TEST(Coding, Varint64Truncation) { + uint64_t large_value = (1ull << 63) + 100ull; + std::string s; + PutVarint64(&s, large_value); + uint64_t result; + for (size_t len = 0; len < s.size() - 1; len++) { + ASSERT_TRUE(GetVarint64Ptr(s.data(), s.data() + len, &result) == NULL); + } + ASSERT_TRUE(GetVarint64Ptr(s.data(), s.data() + s.size(), &result) != NULL); + ASSERT_EQ(large_value, result); +} + +TEST(Coding, Strings) { + std::string s; + PutLengthPrefixedSlice(&s, Slice("")); + PutLengthPrefixedSlice(&s, Slice("foo")); + PutLengthPrefixedSlice(&s, Slice("bar")); + PutLengthPrefixedSlice(&s, Slice(std::string(200, 'x'))); + + Slice input(s); + Slice v; + ASSERT_TRUE(GetLengthPrefixedSlice(&input, &v)); + ASSERT_EQ("", v.ToString()); + ASSERT_TRUE(GetLengthPrefixedSlice(&input, &v)); + ASSERT_EQ("foo", v.ToString()); + ASSERT_TRUE(GetLengthPrefixedSlice(&input, &v)); + ASSERT_EQ("bar", v.ToString()); + ASSERT_TRUE(GetLengthPrefixedSlice(&input, &v)); + ASSERT_EQ(std::string(200, 'x'), v.ToString()); + ASSERT_EQ("", input.ToString()); +} + +} // namespace leveldb + +int main(int argc, char** argv) { + return leveldb::test::RunAllTests(); +} diff --git a/src/leveldb/util/comparator.cc b/src/leveldb/util/comparator.cc new file mode 100644 index 0000000..4b7b572 --- /dev/null +++ b/src/leveldb/util/comparator.cc @@ -0,0 +1,81 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include +#include +#include "leveldb/comparator.h" +#include "leveldb/slice.h" +#include "port/port.h" +#include "util/logging.h" + +namespace leveldb { + +Comparator::~Comparator() { } + +namespace { +class BytewiseComparatorImpl : public Comparator { + public: + BytewiseComparatorImpl() { } + + virtual const char* Name() const { + return "leveldb.BytewiseComparator"; + } + + virtual int Compare(const Slice& a, const Slice& b) const { + return a.compare(b); + } + + virtual void FindShortestSeparator( + std::string* start, + const Slice& limit) const { + // Find length of common prefix + size_t min_length = std::min(start->size(), limit.size()); + size_t diff_index = 0; + while ((diff_index < min_length) && + ((*start)[diff_index] == limit[diff_index])) { + diff_index++; + } + + if (diff_index >= min_length) { + // Do not shorten if one string is a prefix of the other + } else { + uint8_t diff_byte = static_cast((*start)[diff_index]); + if (diff_byte < static_cast(0xff) && + diff_byte + 1 < static_cast(limit[diff_index])) { + (*start)[diff_index]++; + start->resize(diff_index + 1); + assert(Compare(*start, limit) < 0); + } + } + } + + virtual void FindShortSuccessor(std::string* key) const { + // Find first character that can be incremented + size_t n = key->size(); + for (size_t i = 0; i < n; i++) { + const uint8_t byte = (*key)[i]; + if (byte != static_cast(0xff)) { + (*key)[i] = byte + 1; + key->resize(i+1); + return; + } + } + // *key is a run of 0xffs. Leave it alone. + } +}; +} // namespace + +static port::OnceType once = LEVELDB_ONCE_INIT; +static const Comparator* bytewise; + +static void InitModule() { + bytewise = new BytewiseComparatorImpl; +} + +const Comparator* BytewiseComparator() { + port::InitOnce(&once, InitModule); + return bytewise; +} + +} // namespace leveldb diff --git a/src/leveldb/util/crc32c.cc b/src/leveldb/util/crc32c.cc new file mode 100644 index 0000000..6db9e77 --- /dev/null +++ b/src/leveldb/util/crc32c.cc @@ -0,0 +1,332 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. +// +// A portable implementation of crc32c, optimized to handle +// four bytes at a time. + +#include "util/crc32c.h" + +#include +#include "util/coding.h" + +namespace leveldb { +namespace crc32c { + +static const uint32_t table0_[256] = { + 0x00000000, 0xf26b8303, 0xe13b70f7, 0x1350f3f4, + 0xc79a971f, 0x35f1141c, 0x26a1e7e8, 0xd4ca64eb, + 0x8ad958cf, 0x78b2dbcc, 0x6be22838, 0x9989ab3b, + 0x4d43cfd0, 0xbf284cd3, 0xac78bf27, 0x5e133c24, + 0x105ec76f, 0xe235446c, 0xf165b798, 0x030e349b, + 0xd7c45070, 0x25afd373, 0x36ff2087, 0xc494a384, + 0x9a879fa0, 0x68ec1ca3, 0x7bbcef57, 0x89d76c54, + 0x5d1d08bf, 0xaf768bbc, 0xbc267848, 0x4e4dfb4b, + 0x20bd8ede, 0xd2d60ddd, 0xc186fe29, 0x33ed7d2a, + 0xe72719c1, 0x154c9ac2, 0x061c6936, 0xf477ea35, + 0xaa64d611, 0x580f5512, 0x4b5fa6e6, 0xb93425e5, + 0x6dfe410e, 0x9f95c20d, 0x8cc531f9, 0x7eaeb2fa, + 0x30e349b1, 0xc288cab2, 0xd1d83946, 0x23b3ba45, + 0xf779deae, 0x05125dad, 0x1642ae59, 0xe4292d5a, + 0xba3a117e, 0x4851927d, 0x5b016189, 0xa96ae28a, + 0x7da08661, 0x8fcb0562, 0x9c9bf696, 0x6ef07595, + 0x417b1dbc, 0xb3109ebf, 0xa0406d4b, 0x522bee48, + 0x86e18aa3, 0x748a09a0, 0x67dafa54, 0x95b17957, + 0xcba24573, 0x39c9c670, 0x2a993584, 0xd8f2b687, + 0x0c38d26c, 0xfe53516f, 0xed03a29b, 0x1f682198, + 0x5125dad3, 0xa34e59d0, 0xb01eaa24, 0x42752927, + 0x96bf4dcc, 0x64d4cecf, 0x77843d3b, 0x85efbe38, + 0xdbfc821c, 0x2997011f, 0x3ac7f2eb, 0xc8ac71e8, + 0x1c661503, 0xee0d9600, 0xfd5d65f4, 0x0f36e6f7, + 0x61c69362, 0x93ad1061, 0x80fde395, 0x72966096, + 0xa65c047d, 0x5437877e, 0x4767748a, 0xb50cf789, + 0xeb1fcbad, 0x197448ae, 0x0a24bb5a, 0xf84f3859, + 0x2c855cb2, 0xdeeedfb1, 0xcdbe2c45, 0x3fd5af46, + 0x7198540d, 0x83f3d70e, 0x90a324fa, 0x62c8a7f9, + 0xb602c312, 0x44694011, 0x5739b3e5, 0xa55230e6, + 0xfb410cc2, 0x092a8fc1, 0x1a7a7c35, 0xe811ff36, + 0x3cdb9bdd, 0xceb018de, 0xdde0eb2a, 0x2f8b6829, + 0x82f63b78, 0x709db87b, 0x63cd4b8f, 0x91a6c88c, + 0x456cac67, 0xb7072f64, 0xa457dc90, 0x563c5f93, + 0x082f63b7, 0xfa44e0b4, 0xe9141340, 0x1b7f9043, + 0xcfb5f4a8, 0x3dde77ab, 0x2e8e845f, 0xdce5075c, + 0x92a8fc17, 0x60c37f14, 0x73938ce0, 0x81f80fe3, + 0x55326b08, 0xa759e80b, 0xb4091bff, 0x466298fc, + 0x1871a4d8, 0xea1a27db, 0xf94ad42f, 0x0b21572c, + 0xdfeb33c7, 0x2d80b0c4, 0x3ed04330, 0xccbbc033, + 0xa24bb5a6, 0x502036a5, 0x4370c551, 0xb11b4652, + 0x65d122b9, 0x97baa1ba, 0x84ea524e, 0x7681d14d, + 0x2892ed69, 0xdaf96e6a, 0xc9a99d9e, 0x3bc21e9d, + 0xef087a76, 0x1d63f975, 0x0e330a81, 0xfc588982, + 0xb21572c9, 0x407ef1ca, 0x532e023e, 0xa145813d, + 0x758fe5d6, 0x87e466d5, 0x94b49521, 0x66df1622, + 0x38cc2a06, 0xcaa7a905, 0xd9f75af1, 0x2b9cd9f2, + 0xff56bd19, 0x0d3d3e1a, 0x1e6dcdee, 0xec064eed, + 0xc38d26c4, 0x31e6a5c7, 0x22b65633, 0xd0ddd530, + 0x0417b1db, 0xf67c32d8, 0xe52cc12c, 0x1747422f, + 0x49547e0b, 0xbb3ffd08, 0xa86f0efc, 0x5a048dff, + 0x8ecee914, 0x7ca56a17, 0x6ff599e3, 0x9d9e1ae0, + 0xd3d3e1ab, 0x21b862a8, 0x32e8915c, 0xc083125f, + 0x144976b4, 0xe622f5b7, 0xf5720643, 0x07198540, + 0x590ab964, 0xab613a67, 0xb831c993, 0x4a5a4a90, + 0x9e902e7b, 0x6cfbad78, 0x7fab5e8c, 0x8dc0dd8f, + 0xe330a81a, 0x115b2b19, 0x020bd8ed, 0xf0605bee, + 0x24aa3f05, 0xd6c1bc06, 0xc5914ff2, 0x37faccf1, + 0x69e9f0d5, 0x9b8273d6, 0x88d28022, 0x7ab90321, + 0xae7367ca, 0x5c18e4c9, 0x4f48173d, 0xbd23943e, + 0xf36e6f75, 0x0105ec76, 0x12551f82, 0xe03e9c81, + 0x34f4f86a, 0xc69f7b69, 0xd5cf889d, 0x27a40b9e, + 0x79b737ba, 0x8bdcb4b9, 0x988c474d, 0x6ae7c44e, + 0xbe2da0a5, 0x4c4623a6, 0x5f16d052, 0xad7d5351 +}; +static const uint32_t table1_[256] = { + 0x00000000, 0x13a29877, 0x274530ee, 0x34e7a899, + 0x4e8a61dc, 0x5d28f9ab, 0x69cf5132, 0x7a6dc945, + 0x9d14c3b8, 0x8eb65bcf, 0xba51f356, 0xa9f36b21, + 0xd39ea264, 0xc03c3a13, 0xf4db928a, 0xe7790afd, + 0x3fc5f181, 0x2c6769f6, 0x1880c16f, 0x0b225918, + 0x714f905d, 0x62ed082a, 0x560aa0b3, 0x45a838c4, + 0xa2d13239, 0xb173aa4e, 0x859402d7, 0x96369aa0, + 0xec5b53e5, 0xfff9cb92, 0xcb1e630b, 0xd8bcfb7c, + 0x7f8be302, 0x6c297b75, 0x58ced3ec, 0x4b6c4b9b, + 0x310182de, 0x22a31aa9, 0x1644b230, 0x05e62a47, + 0xe29f20ba, 0xf13db8cd, 0xc5da1054, 0xd6788823, + 0xac154166, 0xbfb7d911, 0x8b507188, 0x98f2e9ff, + 0x404e1283, 0x53ec8af4, 0x670b226d, 0x74a9ba1a, + 0x0ec4735f, 0x1d66eb28, 0x298143b1, 0x3a23dbc6, + 0xdd5ad13b, 0xcef8494c, 0xfa1fe1d5, 0xe9bd79a2, + 0x93d0b0e7, 0x80722890, 0xb4958009, 0xa737187e, + 0xff17c604, 0xecb55e73, 0xd852f6ea, 0xcbf06e9d, + 0xb19da7d8, 0xa23f3faf, 0x96d89736, 0x857a0f41, + 0x620305bc, 0x71a19dcb, 0x45463552, 0x56e4ad25, + 0x2c896460, 0x3f2bfc17, 0x0bcc548e, 0x186eccf9, + 0xc0d23785, 0xd370aff2, 0xe797076b, 0xf4359f1c, + 0x8e585659, 0x9dface2e, 0xa91d66b7, 0xbabffec0, + 0x5dc6f43d, 0x4e646c4a, 0x7a83c4d3, 0x69215ca4, + 0x134c95e1, 0x00ee0d96, 0x3409a50f, 0x27ab3d78, + 0x809c2506, 0x933ebd71, 0xa7d915e8, 0xb47b8d9f, + 0xce1644da, 0xddb4dcad, 0xe9537434, 0xfaf1ec43, + 0x1d88e6be, 0x0e2a7ec9, 0x3acdd650, 0x296f4e27, + 0x53028762, 0x40a01f15, 0x7447b78c, 0x67e52ffb, + 0xbf59d487, 0xacfb4cf0, 0x981ce469, 0x8bbe7c1e, + 0xf1d3b55b, 0xe2712d2c, 0xd69685b5, 0xc5341dc2, + 0x224d173f, 0x31ef8f48, 0x050827d1, 0x16aabfa6, + 0x6cc776e3, 0x7f65ee94, 0x4b82460d, 0x5820de7a, + 0xfbc3faf9, 0xe861628e, 0xdc86ca17, 0xcf245260, + 0xb5499b25, 0xa6eb0352, 0x920cabcb, 0x81ae33bc, + 0x66d73941, 0x7575a136, 0x419209af, 0x523091d8, + 0x285d589d, 0x3bffc0ea, 0x0f186873, 0x1cbaf004, + 0xc4060b78, 0xd7a4930f, 0xe3433b96, 0xf0e1a3e1, + 0x8a8c6aa4, 0x992ef2d3, 0xadc95a4a, 0xbe6bc23d, + 0x5912c8c0, 0x4ab050b7, 0x7e57f82e, 0x6df56059, + 0x1798a91c, 0x043a316b, 0x30dd99f2, 0x237f0185, + 0x844819fb, 0x97ea818c, 0xa30d2915, 0xb0afb162, + 0xcac27827, 0xd960e050, 0xed8748c9, 0xfe25d0be, + 0x195cda43, 0x0afe4234, 0x3e19eaad, 0x2dbb72da, + 0x57d6bb9f, 0x447423e8, 0x70938b71, 0x63311306, + 0xbb8de87a, 0xa82f700d, 0x9cc8d894, 0x8f6a40e3, + 0xf50789a6, 0xe6a511d1, 0xd242b948, 0xc1e0213f, + 0x26992bc2, 0x353bb3b5, 0x01dc1b2c, 0x127e835b, + 0x68134a1e, 0x7bb1d269, 0x4f567af0, 0x5cf4e287, + 0x04d43cfd, 0x1776a48a, 0x23910c13, 0x30339464, + 0x4a5e5d21, 0x59fcc556, 0x6d1b6dcf, 0x7eb9f5b8, + 0x99c0ff45, 0x8a626732, 0xbe85cfab, 0xad2757dc, + 0xd74a9e99, 0xc4e806ee, 0xf00fae77, 0xe3ad3600, + 0x3b11cd7c, 0x28b3550b, 0x1c54fd92, 0x0ff665e5, + 0x759baca0, 0x663934d7, 0x52de9c4e, 0x417c0439, + 0xa6050ec4, 0xb5a796b3, 0x81403e2a, 0x92e2a65d, + 0xe88f6f18, 0xfb2df76f, 0xcfca5ff6, 0xdc68c781, + 0x7b5fdfff, 0x68fd4788, 0x5c1aef11, 0x4fb87766, + 0x35d5be23, 0x26772654, 0x12908ecd, 0x013216ba, + 0xe64b1c47, 0xf5e98430, 0xc10e2ca9, 0xd2acb4de, + 0xa8c17d9b, 0xbb63e5ec, 0x8f844d75, 0x9c26d502, + 0x449a2e7e, 0x5738b609, 0x63df1e90, 0x707d86e7, + 0x0a104fa2, 0x19b2d7d5, 0x2d557f4c, 0x3ef7e73b, + 0xd98eedc6, 0xca2c75b1, 0xfecbdd28, 0xed69455f, + 0x97048c1a, 0x84a6146d, 0xb041bcf4, 0xa3e32483 +}; +static const uint32_t table2_[256] = { + 0x00000000, 0xa541927e, 0x4f6f520d, 0xea2ec073, + 0x9edea41a, 0x3b9f3664, 0xd1b1f617, 0x74f06469, + 0x38513ec5, 0x9d10acbb, 0x773e6cc8, 0xd27ffeb6, + 0xa68f9adf, 0x03ce08a1, 0xe9e0c8d2, 0x4ca15aac, + 0x70a27d8a, 0xd5e3eff4, 0x3fcd2f87, 0x9a8cbdf9, + 0xee7cd990, 0x4b3d4bee, 0xa1138b9d, 0x045219e3, + 0x48f3434f, 0xedb2d131, 0x079c1142, 0xa2dd833c, + 0xd62de755, 0x736c752b, 0x9942b558, 0x3c032726, + 0xe144fb14, 0x4405696a, 0xae2ba919, 0x0b6a3b67, + 0x7f9a5f0e, 0xdadbcd70, 0x30f50d03, 0x95b49f7d, + 0xd915c5d1, 0x7c5457af, 0x967a97dc, 0x333b05a2, + 0x47cb61cb, 0xe28af3b5, 0x08a433c6, 0xade5a1b8, + 0x91e6869e, 0x34a714e0, 0xde89d493, 0x7bc846ed, + 0x0f382284, 0xaa79b0fa, 0x40577089, 0xe516e2f7, + 0xa9b7b85b, 0x0cf62a25, 0xe6d8ea56, 0x43997828, + 0x37691c41, 0x92288e3f, 0x78064e4c, 0xdd47dc32, + 0xc76580d9, 0x622412a7, 0x880ad2d4, 0x2d4b40aa, + 0x59bb24c3, 0xfcfab6bd, 0x16d476ce, 0xb395e4b0, + 0xff34be1c, 0x5a752c62, 0xb05bec11, 0x151a7e6f, + 0x61ea1a06, 0xc4ab8878, 0x2e85480b, 0x8bc4da75, + 0xb7c7fd53, 0x12866f2d, 0xf8a8af5e, 0x5de93d20, + 0x29195949, 0x8c58cb37, 0x66760b44, 0xc337993a, + 0x8f96c396, 0x2ad751e8, 0xc0f9919b, 0x65b803e5, + 0x1148678c, 0xb409f5f2, 0x5e273581, 0xfb66a7ff, + 0x26217bcd, 0x8360e9b3, 0x694e29c0, 0xcc0fbbbe, + 0xb8ffdfd7, 0x1dbe4da9, 0xf7908dda, 0x52d11fa4, + 0x1e704508, 0xbb31d776, 0x511f1705, 0xf45e857b, + 0x80aee112, 0x25ef736c, 0xcfc1b31f, 0x6a802161, + 0x56830647, 0xf3c29439, 0x19ec544a, 0xbcadc634, + 0xc85da25d, 0x6d1c3023, 0x8732f050, 0x2273622e, + 0x6ed23882, 0xcb93aafc, 0x21bd6a8f, 0x84fcf8f1, + 0xf00c9c98, 0x554d0ee6, 0xbf63ce95, 0x1a225ceb, + 0x8b277743, 0x2e66e53d, 0xc448254e, 0x6109b730, + 0x15f9d359, 0xb0b84127, 0x5a968154, 0xffd7132a, + 0xb3764986, 0x1637dbf8, 0xfc191b8b, 0x595889f5, + 0x2da8ed9c, 0x88e97fe2, 0x62c7bf91, 0xc7862def, + 0xfb850ac9, 0x5ec498b7, 0xb4ea58c4, 0x11abcaba, + 0x655baed3, 0xc01a3cad, 0x2a34fcde, 0x8f756ea0, + 0xc3d4340c, 0x6695a672, 0x8cbb6601, 0x29faf47f, + 0x5d0a9016, 0xf84b0268, 0x1265c21b, 0xb7245065, + 0x6a638c57, 0xcf221e29, 0x250cde5a, 0x804d4c24, + 0xf4bd284d, 0x51fcba33, 0xbbd27a40, 0x1e93e83e, + 0x5232b292, 0xf77320ec, 0x1d5de09f, 0xb81c72e1, + 0xccec1688, 0x69ad84f6, 0x83834485, 0x26c2d6fb, + 0x1ac1f1dd, 0xbf8063a3, 0x55aea3d0, 0xf0ef31ae, + 0x841f55c7, 0x215ec7b9, 0xcb7007ca, 0x6e3195b4, + 0x2290cf18, 0x87d15d66, 0x6dff9d15, 0xc8be0f6b, + 0xbc4e6b02, 0x190ff97c, 0xf321390f, 0x5660ab71, + 0x4c42f79a, 0xe90365e4, 0x032da597, 0xa66c37e9, + 0xd29c5380, 0x77ddc1fe, 0x9df3018d, 0x38b293f3, + 0x7413c95f, 0xd1525b21, 0x3b7c9b52, 0x9e3d092c, + 0xeacd6d45, 0x4f8cff3b, 0xa5a23f48, 0x00e3ad36, + 0x3ce08a10, 0x99a1186e, 0x738fd81d, 0xd6ce4a63, + 0xa23e2e0a, 0x077fbc74, 0xed517c07, 0x4810ee79, + 0x04b1b4d5, 0xa1f026ab, 0x4bdee6d8, 0xee9f74a6, + 0x9a6f10cf, 0x3f2e82b1, 0xd50042c2, 0x7041d0bc, + 0xad060c8e, 0x08479ef0, 0xe2695e83, 0x4728ccfd, + 0x33d8a894, 0x96993aea, 0x7cb7fa99, 0xd9f668e7, + 0x9557324b, 0x3016a035, 0xda386046, 0x7f79f238, + 0x0b899651, 0xaec8042f, 0x44e6c45c, 0xe1a75622, + 0xdda47104, 0x78e5e37a, 0x92cb2309, 0x378ab177, + 0x437ad51e, 0xe63b4760, 0x0c158713, 0xa954156d, + 0xe5f54fc1, 0x40b4ddbf, 0xaa9a1dcc, 0x0fdb8fb2, + 0x7b2bebdb, 0xde6a79a5, 0x3444b9d6, 0x91052ba8 +}; +static const uint32_t table3_[256] = { + 0x00000000, 0xdd45aab8, 0xbf672381, 0x62228939, + 0x7b2231f3, 0xa6679b4b, 0xc4451272, 0x1900b8ca, + 0xf64463e6, 0x2b01c95e, 0x49234067, 0x9466eadf, + 0x8d665215, 0x5023f8ad, 0x32017194, 0xef44db2c, + 0xe964b13d, 0x34211b85, 0x560392bc, 0x8b463804, + 0x924680ce, 0x4f032a76, 0x2d21a34f, 0xf06409f7, + 0x1f20d2db, 0xc2657863, 0xa047f15a, 0x7d025be2, + 0x6402e328, 0xb9474990, 0xdb65c0a9, 0x06206a11, + 0xd725148b, 0x0a60be33, 0x6842370a, 0xb5079db2, + 0xac072578, 0x71428fc0, 0x136006f9, 0xce25ac41, + 0x2161776d, 0xfc24ddd5, 0x9e0654ec, 0x4343fe54, + 0x5a43469e, 0x8706ec26, 0xe524651f, 0x3861cfa7, + 0x3e41a5b6, 0xe3040f0e, 0x81268637, 0x5c632c8f, + 0x45639445, 0x98263efd, 0xfa04b7c4, 0x27411d7c, + 0xc805c650, 0x15406ce8, 0x7762e5d1, 0xaa274f69, + 0xb327f7a3, 0x6e625d1b, 0x0c40d422, 0xd1057e9a, + 0xaba65fe7, 0x76e3f55f, 0x14c17c66, 0xc984d6de, + 0xd0846e14, 0x0dc1c4ac, 0x6fe34d95, 0xb2a6e72d, + 0x5de23c01, 0x80a796b9, 0xe2851f80, 0x3fc0b538, + 0x26c00df2, 0xfb85a74a, 0x99a72e73, 0x44e284cb, + 0x42c2eeda, 0x9f874462, 0xfda5cd5b, 0x20e067e3, + 0x39e0df29, 0xe4a57591, 0x8687fca8, 0x5bc25610, + 0xb4868d3c, 0x69c32784, 0x0be1aebd, 0xd6a40405, + 0xcfa4bccf, 0x12e11677, 0x70c39f4e, 0xad8635f6, + 0x7c834b6c, 0xa1c6e1d4, 0xc3e468ed, 0x1ea1c255, + 0x07a17a9f, 0xdae4d027, 0xb8c6591e, 0x6583f3a6, + 0x8ac7288a, 0x57828232, 0x35a00b0b, 0xe8e5a1b3, + 0xf1e51979, 0x2ca0b3c1, 0x4e823af8, 0x93c79040, + 0x95e7fa51, 0x48a250e9, 0x2a80d9d0, 0xf7c57368, + 0xeec5cba2, 0x3380611a, 0x51a2e823, 0x8ce7429b, + 0x63a399b7, 0xbee6330f, 0xdcc4ba36, 0x0181108e, + 0x1881a844, 0xc5c402fc, 0xa7e68bc5, 0x7aa3217d, + 0x52a0c93f, 0x8fe56387, 0xedc7eabe, 0x30824006, + 0x2982f8cc, 0xf4c75274, 0x96e5db4d, 0x4ba071f5, + 0xa4e4aad9, 0x79a10061, 0x1b838958, 0xc6c623e0, + 0xdfc69b2a, 0x02833192, 0x60a1b8ab, 0xbde41213, + 0xbbc47802, 0x6681d2ba, 0x04a35b83, 0xd9e6f13b, + 0xc0e649f1, 0x1da3e349, 0x7f816a70, 0xa2c4c0c8, + 0x4d801be4, 0x90c5b15c, 0xf2e73865, 0x2fa292dd, + 0x36a22a17, 0xebe780af, 0x89c50996, 0x5480a32e, + 0x8585ddb4, 0x58c0770c, 0x3ae2fe35, 0xe7a7548d, + 0xfea7ec47, 0x23e246ff, 0x41c0cfc6, 0x9c85657e, + 0x73c1be52, 0xae8414ea, 0xcca69dd3, 0x11e3376b, + 0x08e38fa1, 0xd5a62519, 0xb784ac20, 0x6ac10698, + 0x6ce16c89, 0xb1a4c631, 0xd3864f08, 0x0ec3e5b0, + 0x17c35d7a, 0xca86f7c2, 0xa8a47efb, 0x75e1d443, + 0x9aa50f6f, 0x47e0a5d7, 0x25c22cee, 0xf8878656, + 0xe1873e9c, 0x3cc29424, 0x5ee01d1d, 0x83a5b7a5, + 0xf90696d8, 0x24433c60, 0x4661b559, 0x9b241fe1, + 0x8224a72b, 0x5f610d93, 0x3d4384aa, 0xe0062e12, + 0x0f42f53e, 0xd2075f86, 0xb025d6bf, 0x6d607c07, + 0x7460c4cd, 0xa9256e75, 0xcb07e74c, 0x16424df4, + 0x106227e5, 0xcd278d5d, 0xaf050464, 0x7240aedc, + 0x6b401616, 0xb605bcae, 0xd4273597, 0x09629f2f, + 0xe6264403, 0x3b63eebb, 0x59416782, 0x8404cd3a, + 0x9d0475f0, 0x4041df48, 0x22635671, 0xff26fcc9, + 0x2e238253, 0xf36628eb, 0x9144a1d2, 0x4c010b6a, + 0x5501b3a0, 0x88441918, 0xea669021, 0x37233a99, + 0xd867e1b5, 0x05224b0d, 0x6700c234, 0xba45688c, + 0xa345d046, 0x7e007afe, 0x1c22f3c7, 0xc167597f, + 0xc747336e, 0x1a0299d6, 0x782010ef, 0xa565ba57, + 0xbc65029d, 0x6120a825, 0x0302211c, 0xde478ba4, + 0x31035088, 0xec46fa30, 0x8e647309, 0x5321d9b1, + 0x4a21617b, 0x9764cbc3, 0xf54642fa, 0x2803e842 +}; + +// Used to fetch a naturally-aligned 32-bit word in little endian byte-order +static inline uint32_t LE_LOAD32(const uint8_t *p) { + return DecodeFixed32(reinterpret_cast(p)); +} + +uint32_t Extend(uint32_t crc, const char* buf, size_t size) { + const uint8_t *p = reinterpret_cast(buf); + const uint8_t *e = p + size; + uint32_t l = crc ^ 0xffffffffu; + +#define STEP1 do { \ + int c = (l & 0xff) ^ *p++; \ + l = table0_[c] ^ (l >> 8); \ +} while (0) +#define STEP4 do { \ + uint32_t c = l ^ LE_LOAD32(p); \ + p += 4; \ + l = table3_[c & 0xff] ^ \ + table2_[(c >> 8) & 0xff] ^ \ + table1_[(c >> 16) & 0xff] ^ \ + table0_[c >> 24]; \ +} while (0) + + // Point x at first 4-byte aligned byte in string. This might be + // just past the end of the string. + const uintptr_t pval = reinterpret_cast(p); + const uint8_t* x = reinterpret_cast(((pval + 3) >> 2) << 2); + if (x <= e) { + // Process bytes until finished or p is 4-byte aligned + while (p != x) { + STEP1; + } + } + // Process bytes 16 at a time + while ((e-p) >= 16) { + STEP4; STEP4; STEP4; STEP4; + } + // Process bytes 4 at a time + while ((e-p) >= 4) { + STEP4; + } + // Process the last few bytes + while (p != e) { + STEP1; + } +#undef STEP4 +#undef STEP1 + return l ^ 0xffffffffu; +} + +} // namespace crc32c +} // namespace leveldb diff --git a/src/leveldb/util/crc32c.h b/src/leveldb/util/crc32c.h new file mode 100644 index 0000000..1d7e5c0 --- /dev/null +++ b/src/leveldb/util/crc32c.h @@ -0,0 +1,45 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#ifndef STORAGE_LEVELDB_UTIL_CRC32C_H_ +#define STORAGE_LEVELDB_UTIL_CRC32C_H_ + +#include +#include + +namespace leveldb { +namespace crc32c { + +// Return the crc32c of concat(A, data[0,n-1]) where init_crc is the +// crc32c of some string A. Extend() is often used to maintain the +// crc32c of a stream of data. +extern uint32_t Extend(uint32_t init_crc, const char* data, size_t n); + +// Return the crc32c of data[0,n-1] +inline uint32_t Value(const char* data, size_t n) { + return Extend(0, data, n); +} + +static const uint32_t kMaskDelta = 0xa282ead8ul; + +// Return a masked representation of crc. +// +// Motivation: it is problematic to compute the CRC of a string that +// contains embedded CRCs. Therefore we recommend that CRCs stored +// somewhere (e.g., in files) should be masked before being stored. +inline uint32_t Mask(uint32_t crc) { + // Rotate right by 15 bits and add a constant. + return ((crc >> 15) | (crc << 17)) + kMaskDelta; +} + +// Return the crc whose masked representation is masked_crc. +inline uint32_t Unmask(uint32_t masked_crc) { + uint32_t rot = masked_crc - kMaskDelta; + return ((rot >> 17) | (rot << 15)); +} + +} // namespace crc32c +} // namespace leveldb + +#endif // STORAGE_LEVELDB_UTIL_CRC32C_H_ diff --git a/src/leveldb/util/crc32c_test.cc b/src/leveldb/util/crc32c_test.cc new file mode 100644 index 0000000..4b957ee --- /dev/null +++ b/src/leveldb/util/crc32c_test.cc @@ -0,0 +1,72 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "util/crc32c.h" +#include "util/testharness.h" + +namespace leveldb { +namespace crc32c { + +class CRC { }; + +TEST(CRC, StandardResults) { + // From rfc3720 section B.4. + char buf[32]; + + memset(buf, 0, sizeof(buf)); + ASSERT_EQ(0x8a9136aa, Value(buf, sizeof(buf))); + + memset(buf, 0xff, sizeof(buf)); + ASSERT_EQ(0x62a8ab43, Value(buf, sizeof(buf))); + + for (int i = 0; i < 32; i++) { + buf[i] = i; + } + ASSERT_EQ(0x46dd794e, Value(buf, sizeof(buf))); + + for (int i = 0; i < 32; i++) { + buf[i] = 31 - i; + } + ASSERT_EQ(0x113fdb5c, Value(buf, sizeof(buf))); + + unsigned char data[48] = { + 0x01, 0xc0, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x14, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x04, 0x00, + 0x00, 0x00, 0x00, 0x14, + 0x00, 0x00, 0x00, 0x18, + 0x28, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + }; + ASSERT_EQ(0xd9963a56, Value(reinterpret_cast(data), sizeof(data))); +} + +TEST(CRC, Values) { + ASSERT_NE(Value("a", 1), Value("foo", 3)); +} + +TEST(CRC, Extend) { + ASSERT_EQ(Value("hello world", 11), + Extend(Value("hello ", 6), "world", 5)); +} + +TEST(CRC, Mask) { + uint32_t crc = Value("foo", 3); + ASSERT_NE(crc, Mask(crc)); + ASSERT_NE(crc, Mask(Mask(crc))); + ASSERT_EQ(crc, Unmask(Mask(crc))); + ASSERT_EQ(crc, Unmask(Unmask(Mask(Mask(crc))))); +} + +} // namespace crc32c +} // namespace leveldb + +int main(int argc, char** argv) { + return leveldb::test::RunAllTests(); +} diff --git a/src/leveldb/util/env.cc b/src/leveldb/util/env.cc new file mode 100644 index 0000000..c2600e9 --- /dev/null +++ b/src/leveldb/util/env.cc @@ -0,0 +1,96 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "leveldb/env.h" + +namespace leveldb { + +Env::~Env() { +} + +SequentialFile::~SequentialFile() { +} + +RandomAccessFile::~RandomAccessFile() { +} + +WritableFile::~WritableFile() { +} + +Logger::~Logger() { +} + +FileLock::~FileLock() { +} + +void Log(Logger* info_log, const char* format, ...) { + if (info_log != NULL) { + va_list ap; + va_start(ap, format); + info_log->Logv(format, ap); + va_end(ap); + } +} + +static Status DoWriteStringToFile(Env* env, const Slice& data, + const std::string& fname, + bool should_sync) { + WritableFile* file; + Status s = env->NewWritableFile(fname, &file); + if (!s.ok()) { + return s; + } + s = file->Append(data); + if (s.ok() && should_sync) { + s = file->Sync(); + } + if (s.ok()) { + s = file->Close(); + } + delete file; // Will auto-close if we did not close above + if (!s.ok()) { + env->DeleteFile(fname); + } + return s; +} + +Status WriteStringToFile(Env* env, const Slice& data, + const std::string& fname) { + return DoWriteStringToFile(env, data, fname, false); +} + +Status WriteStringToFileSync(Env* env, const Slice& data, + const std::string& fname) { + return DoWriteStringToFile(env, data, fname, true); +} + +Status ReadFileToString(Env* env, const std::string& fname, std::string* data) { + data->clear(); + SequentialFile* file; + Status s = env->NewSequentialFile(fname, &file); + if (!s.ok()) { + return s; + } + static const int kBufferSize = 8192; + char* space = new char[kBufferSize]; + while (true) { + Slice fragment; + s = file->Read(kBufferSize, &fragment, space); + if (!s.ok()) { + break; + } + data->append(fragment.data(), fragment.size()); + if (fragment.empty()) { + break; + } + } + delete[] space; + delete file; + return s; +} + +EnvWrapper::~EnvWrapper() { +} + +} // namespace leveldb diff --git a/src/leveldb/util/env_posix.cc b/src/leveldb/util/env_posix.cc new file mode 100644 index 0000000..93eadb1 --- /dev/null +++ b/src/leveldb/util/env_posix.cc @@ -0,0 +1,610 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. +#if !defined(LEVELDB_PLATFORM_WINDOWS) + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if defined(LEVELDB_PLATFORM_ANDROID) +#include +#endif +#include "leveldb/env.h" +#include "leveldb/slice.h" +#include "port/port.h" +#include "util/logging.h" +#include "util/mutexlock.h" +#include "util/posix_logger.h" + +namespace leveldb { + +namespace { + +static Status IOError(const std::string& context, int err_number) { + return Status::IOError(context, strerror(err_number)); +} + +class PosixSequentialFile: public SequentialFile { + private: + std::string filename_; + FILE* file_; + + public: + PosixSequentialFile(const std::string& fname, FILE* f) + : filename_(fname), file_(f) { } + virtual ~PosixSequentialFile() { fclose(file_); } + + virtual Status Read(size_t n, Slice* result, char* scratch) { + Status s; + size_t r = fread_unlocked(scratch, 1, n, file_); + *result = Slice(scratch, r); + if (r < n) { + if (feof(file_)) { + // We leave status as ok if we hit the end of the file + } else { + // A partial read with an error: return a non-ok status + s = IOError(filename_, errno); + } + } + return s; + } + + virtual Status Skip(uint64_t n) { + if (fseek(file_, n, SEEK_CUR)) { + return IOError(filename_, errno); + } + return Status::OK(); + } +}; + +// pread() based random-access +class PosixRandomAccessFile: public RandomAccessFile { + private: + std::string filename_; + int fd_; + + public: + PosixRandomAccessFile(const std::string& fname, int fd) + : filename_(fname), fd_(fd) { } + virtual ~PosixRandomAccessFile() { close(fd_); } + + virtual Status Read(uint64_t offset, size_t n, Slice* result, + char* scratch) const { + Status s; + ssize_t r = pread(fd_, scratch, n, static_cast(offset)); + *result = Slice(scratch, (r < 0) ? 0 : r); + if (r < 0) { + // An error: return a non-ok status + s = IOError(filename_, errno); + } + return s; + } +}; + +// Helper class to limit mmap file usage so that we do not end up +// running out virtual memory or running into kernel performance +// problems for very large databases. +class MmapLimiter { + public: + // Up to 1000 mmaps for 64-bit binaries; none for smaller pointer sizes. + MmapLimiter() { + SetAllowed(sizeof(void*) >= 8 ? 1000 : 0); + } + + // If another mmap slot is available, acquire it and return true. + // Else return false. + bool Acquire() { + if (GetAllowed() <= 0) { + return false; + } + MutexLock l(&mu_); + intptr_t x = GetAllowed(); + if (x <= 0) { + return false; + } else { + SetAllowed(x - 1); + return true; + } + } + + // Release a slot acquired by a previous call to Acquire() that returned true. + void Release() { + MutexLock l(&mu_); + SetAllowed(GetAllowed() + 1); + } + + private: + port::Mutex mu_; + port::AtomicPointer allowed_; + + intptr_t GetAllowed() const { + return reinterpret_cast(allowed_.Acquire_Load()); + } + + // REQUIRES: mu_ must be held + void SetAllowed(intptr_t v) { + allowed_.Release_Store(reinterpret_cast(v)); + } + + MmapLimiter(const MmapLimiter&); + void operator=(const MmapLimiter&); +}; + +// mmap() based random-access +class PosixMmapReadableFile: public RandomAccessFile { + private: + std::string filename_; + void* mmapped_region_; + size_t length_; + MmapLimiter* limiter_; + + public: + // base[0,length-1] contains the mmapped contents of the file. + PosixMmapReadableFile(const std::string& fname, void* base, size_t length, + MmapLimiter* limiter) + : filename_(fname), mmapped_region_(base), length_(length), + limiter_(limiter) { + } + + virtual ~PosixMmapReadableFile() { + munmap(mmapped_region_, length_); + limiter_->Release(); + } + + virtual Status Read(uint64_t offset, size_t n, Slice* result, + char* scratch) const { + Status s; + if (offset + n > length_) { + *result = Slice(); + s = IOError(filename_, EINVAL); + } else { + *result = Slice(reinterpret_cast(mmapped_region_) + offset, n); + } + return s; + } +}; + +class PosixWritableFile : public WritableFile { + private: + std::string filename_; + FILE* file_; + + public: + PosixWritableFile(const std::string& fname, FILE* f) + : filename_(fname), file_(f) { } + + ~PosixWritableFile() { + if (file_ != NULL) { + // Ignoring any potential errors + fclose(file_); + } + } + + virtual Status Append(const Slice& data) { + size_t r = fwrite_unlocked(data.data(), 1, data.size(), file_); + if (r != data.size()) { + return IOError(filename_, errno); + } + return Status::OK(); + } + + virtual Status Close() { + Status result; + if (fclose(file_) != 0) { + result = IOError(filename_, errno); + } + file_ = NULL; + return result; + } + + virtual Status Flush() { + if (fflush_unlocked(file_) != 0) { + return IOError(filename_, errno); + } + return Status::OK(); + } + + Status SyncDirIfManifest() { + const char* f = filename_.c_str(); + const char* sep = strrchr(f, '/'); + Slice basename; + std::string dir; + if (sep == NULL) { + dir = "."; + basename = f; + } else { + dir = std::string(f, sep - f); + basename = sep + 1; + } + Status s; + if (basename.starts_with("MANIFEST")) { + int fd = open(dir.c_str(), O_RDONLY); + if (fd < 0) { + s = IOError(dir, errno); + } else { + if (fsync(fd) < 0) { + s = IOError(dir, errno); + } + close(fd); + } + } + return s; + } + + virtual Status Sync() { + // Ensure new files referred to by the manifest are in the filesystem. + Status s = SyncDirIfManifest(); + if (!s.ok()) { + return s; + } + if (fflush_unlocked(file_) != 0 || + fdatasync(fileno(file_)) != 0) { + s = Status::IOError(filename_, strerror(errno)); + } + return s; + } +}; + +static int LockOrUnlock(int fd, bool lock) { + errno = 0; + struct flock f; + memset(&f, 0, sizeof(f)); + f.l_type = (lock ? F_WRLCK : F_UNLCK); + f.l_whence = SEEK_SET; + f.l_start = 0; + f.l_len = 0; // Lock/unlock entire file + return fcntl(fd, F_SETLK, &f); +} + +class PosixFileLock : public FileLock { + public: + int fd_; + std::string name_; +}; + +// Set of locked files. We keep a separate set instead of just +// relying on fcntrl(F_SETLK) since fcntl(F_SETLK) does not provide +// any protection against multiple uses from the same process. +class PosixLockTable { + private: + port::Mutex mu_; + std::set locked_files_; + public: + bool Insert(const std::string& fname) { + MutexLock l(&mu_); + return locked_files_.insert(fname).second; + } + void Remove(const std::string& fname) { + MutexLock l(&mu_); + locked_files_.erase(fname); + } +}; + +class PosixEnv : public Env { + public: + PosixEnv(); + virtual ~PosixEnv() { + fprintf(stderr, "Destroying Env::Default()\n"); + abort(); + } + + virtual Status NewSequentialFile(const std::string& fname, + SequentialFile** result) { + FILE* f = fopen(fname.c_str(), "r"); + if (f == NULL) { + *result = NULL; + return IOError(fname, errno); + } else { + *result = new PosixSequentialFile(fname, f); + return Status::OK(); + } + } + + virtual Status NewRandomAccessFile(const std::string& fname, + RandomAccessFile** result) { + *result = NULL; + Status s; + int fd = open(fname.c_str(), O_RDONLY); + if (fd < 0) { + s = IOError(fname, errno); + } else if (mmap_limit_.Acquire()) { + uint64_t size; + s = GetFileSize(fname, &size); + if (s.ok()) { + void* base = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0); + if (base != MAP_FAILED) { + *result = new PosixMmapReadableFile(fname, base, size, &mmap_limit_); + } else { + s = IOError(fname, errno); + } + } + close(fd); + if (!s.ok()) { + mmap_limit_.Release(); + } + } else { + *result = new PosixRandomAccessFile(fname, fd); + } + return s; + } + + virtual Status NewWritableFile(const std::string& fname, + WritableFile** result) { + Status s; + FILE* f = fopen(fname.c_str(), "w"); + if (f == NULL) { + *result = NULL; + s = IOError(fname, errno); + } else { + *result = new PosixWritableFile(fname, f); + } + return s; + } + + virtual bool FileExists(const std::string& fname) { + return access(fname.c_str(), F_OK) == 0; + } + + virtual Status GetChildren(const std::string& dir, + std::vector* result) { + result->clear(); + DIR* d = opendir(dir.c_str()); + if (d == NULL) { + return IOError(dir, errno); + } + struct dirent* entry; + while ((entry = readdir(d)) != NULL) { + result->push_back(entry->d_name); + } + closedir(d); + return Status::OK(); + } + + virtual Status DeleteFile(const std::string& fname) { + Status result; + if (unlink(fname.c_str()) != 0) { + result = IOError(fname, errno); + } + return result; + } + + virtual Status CreateDir(const std::string& name) { + Status result; + if (mkdir(name.c_str(), 0755) != 0) { + result = IOError(name, errno); + } + return result; + } + + virtual Status DeleteDir(const std::string& name) { + Status result; + if (rmdir(name.c_str()) != 0) { + result = IOError(name, errno); + } + return result; + } + + virtual Status GetFileSize(const std::string& fname, uint64_t* size) { + Status s; + struct stat sbuf; + if (stat(fname.c_str(), &sbuf) != 0) { + *size = 0; + s = IOError(fname, errno); + } else { + *size = sbuf.st_size; + } + return s; + } + + virtual Status RenameFile(const std::string& src, const std::string& target) { + Status result; + if (rename(src.c_str(), target.c_str()) != 0) { + result = IOError(src, errno); + } + return result; + } + + virtual Status LockFile(const std::string& fname, FileLock** lock) { + *lock = NULL; + Status result; + int fd = open(fname.c_str(), O_RDWR | O_CREAT, 0644); + if (fd < 0) { + result = IOError(fname, errno); + } else if (!locks_.Insert(fname)) { + close(fd); + result = Status::IOError("lock " + fname, "already held by process"); + } else if (LockOrUnlock(fd, true) == -1) { + result = IOError("lock " + fname, errno); + close(fd); + locks_.Remove(fname); + } else { + PosixFileLock* my_lock = new PosixFileLock; + my_lock->fd_ = fd; + my_lock->name_ = fname; + *lock = my_lock; + } + return result; + } + + virtual Status UnlockFile(FileLock* lock) { + PosixFileLock* my_lock = reinterpret_cast(lock); + Status result; + if (LockOrUnlock(my_lock->fd_, false) == -1) { + result = IOError("unlock", errno); + } + locks_.Remove(my_lock->name_); + close(my_lock->fd_); + delete my_lock; + return result; + } + + virtual void Schedule(void (*function)(void*), void* arg); + + virtual void StartThread(void (*function)(void* arg), void* arg); + + virtual Status GetTestDirectory(std::string* result) { + const char* env = getenv("TEST_TMPDIR"); + if (env && env[0] != '\0') { + *result = env; + } else { + char buf[100]; + snprintf(buf, sizeof(buf), "/tmp/leveldbtest-%d", int(geteuid())); + *result = buf; + } + // Directory may already exist + CreateDir(*result); + return Status::OK(); + } + + static uint64_t gettid() { + pthread_t tid = pthread_self(); + uint64_t thread_id = 0; + memcpy(&thread_id, &tid, std::min(sizeof(thread_id), sizeof(tid))); + return thread_id; + } + + virtual Status NewLogger(const std::string& fname, Logger** result) { + FILE* f = fopen(fname.c_str(), "w"); + if (f == NULL) { + *result = NULL; + return IOError(fname, errno); + } else { + *result = new PosixLogger(f, &PosixEnv::gettid); + return Status::OK(); + } + } + + virtual uint64_t NowMicros() { + struct timeval tv; + gettimeofday(&tv, NULL); + return static_cast(tv.tv_sec) * 1000000 + tv.tv_usec; + } + + virtual void SleepForMicroseconds(int micros) { + usleep(micros); + } + + private: + void PthreadCall(const char* label, int result) { + if (result != 0) { + fprintf(stderr, "pthread %s: %s\n", label, strerror(result)); + abort(); + } + } + + // BGThread() is the body of the background thread + void BGThread(); + static void* BGThreadWrapper(void* arg) { + reinterpret_cast(arg)->BGThread(); + return NULL; + } + + pthread_mutex_t mu_; + pthread_cond_t bgsignal_; + pthread_t bgthread_; + bool started_bgthread_; + + // Entry per Schedule() call + struct BGItem { void* arg; void (*function)(void*); }; + typedef std::deque BGQueue; + BGQueue queue_; + + PosixLockTable locks_; + MmapLimiter mmap_limit_; +}; + +PosixEnv::PosixEnv() : started_bgthread_(false) { + PthreadCall("mutex_init", pthread_mutex_init(&mu_, NULL)); + PthreadCall("cvar_init", pthread_cond_init(&bgsignal_, NULL)); +} + +void PosixEnv::Schedule(void (*function)(void*), void* arg) { + PthreadCall("lock", pthread_mutex_lock(&mu_)); + + // Start background thread if necessary + if (!started_bgthread_) { + started_bgthread_ = true; + PthreadCall( + "create thread", + pthread_create(&bgthread_, NULL, &PosixEnv::BGThreadWrapper, this)); + } + + // If the queue is currently empty, the background thread may currently be + // waiting. + if (queue_.empty()) { + PthreadCall("signal", pthread_cond_signal(&bgsignal_)); + } + + // Add to priority queue + queue_.push_back(BGItem()); + queue_.back().function = function; + queue_.back().arg = arg; + + PthreadCall("unlock", pthread_mutex_unlock(&mu_)); +} + +void PosixEnv::BGThread() { + while (true) { + // Wait until there is an item that is ready to run + PthreadCall("lock", pthread_mutex_lock(&mu_)); + while (queue_.empty()) { + PthreadCall("wait", pthread_cond_wait(&bgsignal_, &mu_)); + } + + void (*function)(void*) = queue_.front().function; + void* arg = queue_.front().arg; + queue_.pop_front(); + + PthreadCall("unlock", pthread_mutex_unlock(&mu_)); + (*function)(arg); + } +} + +namespace { +struct StartThreadState { + void (*user_function)(void*); + void* arg; +}; +} +static void* StartThreadWrapper(void* arg) { + StartThreadState* state = reinterpret_cast(arg); + state->user_function(state->arg); + delete state; + return NULL; +} + +void PosixEnv::StartThread(void (*function)(void* arg), void* arg) { + pthread_t t; + StartThreadState* state = new StartThreadState; + state->user_function = function; + state->arg = arg; + PthreadCall("start thread", + pthread_create(&t, NULL, &StartThreadWrapper, state)); +} + +} // namespace + +static pthread_once_t once = PTHREAD_ONCE_INIT; +static Env* default_env; +static void InitDefaultEnv() { default_env = new PosixEnv; } + +Env* Env::Default() { + pthread_once(&once, InitDefaultEnv); + return default_env; +} + +} // namespace leveldb + +#endif diff --git a/src/leveldb/util/env_test.cc b/src/leveldb/util/env_test.cc new file mode 100644 index 0000000..b72cb44 --- /dev/null +++ b/src/leveldb/util/env_test.cc @@ -0,0 +1,104 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "leveldb/env.h" + +#include "port/port.h" +#include "util/testharness.h" + +namespace leveldb { + +static const int kDelayMicros = 100000; + +class EnvPosixTest { + private: + port::Mutex mu_; + std::string events_; + + public: + Env* env_; + EnvPosixTest() : env_(Env::Default()) { } +}; + +static void SetBool(void* ptr) { + reinterpret_cast(ptr)->NoBarrier_Store(ptr); +} + +TEST(EnvPosixTest, RunImmediately) { + port::AtomicPointer called (NULL); + env_->Schedule(&SetBool, &called); + Env::Default()->SleepForMicroseconds(kDelayMicros); + ASSERT_TRUE(called.NoBarrier_Load() != NULL); +} + +TEST(EnvPosixTest, RunMany) { + port::AtomicPointer last_id (NULL); + + struct CB { + port::AtomicPointer* last_id_ptr; // Pointer to shared slot + uintptr_t id; // Order# for the execution of this callback + + CB(port::AtomicPointer* p, int i) : last_id_ptr(p), id(i) { } + + static void Run(void* v) { + CB* cb = reinterpret_cast(v); + void* cur = cb->last_id_ptr->NoBarrier_Load(); + ASSERT_EQ(cb->id-1, reinterpret_cast(cur)); + cb->last_id_ptr->Release_Store(reinterpret_cast(cb->id)); + } + }; + + // Schedule in different order than start time + CB cb1(&last_id, 1); + CB cb2(&last_id, 2); + CB cb3(&last_id, 3); + CB cb4(&last_id, 4); + env_->Schedule(&CB::Run, &cb1); + env_->Schedule(&CB::Run, &cb2); + env_->Schedule(&CB::Run, &cb3); + env_->Schedule(&CB::Run, &cb4); + + Env::Default()->SleepForMicroseconds(kDelayMicros); + void* cur = last_id.Acquire_Load(); + ASSERT_EQ(4, reinterpret_cast(cur)); +} + +struct State { + port::Mutex mu; + int val; + int num_running; +}; + +static void ThreadBody(void* arg) { + State* s = reinterpret_cast(arg); + s->mu.Lock(); + s->val += 1; + s->num_running -= 1; + s->mu.Unlock(); +} + +TEST(EnvPosixTest, StartThread) { + State state; + state.val = 0; + state.num_running = 3; + for (int i = 0; i < 3; i++) { + env_->StartThread(&ThreadBody, &state); + } + while (true) { + state.mu.Lock(); + int num = state.num_running; + state.mu.Unlock(); + if (num == 0) { + break; + } + Env::Default()->SleepForMicroseconds(kDelayMicros); + } + ASSERT_EQ(state.val, 3); +} + +} // namespace leveldb + +int main(int argc, char** argv) { + return leveldb::test::RunAllTests(); +} diff --git a/src/leveldb/util/env_win.cc b/src/leveldb/util/env_win.cc new file mode 100644 index 0000000..ef2ecae --- /dev/null +++ b/src/leveldb/util/env_win.cc @@ -0,0 +1,1031 @@ +// This file contains source that originates from: +// http://code.google.com/p/leveldbwin/source/browse/trunk/win32_impl_src/env_win32.h +// http://code.google.com/p/leveldbwin/source/browse/trunk/win32_impl_src/port_win32.cc +// Those files dont' have any explict license headers but the +// project (http://code.google.com/p/leveldbwin/) lists the 'New BSD License' +// as the license. +#if defined(LEVELDB_PLATFORM_WINDOWS) +#include + + +#include "leveldb/env.h" + +#include "port/port.h" +#include "leveldb/slice.h" +#include "util/logging.h" + +#include +#include +#include +#include +#include +#include +#include + +#ifdef max +#undef max +#endif + +#ifndef va_copy +#define va_copy(d,s) ((d) = (s)) +#endif + +#if defined DeleteFile +#undef DeleteFile +#endif + +//Declarations +namespace leveldb +{ + +namespace Win32 +{ + +#define DISALLOW_COPY_AND_ASSIGN(TypeName) \ + TypeName(const TypeName&); \ + void operator=(const TypeName&) + +std::string GetCurrentDir(); +std::wstring GetCurrentDirW(); + +static const std::string CurrentDir = GetCurrentDir(); +static const std::wstring CurrentDirW = GetCurrentDirW(); + +std::string& ModifyPath(std::string& path); +std::wstring& ModifyPath(std::wstring& path); + +std::string GetLastErrSz(); +std::wstring GetLastErrSzW(); + +size_t GetPageSize(); + +typedef void (*ScheduleProc)(void*) ; + +struct WorkItemWrapper +{ + WorkItemWrapper(ScheduleProc proc_,void* content_); + ScheduleProc proc; + void* pContent; +}; + +DWORD WINAPI WorkItemWrapperProc(LPVOID pContent); + +class Win32SequentialFile : public SequentialFile +{ +public: + friend class Win32Env; + virtual ~Win32SequentialFile(); + virtual Status Read(size_t n, Slice* result, char* scratch); + virtual Status Skip(uint64_t n); + BOOL isEnable(); +private: + BOOL _Init(); + void _CleanUp(); + Win32SequentialFile(const std::string& fname); + std::string _filename; + ::HANDLE _hFile; + DISALLOW_COPY_AND_ASSIGN(Win32SequentialFile); +}; + +class Win32RandomAccessFile : public RandomAccessFile +{ +public: + friend class Win32Env; + virtual ~Win32RandomAccessFile(); + virtual Status Read(uint64_t offset, size_t n, Slice* result,char* scratch) const; + BOOL isEnable(); +private: + BOOL _Init(LPCWSTR path); + void _CleanUp(); + Win32RandomAccessFile(const std::string& fname); + HANDLE _hFile; + const std::string _filename; + DISALLOW_COPY_AND_ASSIGN(Win32RandomAccessFile); +}; + +class Win32MapFile : public WritableFile +{ +public: + Win32MapFile(const std::string& fname); + + ~Win32MapFile(); + virtual Status Append(const Slice& data); + virtual Status Close(); + virtual Status Flush(); + virtual Status Sync(); + BOOL isEnable(); +private: + std::string _filename; + HANDLE _hFile; + size_t _page_size; + size_t _map_size; // How much extra memory to map at a time + char* _base; // The mapped region + HANDLE _base_handle; + char* _limit; // Limit of the mapped region + char* _dst; // Where to write next (in range [base_,limit_]) + char* _last_sync; // Where have we synced up to + uint64_t _file_offset; // Offset of base_ in file + //LARGE_INTEGER file_offset_; + // Have we done an munmap of unsynced data? + bool _pending_sync; + + // Roundup x to a multiple of y + static size_t _Roundup(size_t x, size_t y); + size_t _TruncateToPageBoundary(size_t s); + bool _UnmapCurrentRegion(); + bool _MapNewRegion(); + DISALLOW_COPY_AND_ASSIGN(Win32MapFile); + BOOL _Init(LPCWSTR Path); +}; + +class Win32FileLock : public FileLock +{ +public: + friend class Win32Env; + virtual ~Win32FileLock(); + BOOL isEnable(); +private: + BOOL _Init(LPCWSTR path); + void _CleanUp(); + Win32FileLock(const std::string& fname); + HANDLE _hFile; + std::string _filename; + DISALLOW_COPY_AND_ASSIGN(Win32FileLock); +}; + +class Win32Logger : public Logger +{ +public: + friend class Win32Env; + virtual ~Win32Logger(); + virtual void Logv(const char* format, va_list ap); +private: + explicit Win32Logger(WritableFile* pFile); + WritableFile* _pFileProxy; + DISALLOW_COPY_AND_ASSIGN(Win32Logger); +}; + +class Win32Env : public Env +{ +public: + Win32Env(); + virtual ~Win32Env(); + virtual Status NewSequentialFile(const std::string& fname, + SequentialFile** result); + + virtual Status NewRandomAccessFile(const std::string& fname, + RandomAccessFile** result); + virtual Status NewWritableFile(const std::string& fname, + WritableFile** result); + + virtual bool FileExists(const std::string& fname); + + virtual Status GetChildren(const std::string& dir, + std::vector* result); + + virtual Status DeleteFile(const std::string& fname); + + virtual Status CreateDir(const std::string& dirname); + + virtual Status DeleteDir(const std::string& dirname); + + virtual Status GetFileSize(const std::string& fname, uint64_t* file_size); + + virtual Status RenameFile(const std::string& src, + const std::string& target); + + virtual Status LockFile(const std::string& fname, FileLock** lock); + + virtual Status UnlockFile(FileLock* lock); + + virtual void Schedule( + void (*function)(void* arg), + void* arg); + + virtual void StartThread(void (*function)(void* arg), void* arg); + + virtual Status GetTestDirectory(std::string* path); + + //virtual void Logv(WritableFile* log, const char* format, va_list ap); + + virtual Status NewLogger(const std::string& fname, Logger** result); + + virtual uint64_t NowMicros(); + + virtual void SleepForMicroseconds(int micros); +}; + +void ToWidePath(const std::string& value, std::wstring& target) { + wchar_t buffer[MAX_PATH]; + MultiByteToWideChar(CP_ACP, 0, value.c_str(), -1, buffer, MAX_PATH); + target = buffer; +} + +void ToNarrowPath(const std::wstring& value, std::string& target) { + char buffer[MAX_PATH]; + WideCharToMultiByte(CP_ACP, 0, value.c_str(), -1, buffer, MAX_PATH, NULL, NULL); + target = buffer; +} + +std::string GetCurrentDir() +{ + CHAR path[MAX_PATH]; + ::GetModuleFileNameA(::GetModuleHandleA(NULL),path,MAX_PATH); + *strrchr(path,'\\') = 0; + return std::string(path); +} + +std::wstring GetCurrentDirW() +{ + WCHAR path[MAX_PATH]; + ::GetModuleFileNameW(::GetModuleHandleW(NULL),path,MAX_PATH); + *wcsrchr(path,L'\\') = 0; + return std::wstring(path); +} + +std::string& ModifyPath(std::string& path) +{ + if(path[0] == '/' || path[0] == '\\'){ + path = CurrentDir + path; + } + std::replace(path.begin(),path.end(),'/','\\'); + + return path; +} + +std::wstring& ModifyPath(std::wstring& path) +{ + if(path[0] == L'/' || path[0] == L'\\'){ + path = CurrentDirW + path; + } + std::replace(path.begin(),path.end(),L'/',L'\\'); + return path; +} + +std::string GetLastErrSz() +{ + LPWSTR lpMsgBuf; + FormatMessageW( + FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, + GetLastError(), + 0, // Default language + (LPWSTR) &lpMsgBuf, + 0, + NULL + ); + std::string Err; + ToNarrowPath(lpMsgBuf, Err); + LocalFree( lpMsgBuf ); + return Err; +} + +std::wstring GetLastErrSzW() +{ + LPVOID lpMsgBuf; + FormatMessageW( + FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, + GetLastError(), + 0, // Default language + (LPWSTR) &lpMsgBuf, + 0, + NULL + ); + std::wstring Err = (LPCWSTR)lpMsgBuf; + LocalFree(lpMsgBuf); + return Err; +} + +WorkItemWrapper::WorkItemWrapper( ScheduleProc proc_,void* content_ ) : + proc(proc_),pContent(content_) +{ + +} + +DWORD WINAPI WorkItemWrapperProc(LPVOID pContent) +{ + WorkItemWrapper* item = static_cast(pContent); + ScheduleProc TempProc = item->proc; + void* arg = item->pContent; + delete item; + TempProc(arg); + return 0; +} + +size_t GetPageSize() +{ + SYSTEM_INFO si; + GetSystemInfo(&si); + return std::max(si.dwPageSize,si.dwAllocationGranularity); +} + +const size_t g_PageSize = GetPageSize(); + + +Win32SequentialFile::Win32SequentialFile( const std::string& fname ) : + _filename(fname),_hFile(NULL) +{ + _Init(); +} + +Win32SequentialFile::~Win32SequentialFile() +{ + _CleanUp(); +} + +Status Win32SequentialFile::Read( size_t n, Slice* result, char* scratch ) +{ + Status sRet; + DWORD hasRead = 0; + if(_hFile && ReadFile(_hFile,scratch,n,&hasRead,NULL) ){ + *result = Slice(scratch,hasRead); + } else { + sRet = Status::IOError(_filename, Win32::GetLastErrSz() ); + } + return sRet; +} + +Status Win32SequentialFile::Skip( uint64_t n ) +{ + Status sRet; + LARGE_INTEGER Move,NowPointer; + Move.QuadPart = n; + if(!SetFilePointerEx(_hFile,Move,&NowPointer,FILE_CURRENT)){ + sRet = Status::IOError(_filename,Win32::GetLastErrSz()); + } + return sRet; +} + +BOOL Win32SequentialFile::isEnable() +{ + return _hFile ? TRUE : FALSE; +} + +BOOL Win32SequentialFile::_Init() +{ + std::wstring path; + ToWidePath(_filename, path); + _hFile = CreateFileW(path.c_str(), + GENERIC_READ, + FILE_SHARE_READ, + NULL, + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, + NULL); + return _hFile ? TRUE : FALSE; +} + +void Win32SequentialFile::_CleanUp() +{ + if(_hFile){ + CloseHandle(_hFile); + _hFile = NULL; + } +} + +Win32RandomAccessFile::Win32RandomAccessFile( const std::string& fname ) : + _filename(fname),_hFile(NULL) +{ + std::wstring path; + ToWidePath(fname, path); + _Init( path.c_str() ); +} + +Win32RandomAccessFile::~Win32RandomAccessFile() +{ + _CleanUp(); +} + +Status Win32RandomAccessFile::Read(uint64_t offset,size_t n,Slice* result,char* scratch) const +{ + Status sRet; + OVERLAPPED ol = {0}; + ZeroMemory(&ol,sizeof(ol)); + ol.Offset = (DWORD)offset; + ol.OffsetHigh = (DWORD)(offset >> 32); + DWORD hasRead = 0; + if(!ReadFile(_hFile,scratch,n,&hasRead,&ol)) + sRet = Status::IOError(_filename,Win32::GetLastErrSz()); + else + *result = Slice(scratch,hasRead); + return sRet; +} + +BOOL Win32RandomAccessFile::_Init( LPCWSTR path ) +{ + BOOL bRet = FALSE; + if(!_hFile) + _hFile = ::CreateFileW(path,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS,NULL); + if(!_hFile || _hFile == INVALID_HANDLE_VALUE ) + _hFile = NULL; + else + bRet = TRUE; + return bRet; +} + +BOOL Win32RandomAccessFile::isEnable() +{ + return _hFile ? TRUE : FALSE; +} + +void Win32RandomAccessFile::_CleanUp() +{ + if(_hFile){ + ::CloseHandle(_hFile); + _hFile = NULL; + } +} + +size_t Win32MapFile::_Roundup( size_t x, size_t y ) +{ + return ((x + y - 1) / y) * y; +} + +size_t Win32MapFile::_TruncateToPageBoundary( size_t s ) +{ + s -= (s & (_page_size - 1)); + assert((s % _page_size) == 0); + return s; +} + +bool Win32MapFile::_UnmapCurrentRegion() +{ + bool result = true; + if (_base != NULL) { + if (_last_sync < _limit) { + // Defer syncing this data until next Sync() call, if any + _pending_sync = true; + } + if (!UnmapViewOfFile(_base) || !CloseHandle(_base_handle)) + result = false; + _file_offset += _limit - _base; + _base = NULL; + _base_handle = NULL; + _limit = NULL; + _last_sync = NULL; + _dst = NULL; + // Increase the amount we map the next time, but capped at 1MB + if (_map_size < (1<<20)) { + _map_size *= 2; + } + } + return result; +} + +bool Win32MapFile::_MapNewRegion() +{ + assert(_base == NULL); + //LONG newSizeHigh = (LONG)((file_offset_ + map_size_) >> 32); + //LONG newSizeLow = (LONG)((file_offset_ + map_size_) & 0xFFFFFFFF); + DWORD off_hi = (DWORD)(_file_offset >> 32); + DWORD off_lo = (DWORD)(_file_offset & 0xFFFFFFFF); + LARGE_INTEGER newSize; + newSize.QuadPart = _file_offset + _map_size; + SetFilePointerEx(_hFile, newSize, NULL, FILE_BEGIN); + SetEndOfFile(_hFile); + + _base_handle = CreateFileMappingA( + _hFile, + NULL, + PAGE_READWRITE, + 0, + 0, + 0); + if (_base_handle != NULL) { + _base = (char*) MapViewOfFile(_base_handle, + FILE_MAP_ALL_ACCESS, + off_hi, + off_lo, + _map_size); + if (_base != NULL) { + _limit = _base + _map_size; + _dst = _base; + _last_sync = _base; + return true; + } + } + return false; +} + +Win32MapFile::Win32MapFile( const std::string& fname) : + _filename(fname), + _hFile(NULL), + _page_size(Win32::g_PageSize), + _map_size(_Roundup(65536, Win32::g_PageSize)), + _base(NULL), + _base_handle(NULL), + _limit(NULL), + _dst(NULL), + _last_sync(NULL), + _file_offset(0), + _pending_sync(false) +{ + std::wstring path; + ToWidePath(fname, path); + _Init(path.c_str()); + assert((Win32::g_PageSize & (Win32::g_PageSize - 1)) == 0); +} + +Status Win32MapFile::Append( const Slice& data ) +{ + const char* src = data.data(); + size_t left = data.size(); + Status s; + while (left > 0) { + assert(_base <= _dst); + assert(_dst <= _limit); + size_t avail = _limit - _dst; + if (avail == 0) { + if (!_UnmapCurrentRegion() || + !_MapNewRegion()) { + return Status::IOError("WinMmapFile.Append::UnmapCurrentRegion or MapNewRegion: ", Win32::GetLastErrSz()); + } + } + size_t n = (left <= avail) ? left : avail; + memcpy(_dst, src, n); + _dst += n; + src += n; + left -= n; + } + return s; +} + +Status Win32MapFile::Close() +{ + Status s; + size_t unused = _limit - _dst; + if (!_UnmapCurrentRegion()) { + s = Status::IOError("WinMmapFile.Close::UnmapCurrentRegion: ",Win32::GetLastErrSz()); + } else if (unused > 0) { + // Trim the extra space at the end of the file + LARGE_INTEGER newSize; + newSize.QuadPart = _file_offset - unused; + if (!SetFilePointerEx(_hFile, newSize, NULL, FILE_BEGIN)) { + s = Status::IOError("WinMmapFile.Close::SetFilePointer: ",Win32::GetLastErrSz()); + } else + SetEndOfFile(_hFile); + } + if (!CloseHandle(_hFile)) { + if (s.ok()) { + s = Status::IOError("WinMmapFile.Close::CloseHandle: ", Win32::GetLastErrSz()); + } + } + _hFile = INVALID_HANDLE_VALUE; + _base = NULL; + _base_handle = NULL; + _limit = NULL; + + return s; +} + +Status Win32MapFile::Sync() +{ + Status s; + if (_pending_sync) { + // Some unmapped data was not synced + _pending_sync = false; + if (!FlushFileBuffers(_hFile)) { + s = Status::IOError("WinMmapFile.Sync::FlushFileBuffers: ",Win32::GetLastErrSz()); + } + } + if (_dst > _last_sync) { + // Find the beginnings of the pages that contain the first and last + // bytes to be synced. + size_t p1 = _TruncateToPageBoundary(_last_sync - _base); + size_t p2 = _TruncateToPageBoundary(_dst - _base - 1); + _last_sync = _dst; + if (!FlushViewOfFile(_base + p1, p2 - p1 + _page_size)) { + s = Status::IOError("WinMmapFile.Sync::FlushViewOfFile: ",Win32::GetLastErrSz()); + } + } + return s; +} + +Status Win32MapFile::Flush() +{ + return Status::OK(); +} + +Win32MapFile::~Win32MapFile() +{ + if (_hFile != INVALID_HANDLE_VALUE) { + Win32MapFile::Close(); + } +} + +BOOL Win32MapFile::_Init( LPCWSTR Path ) +{ + DWORD Flag = PathFileExistsW(Path) ? OPEN_EXISTING : CREATE_ALWAYS; + _hFile = CreateFileW(Path, + GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_READ|FILE_SHARE_DELETE|FILE_SHARE_WRITE, + NULL, + Flag, + FILE_ATTRIBUTE_NORMAL, + NULL); + if(!_hFile || _hFile == INVALID_HANDLE_VALUE) + return FALSE; + else + return TRUE; +} + +BOOL Win32MapFile::isEnable() +{ + return _hFile ? TRUE : FALSE; +} + +Win32FileLock::Win32FileLock( const std::string& fname ) : + _hFile(NULL),_filename(fname) +{ + std::wstring path; + ToWidePath(fname, path); + _Init(path.c_str()); +} + +Win32FileLock::~Win32FileLock() +{ + _CleanUp(); +} + +BOOL Win32FileLock::_Init( LPCWSTR path ) +{ + BOOL bRet = FALSE; + if(!_hFile) + _hFile = ::CreateFileW(path,0,0,NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL); + if(!_hFile || _hFile == INVALID_HANDLE_VALUE ){ + _hFile = NULL; + } + else + bRet = TRUE; + return bRet; +} + +void Win32FileLock::_CleanUp() +{ + ::CloseHandle(_hFile); + _hFile = NULL; +} + +BOOL Win32FileLock::isEnable() +{ + return _hFile ? TRUE : FALSE; +} + +Win32Logger::Win32Logger(WritableFile* pFile) : _pFileProxy(pFile) +{ + assert(_pFileProxy); +} + +Win32Logger::~Win32Logger() +{ + if(_pFileProxy) + delete _pFileProxy; +} + +void Win32Logger::Logv( const char* format, va_list ap ) +{ + uint64_t thread_id = ::GetCurrentThreadId(); + + // We try twice: the first time with a fixed-size stack allocated buffer, + // and the second time with a much larger dynamically allocated buffer. + char buffer[500]; + for (int iter = 0; iter < 2; iter++) { + char* base; + int bufsize; + if (iter == 0) { + bufsize = sizeof(buffer); + base = buffer; + } else { + bufsize = 30000; + base = new char[bufsize]; + } + char* p = base; + char* limit = base + bufsize; + + SYSTEMTIME st; + GetLocalTime(&st); + p += snprintf(p, limit - p, + "%04d/%02d/%02d-%02d:%02d:%02d.%06d %llx ", + int(st.wYear), + int(st.wMonth), + int(st.wDay), + int(st.wHour), + int(st.wMinute), + int(st.wMinute), + int(st.wMilliseconds), + static_cast(thread_id)); + + // Print the message + if (p < limit) { + va_list backup_ap; + va_copy(backup_ap, ap); + p += vsnprintf(p, limit - p, format, backup_ap); + va_end(backup_ap); + } + + // Truncate to available space if necessary + if (p >= limit) { + if (iter == 0) { + continue; // Try again with larger buffer + } else { + p = limit - 1; + } + } + + // Add newline if necessary + if (p == base || p[-1] != '\n') { + *p++ = '\n'; + } + + assert(p <= limit); + DWORD hasWritten = 0; + if(_pFileProxy){ + _pFileProxy->Append(Slice(base, p - base)); + _pFileProxy->Flush(); + } + if (base != buffer) { + delete[] base; + } + break; + } +} + +bool Win32Env::FileExists(const std::string& fname) +{ + std::string path = fname; + std::wstring wpath; + ToWidePath(ModifyPath(path), wpath); + return ::PathFileExistsW(wpath.c_str()) ? true : false; +} + +Status Win32Env::GetChildren(const std::string& dir, std::vector* result) +{ + Status sRet; + ::WIN32_FIND_DATAW wfd; + std::string path = dir; + ModifyPath(path); + path += "\\*.*"; + std::wstring wpath; + ToWidePath(path, wpath); + + ::HANDLE hFind = ::FindFirstFileW(wpath.c_str() ,&wfd); + if(hFind && hFind != INVALID_HANDLE_VALUE){ + BOOL hasNext = TRUE; + std::string child; + while(hasNext){ + ToNarrowPath(wfd.cFileName, child); + if(child != ".." && child != ".") { + result->push_back(child); + } + hasNext = ::FindNextFileW(hFind,&wfd); + } + ::FindClose(hFind); + } + else + sRet = Status::IOError(dir,"Could not get children."); + return sRet; +} + +void Win32Env::SleepForMicroseconds( int micros ) +{ + ::Sleep((micros + 999) /1000); +} + + +Status Win32Env::DeleteFile( const std::string& fname ) +{ + Status sRet; + std::string path = fname; + std::wstring wpath; + ToWidePath(ModifyPath(path), wpath); + + if(!::DeleteFileW(wpath.c_str())) { + sRet = Status::IOError(path, "Could not delete file."); + } + return sRet; +} + +Status Win32Env::GetFileSize( const std::string& fname, uint64_t* file_size ) +{ + Status sRet; + std::string path = fname; + std::wstring wpath; + ToWidePath(ModifyPath(path), wpath); + + HANDLE file = ::CreateFileW(wpath.c_str(), + GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL); + LARGE_INTEGER li; + if(::GetFileSizeEx(file,&li)){ + *file_size = (uint64_t)li.QuadPart; + }else + sRet = Status::IOError(path,"Could not get the file size."); + CloseHandle(file); + return sRet; +} + +Status Win32Env::RenameFile( const std::string& src, const std::string& target ) +{ + Status sRet; + std::string src_path = src; + std::wstring wsrc_path; + ToWidePath(ModifyPath(src_path), wsrc_path); + std::string target_path = target; + std::wstring wtarget_path; + ToWidePath(ModifyPath(target_path), wtarget_path); + + if(!MoveFileW(wsrc_path.c_str(), wtarget_path.c_str() ) ){ + DWORD err = GetLastError(); + if(err == 0x000000b7){ + if(!::DeleteFileW(wtarget_path.c_str() ) ) + sRet = Status::IOError(src, "Could not rename file."); + else if(!::MoveFileW(wsrc_path.c_str(), + wtarget_path.c_str() ) ) + sRet = Status::IOError(src, "Could not rename file."); + } + } + return sRet; +} + +Status Win32Env::LockFile( const std::string& fname, FileLock** lock ) +{ + Status sRet; + std::string path = fname; + ModifyPath(path); + Win32FileLock* _lock = new Win32FileLock(path); + if(!_lock->isEnable()){ + delete _lock; + *lock = NULL; + sRet = Status::IOError(path, "Could not lock file."); + } + else + *lock = _lock; + return sRet; +} + +Status Win32Env::UnlockFile( FileLock* lock ) +{ + Status sRet; + delete lock; + return sRet; +} + +void Win32Env::Schedule( void (*function)(void* arg), void* arg ) +{ + QueueUserWorkItem(Win32::WorkItemWrapperProc, + new Win32::WorkItemWrapper(function,arg), + WT_EXECUTEDEFAULT); +} + +void Win32Env::StartThread( void (*function)(void* arg), void* arg ) +{ + ::_beginthread(function,0,arg); +} + +Status Win32Env::GetTestDirectory( std::string* path ) +{ + Status sRet; + WCHAR TempPath[MAX_PATH]; + ::GetTempPathW(MAX_PATH,TempPath); + ToNarrowPath(TempPath, *path); + path->append("leveldb\\test\\"); + ModifyPath(*path); + return sRet; +} + +uint64_t Win32Env::NowMicros() +{ +#ifndef USE_VISTA_API +#define GetTickCount64 GetTickCount +#endif + return (uint64_t)(GetTickCount64()*1000); +} + +static Status CreateDirInner( const std::string& dirname ) +{ + Status sRet; + DWORD attr = ::GetFileAttributes(dirname.c_str()); + if (attr == INVALID_FILE_ATTRIBUTES) { // doesn't exist: + std::size_t slash = dirname.find_last_of("\\"); + if (slash != std::string::npos){ + sRet = CreateDirInner(dirname.substr(0, slash)); + if (!sRet.ok()) return sRet; + } + BOOL result = ::CreateDirectory(dirname.c_str(), NULL); + if (result == FALSE) { + sRet = Status::IOError(dirname, "Could not create directory."); + return sRet; + } + } + return sRet; +} + +Status Win32Env::CreateDir( const std::string& dirname ) +{ + std::string path = dirname; + if(path[path.length() - 1] != '\\'){ + path += '\\'; + } + ModifyPath(path); + + return CreateDirInner(path); +} + +Status Win32Env::DeleteDir( const std::string& dirname ) +{ + Status sRet; + std::wstring path; + ToWidePath(dirname, path); + ModifyPath(path); + if(!::RemoveDirectoryW( path.c_str() ) ){ + sRet = Status::IOError(dirname, "Could not delete directory."); + } + return sRet; +} + +Status Win32Env::NewSequentialFile( const std::string& fname, SequentialFile** result ) +{ + Status sRet; + std::string path = fname; + ModifyPath(path); + Win32SequentialFile* pFile = new Win32SequentialFile(path); + if(pFile->isEnable()){ + *result = pFile; + }else { + delete pFile; + sRet = Status::IOError(path, Win32::GetLastErrSz()); + } + return sRet; +} + +Status Win32Env::NewRandomAccessFile( const std::string& fname, RandomAccessFile** result ) +{ + Status sRet; + std::string path = fname; + Win32RandomAccessFile* pFile = new Win32RandomAccessFile(ModifyPath(path)); + if(!pFile->isEnable()){ + delete pFile; + *result = NULL; + sRet = Status::IOError(path, Win32::GetLastErrSz()); + }else + *result = pFile; + return sRet; +} + +Status Win32Env::NewLogger( const std::string& fname, Logger** result ) +{ + Status sRet; + std::string path = fname; + Win32MapFile* pMapFile = new Win32MapFile(ModifyPath(path)); + if(!pMapFile->isEnable()){ + delete pMapFile; + *result = NULL; + sRet = Status::IOError(path,"could not create a logger."); + }else + *result = new Win32Logger(pMapFile); + return sRet; +} + +Status Win32Env::NewWritableFile( const std::string& fname, WritableFile** result ) +{ + Status sRet; + std::string path = fname; + Win32MapFile* pFile = new Win32MapFile(ModifyPath(path)); + if(!pFile->isEnable()){ + *result = NULL; + sRet = Status::IOError(fname,Win32::GetLastErrSz()); + }else + *result = pFile; + return sRet; +} + +Win32Env::Win32Env() +{ + +} + +Win32Env::~Win32Env() +{ + +} + + +} // Win32 namespace + +static port::OnceType once = LEVELDB_ONCE_INIT; +static Env* default_env; +static void InitDefaultEnv() { default_env = new Win32::Win32Env(); } + +Env* Env::Default() { + port::InitOnce(&once, InitDefaultEnv); + return default_env; +} + +} // namespace leveldb + +#endif // defined(LEVELDB_PLATFORM_WINDOWS) diff --git a/src/leveldb/util/filter_policy.cc b/src/leveldb/util/filter_policy.cc new file mode 100644 index 0000000..7b045c8 --- /dev/null +++ b/src/leveldb/util/filter_policy.cc @@ -0,0 +1,11 @@ +// Copyright (c) 2012 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "leveldb/filter_policy.h" + +namespace leveldb { + +FilterPolicy::~FilterPolicy() { } + +} // namespace leveldb diff --git a/src/leveldb/util/hash.cc b/src/leveldb/util/hash.cc new file mode 100644 index 0000000..07cf022 --- /dev/null +++ b/src/leveldb/util/hash.cc @@ -0,0 +1,52 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include +#include "util/coding.h" +#include "util/hash.h" + +// The FALLTHROUGH_INTENDED macro can be used to annotate implicit fall-through +// between switch labels. The real definition should be provided externally. +// This one is a fallback version for unsupported compilers. +#ifndef FALLTHROUGH_INTENDED +#define FALLTHROUGH_INTENDED do { } while (0) +#endif + +namespace leveldb { + +uint32_t Hash(const char* data, size_t n, uint32_t seed) { + // Similar to murmur hash + const uint32_t m = 0xc6a4a793; + const uint32_t r = 24; + const char* limit = data + n; + uint32_t h = seed ^ (n * m); + + // Pick up four bytes at a time + while (data + 4 <= limit) { + uint32_t w = DecodeFixed32(data); + data += 4; + h += w; + h *= m; + h ^= (h >> 16); + } + + // Pick up remaining bytes + switch (limit - data) { + case 3: + h += data[2] << 16; + FALLTHROUGH_INTENDED; + case 2: + h += data[1] << 8; + FALLTHROUGH_INTENDED; + case 1: + h += data[0]; + h *= m; + h ^= (h >> r); + break; + } + return h; +} + + +} // namespace leveldb diff --git a/src/leveldb/util/hash.h b/src/leveldb/util/hash.h new file mode 100644 index 0000000..8889d56 --- /dev/null +++ b/src/leveldb/util/hash.h @@ -0,0 +1,19 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. +// +// Simple hash function used for internal data structures + +#ifndef STORAGE_LEVELDB_UTIL_HASH_H_ +#define STORAGE_LEVELDB_UTIL_HASH_H_ + +#include +#include + +namespace leveldb { + +extern uint32_t Hash(const char* data, size_t n, uint32_t seed); + +} + +#endif // STORAGE_LEVELDB_UTIL_HASH_H_ diff --git a/src/leveldb/util/histogram.cc b/src/leveldb/util/histogram.cc new file mode 100644 index 0000000..bb95f58 --- /dev/null +++ b/src/leveldb/util/histogram.cc @@ -0,0 +1,139 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include +#include +#include "port/port.h" +#include "util/histogram.h" + +namespace leveldb { + +const double Histogram::kBucketLimit[kNumBuckets] = { + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 12, 14, 16, 18, 20, 25, 30, 35, 40, 45, + 50, 60, 70, 80, 90, 100, 120, 140, 160, 180, 200, 250, 300, 350, 400, 450, + 500, 600, 700, 800, 900, 1000, 1200, 1400, 1600, 1800, 2000, 2500, 3000, + 3500, 4000, 4500, 5000, 6000, 7000, 8000, 9000, 10000, 12000, 14000, + 16000, 18000, 20000, 25000, 30000, 35000, 40000, 45000, 50000, 60000, + 70000, 80000, 90000, 100000, 120000, 140000, 160000, 180000, 200000, + 250000, 300000, 350000, 400000, 450000, 500000, 600000, 700000, 800000, + 900000, 1000000, 1200000, 1400000, 1600000, 1800000, 2000000, 2500000, + 3000000, 3500000, 4000000, 4500000, 5000000, 6000000, 7000000, 8000000, + 9000000, 10000000, 12000000, 14000000, 16000000, 18000000, 20000000, + 25000000, 30000000, 35000000, 40000000, 45000000, 50000000, 60000000, + 70000000, 80000000, 90000000, 100000000, 120000000, 140000000, 160000000, + 180000000, 200000000, 250000000, 300000000, 350000000, 400000000, + 450000000, 500000000, 600000000, 700000000, 800000000, 900000000, + 1000000000, 1200000000, 1400000000, 1600000000, 1800000000, 2000000000, + 2500000000.0, 3000000000.0, 3500000000.0, 4000000000.0, 4500000000.0, + 5000000000.0, 6000000000.0, 7000000000.0, 8000000000.0, 9000000000.0, + 1e200, +}; + +void Histogram::Clear() { + min_ = kBucketLimit[kNumBuckets-1]; + max_ = 0; + num_ = 0; + sum_ = 0; + sum_squares_ = 0; + for (int i = 0; i < kNumBuckets; i++) { + buckets_[i] = 0; + } +} + +void Histogram::Add(double value) { + // Linear search is fast enough for our usage in db_bench + int b = 0; + while (b < kNumBuckets - 1 && kBucketLimit[b] <= value) { + b++; + } + buckets_[b] += 1.0; + if (min_ > value) min_ = value; + if (max_ < value) max_ = value; + num_++; + sum_ += value; + sum_squares_ += (value * value); +} + +void Histogram::Merge(const Histogram& other) { + if (other.min_ < min_) min_ = other.min_; + if (other.max_ > max_) max_ = other.max_; + num_ += other.num_; + sum_ += other.sum_; + sum_squares_ += other.sum_squares_; + for (int b = 0; b < kNumBuckets; b++) { + buckets_[b] += other.buckets_[b]; + } +} + +double Histogram::Median() const { + return Percentile(50.0); +} + +double Histogram::Percentile(double p) const { + double threshold = num_ * (p / 100.0); + double sum = 0; + for (int b = 0; b < kNumBuckets; b++) { + sum += buckets_[b]; + if (sum >= threshold) { + // Scale linearly within this bucket + double left_point = (b == 0) ? 0 : kBucketLimit[b-1]; + double right_point = kBucketLimit[b]; + double left_sum = sum - buckets_[b]; + double right_sum = sum; + double pos = (threshold - left_sum) / (right_sum - left_sum); + double r = left_point + (right_point - left_point) * pos; + if (r < min_) r = min_; + if (r > max_) r = max_; + return r; + } + } + return max_; +} + +double Histogram::Average() const { + if (num_ == 0.0) return 0; + return sum_ / num_; +} + +double Histogram::StandardDeviation() const { + if (num_ == 0.0) return 0; + double variance = (sum_squares_ * num_ - sum_ * sum_) / (num_ * num_); + return sqrt(variance); +} + +std::string Histogram::ToString() const { + std::string r; + char buf[200]; + snprintf(buf, sizeof(buf), + "Count: %.0f Average: %.4f StdDev: %.2f\n", + num_, Average(), StandardDeviation()); + r.append(buf); + snprintf(buf, sizeof(buf), + "Min: %.4f Median: %.4f Max: %.4f\n", + (num_ == 0.0 ? 0.0 : min_), Median(), max_); + r.append(buf); + r.append("------------------------------------------------------\n"); + const double mult = 100.0 / num_; + double sum = 0; + for (int b = 0; b < kNumBuckets; b++) { + if (buckets_[b] <= 0.0) continue; + sum += buckets_[b]; + snprintf(buf, sizeof(buf), + "[ %7.0f, %7.0f ) %7.0f %7.3f%% %7.3f%% ", + ((b == 0) ? 0.0 : kBucketLimit[b-1]), // left + kBucketLimit[b], // right + buckets_[b], // count + mult * buckets_[b], // percentage + mult * sum); // cumulative percentage + r.append(buf); + + // Add hash marks based on percentage; 20 marks for 100%. + int marks = static_cast(20*(buckets_[b] / num_) + 0.5); + r.append(marks, '#'); + r.push_back('\n'); + } + return r; +} + +} // namespace leveldb diff --git a/src/leveldb/util/histogram.h b/src/leveldb/util/histogram.h new file mode 100644 index 0000000..1ef9f3c --- /dev/null +++ b/src/leveldb/util/histogram.h @@ -0,0 +1,42 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#ifndef STORAGE_LEVELDB_UTIL_HISTOGRAM_H_ +#define STORAGE_LEVELDB_UTIL_HISTOGRAM_H_ + +#include + +namespace leveldb { + +class Histogram { + public: + Histogram() { } + ~Histogram() { } + + void Clear(); + void Add(double value); + void Merge(const Histogram& other); + + std::string ToString() const; + + private: + double min_; + double max_; + double num_; + double sum_; + double sum_squares_; + + enum { kNumBuckets = 154 }; + static const double kBucketLimit[kNumBuckets]; + double buckets_[kNumBuckets]; + + double Median() const; + double Percentile(double p) const; + double Average() const; + double StandardDeviation() const; +}; + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_UTIL_HISTOGRAM_H_ diff --git a/src/leveldb/util/logging.cc b/src/leveldb/util/logging.cc new file mode 100644 index 0000000..22cf278 --- /dev/null +++ b/src/leveldb/util/logging.cc @@ -0,0 +1,81 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "util/logging.h" + +#include +#include +#include +#include +#include "leveldb/env.h" +#include "leveldb/slice.h" + +namespace leveldb { + +void AppendNumberTo(std::string* str, uint64_t num) { + char buf[30]; + snprintf(buf, sizeof(buf), "%llu", (unsigned long long) num); + str->append(buf); +} + +void AppendEscapedStringTo(std::string* str, const Slice& value) { + for (size_t i = 0; i < value.size(); i++) { + char c = value[i]; + if (c >= ' ' && c <= '~') { + str->push_back(c); + } else { + char buf[10]; + snprintf(buf, sizeof(buf), "\\x%02x", + static_cast(c) & 0xff); + str->append(buf); + } + } +} + +std::string NumberToString(uint64_t num) { + std::string r; + AppendNumberTo(&r, num); + return r; +} + +std::string EscapeString(const Slice& value) { + std::string r; + AppendEscapedStringTo(&r, value); + return r; +} + +bool ConsumeChar(Slice* in, char c) { + if (!in->empty() && (*in)[0] == c) { + in->remove_prefix(1); + return true; + } else { + return false; + } +} + +bool ConsumeDecimalNumber(Slice* in, uint64_t* val) { + uint64_t v = 0; + int digits = 0; + while (!in->empty()) { + char c = (*in)[0]; + if (c >= '0' && c <= '9') { + ++digits; + const int delta = (c - '0'); + static const uint64_t kMaxUint64 = ~static_cast(0); + if (v > kMaxUint64/10 || + (v == kMaxUint64/10 && delta > kMaxUint64%10)) { + // Overflow + return false; + } + v = (v * 10) + delta; + in->remove_prefix(1); + } else { + break; + } + } + *val = v; + return (digits > 0); +} + +} // namespace leveldb diff --git a/src/leveldb/util/logging.h b/src/leveldb/util/logging.h new file mode 100644 index 0000000..b0c5da8 --- /dev/null +++ b/src/leveldb/util/logging.h @@ -0,0 +1,47 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. +// +// Must not be included from any .h files to avoid polluting the namespace +// with macros. + +#ifndef STORAGE_LEVELDB_UTIL_LOGGING_H_ +#define STORAGE_LEVELDB_UTIL_LOGGING_H_ + +#include +#include +#include +#include "port/port.h" + +namespace leveldb { + +class Slice; +class WritableFile; + +// Append a human-readable printout of "num" to *str +extern void AppendNumberTo(std::string* str, uint64_t num); + +// Append a human-readable printout of "value" to *str. +// Escapes any non-printable characters found in "value". +extern void AppendEscapedStringTo(std::string* str, const Slice& value); + +// Return a human-readable printout of "num" +extern std::string NumberToString(uint64_t num); + +// Return a human-readable version of "value". +// Escapes any non-printable characters found in "value". +extern std::string EscapeString(const Slice& value); + +// If *in starts with "c", advances *in past the first character and +// returns true. Otherwise, returns false. +extern bool ConsumeChar(Slice* in, char c); + +// Parse a human-readable number from "*in" into *value. On success, +// advances "*in" past the consumed number and sets "*val" to the +// numeric value. Otherwise, returns false and leaves *in in an +// unspecified state. +extern bool ConsumeDecimalNumber(Slice* in, uint64_t* val); + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_UTIL_LOGGING_H_ diff --git a/src/leveldb/util/mutexlock.h b/src/leveldb/util/mutexlock.h new file mode 100644 index 0000000..1ff5a9e --- /dev/null +++ b/src/leveldb/util/mutexlock.h @@ -0,0 +1,41 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#ifndef STORAGE_LEVELDB_UTIL_MUTEXLOCK_H_ +#define STORAGE_LEVELDB_UTIL_MUTEXLOCK_H_ + +#include "port/port.h" +#include "port/thread_annotations.h" + +namespace leveldb { + +// Helper class that locks a mutex on construction and unlocks the mutex when +// the destructor of the MutexLock object is invoked. +// +// Typical usage: +// +// void MyClass::MyMethod() { +// MutexLock l(&mu_); // mu_ is an instance variable +// ... some complex code, possibly with multiple return paths ... +// } + +class SCOPED_LOCKABLE MutexLock { + public: + explicit MutexLock(port::Mutex *mu) EXCLUSIVE_LOCK_FUNCTION(mu) + : mu_(mu) { + this->mu_->Lock(); + } + ~MutexLock() UNLOCK_FUNCTION() { this->mu_->Unlock(); } + + private: + port::Mutex *const mu_; + // No copying allowed + MutexLock(const MutexLock&); + void operator=(const MutexLock&); +}; + +} // namespace leveldb + + +#endif // STORAGE_LEVELDB_UTIL_MUTEXLOCK_H_ diff --git a/src/leveldb/util/options.cc b/src/leveldb/util/options.cc new file mode 100644 index 0000000..76af5b9 --- /dev/null +++ b/src/leveldb/util/options.cc @@ -0,0 +1,29 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "leveldb/options.h" + +#include "leveldb/comparator.h" +#include "leveldb/env.h" + +namespace leveldb { + +Options::Options() + : comparator(BytewiseComparator()), + create_if_missing(false), + error_if_exists(false), + paranoid_checks(false), + env(Env::Default()), + info_log(NULL), + write_buffer_size(4<<20), + max_open_files(1000), + block_cache(NULL), + block_size(4096), + block_restart_interval(16), + compression(kSnappyCompression), + filter_policy(NULL) { +} + + +} // namespace leveldb diff --git a/src/leveldb/util/posix_logger.h b/src/leveldb/util/posix_logger.h new file mode 100644 index 0000000..c063c2b --- /dev/null +++ b/src/leveldb/util/posix_logger.h @@ -0,0 +1,98 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. +// +// Logger implementation that can be shared by all environments +// where enough Posix functionality is available. + +#ifndef STORAGE_LEVELDB_UTIL_POSIX_LOGGER_H_ +#define STORAGE_LEVELDB_UTIL_POSIX_LOGGER_H_ + +#include +#include +#include +#include +#include "leveldb/env.h" + +namespace leveldb { + +class PosixLogger : public Logger { + private: + FILE* file_; + uint64_t (*gettid_)(); // Return the thread id for the current thread + public: + PosixLogger(FILE* f, uint64_t (*gettid)()) : file_(f), gettid_(gettid) { } + virtual ~PosixLogger() { + fclose(file_); + } + virtual void Logv(const char* format, va_list ap) { + const uint64_t thread_id = (*gettid_)(); + + // We try twice: the first time with a fixed-size stack allocated buffer, + // and the second time with a much larger dynamically allocated buffer. + char buffer[500]; + for (int iter = 0; iter < 2; iter++) { + char* base; + int bufsize; + if (iter == 0) { + bufsize = sizeof(buffer); + base = buffer; + } else { + bufsize = 30000; + base = new char[bufsize]; + } + char* p = base; + char* limit = base + bufsize; + + struct timeval now_tv; + gettimeofday(&now_tv, NULL); + const time_t seconds = now_tv.tv_sec; + struct tm t; + localtime_r(&seconds, &t); + p += snprintf(p, limit - p, + "%04d/%02d/%02d-%02d:%02d:%02d.%06d %llx ", + t.tm_year + 1900, + t.tm_mon + 1, + t.tm_mday, + t.tm_hour, + t.tm_min, + t.tm_sec, + static_cast(now_tv.tv_usec), + static_cast(thread_id)); + + // Print the message + if (p < limit) { + va_list backup_ap; + va_copy(backup_ap, ap); + p += vsnprintf(p, limit - p, format, backup_ap); + va_end(backup_ap); + } + + // Truncate to available space if necessary + if (p >= limit) { + if (iter == 0) { + continue; // Try again with larger buffer + } else { + p = limit - 1; + } + } + + // Add newline if necessary + if (p == base || p[-1] != '\n') { + *p++ = '\n'; + } + + assert(p <= limit); + fwrite(base, 1, p - base, file_); + fflush(file_); + if (base != buffer) { + delete[] base; + } + break; + } + } +}; + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_UTIL_POSIX_LOGGER_H_ diff --git a/src/leveldb/util/random.h b/src/leveldb/util/random.h new file mode 100644 index 0000000..ddd51b1 --- /dev/null +++ b/src/leveldb/util/random.h @@ -0,0 +1,64 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#ifndef STORAGE_LEVELDB_UTIL_RANDOM_H_ +#define STORAGE_LEVELDB_UTIL_RANDOM_H_ + +#include + +namespace leveldb { + +// A very simple random number generator. Not especially good at +// generating truly random bits, but good enough for our needs in this +// package. +class Random { + private: + uint32_t seed_; + public: + explicit Random(uint32_t s) : seed_(s & 0x7fffffffu) { + // Avoid bad seeds. + if (seed_ == 0 || seed_ == 2147483647L) { + seed_ = 1; + } + } + uint32_t Next() { + static const uint32_t M = 2147483647L; // 2^31-1 + static const uint64_t A = 16807; // bits 14, 8, 7, 5, 2, 1, 0 + // We are computing + // seed_ = (seed_ * A) % M, where M = 2^31-1 + // + // seed_ must not be zero or M, or else all subsequent computed values + // will be zero or M respectively. For all other values, seed_ will end + // up cycling through every number in [1,M-1] + uint64_t product = seed_ * A; + + // Compute (product % M) using the fact that ((x << 31) % M) == x. + seed_ = static_cast((product >> 31) + (product & M)); + // The first reduction may overflow by 1 bit, so we may need to + // repeat. mod == M is not possible; using > allows the faster + // sign-bit-based test. + if (seed_ > M) { + seed_ -= M; + } + return seed_; + } + // Returns a uniformly distributed value in the range [0..n-1] + // REQUIRES: n > 0 + uint32_t Uniform(int n) { return Next() % n; } + + // Randomly returns true ~"1/n" of the time, and false otherwise. + // REQUIRES: n > 0 + bool OneIn(int n) { return (Next() % n) == 0; } + + // Skewed: pick "base" uniformly from range [0,max_log] and then + // return "base" random bits. The effect is to pick a number in the + // range [0,2^max_log-1] with exponential bias towards smaller numbers. + uint32_t Skewed(int max_log) { + return Uniform(1 << Uniform(max_log + 1)); + } +}; + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_UTIL_RANDOM_H_ diff --git a/src/leveldb/util/status.cc b/src/leveldb/util/status.cc new file mode 100644 index 0000000..a44f35b --- /dev/null +++ b/src/leveldb/util/status.cc @@ -0,0 +1,75 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include +#include "port/port.h" +#include "leveldb/status.h" + +namespace leveldb { + +const char* Status::CopyState(const char* state) { + uint32_t size; + memcpy(&size, state, sizeof(size)); + char* result = new char[size + 5]; + memcpy(result, state, size + 5); + return result; +} + +Status::Status(Code code, const Slice& msg, const Slice& msg2) { + assert(code != kOk); + const uint32_t len1 = msg.size(); + const uint32_t len2 = msg2.size(); + const uint32_t size = len1 + (len2 ? (2 + len2) : 0); + char* result = new char[size + 5]; + memcpy(result, &size, sizeof(size)); + result[4] = static_cast(code); + memcpy(result + 5, msg.data(), len1); + if (len2) { + result[5 + len1] = ':'; + result[6 + len1] = ' '; + memcpy(result + 7 + len1, msg2.data(), len2); + } + state_ = result; +} + +std::string Status::ToString() const { + if (state_ == NULL) { + return "OK"; + } else { + char tmp[30]; + const char* type; + switch (code()) { + case kOk: + type = "OK"; + break; + case kNotFound: + type = "NotFound: "; + break; + case kCorruption: + type = "Corruption: "; + break; + case kNotSupported: + type = "Not implemented: "; + break; + case kInvalidArgument: + type = "Invalid argument: "; + break; + case kIOError: + type = "IO error: "; + break; + default: + snprintf(tmp, sizeof(tmp), "Unknown code(%d): ", + static_cast(code())); + type = tmp; + break; + } + std::string result(type); + uint32_t length; + memcpy(&length, state_, sizeof(length)); + result.append(state_ + 5, length); + return result; + } +} + +} // namespace leveldb diff --git a/src/leveldb/util/testharness.cc b/src/leveldb/util/testharness.cc new file mode 100644 index 0000000..402fab3 --- /dev/null +++ b/src/leveldb/util/testharness.cc @@ -0,0 +1,77 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "util/testharness.h" + +#include +#include +#include +#include + +namespace leveldb { +namespace test { + +namespace { +struct Test { + const char* base; + const char* name; + void (*func)(); +}; +std::vector* tests; +} + +bool RegisterTest(const char* base, const char* name, void (*func)()) { + if (tests == NULL) { + tests = new std::vector; + } + Test t; + t.base = base; + t.name = name; + t.func = func; + tests->push_back(t); + return true; +} + +int RunAllTests() { + const char* matcher = getenv("LEVELDB_TESTS"); + + int num = 0; + if (tests != NULL) { + for (size_t i = 0; i < tests->size(); i++) { + const Test& t = (*tests)[i]; + if (matcher != NULL) { + std::string name = t.base; + name.push_back('.'); + name.append(t.name); + if (strstr(name.c_str(), matcher) == NULL) { + continue; + } + } + fprintf(stderr, "==== Test %s.%s\n", t.base, t.name); + (*t.func)(); + ++num; + } + } + fprintf(stderr, "==== PASSED %d tests\n", num); + return 0; +} + +std::string TmpDir() { + std::string dir; + Status s = Env::Default()->GetTestDirectory(&dir); + ASSERT_TRUE(s.ok()) << s.ToString(); + return dir; +} + +int RandomSeed() { + const char* env = getenv("TEST_RANDOM_SEED"); + int result = (env != NULL ? atoi(env) : 301); + if (result <= 0) { + result = 301; + } + return result; +} + +} // namespace test +} // namespace leveldb diff --git a/src/leveldb/util/testharness.h b/src/leveldb/util/testharness.h new file mode 100644 index 0000000..da4fe68 --- /dev/null +++ b/src/leveldb/util/testharness.h @@ -0,0 +1,138 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#ifndef STORAGE_LEVELDB_UTIL_TESTHARNESS_H_ +#define STORAGE_LEVELDB_UTIL_TESTHARNESS_H_ + +#include +#include +#include +#include "leveldb/env.h" +#include "leveldb/slice.h" +#include "util/random.h" + +namespace leveldb { +namespace test { + +// Run some of the tests registered by the TEST() macro. If the +// environment variable "LEVELDB_TESTS" is not set, runs all tests. +// Otherwise, runs only the tests whose name contains the value of +// "LEVELDB_TESTS" as a substring. E.g., suppose the tests are: +// TEST(Foo, Hello) { ... } +// TEST(Foo, World) { ... } +// LEVELDB_TESTS=Hello will run the first test +// LEVELDB_TESTS=o will run both tests +// LEVELDB_TESTS=Junk will run no tests +// +// Returns 0 if all tests pass. +// Dies or returns a non-zero value if some test fails. +extern int RunAllTests(); + +// Return the directory to use for temporary storage. +extern std::string TmpDir(); + +// Return a randomization seed for this run. Typically returns the +// same number on repeated invocations of this binary, but automated +// runs may be able to vary the seed. +extern int RandomSeed(); + +// An instance of Tester is allocated to hold temporary state during +// the execution of an assertion. +class Tester { + private: + bool ok_; + const char* fname_; + int line_; + std::stringstream ss_; + + public: + Tester(const char* f, int l) + : ok_(true), fname_(f), line_(l) { + } + + ~Tester() { + if (!ok_) { + fprintf(stderr, "%s:%d:%s\n", fname_, line_, ss_.str().c_str()); + exit(1); + } + } + + Tester& Is(bool b, const char* msg) { + if (!b) { + ss_ << " Assertion failure " << msg; + ok_ = false; + } + return *this; + } + + Tester& IsOk(const Status& s) { + if (!s.ok()) { + ss_ << " " << s.ToString(); + ok_ = false; + } + return *this; + } + +#define BINARY_OP(name,op) \ + template \ + Tester& name(const X& x, const Y& y) { \ + if (! (x op y)) { \ + ss_ << " failed: " << x << (" " #op " ") << y; \ + ok_ = false; \ + } \ + return *this; \ + } + + BINARY_OP(IsEq, ==) + BINARY_OP(IsNe, !=) + BINARY_OP(IsGe, >=) + BINARY_OP(IsGt, >) + BINARY_OP(IsLe, <=) + BINARY_OP(IsLt, <) +#undef BINARY_OP + + // Attach the specified value to the error message if an error has occurred + template + Tester& operator<<(const V& value) { + if (!ok_) { + ss_ << " " << value; + } + return *this; + } +}; + +#define ASSERT_TRUE(c) ::leveldb::test::Tester(__FILE__, __LINE__).Is((c), #c) +#define ASSERT_OK(s) ::leveldb::test::Tester(__FILE__, __LINE__).IsOk((s)) +#define ASSERT_EQ(a,b) ::leveldb::test::Tester(__FILE__, __LINE__).IsEq((a),(b)) +#define ASSERT_NE(a,b) ::leveldb::test::Tester(__FILE__, __LINE__).IsNe((a),(b)) +#define ASSERT_GE(a,b) ::leveldb::test::Tester(__FILE__, __LINE__).IsGe((a),(b)) +#define ASSERT_GT(a,b) ::leveldb::test::Tester(__FILE__, __LINE__).IsGt((a),(b)) +#define ASSERT_LE(a,b) ::leveldb::test::Tester(__FILE__, __LINE__).IsLe((a),(b)) +#define ASSERT_LT(a,b) ::leveldb::test::Tester(__FILE__, __LINE__).IsLt((a),(b)) + +#define TCONCAT(a,b) TCONCAT1(a,b) +#define TCONCAT1(a,b) a##b + +#define TEST(base,name) \ +class TCONCAT(_Test_,name) : public base { \ + public: \ + void _Run(); \ + static void _RunIt() { \ + TCONCAT(_Test_,name) t; \ + t._Run(); \ + } \ +}; \ +bool TCONCAT(_Test_ignored_,name) = \ + ::leveldb::test::RegisterTest(#base, #name, &TCONCAT(_Test_,name)::_RunIt); \ +void TCONCAT(_Test_,name)::_Run() + +// Register the specified test. Typically not used directly, but +// invoked via the macro expansion of TEST. +extern bool RegisterTest(const char* base, const char* name, void (*func)()); + + +} // namespace test +} // namespace leveldb + +#endif // STORAGE_LEVELDB_UTIL_TESTHARNESS_H_ diff --git a/src/leveldb/util/testutil.cc b/src/leveldb/util/testutil.cc new file mode 100644 index 0000000..bee56bf --- /dev/null +++ b/src/leveldb/util/testutil.cc @@ -0,0 +1,51 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "util/testutil.h" + +#include "util/random.h" + +namespace leveldb { +namespace test { + +Slice RandomString(Random* rnd, int len, std::string* dst) { + dst->resize(len); + for (int i = 0; i < len; i++) { + (*dst)[i] = static_cast(' ' + rnd->Uniform(95)); // ' ' .. '~' + } + return Slice(*dst); +} + +std::string RandomKey(Random* rnd, int len) { + // Make sure to generate a wide variety of characters so we + // test the boundary conditions for short-key optimizations. + static const char kTestChars[] = { + '\0', '\1', 'a', 'b', 'c', 'd', 'e', '\xfd', '\xfe', '\xff' + }; + std::string result; + for (int i = 0; i < len; i++) { + result += kTestChars[rnd->Uniform(sizeof(kTestChars))]; + } + return result; +} + + +extern Slice CompressibleString(Random* rnd, double compressed_fraction, + size_t len, std::string* dst) { + int raw = static_cast(len * compressed_fraction); + if (raw < 1) raw = 1; + std::string raw_data; + RandomString(rnd, raw, &raw_data); + + // Duplicate the random data until we have filled "len" bytes + dst->clear(); + while (dst->size() < len) { + dst->append(raw_data); + } + dst->resize(len); + return Slice(*dst); +} + +} // namespace test +} // namespace leveldb diff --git a/src/leveldb/util/testutil.h b/src/leveldb/util/testutil.h new file mode 100644 index 0000000..adad3fc --- /dev/null +++ b/src/leveldb/util/testutil.h @@ -0,0 +1,53 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#ifndef STORAGE_LEVELDB_UTIL_TESTUTIL_H_ +#define STORAGE_LEVELDB_UTIL_TESTUTIL_H_ + +#include "leveldb/env.h" +#include "leveldb/slice.h" +#include "util/random.h" + +namespace leveldb { +namespace test { + +// Store in *dst a random string of length "len" and return a Slice that +// references the generated data. +extern Slice RandomString(Random* rnd, int len, std::string* dst); + +// Return a random key with the specified length that may contain interesting +// characters (e.g. \x00, \xff, etc.). +extern std::string RandomKey(Random* rnd, int len); + +// Store in *dst a string of length "len" that will compress to +// "N*compressed_fraction" bytes and return a Slice that references +// the generated data. +extern Slice CompressibleString(Random* rnd, double compressed_fraction, + size_t len, std::string* dst); + +// A wrapper that allows injection of errors. +class ErrorEnv : public EnvWrapper { + public: + bool writable_file_error_; + int num_writable_file_errors_; + + ErrorEnv() : EnvWrapper(Env::Default()), + writable_file_error_(false), + num_writable_file_errors_(0) { } + + virtual Status NewWritableFile(const std::string& fname, + WritableFile** result) { + if (writable_file_error_) { + ++num_writable_file_errors_; + *result = NULL; + return Status::IOError(fname, "fake error"); + } + return target()->NewWritableFile(fname, result); + } +}; + +} // namespace test +} // namespace leveldb + +#endif // STORAGE_LEVELDB_UTIL_TESTUTIL_H_ diff --git a/src/main.cpp b/src/main.cpp new file mode 100644 index 0000000..4074fad --- /dev/null +++ b/src/main.cpp @@ -0,0 +1,3816 @@ +// Copyright (c) 2009-2010 Satoshi Nakamoto +// Copyright (c) 2009-2012 The Bitcoin developers +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include "alert.h" +#include "checkpoints.h" +#include "db.h" +#include "txdb.h" +#include "net.h" +#include "init.h" +#include "ui_interface.h" +#include "kernel.h" +#include "zerocoin/Zerocoin.h" +#include +#include +#include + + +using namespace std; +using namespace boost; + +// +// Global state +// + +CCriticalSection cs_setpwalletRegistered; +set setpwalletRegistered; + +CCriticalSection cs_main; + +CTxMemPool mempool; +unsigned int nTransactionsUpdated = 0; + +map mapBlockIndex; +set > setStakeSeen; +libzerocoin::Params* ZCParams; + +CBigNum bnProofOfWorkLimit(~uint256(0) >> 20); // "standard" scrypt target limit for proof of work, results with 0,000244140625 proof-of-work difficulty +CBigNum bnProofOfStakeLimit(~uint256(0) >> 20); +CBigNum bnProofOfWorkLimitTestNet(~uint256(0) >> 16); + +unsigned int nTargetSpacing = 1 * 60; // 1 minute +unsigned int nStakeMinAge = 6 * 60 * 60; +unsigned int nStakeMaxAge = -1; // unlimited +unsigned int nModifierInterval = 10 * 60; // time to elapse before new modifier is computed + +CBlockIndex* pindexGenesisBlock = NULL; +int nBestHeight = -1; + +uint256 nBestChainTrust = 0; +uint256 nBestInvalidTrust = 0; + +uint256 hashBestChain = 0; +CBlockIndex* pindexBest = NULL; +int64_t nTimeBestReceived = 0; + +CMedianFilter cPeerBlockCounts(5, 0); // Amount of blocks that other nodes claim to have + +map mapOrphanBlocks; +multimap mapOrphanBlocksByPrev; +set > setStakeSeenOrphan; + +map mapOrphanTransactions; +map > mapOrphanTransactionsByPrev; + +// Constant stuff for coinbase transactions we create: +CScript COINBASE_FLAGS; + +const string strMessageMagic = "arepacoin Signed Message:\n"; + +// Settings +int64_t nTransactionFee = MIN_TX_FEE; +int64_t nReserveBalance = 0; +int64_t nMinimumInputValue = 0; + +extern enum Checkpoints::CPMode CheckpointsMode; + +////////////////////////////////////////////////////////////////////////////// +// +// dispatching functions +// + +// These functions dispatch to one or all registered wallets + + +void RegisterWallet(CWallet* pwalletIn) +{ + { + LOCK(cs_setpwalletRegistered); + setpwalletRegistered.insert(pwalletIn); + } +} + +void UnregisterWallet(CWallet* pwalletIn) +{ + { + LOCK(cs_setpwalletRegistered); + setpwalletRegistered.erase(pwalletIn); + } +} + +// check whether the passed transaction is from us +bool static IsFromMe(CTransaction& tx) +{ + BOOST_FOREACH(CWallet* pwallet, setpwalletRegistered) + if (pwallet->IsFromMe(tx)) + return true; + return false; +} + +// get the wallet transaction with the given hash (if it exists) +bool static GetTransaction(const uint256& hashTx, CWalletTx& wtx) +{ + BOOST_FOREACH(CWallet* pwallet, setpwalletRegistered) + if (pwallet->GetTransaction(hashTx,wtx)) + return true; + return false; +} + +// erases transaction with the given hash from all wallets +void static EraseFromWallets(uint256 hash) +{ + BOOST_FOREACH(CWallet* pwallet, setpwalletRegistered) + pwallet->EraseFromWallet(hash); +} + +// make sure all wallets know about the given transaction, in the given block +void SyncWithWallets(const CTransaction& tx, const CBlock* pblock, bool fUpdate, bool fConnect) +{ + if (!fConnect) + { + // ppcoin: wallets need to refund inputs when disconnecting coinstake + if (tx.IsCoinStake()) + { + BOOST_FOREACH(CWallet* pwallet, setpwalletRegistered) + if (pwallet->IsFromMe(tx)) + pwallet->DisableTransaction(tx); + } + return; + } + + BOOST_FOREACH(CWallet* pwallet, setpwalletRegistered) + pwallet->AddToWalletIfInvolvingMe(tx, pblock, fUpdate); +} + +// notify wallets about a new best chain +void static SetBestChain(const CBlockLocator& loc) +{ + BOOST_FOREACH(CWallet* pwallet, setpwalletRegistered) + pwallet->SetBestChain(loc); +} + +// notify wallets about an updated transaction +void static UpdatedTransaction(const uint256& hashTx) +{ + BOOST_FOREACH(CWallet* pwallet, setpwalletRegistered) + pwallet->UpdatedTransaction(hashTx); +} + +// dump all wallets +void static PrintWallets(const CBlock& block) +{ + BOOST_FOREACH(CWallet* pwallet, setpwalletRegistered) + pwallet->PrintWallet(block); +} + +// notify wallets about an incoming inventory (for request counts) +void static Inventory(const uint256& hash) +{ + BOOST_FOREACH(CWallet* pwallet, setpwalletRegistered) + pwallet->Inventory(hash); +} + +// ask wallets to resend their transactions +void ResendWalletTransactions(bool fForce) +{ + BOOST_FOREACH(CWallet* pwallet, setpwalletRegistered) + pwallet->ResendWalletTransactions(fForce); +} + + + + + + + +////////////////////////////////////////////////////////////////////////////// +// +// mapOrphanTransactions +// + +bool AddOrphanTx(const CTransaction& tx) +{ + uint256 hash = tx.GetHash(); + if (mapOrphanTransactions.count(hash)) + return false; + + // Ignore big transactions, to avoid a + // send-big-orphans memory exhaustion attack. If a peer has a legitimate + // large transaction with a missing parent then we assume + // it will rebroadcast it later, after the parent transaction(s) + // have been mined or received. + // 10,000 orphans, each of which is at most 5,000 bytes big is + // at most 500 megabytes of orphans: + + size_t nSize = tx.GetSerializeSize(SER_NETWORK, CTransaction::CURRENT_VERSION); + + if (nSize > 5000) + { + printf("ignoring large orphan tx (size: %" PRIszu", hash: %s)\n", nSize, hash.ToString().substr(0,10).c_str()); + return false; + } + + mapOrphanTransactions[hash] = tx; + BOOST_FOREACH(const CTxIn& txin, tx.vin) + mapOrphanTransactionsByPrev[txin.prevout.hash].insert(hash); + + printf("stored orphan tx %s (mapsz %" PRIszu")\n", hash.ToString().substr(0,10).c_str(), + mapOrphanTransactions.size()); + return true; +} + +void static EraseOrphanTx(uint256 hash) +{ + if (!mapOrphanTransactions.count(hash)) + return; + const CTransaction& tx = mapOrphanTransactions[hash]; + BOOST_FOREACH(const CTxIn& txin, tx.vin) + { + mapOrphanTransactionsByPrev[txin.prevout.hash].erase(hash); + if (mapOrphanTransactionsByPrev[txin.prevout.hash].empty()) + mapOrphanTransactionsByPrev.erase(txin.prevout.hash); + } + mapOrphanTransactions.erase(hash); +} + +unsigned int LimitOrphanTxSize(unsigned int nMaxOrphans) +{ + unsigned int nEvicted = 0; + while (mapOrphanTransactions.size() > nMaxOrphans) + { + // Evict a random orphan: + uint256 randomhash = GetRandHash(); + map::iterator it = mapOrphanTransactions.lower_bound(randomhash); + if (it == mapOrphanTransactions.end()) + it = mapOrphanTransactions.begin(); + EraseOrphanTx(it->first); + ++nEvicted; + } + return nEvicted; +} + + + + + + + +////////////////////////////////////////////////////////////////////////////// +// +// CTransaction and CTxIndex +// + +bool CTransaction::ReadFromDisk(CTxDB& txdb, COutPoint prevout, CTxIndex& txindexRet) +{ + SetNull(); + if (!txdb.ReadTxIndex(prevout.hash, txindexRet)) + return false; + if (!ReadFromDisk(txindexRet.pos)) + return false; + if (prevout.n >= vout.size()) + { + SetNull(); + return false; + } + return true; +} + +bool CTransaction::ReadFromDisk(CTxDB& txdb, COutPoint prevout) +{ + CTxIndex txindex; + return ReadFromDisk(txdb, prevout, txindex); +} + +bool CTransaction::ReadFromDisk(COutPoint prevout) +{ + CTxDB txdb("r"); + CTxIndex txindex; + return ReadFromDisk(txdb, prevout, txindex); +} + +bool IsStandardTx(const CTransaction& tx) +{ + if (tx.nVersion > CTransaction::CURRENT_VERSION) + return false; + + // Treat non-final transactions as non-standard to prevent a specific type + // of double-spend attack, as well as DoS attacks. (if the transaction + // can't be mined, the attacker isn't expending resources broadcasting it) + // Basically we don't want to propagate transactions that can't included in + // the next block. + // + // However, IsFinalTx() is confusing... Without arguments, it uses + // chainActive.Height() to evaluate nLockTime; when a block is accepted, chainActive.Height() + // is set to the value of nHeight in the block. However, when IsFinalTx() + // is called within CBlock::AcceptBlock(), the height of the block *being* + // evaluated is what is used. Thus if we want to know if a transaction can + // be part of the *next* block, we need to call IsFinalTx() with one more + // than chainActive.Height(). + // + // Timestamps on the other hand don't get any special treatment, because we + // can't know what timestamp the next block will have, and there aren't + // timestamp applications where it matters. + if (!IsFinalTx(tx, nBestHeight + 1)) { + return false; + } + // nTime has different purpose from nLockTime but can be used in similar attacks + if (tx.nTime > FutureDrift(GetAdjustedTime())) { + return false; + } + + // Extremely large transactions with lots of inputs can cost the network + // almost as much to process as they cost the sender in fees, because + // computing signature hashes is O(ninputs*txsize). Limiting transactions + // to MAX_STANDARD_TX_SIZE mitigates CPU exhaustion attacks. + unsigned int sz = tx.GetSerializeSize(SER_NETWORK, CTransaction::CURRENT_VERSION); + if (sz >= MAX_STANDARD_TX_SIZE) + return false; + + BOOST_FOREACH(const CTxIn& txin, tx.vin) + { + // Biggest 'standard' txin is a 3-signature 3-of-3 CHECKMULTISIG + // pay-to-script-hash, which is 3 ~80-byte signatures, 3 + // ~65-byte public keys, plus a few script ops. + if (txin.scriptSig.size() > 500) + return false; + if (!txin.scriptSig.IsPushOnly()) + return false; + if (fEnforceCanonical && !txin.scriptSig.HasCanonicalPushes()) { + return false; + } + } + + unsigned int nDataOut = 0; + txnouttype whichType; + BOOST_FOREACH(const CTxOut& txout, tx.vout) { + if (!::IsStandard(txout.scriptPubKey, whichType)) + return false; + if (whichType == TX_NULL_DATA) + nDataOut++; + if (txout.nValue == 0) + return false; + if (fEnforceCanonical && !txout.scriptPubKey.HasCanonicalPushes()) { + return false; + } + } + + // only one OP_RETURN txout is permitted + if (nDataOut > 1) { + return false; + } + + return true; +} + +bool IsFinalTx(const CTransaction &tx, int nBlockHeight, int64_t nBlockTime) +{ + AssertLockHeld(cs_main); + // Time based nLockTime implemented in 0.1.6 + if (tx.nLockTime == 0) + return true; + if (nBlockHeight == 0) + nBlockHeight = nBestHeight; + if (nBlockTime == 0) + nBlockTime = GetAdjustedTime(); + if ((int64_t)tx.nLockTime < ((int64_t)tx.nLockTime < LOCKTIME_THRESHOLD ? (int64_t)nBlockHeight : nBlockTime)) + return true; + BOOST_FOREACH(const CTxIn& txin, tx.vin) + if (!txin.IsFinal()) + return false; + return true; +} + +// +// Check transaction inputs, and make sure any +// pay-to-script-hash transactions are evaluating IsStandard scripts +// +// Why bother? To avoid denial-of-service attacks; an attacker +// can submit a standard HASH... OP_EQUAL transaction, +// which will get accepted into blocks. The redemption +// script can be anything; an attacker could use a very +// expensive-to-check-upon-redemption script like: +// DUP CHECKSIG DROP ... repeated 100 times... OP_1 +// +bool CTransaction::AreInputsStandard(const MapPrevTx& mapInputs) const +{ + if (IsCoinBase()) + return true; // Coinbases don't use vin normally + + for (unsigned int i = 0; i < vin.size(); i++) + { + const CTxOut& prev = GetOutputFor(vin[i], mapInputs); + + vector > vSolutions; + txnouttype whichType; + // get the scriptPubKey corresponding to this input: + const CScript& prevScript = prev.scriptPubKey; + if (!Solver(prevScript, whichType, vSolutions)) + return false; + int nArgsExpected = ScriptSigArgsExpected(whichType, vSolutions); + if (nArgsExpected < 0) + return false; + + // Transactions with extra stuff in their scriptSigs are + // non-standard. Note that this EvalScript() call will + // be quick, because if there are any operations + // beside "push data" in the scriptSig the + // IsStandard() call returns false + vector > stack; + if (!EvalScript(stack, vin[i].scriptSig, *this, i, 0)) + return false; + + if (whichType == TX_SCRIPTHASH) + { + if (stack.empty()) + return false; + CScript subscript(stack.back().begin(), stack.back().end()); + vector > vSolutions2; + txnouttype whichType2; + if (!Solver(subscript, whichType2, vSolutions2)) + return false; + if (whichType2 == TX_SCRIPTHASH) + return false; + + int tmpExpected; + tmpExpected = ScriptSigArgsExpected(whichType2, vSolutions2); + if (tmpExpected < 0) + return false; + nArgsExpected += tmpExpected; + } + + if (stack.size() != (unsigned int)nArgsExpected) + return false; + } + + return true; +} + +unsigned int +CTransaction::GetLegacySigOpCount() const +{ + unsigned int nSigOps = 0; + BOOST_FOREACH(const CTxIn& txin, vin) + { + nSigOps += txin.scriptSig.GetSigOpCount(false); + } + BOOST_FOREACH(const CTxOut& txout, vout) + { + nSigOps += txout.scriptPubKey.GetSigOpCount(false); + } + return nSigOps; +} + + +int CMerkleTx::SetMerkleBranch(const CBlock* pblock) +{ + AssertLockHeld(cs_main); + + CBlock blockTmp; + if (pblock == NULL) + { + // Load the block this tx is in + CTxIndex txindex; + if (!CTxDB("r").ReadTxIndex(GetHash(), txindex)) + return 0; + if (!blockTmp.ReadFromDisk(txindex.pos.nFile, txindex.pos.nBlockPos)) + return 0; + pblock = &blockTmp; + } + + // Update the tx's hashBlock + hashBlock = pblock->GetHash(); + + // Locate the transaction + for (nIndex = 0; nIndex < (int)pblock->vtx.size(); nIndex++) + if (pblock->vtx[nIndex] == *(CTransaction*)this) + break; + if (nIndex == (int)pblock->vtx.size()) + { + vMerkleBranch.clear(); + nIndex = -1; + printf("ERROR: SetMerkleBranch() : couldn't find tx in block\n"); + return 0; + } + + // Fill in merkle branch + vMerkleBranch = pblock->GetMerkleBranch(nIndex); + + // Is the tx in a block that's in the main chain + map::iterator mi = mapBlockIndex.find(hashBlock); + if (mi == mapBlockIndex.end()) + return 0; + CBlockIndex* pindex = (*mi).second; + if (!pindex || !pindex->IsInMainChain()) + return 0; + + return pindexBest->nHeight - pindex->nHeight + 1; +} + + + + + + + +bool CTransaction::CheckTransaction() const +{ + // Basic checks that don't depend on any context + if (vin.empty()) + return DoS(10, error("CTransaction::CheckTransaction() : vin empty")); + if (vout.empty()) + return DoS(10, error("CTransaction::CheckTransaction() : vout empty")); + // Size limits + if (::GetSerializeSize(*this, SER_NETWORK, PROTOCOL_VERSION) > MAX_BLOCK_SIZE) + return DoS(100, error("CTransaction::CheckTransaction() : size limits failed")); + + // Check for negative or overflow output values + int64_t nValueOut = 0; + for (unsigned int i = 0; i < vout.size(); i++) + { + const CTxOut& txout = vout[i]; + if (txout.IsEmpty() && !IsCoinBase() && !IsCoinStake()) + return DoS(100, error("CTransaction::CheckTransaction() : txout empty for user transaction")); + if (txout.nValue < 0) + return DoS(100, error("CTransaction::CheckTransaction() : txout.nValue negative")); + if (txout.nValue > MAX_MONEY) + return DoS(100, error("CTransaction::CheckTransaction() : txout.nValue too high")); + nValueOut += txout.nValue; + if (!MoneyRange(nValueOut)) + return DoS(100, error("CTransaction::CheckTransaction() : txout total out of range")); + } + + // Check for duplicate inputs + set vInOutPoints; + BOOST_FOREACH(const CTxIn& txin, vin) + { + if (vInOutPoints.count(txin.prevout)) + return false; + vInOutPoints.insert(txin.prevout); + } + + if (IsCoinBase()) + { + if (vin[0].scriptSig.size() < 2 || vin[0].scriptSig.size() > 100) + return DoS(100, error("CTransaction::CheckTransaction() : coinbase script size is invalid")); + } + else + { + BOOST_FOREACH(const CTxIn& txin, vin) + if (txin.prevout.IsNull()) + return DoS(10, error("CTransaction::CheckTransaction() : prevout is null")); + } + + return true; +} + +int64_t CTransaction::GetMinFee(unsigned int nBlockSize, enum GetMinFee_mode mode, unsigned int nBytes) const +{ + // Base fee is either MIN_TX_FEE or MIN_RELAY_TX_FEE + int64_t nBaseFee = (mode == GMF_RELAY) ? MIN_RELAY_TX_FEE : MIN_TX_FEE; + + unsigned int nNewBlockSize = nBlockSize + nBytes; + int64_t nMinFee = (1 + (int64_t)nBytes / 1000) * nBaseFee; + + // To limit dust spam, require MIN_TX_FEE/MIN_RELAY_TX_FEE if any output is less than 0.01 + if (nMinFee < nBaseFee) + { + BOOST_FOREACH(const CTxOut& txout, vout) + if (txout.nValue < CENT) + nMinFee = nBaseFee; + } + + // Raise the price as the block approaches full + if (nBlockSize != 1 && nNewBlockSize >= MAX_BLOCK_SIZE_GEN/2) + { + if (nNewBlockSize >= MAX_BLOCK_SIZE_GEN) + return MAX_MONEY; + nMinFee *= MAX_BLOCK_SIZE_GEN / (MAX_BLOCK_SIZE_GEN - nNewBlockSize); + } + + if (!MoneyRange(nMinFee)) + nMinFee = MAX_MONEY; + return nMinFee; +} + + +bool AcceptToMemoryPool(CTxMemPool& pool, CTransaction &tx, + bool* pfMissingInputs) +{ + AssertLockHeld(cs_main); + if (pfMissingInputs) + *pfMissingInputs = false; + + if (!tx.CheckTransaction()) + return error("AcceptToMemoryPool : CheckTransaction failed"); + + // Coinbase is only valid in a block, not as a loose transaction + if (tx.IsCoinBase()) + return tx.DoS(100, error("AcceptToMemoryPool : coinbase as individual tx")); + + // ppcoin: coinstake is also only valid in a block, not as a loose transaction + if (tx.IsCoinStake()) + return tx.DoS(100, error("AcceptToMemoryPool : coinstake as individual tx")); + + // Rather not work on nonstandard transactions (unless -testnet) + if (!fTestNet && !IsStandardTx(tx)) + return error("AcceptToMemoryPool : nonstandard transaction type"); + + // is it already in the memory pool? + uint256 hash = tx.GetHash(); + if (pool.exists(hash)) + return false; + + // Check for conflicts with in-memory transactions + CTransaction* ptxOld = NULL; + { + LOCK(pool.cs); // protect pool.mapNextTx + for (unsigned int i = 0; i < tx.vin.size(); i++) + { + COutPoint outpoint = tx.vin[i].prevout; + if (pool.mapNextTx.count(outpoint)) + { + // Disable replacement feature for now + return false; + + // Allow replacing with a newer version of the same transaction + if (i != 0) + return false; + ptxOld = pool.mapNextTx[outpoint].ptx; + if (IsFinalTx(*ptxOld)) + return false; + if (!tx.IsNewerThan(*ptxOld)) + return false; + for (unsigned int i = 0; i < tx.vin.size(); i++) + { + COutPoint outpoint = tx.vin[i].prevout; + if (!pool.mapNextTx.count(outpoint) || pool.mapNextTx[outpoint].ptx != ptxOld) + return false; + } + break; + } + } + } + + { + CTxDB txdb("r"); + + // do we already have it? + if (txdb.ContainsTx(hash)) + return false; + + MapPrevTx mapInputs; + map mapUnused; + bool fInvalid = false; + if (!tx.FetchInputs(txdb, mapUnused, false, false, mapInputs, fInvalid)) + { + if (fInvalid) + return error("AcceptToMemoryPool : FetchInputs found invalid tx %s", hash.ToString().substr(0,10).c_str()); + if (pfMissingInputs) + *pfMissingInputs = true; + return false; + } + + // Check for non-standard pay-to-script-hash in inputs + if (!tx.AreInputsStandard(mapInputs) && !fTestNet) + return error("AcceptToMemoryPool : nonstandard transaction input"); + + // Note: if you modify this code to accept non-standard transactions, then + // you should add code here to check that the transaction does a + // reasonable number of ECDSA signature verifications. + + int64_t nFees = tx.GetValueIn(mapInputs)-tx.GetValueOut(); + unsigned int nSize = ::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION); + + // Don't accept it if it can't get into a block + int64_t txMinFee = tx.GetMinFee(1000, GMF_RELAY, nSize); + if (nFees < txMinFee) + return error("AcceptToMemoryPool : not enough fees %s, %" PRId64" < %" PRId64, + hash.ToString().c_str(), + nFees, txMinFee); + + // Continuously rate-limit free transactions + // This mitigates 'penny-flooding' -- sending thousands of free transactions just to + // be annoying or make others' transactions take longer to confirm. + if (nFees < MIN_RELAY_TX_FEE) + { + static CCriticalSection cs; + static double dFreeCount; + static int64_t nLastTime; + int64_t nNow = GetTime(); + + { + LOCK(pool.cs); + // Use an exponentially decaying ~10-minute window: + dFreeCount *= pow(1.0 - 1.0/600.0, (double)(nNow - nLastTime)); + nLastTime = nNow; + // -limitfreerelay unit is thousand-bytes-per-minute + // At default rate it would take over a month to fill 1GB + if (dFreeCount > GetArg("-limitfreerelay", 15)*10*1000 && !IsFromMe(tx)) + return error("AcceptToMemoryPool : free transaction rejected by rate limiter"); + if (fDebug) + printf("Rate limit dFreeCount: %g => %g\n", dFreeCount, dFreeCount+nSize); + dFreeCount += nSize; + } + } + + // Check against previous transactions + // This is done last to help prevent CPU exhaustion denial-of-service attacks. + if (!tx.ConnectInputs(txdb, mapInputs, mapUnused, CDiskTxPos(1,1,1), pindexBest, false, false)) + { + return error("AcceptToMemoryPool : ConnectInputs failed %s", hash.ToString().substr(0,10).c_str()); + } + } + + // Store transaction in memory + { + LOCK(pool.cs); + if (ptxOld) + { + printf("AcceptToMemoryPool : replacing tx %s with new version\n", ptxOld->GetHash().ToString().c_str()); + pool.remove(*ptxOld); + } + pool.addUnchecked(hash, tx); + } + + ///// are we sure this is ok when loading transactions or restoring block txes + // If updated, erase old tx from wallet + if (ptxOld) + EraseFromWallets(ptxOld->GetHash()); + + printf("AcceptToMemoryPool : accepted %s (poolsz %" PRIszu")\n", + hash.ToString().substr(0,10).c_str(), + pool.mapTx.size()); + return true; +} + +bool CTxMemPool::addUnchecked(const uint256& hash, CTransaction &tx) +{ + // Add to memory pool without checking anything. Don't call this directly, + // call AcceptToMemoryPool to properly check the transaction first. + { + mapTx[hash] = tx; + for (unsigned int i = 0; i < tx.vin.size(); i++) + mapNextTx[tx.vin[i].prevout] = CInPoint(&mapTx[hash], i); + nTransactionsUpdated++; + } + return true; +} + + +bool CTxMemPool::remove(const CTransaction &tx, bool fRecursive) +{ + // Remove transaction from memory pool + { + LOCK(cs); + uint256 hash = tx.GetHash(); + if (mapTx.count(hash)) + { + if (fRecursive) { + for (unsigned int i = 0; i < tx.vout.size(); i++) { + std::map::iterator it = mapNextTx.find(COutPoint(hash, i)); + if (it != mapNextTx.end()) + remove(*it->second.ptx, true); + } + } + BOOST_FOREACH(const CTxIn& txin, tx.vin) + mapNextTx.erase(txin.prevout); + mapTx.erase(hash); + nTransactionsUpdated++; + } + } + return true; +} + +bool CTxMemPool::removeConflicts(const CTransaction &tx) +{ + // Remove transactions which depend on inputs of tx, recursively + LOCK(cs); + BOOST_FOREACH(const CTxIn &txin, tx.vin) { + std::map::iterator it = mapNextTx.find(txin.prevout); + if (it != mapNextTx.end()) { + const CTransaction &txConflict = *it->second.ptx; + if (txConflict != tx) + remove(txConflict, true); + } + } + return true; +} + +void CTxMemPool::clear() +{ + LOCK(cs); + mapTx.clear(); + mapNextTx.clear(); + ++nTransactionsUpdated; +} + +void CTxMemPool::queryHashes(std::vector& vtxid) +{ + vtxid.clear(); + + LOCK(cs); + vtxid.reserve(mapTx.size()); + for (map::iterator mi = mapTx.begin(); mi != mapTx.end(); ++mi) + vtxid.push_back((*mi).first); +} + + + + +int CMerkleTx::GetDepthInMainChainINTERNAL(CBlockIndex* &pindexRet) const +{ + if (hashBlock == 0 || nIndex == -1) + return 0; + AssertLockHeld(cs_main); + + // Find the block it claims to be in + map::iterator mi = mapBlockIndex.find(hashBlock); + if (mi == mapBlockIndex.end()) + return 0; + CBlockIndex* pindex = (*mi).second; + if (!pindex || !pindex->IsInMainChain()) + return 0; + + // Make sure the merkle branch connects to this block + if (!fMerkleVerified) + { + if (CBlock::CheckMerkleBranch(GetHash(), vMerkleBranch, nIndex) != pindex->hashMerkleRoot) + return 0; + fMerkleVerified = true; + } + + pindexRet = pindex; + return pindexBest->nHeight - pindex->nHeight + 1; +} + +int CMerkleTx::GetDepthInMainChain(CBlockIndex* &pindexRet) const +{ + AssertLockHeld(cs_main); + int nResult = GetDepthInMainChainINTERNAL(pindexRet); + if (nResult == 0 && !mempool.exists(GetHash())) + return -1; // Not in chain, not in mempool + + return nResult; +} + +int CMerkleTx::GetHeightInMainChain(CBlockIndex* &pindexRet) const +{ + return GetDepthInMainChain(pindexRet) + pindexBest->nHeight - 1; +} + +int GetCoinbaseMaturity(int nHeight) +{ + return ( (nHeight < 1467000) ? nCoinbaseMaturity : nCoinbaseMaturityADJ ); +} + +int CMerkleTx::GetBlocksToMaturity() const +{ + if (!(IsCoinBase() || IsCoinStake())) + return 0; + return max(0, (GetCoinbaseMaturity(GetHeightInMainChain()) +0) - GetDepthInMainChain()); +} + + +bool CMerkleTx::AcceptToMemoryPool() +{ + return ::AcceptToMemoryPool(mempool, *this, NULL); +} + + + +bool CWalletTx::AcceptWalletTransaction(CTxDB& txdb) +{ + + { + // Add previous supporting transactions first + BOOST_FOREACH(CMerkleTx& tx, vtxPrev) + { + if (!(tx.IsCoinBase() || tx.IsCoinStake())) + { + uint256 hash = tx.GetHash(); + if (!mempool.exists(hash) && !txdb.ContainsTx(hash)) + tx.AcceptToMemoryPool(); + } + } + return AcceptToMemoryPool(); + } + return false; +} + +bool CWalletTx::AcceptWalletTransaction() +{ + CTxDB txdb("r"); + return AcceptWalletTransaction(txdb); +} + +int CTxIndex::GetDepthInMainChain() const +{ + // Read block header + CBlock block; + if (!block.ReadFromDisk(pos.nFile, pos.nBlockPos, false)) + return 0; + // Find the block in the index + map::iterator mi = mapBlockIndex.find(block.GetHash()); + if (mi == mapBlockIndex.end()) + return 0; + CBlockIndex* pindex = (*mi).second; + if (!pindex || !pindex->IsInMainChain()) + return 0; + return 1 + nBestHeight - pindex->nHeight; +} + +// Return transaction in tx, and if it was found inside a block, its hash is placed in hashBlock +bool GetTransaction(const uint256 &hash, CTransaction &tx, uint256 &hashBlock) +{ + { + LOCK(cs_main); + { + if (mempool.lookup(hash, tx)) + { + return true; + } + } + CTxDB txdb("r"); + CTxIndex txindex; + if (tx.ReadFromDisk(txdb, COutPoint(hash, 0), txindex)) + { + CBlock block; + if (block.ReadFromDisk(txindex.pos.nFile, txindex.pos.nBlockPos, false)) + hashBlock = block.GetHash(); + return true; + } + // look for transaction in disconnected blocks to find orphaned CoinBase and CoinStake transactions + BOOST_FOREACH(PAIRTYPE(const uint256, CBlockIndex*)& item, mapBlockIndex) + { + CBlockIndex* pindex = item.second; + if (pindex == pindexBest || pindex->pnext != 0) + continue; + CBlock block; + if (!block.ReadFromDisk(pindex)) + continue; + BOOST_FOREACH(const CTransaction& txOrphan, block.vtx) + { + if (txOrphan.GetHash() == hash) + { + tx = txOrphan; + return true; + } + } + } + + } + return false; +} + + + + + + + + +////////////////////////////////////////////////////////////////////////////// +// +// CBlock and CBlockIndex +// + +static CBlockIndex* pblockindexFBBHLast; +CBlockIndex* FindBlockByHeight(int nHeight) +{ + CBlockIndex *pblockindex; + if (nHeight < nBestHeight / 2) + pblockindex = pindexGenesisBlock; + else + pblockindex = pindexBest; + if (pblockindexFBBHLast && abs(nHeight - pblockindex->nHeight) > abs(nHeight - pblockindexFBBHLast->nHeight)) + pblockindex = pblockindexFBBHLast; + while (pblockindex->nHeight > nHeight) + pblockindex = pblockindex->pprev; + while (pblockindex->nHeight < nHeight) + pblockindex = pblockindex->pnext; + pblockindexFBBHLast = pblockindex; + return pblockindex; +} + +bool CBlock::ReadFromDisk(const CBlockIndex* pindex, bool fReadTransactions) +{ + if (!fReadTransactions) + { + *this = pindex->GetBlockHeader(); + return true; + } + if (!ReadFromDisk(pindex->nFile, pindex->nBlockPos, fReadTransactions)) + return false; + if (GetHash() != pindex->GetBlockHash()) + return error("CBlock::ReadFromDisk() : GetHash() doesn't match index"); + return true; +} + +uint256 static GetOrphanRoot(const CBlock* pblock) +{ + // Work back to the first block in the orphan chain + while (mapOrphanBlocks.count(pblock->hashPrevBlock)) + pblock = mapOrphanBlocks[pblock->hashPrevBlock]; + return pblock->GetHash(); +} + +// ppcoin: find block wanted by given orphan block +uint256 WantedByOrphan(const CBlock* pblockOrphan) +{ + // Work back to the first block in the orphan chain + while (mapOrphanBlocks.count(pblockOrphan->hashPrevBlock)) + pblockOrphan = mapOrphanBlocks[pblockOrphan->hashPrevBlock]; + return pblockOrphan->hashPrevBlock; +} + +// miner's coin base reward +int64_t GetProofOfWorkReward(int64_t nFees) +{ + + int64_t nSubsidy = 50 * COIN; + + if(nBestHeight <= 10000) + { + nSubsidy = 325 * COIN; + } + + else if(nBestHeight <= 250000) + { + nSubsidy = 50 * COIN;; // + } + + else if(nBestHeight <= 500000) + { + nSubsidy = 25 * COIN;; // + } + + else if(nBestHeight <= 750000) + { + nSubsidy = 12 * COIN;; // + } + + else if(nBestHeight <= 1000000) + { + nSubsidy = 6 * COIN;; // + } + + else if(nBestHeight <= 2000000) + { + nSubsidy = 3 * COIN;; // + } + + else if(nBestHeight > 2000000) + { + nSubsidy = 1 * COIN;; // + } + if (fDebug && GetBoolArg("-printcreation")) + printf("GetProofOfWorkReward() : create=%s nSubsidy=%" PRId64 "\n", FormatMoney(nSubsidy).c_str(), nSubsidy); + + return nSubsidy + nFees; +} + +// miner's coin stake reward based on coin age spent (coin-days) +int64_t GetProofOfStakeReward(int64_t nCoinAge, int64_t nFees) +{ + int64_t nSubsidy = nCoinAge * COIN_YEAR_REWARD * 33 / (365 * 33 + 8); + + if (fDebug && GetBoolArg("-printcreation")) + printf("GetProofOfStakeReward(): create=%s nCoinAge=%" PRId64 "\n", FormatMoney(nSubsidy).c_str(), nCoinAge); + + return nSubsidy + nFees; +} + +static const int64_t nTargetTimespan = 16 * 60; // 16 mins + +// +// maximum nBits value could possible be required nTime after +// +unsigned int ComputeMaxBits(CBigNum bnTargetLimit, unsigned int nBase, int64_t nTime) +{ + CBigNum bnResult; + bnResult.SetCompact(nBase); + bnResult *= 2; + while (nTime > 0 && bnResult < bnTargetLimit) + { + // Maximum 200% adjustment per day... + bnResult *= 2; + nTime -= 24 * 60 * 60; + } + if (bnResult > bnTargetLimit) + bnResult = bnTargetLimit; + return bnResult.GetCompact(); +} + +// +// minimum amount of work that could possibly be required nTime after +// minimum proof-of-work required was nBase +// +unsigned int ComputeMinWork(unsigned int nBase, int64_t nTime) +{ + return ComputeMaxBits(bnProofOfWorkLimit, nBase, nTime); +} + +// +// minimum amount of stake that could possibly be required nTime after +// minimum proof-of-stake required was nBase +// +unsigned int ComputeMinStake(unsigned int nBase, int64_t nTime, unsigned int nBlockTime) +{ + return ComputeMaxBits(bnProofOfStakeLimit, nBase, nTime); +} + + +// ppcoin: find last block index up to pindex +const CBlockIndex* GetLastBlockIndex(const CBlockIndex* pindex, bool fProofOfStake) +{ + while (pindex && pindex->pprev && (pindex->IsProofOfStake() != fProofOfStake)) + pindex = pindex->pprev; + return pindex; +} + +static unsigned int GetNextTargetRequiredV1(const CBlockIndex* pindexLast, bool fProofOfStake) +{ + CBigNum bnTargetLimit = fProofOfStake ? bnProofOfStakeLimit : bnProofOfWorkLimit; + + if (pindexLast == NULL) + return bnTargetLimit.GetCompact(); // genesis block + + const CBlockIndex* pindexPrev = GetLastBlockIndex(pindexLast, fProofOfStake); + if (pindexPrev->pprev == NULL) + return bnTargetLimit.GetCompact(); // first block + const CBlockIndex* pindexPrevPrev = GetLastBlockIndex(pindexPrev->pprev, fProofOfStake); + if (pindexPrevPrev->pprev == NULL) + return bnTargetLimit.GetCompact(); // second block + + int64_t nActualSpacing = pindexPrev->GetBlockTime() - pindexPrevPrev->GetBlockTime(); + + // ppcoin: target change every block + // ppcoin: retarget with exponential moving toward target spacing + CBigNum bnNew; + bnNew.SetCompact(pindexPrev->nBits); + int64_t nInterval = nTargetTimespan / nTargetSpacing; + bnNew *= ((nInterval - 1) * nTargetSpacing + nActualSpacing + nActualSpacing); + bnNew /= ((nInterval + 1) * nTargetSpacing); + + if (bnNew > bnTargetLimit) + bnNew = bnTargetLimit; + + return bnNew.GetCompact(); +} + +static unsigned int GetNextTargetRequiredV2(const CBlockIndex* pindexLast, bool fProofOfStake) +{ + CBigNum bnTargetLimit = fProofOfStake ? bnProofOfStakeLimit : bnProofOfWorkLimit; + + if (pindexLast == NULL) + return bnTargetLimit.GetCompact(); // genesis block + + const CBlockIndex* pindexPrev = GetLastBlockIndex(pindexLast, fProofOfStake); + if (pindexPrev->pprev == NULL) + return bnTargetLimit.GetCompact(); // first block + const CBlockIndex* pindexPrevPrev = GetLastBlockIndex(pindexPrev->pprev, fProofOfStake); + if (pindexPrevPrev->pprev == NULL) + return bnTargetLimit.GetCompact(); // second block + + int64_t nActualSpacing = pindexPrev->GetBlockTime() - pindexPrevPrev->GetBlockTime(); + if (nActualSpacing < 0) + nActualSpacing = nTargetSpacing; + + // ppcoin: target change every block + // ppcoin: retarget with exponential moving toward target spacing + CBigNum bnNew; + bnNew.SetCompact(pindexPrev->nBits); + int64_t nInterval = nTargetTimespan / nTargetSpacing; + bnNew *= ((nInterval - 1) * nTargetSpacing + nActualSpacing + nActualSpacing); + bnNew /= ((nInterval + 1) * nTargetSpacing); + + if (bnNew <= 0 || bnNew > bnTargetLimit) + bnNew = bnTargetLimit; + + return bnNew.GetCompact(); +} + +unsigned int GetNextTargetRequired(const CBlockIndex* pindexLast, bool fProofOfStake) +{ + if (pindexLast->nHeight < 10000) + return GetNextTargetRequiredV1(pindexLast, fProofOfStake); + else + return GetNextTargetRequiredV2(pindexLast, fProofOfStake); +} + +bool CheckProofOfWork(uint256 hash, unsigned int nBits) +{ + CBigNum bnTarget; + bnTarget.SetCompact(nBits); + + // Check range + if (bnTarget <= 0 || bnTarget > bnProofOfWorkLimit) + return error("CheckProofOfWork() : nBits below minimum work"); + + // Check proof of work matches claimed amount + if (hash > bnTarget.getuint256()) + return error("CheckProofOfWork() : hash doesn't match nBits"); + + return true; +} + +// Return maximum amount of blocks that other nodes claim to have +int GetNumBlocksOfPeers() +{ + return std::max(cPeerBlockCounts.median(), Checkpoints::GetTotalBlocksEstimate()); +} + +bool IsInitialBlockDownload() +{ + LOCK(cs_main); + if (pindexBest == NULL || nBestHeight < Checkpoints::GetTotalBlocksEstimate()) + return true; + static int64_t nLastUpdate; + static CBlockIndex* pindexLastBest; + if (pindexBest != pindexLastBest) + { + pindexLastBest = pindexBest; + nLastUpdate = GetTime(); + } + return (GetTime() - nLastUpdate < 15 && + pindexBest->GetBlockTime() < GetTime() - 8 * 60 * 60); +} + +void static InvalidChainFound(CBlockIndex* pindexNew) +{ + if (pindexNew->nChainTrust > nBestInvalidTrust) + { + nBestInvalidTrust = pindexNew->nChainTrust; + CTxDB().WriteBestInvalidTrust(CBigNum(nBestInvalidTrust)); + uiInterface.NotifyBlocksChanged(); + } + + uint256 nBestInvalidBlockTrust = pindexNew->nChainTrust - pindexNew->pprev->nChainTrust; + uint256 nBestBlockTrust = pindexBest->nHeight != 0 ? (pindexBest->nChainTrust - pindexBest->pprev->nChainTrust) : pindexBest->nChainTrust; + + printf("InvalidChainFound: invalid block=%s height=%d trust=%s blocktrust=%" PRId64" date=%s\n", + pindexNew->GetBlockHash().ToString().substr(0,20).c_str(), pindexNew->nHeight, + CBigNum(pindexNew->nChainTrust).ToString().c_str(), nBestInvalidBlockTrust.Get64(), + DateTimeStrFormat("%x %H:%M:%S", pindexNew->GetBlockTime()).c_str()); + printf("InvalidChainFound: current best=%s height=%d trust=%s blocktrust=%" PRId64" date=%s\n", + hashBestChain.ToString().substr(0,20).c_str(), nBestHeight, + CBigNum(pindexBest->nChainTrust).ToString().c_str(), + nBestBlockTrust.Get64(), + DateTimeStrFormat("%x %H:%M:%S", pindexBest->GetBlockTime()).c_str()); +} + + +void CBlock::UpdateTime(const CBlockIndex* pindexPrev) +{ + nTime = max(GetBlockTime(), GetAdjustedTime()); +} + + + + + + + + + + + +bool CTransaction::DisconnectInputs(CTxDB& txdb) +{ + // Relinquish previous transactions' spent pointers + if (!IsCoinBase()) + { + BOOST_FOREACH(const CTxIn& txin, vin) + { + COutPoint prevout = txin.prevout; + + // Get prev txindex from disk + CTxIndex txindex; + if (!txdb.ReadTxIndex(prevout.hash, txindex)) + return error("DisconnectInputs() : ReadTxIndex failed"); + + if (prevout.n >= txindex.vSpent.size()) + return error("DisconnectInputs() : prevout.n out of range"); + + // Mark outpoint as not spent + txindex.vSpent[prevout.n].SetNull(); + + // Write back + if (!txdb.UpdateTxIndex(prevout.hash, txindex)) + return error("DisconnectInputs() : UpdateTxIndex failed"); + } + } + + // Remove transaction from index + // This can fail if a duplicate of this transaction was in a chain that got + // reorganized away. This is only possible if this transaction was completely + // spent, so erasing it would be a no-op anyway. + txdb.EraseTxIndex(*this); + + return true; +} + + +bool CTransaction::FetchInputs(CTxDB& txdb, const map& mapTestPool, + bool fBlock, bool fMiner, MapPrevTx& inputsRet, bool& fInvalid) +{ + // FetchInputs can return false either because we just haven't seen some inputs + // (in which case the transaction should be stored as an orphan) + // or because the transaction is malformed (in which case the transaction should + // be dropped). If tx is definitely invalid, fInvalid will be set to true. + fInvalid = false; + + if (IsCoinBase()) + return true; // Coinbase transactions have no inputs to fetch. + + for (unsigned int i = 0; i < vin.size(); i++) + { + COutPoint prevout = vin[i].prevout; + if (inputsRet.count(prevout.hash)) + continue; // Got it already + + // Read txindex + CTxIndex& txindex = inputsRet[prevout.hash].first; + bool fFound = true; + if ((fBlock || fMiner) && mapTestPool.count(prevout.hash)) + { + // Get txindex from current proposed changes + txindex = mapTestPool.find(prevout.hash)->second; + } + else + { + // Read txindex from txdb + fFound = txdb.ReadTxIndex(prevout.hash, txindex); + } + if (!fFound && (fBlock || fMiner)) + return fMiner ? false : error("FetchInputs() : %s prev tx %s index entry not found", GetHash().ToString().substr(0,10).c_str(), prevout.hash.ToString().substr(0,10).c_str()); + + // Read txPrev + CTransaction& txPrev = inputsRet[prevout.hash].second; + if (!fFound || txindex.pos == CDiskTxPos(1,1,1)) + { + // Get prev tx from single transactions in memory + if (!mempool.lookup(prevout.hash, txPrev)) + return error("FetchInputs() : %s mempool Tx prev not found %s", GetHash().ToString().substr(0,10).c_str(), prevout.hash.ToString().substr(0,10).c_str()); + if (!fFound) + txindex.vSpent.resize(txPrev.vout.size()); + } + else + { + // Get prev tx from disk + if (!txPrev.ReadFromDisk(txindex.pos)) + return error("FetchInputs() : %s ReadFromDisk prev tx %s failed", GetHash().ToString().substr(0,10).c_str(), prevout.hash.ToString().substr(0,10).c_str()); + } + } + + // Make sure all prevout.n indexes are valid: + for (unsigned int i = 0; i < vin.size(); i++) + { + const COutPoint prevout = vin[i].prevout; + assert(inputsRet.count(prevout.hash) != 0); + const CTxIndex& txindex = inputsRet[prevout.hash].first; + const CTransaction& txPrev = inputsRet[prevout.hash].second; + if (prevout.n >= txPrev.vout.size() || prevout.n >= txindex.vSpent.size()) + { + // Revisit this if/when transaction replacement is implemented and allows + // adding inputs: + fInvalid = true; + return DoS(100, error("FetchInputs() : %s prevout.n out of range %d %" PRIszu" %" PRIszu" prev tx %s\n%s", GetHash().ToString().substr(0,10).c_str(), prevout.n, txPrev.vout.size(), txindex.vSpent.size(), prevout.hash.ToString().substr(0,10).c_str(), txPrev.ToString().c_str())); + } + } + + return true; +} + +const CTxOut& CTransaction::GetOutputFor(const CTxIn& input, const MapPrevTx& inputs) const +{ + MapPrevTx::const_iterator mi = inputs.find(input.prevout.hash); + if (mi == inputs.end()) + throw std::runtime_error("CTransaction::GetOutputFor() : prevout.hash not found"); + + const CTransaction& txPrev = (mi->second).second; + if (input.prevout.n >= txPrev.vout.size()) + throw std::runtime_error("CTransaction::GetOutputFor() : prevout.n out of range"); + + return txPrev.vout[input.prevout.n]; +} + +int64_t CTransaction::GetValueIn(const MapPrevTx& inputs) const +{ + if (IsCoinBase()) + return 0; + + int64_t nResult = 0; + for (unsigned int i = 0; i < vin.size(); i++) + { + nResult += GetOutputFor(vin[i], inputs).nValue; + } + return nResult; + +} + +unsigned int CTransaction::GetP2SHSigOpCount(const MapPrevTx& inputs) const +{ + if (IsCoinBase()) + return 0; + + unsigned int nSigOps = 0; + for (unsigned int i = 0; i < vin.size(); i++) + { + const CTxOut& prevout = GetOutputFor(vin[i], inputs); + if (prevout.scriptPubKey.IsPayToScriptHash()) + nSigOps += prevout.scriptPubKey.GetSigOpCount(vin[i].scriptSig); + } + return nSigOps; +} + +bool CTransaction::ConnectInputs(CTxDB& txdb, MapPrevTx inputs, map& mapTestPool, const CDiskTxPos& posThisTx, + const CBlockIndex* pindexBlock, bool fBlock, bool fMiner) +{ + // Take over previous transactions' spent pointers + // fBlock is true when this is called from AcceptBlock when a new best-block is added to the blockchain + // fMiner is true when called from the internal bitcoin miner + // ... both are false when called from CTransaction::AcceptToMemoryPool + if (!IsCoinBase()) + { + int64_t nValueIn = 0; + int64_t nFees = 0; + for (unsigned int i = 0; i < vin.size(); i++) + { + COutPoint prevout = vin[i].prevout; + assert(inputs.count(prevout.hash) > 0); + CTxIndex& txindex = inputs[prevout.hash].first; + CTransaction& txPrev = inputs[prevout.hash].second; + + if (prevout.n >= txPrev.vout.size() || prevout.n >= txindex.vSpent.size()) + return DoS(100, error("ConnectInputs() : %s prevout.n out of range %d %" PRIszu" %" PRIszu" prev tx %s\n%s", GetHash().ToString().substr(0,10).c_str(), prevout.n, txPrev.vout.size(), txindex.vSpent.size(), prevout.hash.ToString().substr(0,10).c_str(), txPrev.ToString().c_str())); + + // If prev is coinbase or coinstake, check that it's matured + if (txPrev.IsCoinBase() || txPrev.IsCoinStake()) + for (const CBlockIndex* pindex = pindexBlock; pindex && pindexBlock->nHeight - pindex->nHeight < GetCoinbaseMaturity(pindex->nHeight); pindex = pindex->pprev) + if (pindex->nBlockPos == txindex.pos.nBlockPos && pindex->nFile == txindex.pos.nFile) + return error("ConnectInputs() : tried to spend %s at depth %d", txPrev.IsCoinBase() ? "coinbase" : "coinstake", pindexBlock->nHeight - pindex->nHeight); + + // ppcoin: check transaction timestamp + if (txPrev.nTime > nTime) + return DoS(100, error("ConnectInputs() : transaction timestamp earlier than input transaction")); + + // Check for negative or overflow input values + nValueIn += txPrev.vout[prevout.n].nValue; + if (!MoneyRange(txPrev.vout[prevout.n].nValue) || !MoneyRange(nValueIn)) + return DoS(100, error("ConnectInputs() : txin values out of range")); + + } + // The first loop above does all the inexpensive checks. + // Only if ALL inputs pass do we perform expensive ECDSA signature checks. + // Helps prevent CPU exhaustion attacks. + for (unsigned int i = 0; i < vin.size(); i++) + { + COutPoint prevout = vin[i].prevout; + assert(inputs.count(prevout.hash) > 0); + CTxIndex& txindex = inputs[prevout.hash].first; + CTransaction& txPrev = inputs[prevout.hash].second; + + // Check for conflicts (double-spend) + // This doesn't trigger the DoS code on purpose; if it did, it would make it easier + // for an attacker to attempt to split the network. + if (!txindex.vSpent[prevout.n].IsNull()) + return fMiner ? false : error("ConnectInputs() : %s prev tx already used at %s", GetHash().ToString().substr(0,10).c_str(), txindex.vSpent[prevout.n].ToString().c_str()); + + // Skip ECDSA signature verification when connecting blocks (fBlock=true) + // before the last blockchain checkpoint. This is safe because block merkle hashes are + // still computed and checked, and any change will be caught at the next checkpoint. + if (!(fBlock && (nBestHeight < Checkpoints::GetTotalBlocksEstimate()))) + { + // Verify signature + if (!VerifySignature(txPrev, *this, i, 0)) + { + return DoS(100,error("ConnectInputs() : %s VerifySignature failed", GetHash().ToString().substr(0,10).c_str())); + } + } + + // Mark outpoints as spent + txindex.vSpent[prevout.n] = posThisTx; + + // Write back + if (fBlock || fMiner) + { + mapTestPool[prevout.hash] = txindex; + } + } + + if (!IsCoinStake()) + { + if (nValueIn < GetValueOut()) + return DoS(100, error("ConnectInputs() : %s value in < value out", GetHash().ToString().substr(0,10).c_str())); + + // Tally transaction fees + int64_t nTxFee = nValueIn - GetValueOut(); + if (nTxFee < 0) + return DoS(100, error("ConnectInputs() : %s nTxFee < 0", GetHash().ToString().substr(0,10).c_str())); + + // enforce transaction fees for every block + if (nTxFee < GetMinFee()) + return fBlock? DoS(100, error("ConnectInputs() : %s not paying required fee=%s, paid=%s", GetHash().ToString().substr(0,10).c_str(), FormatMoney(GetMinFee()).c_str(), FormatMoney(nTxFee).c_str())) : false; + + nFees += nTxFee; + if (!MoneyRange(nFees)) + return DoS(100, error("ConnectInputs() : nFees out of range")); + } + } + + return true; +} + +bool CBlock::DisconnectBlock(CTxDB& txdb, CBlockIndex* pindex) +{ + // Disconnect in reverse order + for (int i = vtx.size()-1; i >= 0; i--) + if (!vtx[i].DisconnectInputs(txdb)) + return false; + + // Update block index on disk without changing it in memory. + // The memory index structure will be changed after the db commits. + if (pindex->pprev) + { + CDiskBlockIndex blockindexPrev(pindex->pprev); + blockindexPrev.hashNext = 0; + if (!txdb.WriteBlockIndex(blockindexPrev)) + return error("DisconnectBlock() : WriteBlockIndex failed"); + } + + // ppcoin: clean up wallet after disconnecting coinstake + BOOST_FOREACH(CTransaction& tx, vtx) + SyncWithWallets(tx, this, false, false); + + return true; +} + +bool CBlock::ConnectBlock(CTxDB& txdb, CBlockIndex* pindex, bool fJustCheck) +{ + // Check it again in case a previous version let a bad block in, but skip BlockSig checking + if (!CheckBlock(!fJustCheck, !fJustCheck, false)) + return false; + + //// issue here: it doesn't know the version + unsigned int nTxPos; + if (fJustCheck) + // FetchInputs treats CDiskTxPos(1,1,1) as a special "refer to memorypool" indicator + // Since we're just checking the block and not actually connecting it, it might not (and probably shouldn't) be on the disk to get the transaction from + nTxPos = 1; + else + nTxPos = pindex->nBlockPos + ::GetSerializeSize(CBlock(), SER_DISK, CLIENT_VERSION) - (2 * GetSizeOfCompactSize(0)) + GetSizeOfCompactSize(vtx.size()); + + map mapQueuedChanges; + int64_t nFees = 0; + int64_t nValueIn = 0; + int64_t nValueOut = 0; + int64_t nStakeReward = 0; + unsigned int nSigOps = 0; + BOOST_FOREACH(CTransaction& tx, vtx) + { + uint256 hashTx = tx.GetHash(); + + // Do not allow blocks that contain transactions which 'overwrite' older transactions, + // unless those are already completely spent. + // If such overwrites are allowed, coinbases and transactions depending upon those + // can be duplicated to remove the ability to spend the first instance -- even after + // being sent to another address. + // See BIP30 and http://r6.ca/blog/20120206T005236Z.html for more information. + // This logic is not necessary for memory pool transactions, as AcceptToMemoryPool + // already refuses previously-known transaction ids entirely. + // This rule was originally applied all blocks whose timestamp was after March 15, 2012, 0:00 UTC. + // Now that the whole chain is irreversibly beyond that time it is applied to all blocks except the + // two in the chain that violate it. This prevents exploiting the issue against nodes in their + // initial block download. + CTxIndex txindexOld; + if (txdb.ReadTxIndex(hashTx, txindexOld)) { + BOOST_FOREACH(CDiskTxPos &pos, txindexOld.vSpent) + if (pos.IsNull()) + return false; + } + + nSigOps += tx.GetLegacySigOpCount(); + if (nSigOps > MAX_BLOCK_SIGOPS) + return DoS(100, error("ConnectBlock() : too many sigops")); + + CDiskTxPos posThisTx(pindex->nFile, pindex->nBlockPos, nTxPos); + if (!fJustCheck) + nTxPos += ::GetSerializeSize(tx, SER_DISK, CLIENT_VERSION); + + MapPrevTx mapInputs; + if (tx.IsCoinBase()) + nValueOut += tx.GetValueOut(); + else + { + bool fInvalid; + if (!tx.FetchInputs(txdb, mapQueuedChanges, true, false, mapInputs, fInvalid)) + return false; + + // Add in sigops done by pay-to-script-hash inputs; + // this is to prevent a "rogue miner" from creating + // an incredibly-expensive-to-validate block. + nSigOps += tx.GetP2SHSigOpCount(mapInputs); + if (nSigOps > MAX_BLOCK_SIGOPS) + return DoS(100, error("ConnectBlock() : too many sigops")); + + int64_t nTxValueIn = tx.GetValueIn(mapInputs); + int64_t nTxValueOut = tx.GetValueOut(); + nValueIn += nTxValueIn; + nValueOut += nTxValueOut; + if (!tx.IsCoinStake()) + nFees += nTxValueIn - nTxValueOut; + if (tx.IsCoinStake()) + nStakeReward = nTxValueOut - nTxValueIn; + + if (!tx.ConnectInputs(txdb, mapInputs, mapQueuedChanges, posThisTx, pindex, true, false)) + return false; + } + + mapQueuedChanges[hashTx] = CTxIndex(posThisTx, tx.vout.size()); + } + + if (IsProofOfWork()) + { + int64_t nReward = GetProofOfWorkReward(nFees); + // Check coinbase reward + if (vtx[0].GetValueOut() > nReward) + return DoS(50, error("ConnectBlock() : coinbase reward exceeded (actual=%" PRId64" vs calculated=%" PRId64")", + vtx[0].GetValueOut(), + nReward)); + } + if (IsProofOfStake()) + { + // ppcoin: coin stake tx earns reward instead of paying fee + uint64_t nCoinAge; + if (!vtx[1].GetCoinAge(txdb, nCoinAge)) + return error("ConnectBlock() : %s unable to get coin age for coinstake", vtx[1].GetHash().ToString().substr(0,10).c_str()); + + int64_t nCalculatedStakeReward = GetProofOfStakeReward(nCoinAge, nFees); + + if (pindex->nHeight > 536000 && nStakeReward > nCalculatedStakeReward) + return DoS(100, error("ConnectBlock() : coinstake pays too much(actual=%" PRId64" vs calculated=%" PRId64")", nStakeReward, nCalculatedStakeReward)); + } + + // ppcoin: track money supply and mint amount info + pindex->nMint = nValueOut - nValueIn + nFees; + pindex->nMoneySupply = (pindex->pprev? pindex->pprev->nMoneySupply : 0) + nValueOut - nValueIn; + if (!txdb.WriteBlockIndex(CDiskBlockIndex(pindex))) + return error("Connect() : WriteBlockIndex for pindex failed"); + + if (fJustCheck) + return true; + + // Write queued txindex changes + for (map::iterator mi = mapQueuedChanges.begin(); mi != mapQueuedChanges.end(); ++mi) + { + if (!txdb.UpdateTxIndex((*mi).first, (*mi).second)) + return error("ConnectBlock() : UpdateTxIndex failed"); + } + + // Update block index on disk without changing it in memory. + // The memory index structure will be changed after the db commits. + if (pindex->pprev) + { + CDiskBlockIndex blockindexPrev(pindex->pprev); + blockindexPrev.hashNext = pindex->GetBlockHash(); + if (!txdb.WriteBlockIndex(blockindexPrev)) + return error("ConnectBlock() : WriteBlockIndex failed"); + } + + // Watch for transactions paying to me + BOOST_FOREACH(CTransaction& tx, vtx) + SyncWithWallets(tx, this, true); + + return true; +} + +bool static Reorganize(CTxDB& txdb, CBlockIndex* pindexNew) +{ + printf("REORGANIZE\n"); + + // Find the fork + CBlockIndex* pfork = pindexBest; + CBlockIndex* plonger = pindexNew; + while (pfork != plonger) + { + while (plonger->nHeight > pfork->nHeight) + if (!(plonger = plonger->pprev)) + return error("Reorganize() : plonger->pprev is null"); + if (pfork == plonger) + break; + if (!(pfork = pfork->pprev)) + return error("Reorganize() : pfork->pprev is null"); + } + + // List of what to disconnect + vector vDisconnect; + for (CBlockIndex* pindex = pindexBest; pindex != pfork; pindex = pindex->pprev) + vDisconnect.push_back(pindex); + + // List of what to connect + vector vConnect; + for (CBlockIndex* pindex = pindexNew; pindex != pfork; pindex = pindex->pprev) + vConnect.push_back(pindex); + reverse(vConnect.begin(), vConnect.end()); + + printf("REORGANIZE: Disconnect %" PRIszu" blocks; %s..%s\n", vDisconnect.size(), pfork->GetBlockHash().ToString().substr(0,20).c_str(), pindexBest->GetBlockHash().ToString().substr(0,20).c_str()); + printf("REORGANIZE: Connect %" PRIszu" blocks; %s..%s\n", vConnect.size(), pfork->GetBlockHash().ToString().substr(0,20).c_str(), pindexNew->GetBlockHash().ToString().substr(0,20).c_str()); + + // Disconnect shorter branch + list vResurrect; + BOOST_FOREACH(CBlockIndex* pindex, vDisconnect) + { + CBlock block; + if (!block.ReadFromDisk(pindex)) + return error("Reorganize() : ReadFromDisk for disconnect failed"); + if (!block.DisconnectBlock(txdb, pindex)) + return error("Reorganize() : DisconnectBlock %s failed", pindex->GetBlockHash().ToString().substr(0,20).c_str()); + + // Queue memory transactions to resurrect. + // We only do this for blocks after the last checkpoint (reorganisation before that + // point should only happen with -reindex/-loadblock, or a misbehaving peer. + BOOST_REVERSE_FOREACH(const CTransaction& tx, block.vtx) + if (!(tx.IsCoinBase() || tx.IsCoinStake()) && pindex->nHeight > Checkpoints::GetTotalBlocksEstimate()) + vResurrect.push_front(tx); + } + + // Connect longer branch + vector vDelete; + for (unsigned int i = 0; i < vConnect.size(); i++) + { + CBlockIndex* pindex = vConnect[i]; + CBlock block; + if (!block.ReadFromDisk(pindex)) + return error("Reorganize() : ReadFromDisk for connect failed"); + if (!block.ConnectBlock(txdb, pindex)) + { + // Invalid block + return error("Reorganize() : ConnectBlock %s failed", pindex->GetBlockHash().ToString().substr(0,20).c_str()); + } + + // Queue memory transactions to delete + BOOST_FOREACH(const CTransaction& tx, block.vtx) + vDelete.push_back(tx); + } + if (!txdb.WriteHashBestChain(pindexNew->GetBlockHash())) + return error("Reorganize() : WriteHashBestChain failed"); + + // Make sure it's successfully written to disk before changing memory structure + if (!txdb.TxnCommit()) + return error("Reorganize() : TxnCommit failed"); + + // Disconnect shorter branch + BOOST_FOREACH(CBlockIndex* pindex, vDisconnect) + if (pindex->pprev) + pindex->pprev->pnext = NULL; + + // Connect longer branch + BOOST_FOREACH(CBlockIndex* pindex, vConnect) + if (pindex->pprev) + pindex->pprev->pnext = pindex; + + // Resurrect memory transactions that were in the disconnected branch + BOOST_FOREACH(CTransaction& tx, vResurrect) + AcceptToMemoryPool(mempool, tx, NULL); + + // Delete redundant memory transactions that are in the connected branch + BOOST_FOREACH(CTransaction& tx, vDelete) { + mempool.remove(tx); + mempool.removeConflicts(tx); + } + + printf("REORGANIZE: done\n"); + + return true; +} + + +// Called from inside SetBestChain: attaches a block to the new best chain being built +bool CBlock::SetBestChainInner(CTxDB& txdb, CBlockIndex *pindexNew) +{ + uint256 hash = GetHash(); + + // Adding to current best branch + if (!ConnectBlock(txdb, pindexNew) || !txdb.WriteHashBestChain(hash)) + { + txdb.TxnAbort(); + InvalidChainFound(pindexNew); + return false; + } + if (!txdb.TxnCommit()) + return error("SetBestChain() : TxnCommit failed"); + + // Add to current best branch + pindexNew->pprev->pnext = pindexNew; + + // Delete redundant memory transactions + BOOST_FOREACH(CTransaction& tx, vtx) + mempool.remove(tx); + + return true; +} + +bool CBlock::SetBestChain(CTxDB& txdb, CBlockIndex* pindexNew) +{ + uint256 hash = GetHash(); + + if (!txdb.TxnBegin()) + return error("SetBestChain() : TxnBegin failed"); + + if (pindexGenesisBlock == NULL && hash == (!fTestNet ? hashGenesisBlock : hashGenesisBlockTestNet)) + { + txdb.WriteHashBestChain(hash); + if (!txdb.TxnCommit()) + return error("SetBestChain() : TxnCommit failed"); + pindexGenesisBlock = pindexNew; + } + else if (hashPrevBlock == hashBestChain) + { + if (!SetBestChainInner(txdb, pindexNew)) + return error("SetBestChain() : SetBestChainInner failed"); + } + else + { + // the first block in the new chain that will cause it to become the new best chain + CBlockIndex *pindexIntermediate = pindexNew; + + // list of blocks that need to be connected afterwards + std::vector vpindexSecondary; + + // Reorganize is costly in terms of db load, as it works in a single db transaction. + // Try to limit how much needs to be done inside + while (pindexIntermediate->pprev && pindexIntermediate->pprev->nChainTrust > pindexBest->nChainTrust) + { + vpindexSecondary.push_back(pindexIntermediate); + pindexIntermediate = pindexIntermediate->pprev; + } + + if (!vpindexSecondary.empty()) + printf("Postponing %" PRIszu" reconnects\n", vpindexSecondary.size()); + + // Switch to new best branch + if (!Reorganize(txdb, pindexIntermediate)) + { + txdb.TxnAbort(); + InvalidChainFound(pindexNew); + return error("SetBestChain() : Reorganize failed"); + } + + // Connect further blocks + BOOST_REVERSE_FOREACH(CBlockIndex *pindex, vpindexSecondary) + { + CBlock block; + if (!block.ReadFromDisk(pindex)) + { + printf("SetBestChain() : ReadFromDisk failed\n"); + break; + } + if (!txdb.TxnBegin()) { + printf("SetBestChain() : TxnBegin 2 failed\n"); + break; + } + // errors now are not fatal, we still did a reorganisation to a new chain in a valid way + if (!block.SetBestChainInner(txdb, pindex)) + break; + } + } + + // Update best block in wallet (so we can detect restored wallets) + bool fIsInitialDownload = IsInitialBlockDownload(); + if (!fIsInitialDownload) + { + const CBlockLocator locator(pindexNew); + ::SetBestChain(locator); + } + + // New best block + hashBestChain = hash; + pindexBest = pindexNew; + pblockindexFBBHLast = NULL; + nBestHeight = pindexBest->nHeight; + nBestChainTrust = pindexNew->nChainTrust; + nTimeBestReceived = GetTime(); + nTransactionsUpdated++; + + uint256 nBestBlockTrust = pindexBest->nHeight != 0 ? (pindexBest->nChainTrust - pindexBest->pprev->nChainTrust) : pindexBest->nChainTrust; + + printf("SetBestChain: new best=%s height=%d trust=%s blocktrust=%" PRId64" date=%s\n", + hashBestChain.ToString().substr(0,20).c_str(), nBestHeight, + CBigNum(nBestChainTrust).ToString().c_str(), + nBestBlockTrust.Get64(), + DateTimeStrFormat("%x %H:%M:%S", pindexBest->GetBlockTime()).c_str()); + + // Check the version of the last 100 blocks to see if we need to upgrade: + if (!fIsInitialDownload) + { + int nUpgraded = 0; + const CBlockIndex* pindex = pindexBest; + for (int i = 0; i < 100 && pindex != NULL; i++) + { + if (pindex->nVersion > CBlock::CURRENT_VERSION) + ++nUpgraded; + pindex = pindex->pprev; + } + if (nUpgraded > 0) + printf("SetBestChain: %d of last 100 blocks above version %d\n", nUpgraded, CBlock::CURRENT_VERSION); + if (nUpgraded > 100/2) + // strMiscWarning is read by GetWarnings(), called by Qt and the JSON-RPC code to warn the user: + strMiscWarning = _("Warning: This version is obsolete, upgrade required!"); + } + + std::string strCmd = GetArg("-blocknotify", ""); + + if (!fIsInitialDownload && !strCmd.empty()) + { + boost::replace_all(strCmd, "%s", hashBestChain.GetHex()); + boost::thread t(runCommand, strCmd); // thread runs free + } + + return true; +} + +// ppcoin: total coin age spent in transaction, in the unit of coin-days. +// Only those coins meeting minimum age requirement counts. As those +// transactions not in main chain are not currently indexed so we +// might not find out about their coin age. Older transactions are +// guaranteed to be in main chain by sync-checkpoint. This rule is +// introduced to help nodes establish a consistent view of the coin +// age (trust score) of competing branches. +bool CTransaction::GetCoinAge(CTxDB& txdb, uint64_t& nCoinAge) const +{ + CBigNum bnCentSecond = 0; // coin age in the unit of cent-seconds + nCoinAge = 0; + + if (IsCoinBase()) + return true; + + BOOST_FOREACH(const CTxIn& txin, vin) + { + // First try finding the previous transaction in database + CTransaction txPrev; + CTxIndex txindex; + if (!txPrev.ReadFromDisk(txdb, txin.prevout, txindex)) + continue; // previous transaction not in main chain + if (nTime < txPrev.nTime) + return false; // Transaction timestamp violation + + // Read block header + CBlock block; + if (!block.ReadFromDisk(txindex.pos.nFile, txindex.pos.nBlockPos, false)) + return false; // unable to read block of previous transaction + if (block.GetBlockTime() + nStakeMinAge > nTime) + continue; // only count coins meeting min age requirement + + int64_t nValueIn = txPrev.vout[txin.prevout.n].nValue; + bnCentSecond += CBigNum(nValueIn) * (nTime-txPrev.nTime) / CENT; + + if (fDebug && GetBoolArg("-printcoinage")) + printf("coin age nValueIn=%" PRId64" nTimeDiff=%d bnCentSecond=%s\n", nValueIn, nTime - txPrev.nTime, bnCentSecond.ToString().c_str()); + } + + CBigNum bnCoinDay = bnCentSecond * CENT / COIN / (24 * 60 * 60); + if (fDebug && GetBoolArg("-printcoinage")) + printf("coin age bnCoinDay=%s\n", bnCoinDay.ToString().c_str()); + nCoinAge = bnCoinDay.getuint64(); + return true; +} + +// ppcoin: total coin age spent in block, in the unit of coin-days. +bool CBlock::GetCoinAge(uint64_t& nCoinAge) const +{ + nCoinAge = 0; + + CTxDB txdb("r"); + BOOST_FOREACH(const CTransaction& tx, vtx) + { + uint64_t nTxCoinAge; + if (tx.GetCoinAge(txdb, nTxCoinAge)) + nCoinAge += nTxCoinAge; + else + return false; + } + + if (nCoinAge == 0) // block coin age minimum 1 coin-day + nCoinAge = 1; + if (fDebug && GetBoolArg("-printcoinage")) + printf("block coin age total nCoinDays=%" PRId64"\n", nCoinAge); + return true; +} + +bool CBlock::AddToBlockIndex(unsigned int nFile, unsigned int nBlockPos, const uint256& hashProof) +{ + // Check for duplicate + uint256 hash = GetHash(); + if (mapBlockIndex.count(hash)) + return error("AddToBlockIndex() : %s already exists", hash.ToString().substr(0,20).c_str()); + + // Construct new block index object + CBlockIndex* pindexNew = new CBlockIndex(nFile, nBlockPos, *this); + if (!pindexNew) + return error("AddToBlockIndex() : new CBlockIndex failed"); + pindexNew->phashBlock = &hash; + map::iterator miPrev = mapBlockIndex.find(hashPrevBlock); + if (miPrev != mapBlockIndex.end()) + { + pindexNew->pprev = (*miPrev).second; + pindexNew->nHeight = pindexNew->pprev->nHeight + 1; + } + + // ppcoin: compute chain trust score + pindexNew->nChainTrust = (pindexNew->pprev ? pindexNew->pprev->nChainTrust : 0) + pindexNew->GetBlockTrust(); + + // ppcoin: compute stake entropy bit for stake modifier + if (!pindexNew->SetStakeEntropyBit(GetStakeEntropyBit())) + return error("AddToBlockIndex() : SetStakeEntropyBit() failed"); + + // Record proof hash value + pindexNew->hashProof = hashProof; + + // ppcoin: compute stake modifier + uint64_t nStakeModifier = 0; + bool fGeneratedStakeModifier = false; + if (!ComputeNextStakeModifier(pindexNew->pprev, nStakeModifier, fGeneratedStakeModifier)) + return error("AddToBlockIndex() : ComputeNextStakeModifier() failed"); + pindexNew->SetStakeModifier(nStakeModifier, fGeneratedStakeModifier); + pindexNew->nStakeModifierChecksum = GetStakeModifierChecksum(pindexNew); + if (!CheckStakeModifierCheckpoints(pindexNew->nHeight, pindexNew->nStakeModifierChecksum)) + return error("AddToBlockIndex() : Rejected by stake modifier checkpoint height=%d, modifier=0x%016" PRIx64, pindexNew->nHeight, nStakeModifier); + + // Add to mapBlockIndex + map::iterator mi = mapBlockIndex.insert(make_pair(hash, pindexNew)).first; + if (pindexNew->IsProofOfStake()) + setStakeSeen.insert(make_pair(pindexNew->prevoutStake, pindexNew->nStakeTime)); + pindexNew->phashBlock = &((*mi).first); + + // Write to disk block index + CTxDB txdb; + if (!txdb.TxnBegin()) + return false; + txdb.WriteBlockIndex(CDiskBlockIndex(pindexNew)); + if (!txdb.TxnCommit()) + return false; + + LOCK(cs_main); + + // New best + if (pindexNew->nChainTrust > nBestChainTrust) + if (!SetBestChain(txdb, pindexNew)) + return false; + + if (pindexNew == pindexBest) + { + // Notify UI to display prev block's coinbase if it was ours + static uint256 hashPrevBestCoinBase; + UpdatedTransaction(hashPrevBestCoinBase); + hashPrevBestCoinBase = vtx[0].GetHash(); + } + + uiInterface.NotifyBlocksChanged(); + return true; +} + + + + +bool CBlock::CheckBlock(bool fCheckPOW, bool fCheckMerkleRoot, bool fCheckSig) const +{ + // These are checks that are independent of context + // that can be verified before saving an orphan block. + + // Size limits + if (vtx.empty() || vtx.size() > MAX_BLOCK_SIZE || ::GetSerializeSize(*this, SER_NETWORK, PROTOCOL_VERSION) > MAX_BLOCK_SIZE) + return DoS(100, error("CheckBlock() : size limits failed")); + + // Check proof of work matches claimed amount + if (fCheckPOW && IsProofOfWork() && !CheckProofOfWork(GetPoWHash(), nBits)) + return DoS(50, error("CheckBlock() : proof of work failed")); + + // Check timestamp + if (GetBlockTime() > FutureDrift(GetAdjustedTime())) + return error("CheckBlock() : block timestamp too far in the future"); + + // First transaction must be coinbase, the rest must not be + if (vtx.empty() || !vtx[0].IsCoinBase()) + return DoS(100, error("CheckBlock() : first tx is not coinbase")); + for (unsigned int i = 1; i < vtx.size(); i++) + if (vtx[i].IsCoinBase()) + return DoS(100, error("CheckBlock() : more than one coinbase")); + + // Check coinbase timestamp + if (GetBlockTime() > FutureDrift((int64_t)vtx[0].nTime)) + return DoS(50, error("CheckBlock() : coinbase timestamp is too early")); + + if (IsProofOfStake()) + { + // Coinbase output should be empty if proof-of-stake block + if (vtx[0].vout.size() != 1 || !vtx[0].vout[0].IsEmpty()) + return DoS(100, error("CheckBlock() : coinbase output not empty for proof-of-stake block")); + + // Second transaction must be coinstake, the rest must not be + if (vtx.empty() || !vtx[1].IsCoinStake()) + return DoS(100, error("CheckBlock() : second tx is not coinstake")); + for (unsigned int i = 2; i < vtx.size(); i++) + if (vtx[i].IsCoinStake()) + return DoS(100, error("CheckBlock() : more than one coinstake")); + + // Check coinstake timestamp + if (!CheckCoinStakeTimestamp(GetBlockTime(), (int64_t)vtx[1].nTime)) + return DoS(50, error("CheckBlock() : coinstake timestamp violation nTimeBlock=%" PRId64" nTimeTx=%u", GetBlockTime(), vtx[1].nTime)); + + // NovaCoin: check proof-of-stake block signature + if (fCheckSig && !CheckBlockSignature()) + return DoS(100, error("CheckBlock() : bad proof-of-stake block signature")); + } + + // Check transactions + BOOST_FOREACH(const CTransaction& tx, vtx) + { + if (!tx.CheckTransaction()) + return DoS(tx.nDoS, error("CheckBlock() : CheckTransaction failed")); + + // ppcoin: check transaction timestamp + if (GetBlockTime() < (int64_t)tx.nTime) + return DoS(50, error("CheckBlock() : block timestamp earlier than transaction timestamp")); + } + + // Check for duplicate txids. This is caught by ConnectInputs(), + // but catching it earlier avoids a potential DoS attack: + set uniqueTx; + BOOST_FOREACH(const CTransaction& tx, vtx) + { + uniqueTx.insert(tx.GetHash()); + } + if (uniqueTx.size() != vtx.size()) + return DoS(100, error("CheckBlock() : duplicate transaction")); + + unsigned int nSigOps = 0; + BOOST_FOREACH(const CTransaction& tx, vtx) + { + nSigOps += tx.GetLegacySigOpCount(); + } + if (nSigOps > MAX_BLOCK_SIGOPS) + return DoS(100, error("CheckBlock() : out-of-bounds SigOpCount")); + + // Check merkle root + if (fCheckMerkleRoot && hashMerkleRoot != BuildMerkleTree()) + return DoS(100, error("CheckBlock() : hashMerkleRoot mismatch")); + + + return true; +} + +bool CBlock::AcceptBlock() +{ + AssertLockHeld(cs_main); + + if (nVersion > CURRENT_VERSION) + return DoS(100, error("AcceptBlock() : reject unknown block version %d", nVersion)); + + // Check for duplicate + uint256 hash = GetHash(); + if (mapBlockIndex.count(hash)) + return error("AcceptBlock() : block already in mapBlockIndex"); + + // Get prev block index + map::iterator mi = mapBlockIndex.find(hashPrevBlock); + if (mi == mapBlockIndex.end()) + return DoS(10, error("AcceptBlock() : prev block not found")); + CBlockIndex* pindexPrev = (*mi).second; + int nHeight = pindexPrev->nHeight+1; + + if (IsProofOfWork() && nHeight > LAST_POW_BLOCK) + return DoS(100, error("AcceptBlock() : reject proof-of-work at height %d", nHeight)); + + // Check proof-of-work or proof-of-stake + if (nBits != GetNextTargetRequired(pindexPrev, IsProofOfStake())) + return DoS(100, error("AcceptBlock() : incorrect %s", IsProofOfWork() ? "proof-of-work" : "proof-of-stake")); + + // Check timestamp against prev + if (GetBlockTime() <= pindexPrev->GetPastTimeLimit() || FutureDrift(GetBlockTime()) < pindexPrev->GetBlockTime()) + return error("AcceptBlock() : block's timestamp is too early"); + + // Check that all transactions are finalized + BOOST_FOREACH(const CTransaction& tx, vtx) + if (!IsFinalTx(tx, nHeight, GetBlockTime())) + return DoS(10, error("AcceptBlock() : contains a non-final transaction")); + + // Check that the block chain matches the known block chain up to a checkpoint + if (!Checkpoints::CheckHardened(nHeight, hash)) + return DoS(100, error("AcceptBlock() : rejected by hardened checkpoint lock-in at %d", nHeight)); + + uint256 hashProof; + // Verify hash target and signature of coinstake tx + if (IsProofOfStake()) + { + uint256 targetProofOfStake; + if (!CheckProofOfStake(vtx[1], nBits, hashProof, targetProofOfStake)) + { + printf("WARNING: AcceptBlock(): check proof-of-stake failed for block %s\n", hash.ToString().c_str()); + return false; // do not error here as we expect this during initial block download + } + } + // PoW is checked in CheckBlock() + if (IsProofOfWork()) + { + hashProof = GetPoWHash(); + } + + bool cpSatisfies = Checkpoints::CheckSync(hash, pindexPrev); + + // Check that the block satisfies synchronized checkpoint + if (CheckpointsMode == Checkpoints::STRICT && !cpSatisfies) + return error("AcceptBlock() : rejected by synchronized checkpoint"); + + if (CheckpointsMode == Checkpoints::ADVISORY && !cpSatisfies) + strMiscWarning = _("WARNING: syncronized checkpoint violation detected, but skipped!"); + + // Enforce rule that the coinbase starts with serialized block height + CScript expect = CScript() << nHeight; + if (vtx[0].vin[0].scriptSig.size() < expect.size() || + !std::equal(expect.begin(), expect.end(), vtx[0].vin[0].scriptSig.begin())) + return DoS(100, error("AcceptBlock() : block height mismatch in coinbase")); + + // Write block to history file + if (!CheckDiskSpace(::GetSerializeSize(*this, SER_DISK, CLIENT_VERSION))) + return error("AcceptBlock() : out of disk space"); + unsigned int nFile = -1; + unsigned int nBlockPos = 0; + if (!WriteToDisk(nFile, nBlockPos)) + return error("AcceptBlock() : WriteToDisk failed"); + if (!AddToBlockIndex(nFile, nBlockPos, hashProof)) + return error("AcceptBlock() : AddToBlockIndex failed"); + + // Relay inventory, but don't relay old inventory during initial block download + int nBlockEstimate = Checkpoints::GetTotalBlocksEstimate(); + if (hashBestChain == hash) + { + LOCK(cs_vNodes); + BOOST_FOREACH(CNode* pnode, vNodes) + if (nBestHeight > (pnode->nStartingHeight != -1 ? pnode->nStartingHeight - 2000 : nBlockEstimate)) + pnode->PushInventory(CInv(MSG_BLOCK, hash)); + } + + // ppcoin: check pending sync-checkpoint + Checkpoints::AcceptPendingSyncCheckpoint(); + + return true; +} + +uint256 CBlockIndex::GetBlockTrust() const +{ + CBigNum bnTarget; + bnTarget.SetCompact(nBits); + + if (bnTarget <= 0) + return 0; + + return ((CBigNum(1)<<256) / (bnTarget+1)).getuint256(); +} + +bool CBlockIndex::IsSuperMajority(int minVersion, const CBlockIndex* pstart, unsigned int nRequired, unsigned int nToCheck) +{ + unsigned int nFound = 0; + for (unsigned int i = 0; i < nToCheck && nFound < nRequired && pstart != NULL; i++) + { + if (pstart->nVersion >= minVersion) + ++nFound; + pstart = pstart->pprev; + } + return (nFound >= nRequired); +} + +bool ProcessBlock(CNode* pfrom, CBlock* pblock) +{ + AssertLockHeld(cs_main); + + // Check for duplicate + uint256 hash = pblock->GetHash(); + if (mapBlockIndex.count(hash)) + return error("ProcessBlock() : already have block %d %s", mapBlockIndex[hash]->nHeight, hash.ToString().substr(0,20).c_str()); + if (mapOrphanBlocks.count(hash)) + return error("ProcessBlock() : already have block (orphan) %s", hash.ToString().substr(0,20).c_str()); + + // ppcoin: check proof-of-stake + // Limited duplicity on stake: prevents block flood attack + // Duplicate stake allowed only when there is orphan child block + if (pblock->IsProofOfStake() && setStakeSeen.count(pblock->GetProofOfStake()) && !mapOrphanBlocksByPrev.count(hash) && !Checkpoints::WantedByPendingSyncCheckpoint(hash)) + return error("ProcessBlock() : duplicate proof-of-stake (%s, %d) for block %s", pblock->GetProofOfStake().first.ToString().c_str(), pblock->GetProofOfStake().second, hash.ToString().c_str()); + + + + CBlockIndex* pcheckpoint = Checkpoints::GetLastSyncCheckpoint(); + if (pcheckpoint && pblock->hashPrevBlock != hashBestChain && !Checkpoints::WantedByPendingSyncCheckpoint(hash)) + { + // Extra checks to prevent "fill up memory by spamming with bogus blocks" + int64_t deltaTime = pblock->GetBlockTime() - pcheckpoint->nTime; + CBigNum bnNewBlock; + bnNewBlock.SetCompact(pblock->nBits); + CBigNum bnRequired; + + if (pblock->IsProofOfStake()) + bnRequired.SetCompact(ComputeMinStake(GetLastBlockIndex(pcheckpoint, true)->nBits, deltaTime, pblock->nTime)); + else + bnRequired.SetCompact(ComputeMinWork(GetLastBlockIndex(pcheckpoint, false)->nBits, deltaTime)); + + if (bnNewBlock > bnRequired) + { + if (pfrom) + pfrom->Misbehaving(100); + return error("ProcessBlock() : block with too little %s", pblock->IsProofOfStake()? "proof-of-stake" : "proof-of-work"); + } +} + + // Preliminary checks + if (!pblock->CheckBlock()) + return error("ProcessBlock() : CheckBlock FAILED"); + + // ppcoin: ask for pending sync-checkpoint if any + if (!IsInitialBlockDownload()) + Checkpoints::AskForPendingSyncCheckpoint(pfrom); + + // If don't already have its previous block, shunt it off to holding area until we get it + if (!mapBlockIndex.count(pblock->hashPrevBlock)) + { + printf("ProcessBlock: ORPHAN BLOCK, prev=%s\n", pblock->hashPrevBlock.ToString().substr(0,20).c_str()); + // ppcoin: check proof-of-stake + if (pblock->IsProofOfStake()) + { + // Limited duplicity on stake: prevents block flood attack + // Duplicate stake allowed only when there is orphan child block + if (setStakeSeenOrphan.count(pblock->GetProofOfStake()) && !mapOrphanBlocksByPrev.count(hash) && !Checkpoints::WantedByPendingSyncCheckpoint(hash)) + return error("ProcessBlock() : duplicate proof-of-stake (%s, %d) for orphan block %s", pblock->GetProofOfStake().first.ToString().c_str(), pblock->GetProofOfStake().second, hash.ToString().c_str()); + else + setStakeSeenOrphan.insert(pblock->GetProofOfStake()); + } + CBlock* pblock2 = new CBlock(*pblock); + mapOrphanBlocks.insert(make_pair(hash, pblock2)); + mapOrphanBlocksByPrev.insert(make_pair(pblock2->hashPrevBlock, pblock2)); + + // Ask this guy to fill in what we're missing + if (pfrom) + { + pfrom->PushGetBlocks(pindexBest, GetOrphanRoot(pblock2)); + // ppcoin: getblocks may not obtain the ancestor block rejected + // earlier by duplicate-stake check so we ask for it again directly + if (!IsInitialBlockDownload()) + pfrom->AskFor(CInv(MSG_BLOCK, WantedByOrphan(pblock2))); + } + return true; +} + + // Store to disk + if (!pblock->AcceptBlock()) + return error("ProcessBlock() : AcceptBlock FAILED"); + + // Recursively process any orphan blocks that depended on this one + vector vWorkQueue; + vWorkQueue.push_back(hash); + for (unsigned int i = 0; i < vWorkQueue.size(); i++) + { + uint256 hashPrev = vWorkQueue[i]; + for (multimap::iterator mi = mapOrphanBlocksByPrev.lower_bound(hashPrev); + mi != mapOrphanBlocksByPrev.upper_bound(hashPrev); + ++mi) + { + CBlock* pblockOrphan = (*mi).second; + if (pblockOrphan->AcceptBlock()) + vWorkQueue.push_back(pblockOrphan->GetHash()); + mapOrphanBlocks.erase(pblockOrphan->GetHash()); + setStakeSeenOrphan.erase(pblockOrphan->GetProofOfStake()); + delete pblockOrphan; + } + mapOrphanBlocksByPrev.erase(hashPrev); + } + + printf("ProcessBlock: ACCEPTED\n"); + + // ppcoin: if responsible for sync-checkpoint send it + if (pfrom && !CSyncCheckpoint::strMasterPrivKey.empty()) + Checkpoints::SendSyncCheckpoint(Checkpoints::AutoSelectSyncCheckpoint()); + + return true; +} + +// novacoin: attempt to generate suitable proof-of-stake +bool CBlock::SignBlock(CWallet& wallet, int64_t nFees) +{ + // if we are trying to sign + // something except proof-of-stake block template + if (!vtx[0].vout[0].IsEmpty()) + return false; + + // if we are trying to sign + // a complete proof-of-stake block + if (IsProofOfStake()) + return true; + + static int64_t nLastCoinStakeSearchTime = GetAdjustedTime(); // startup timestamp + + CKey key; + CTransaction txCoinStake; + int64_t nSearchTime = txCoinStake.nTime; // search to current time + + if (nSearchTime > nLastCoinStakeSearchTime) + { + if (wallet.CreateCoinStake(wallet, nBits, nSearchTime-nLastCoinStakeSearchTime, nFees, txCoinStake, key)) + { + if (txCoinStake.nTime >= max(pindexBest->GetPastTimeLimit()+1, PastDrift(pindexBest->GetBlockTime()))) + { + // make sure coinstake would meet timestamp protocol + // as it would be the same as the block timestamp + vtx[0].nTime = nTime = txCoinStake.nTime; + nTime = max(pindexBest->GetPastTimeLimit()+1, GetMaxTransactionTime()); + nTime = max(GetBlockTime(), PastDrift(pindexBest->GetBlockTime())); + + // we have to make sure that we have no future timestamps in + // our transactions set + for (vector::iterator it = vtx.begin(); it != vtx.end();) + if (it->nTime > nTime) { it = vtx.erase(it); } else { ++it; } + + vtx.insert(vtx.begin() + 1, txCoinStake); + hashMerkleRoot = BuildMerkleTree(); + + // append a signature to our block + return key.Sign(GetHash(), vchBlockSig); + } + } + nLastCoinStakeSearchInterval = nSearchTime - nLastCoinStakeSearchTime; + nLastCoinStakeSearchTime = nSearchTime; + } + + return false; +} + +bool CBlock::CheckBlockSignature() const +{ + if (IsProofOfWork()) + return vchBlockSig.empty(); + + vector vSolutions; + txnouttype whichType; + + const CTxOut& txout = vtx[1].vout[1]; + + if (!Solver(txout.scriptPubKey, whichType, vSolutions)) + return false; + + if (whichType == TX_PUBKEY) + { + valtype& vchPubKey = vSolutions[0]; + CKey key; + if (!key.SetPubKey(vchPubKey)) + return false; + if (vchBlockSig.empty()) + return false; + return key.Verify(GetHash(), vchBlockSig); + } + + return false; +} + +bool CheckDiskSpace(uint64_t nAdditionalBytes) +{ + uint64_t nFreeBytesAvailable = filesystem::space(GetDataDir()).available; + + // Check for nMinDiskSpace bytes (currently 50MB) + if (nFreeBytesAvailable < nMinDiskSpace + nAdditionalBytes) + { + fShutdown = true; + string strMessage = _("Warning: Disk space is low!"); + strMiscWarning = strMessage; + printf("*** %s\n", strMessage.c_str()); + uiInterface.ThreadSafeMessageBox(strMessage, "arepacoin", CClientUIInterface::OK | CClientUIInterface::ICON_EXCLAMATION | CClientUIInterface::MODAL); + StartShutdown(); + return false; + } + return true; +} + +static filesystem::path BlockFilePath(unsigned int nFile) +{ + string strBlockFn = strprintf("blk%04u.dat", nFile); + return GetDataDir() / strBlockFn; +} + +FILE* OpenBlockFile(unsigned int nFile, unsigned int nBlockPos, const char* pszMode) +{ + if ((nFile < 1) || (nFile == (unsigned int) -1)) + return NULL; + FILE* file = fopen(BlockFilePath(nFile).string().c_str(), pszMode); + if (!file) + return NULL; + if (nBlockPos != 0 && !strchr(pszMode, 'a') && !strchr(pszMode, 'w')) + { + if (fseek(file, nBlockPos, SEEK_SET) != 0) + { + fclose(file); + return NULL; + } + } + return file; +} + +static unsigned int nCurrentBlockFile = 1; + +FILE* AppendBlockFile(unsigned int& nFileRet) +{ + nFileRet = 0; + while (true) + { + FILE* file = OpenBlockFile(nCurrentBlockFile, 0, "ab"); + if (!file) + return NULL; + if (fseek(file, 0, SEEK_END) != 0) + return NULL; + // FAT32 file size max 4GB, fseek and ftell max 2GB, so we must stay under 2GB + if (ftell(file) < (long)(0x7F000000 - MAX_SIZE)) + { + nFileRet = nCurrentBlockFile; + return file; + } + fclose(file); + nCurrentBlockFile++; + } +} + +bool LoadBlockIndex(bool fAllowNew) +{ + LOCK(cs_main); + + CBigNum bnTrustedModulus; + + if (fTestNet) + { + pchMessageStart[0] = 0x28; + pchMessageStart[1] = 0x04; + pchMessageStart[2] = 0x87; + pchMessageStart[3] = 0x6c; + + bnTrustedModulus.SetHex("f0d14cf72623dacfe738d0892b599be0f31052239cddd95a3f25101c801dc990453b38c9434efe3f372db39a32c2bb44cbaea72d62c8931fa785b0ec44531308df3e46069be5573e49bb29f4d479bfc3d162f57a5965db03810be7636da265bfced9c01a6b0296c77910ebdc8016f70174f0f18a57b3b971ac43a934c6aedbc5c866764a3622b5b7e3f9832b8b3f133c849dbcc0396588abcd1e41048555746e4823fb8aba5b3d23692c6857fccce733d6bb6ec1d5ea0afafecea14a0f6f798b6b27f77dc989c557795cc39a0940ef6bb29a7fc84135193a55bcfc2f01dd73efad1b69f45a55198bd0e6bef4d338e452f6a420f1ae2b1167b923f76633ab6e55"); + bnProofOfWorkLimit = bnProofOfWorkLimitTestNet; // 16 bits PoW target limit for testnet + nStakeMinAge = 1 * 60 * 60; // test net min age is 1 hour + // nCoinbaseMaturity = 10; // test maturity is 10 blocks + } + else + { + bnTrustedModulus.SetHex("d01f952e1090a5a72a3eda261083256596ccc192935ae1454c2bafd03b09e6ed11811be9f3a69f5783bbbced8c6a0c56621f42c2d19087416facf2f13cc7ed7159d1c5253119612b8449f0c7f54248e382d30ecab1928dbf075c5425dcaee1a819aa13550e0f3227b8c685b14e0eae094d65d8a610a6f49fff8145259d1187e4c6a472fa5868b2b67f957cb74b787f4311dbc13c97a2ca13acdb876ff506ebecbb904548c267d68868e07a32cd9ed461fbc2f920e9940e7788fed2e4817f274df5839c2196c80abe5c486df39795186d7bc86314ae1e8342f3c884b158b4b05b4302754bf351477d35370bad6639b2195d30006b77bf3dbb28b848fd9ecff5662bf39dde0c974e83af51b0d3d642d43834827b8c3b189065514636b8f2a59c42ba9b4fc4975d4827a5d89617a3873e4b377b4d559ad165748632bd928439cfbc5a8ef49bc2220e0b15fb0aa302367d5e99e379a961c1bc8cf89825da5525e3c8f14d7d8acca2fa9c133a2176ae69874d8b1d38b26b9c694e211018005a97b40848681b9dd38feb2de141626fb82591aad20dc629b2b6421cef1227809551a0e4e943ab99841939877f18f2d9c0addc93cf672e26b02ed94da3e6d329e8ac8f3736eebbf37bb1a21e5aadf04ee8e3b542f876aa88b2adf2608bd86329b7f7a56fd0dc1c40b48188731d11082aea360c62a0840c2db3dad7178fd7e359317ae081"); + } + +#if 0 + // Set up the Zerocoin Params object + ZCParams = new libzerocoin::Params(bnTrustedModulus); +#endif + + // + // Load block index + // + CTxDB txdb("cr+"); + if (!txdb.LoadBlockIndex()) + return false; + + // + // Init with genesis block + // + if (mapBlockIndex.empty()) + { + if (!fAllowNew) + return false; + + // Genesis block + + // MainNet: + + //CBlock(hash=000001faef25dec4fbcf906e6242621df2c183bf232f263d0ba5b101911e4563, ver=1, hashPrevBlock=0000000000000000000000000000000000000000000000000000000000000000, hashMerkleRoot=d4082f34d13c3e5c4ad7057cd6548bc44274a6234e168157bbb760545aec22e1, nTime=1474758308, nBits=1e0fffff, nNonce=3261211, vtx=1, vchBlockSig=) + // Coinbase(hash=12630d16a9, nTime=1474758308, ver=1, vin.size=1, vout.size=1, nLockTime=0) + // CTxIn(COutPoint(0000000000, 4294967295), coinbase 00012a24323020466562203230313420426974636f696e2041544d7320636f6d6520746f20555341) + // CTxOut(empty) + // vMerkleTree: 12630d16a9 + + // TestNet: + + //CBlock(hash=0000724595fb3b9609d441cbfb9577615c292abf07d996d3edabc48de843642d, ver=1, hashPrevBlock=0000000000000000000000000000000000000000000000000000000000000000, hashMerkleRoot=d4082f34d13c3e5c4ad7057cd6548bc44274a6234e168157bbb760545aec22e1, nTime=1474758308, nBits=1f00ffff, nNonce=216178, vtx=1, vchBlockSig=) + // Coinbase(hash=12630d16a9, nTime=1474758308, ver=1, vin.size=1, vout.size=1, nLockTime=0) + // CTxIn(COutPoint(0000000000, 4294967295), coinbase 00012a24323020466562203230313420426974636f696e2041544d7320636f6d6520746f20555341) + // CTxOut(empty) + // vMerkleTree: 12630d16a9 + + const char* pszTimestamp = "aasdfaf afs as df"; + CTransaction txNew; + txNew.nTime = 1474758308; + txNew.vin.resize(1); + txNew.vout.resize(1); + txNew.vin[0].scriptSig = CScript() << 0 << CBigNum(42) << vector((const unsigned char*)pszTimestamp, (const unsigned char*)pszTimestamp + strlen(pszTimestamp)); + txNew.vout[0].SetEmpty(); + CBlock block; + block.vtx.push_back(txNew); + block.hashPrevBlock = 0; + block.hashMerkleRoot = block.BuildMerkleTree(); + block.nVersion = 1; + block.nTime = 1474758308; + block.nBits = bnProofOfWorkLimit.GetCompact(); + block.nNonce = !fTestNet ? 3261211 : 3261211; + + assert(block.hashMerkleRoot == uint256("0xd4082f34d13c3e5c4ad7057cd6548bc44274a6234e168157bbb760545aec22e1")); + assert(block.GetHash() == (!fTestNet ? hashGenesisBlock : hashGenesisBlockTestNet)); + assert(block.CheckBlock()); + + // Start new block file + unsigned int nFile; + unsigned int nBlockPos; + if (!block.WriteToDisk(nFile, nBlockPos)) + return error("LoadBlockIndex() : writing genesis block to disk failed"); + if (!block.AddToBlockIndex(nFile, nBlockPos, hashGenesisBlock)) + return error("LoadBlockIndex() : genesis block not accepted"); + + // ppcoin: initialize synchronized checkpoint + if (!Checkpoints::WriteSyncCheckpoint((!fTestNet ? hashGenesisBlock : hashGenesisBlockTestNet))) + return error("LoadBlockIndex() : failed to init sync checkpoint"); + } + + string strPubKey = ""; + + // if checkpoint master key changed must reset sync-checkpoint + if (!txdb.ReadCheckpointPubKey(strPubKey) || strPubKey != CSyncCheckpoint::strMasterPubKey) + { + // write checkpoint master key to db + txdb.TxnBegin(); + if (!txdb.WriteCheckpointPubKey(CSyncCheckpoint::strMasterPubKey)) + return error("LoadBlockIndex() : failed to write new checkpoint master key to db"); + if (!txdb.TxnCommit()) + return error("LoadBlockIndex() : failed to commit new checkpoint master key to db"); + if ((!fTestNet) && !Checkpoints::ResetSyncCheckpoint()) + return error("LoadBlockIndex() : failed to reset sync-checkpoint"); + } + + return true; +} + + + +void PrintBlockTree() +{ + AssertLockHeld(cs_main); + // pre-compute tree structure + map > mapNext; + for (map::iterator mi = mapBlockIndex.begin(); mi != mapBlockIndex.end(); ++mi) + { + CBlockIndex* pindex = (*mi).second; + mapNext[pindex->pprev].push_back(pindex); + // test + //while (rand() % 3 == 0) + // mapNext[pindex->pprev].push_back(pindex); + } + + vector > vStack; + vStack.push_back(make_pair(0, pindexGenesisBlock)); + + int nPrevCol = 0; + while (!vStack.empty()) + { + int nCol = vStack.back().first; + CBlockIndex* pindex = vStack.back().second; + vStack.pop_back(); + + // print split or gap + if (nCol > nPrevCol) + { + for (int i = 0; i < nCol-1; i++) + printf("| "); + printf("|\\\n"); + } + else if (nCol < nPrevCol) + { + for (int i = 0; i < nCol; i++) + printf("| "); + printf("|\n"); + } + nPrevCol = nCol; + + // print columns + for (int i = 0; i < nCol; i++) + printf("| "); + + // print item + CBlock block; + block.ReadFromDisk(pindex); + printf("%d (%u,%u) %s %08x %s mint %7s tx %" PRIszu"", + pindex->nHeight, + pindex->nFile, + pindex->nBlockPos, + block.GetHash().ToString().c_str(), + block.nBits, + DateTimeStrFormat("%x %H:%M:%S", block.GetBlockTime()).c_str(), + FormatMoney(pindex->nMint).c_str(), + block.vtx.size()); + + PrintWallets(block); + + // put the main time-chain first + vector& vNext = mapNext[pindex]; + for (unsigned int i = 0; i < vNext.size(); i++) + { + if (vNext[i]->pnext) + { + swap(vNext[0], vNext[i]); + break; + } + } + + // iterate children + for (unsigned int i = 0; i < vNext.size(); i++) + vStack.push_back(make_pair(nCol+i, vNext[i])); + } +} + +bool LoadExternalBlockFile(FILE* fileIn) +{ + int64_t nStart = GetTimeMillis(); + + int nLoaded = 0; + { + LOCK(cs_main); + try { + CAutoFile blkdat(fileIn, SER_DISK, CLIENT_VERSION); + unsigned int nPos = 0; + while (nPos != (unsigned int)-1 && blkdat.good() && !fRequestShutdown) + { + unsigned char pchData[65536]; + do { + fseek(blkdat, nPos, SEEK_SET); + int nRead = fread(pchData, 1, sizeof(pchData), blkdat); + if (nRead <= 8) + { + nPos = (unsigned int)-1; + break; + } + void* nFind = memchr(pchData, pchMessageStart[0], nRead+1-sizeof(pchMessageStart)); + if (nFind) + { + if (memcmp(nFind, pchMessageStart, sizeof(pchMessageStart))==0) + { + nPos += ((unsigned char*)nFind - pchData) + sizeof(pchMessageStart); + break; + } + nPos += ((unsigned char*)nFind - pchData) + 1; + } + else + nPos += sizeof(pchData) - sizeof(pchMessageStart) + 1; + } while(!fRequestShutdown); + if (nPos == (unsigned int)-1) + break; + fseek(blkdat, nPos, SEEK_SET); + unsigned int nSize; + blkdat >> nSize; + if (nSize > 0 && nSize <= MAX_BLOCK_SIZE) + { + CBlock block; + blkdat >> block; + if (ProcessBlock(NULL,&block)) + { + nLoaded++; + nPos += 4 + nSize; + } + } + } + } + catch (std::exception &e) { + printf("%s() : Deserialize or I/O error caught during load\n", + __PRETTY_FUNCTION__); + } + } + printf("Loaded %i blocks from external file in %" PRId64"ms\n", nLoaded, GetTimeMillis() - nStart); + return nLoaded > 0; +} + +////////////////////////////////////////////////////////////////////////////// +// +// CAlert +// + +extern map mapAlerts; +extern CCriticalSection cs_mapAlerts; + +string GetWarnings(string strFor) +{ + int nPriority = 0; + string strStatusBar; + string strRPC; + + if (GetBoolArg("-testsafemode")) + strRPC = "test"; + + // Misc warnings like out of disk space and clock is wrong + if (strMiscWarning != "") + { + nPriority = 1000; + strStatusBar = strMiscWarning; + } + + // if detected invalid checkpoint enter safe mode + if (Checkpoints::hashInvalidCheckpoint != 0) + { + nPriority = 3000; + strStatusBar = strRPC = _("WARNING: Invalid checkpoint found! Displayed transactions may not be correct! You may need to upgrade, or notify developers."); + } + + // Alerts + { + LOCK(cs_mapAlerts); + BOOST_FOREACH(PAIRTYPE(const uint256, CAlert)& item, mapAlerts) + { + const CAlert& alert = item.second; + if (alert.AppliesToMe() && alert.nPriority > nPriority) + { + nPriority = alert.nPriority; + strStatusBar = alert.strStatusBar; + if (nPriority > 1000) + strRPC = strStatusBar; + } + } + } + + if (strFor == "statusbar") + return strStatusBar; + else if (strFor == "rpc") + return strRPC; + assert(!"GetWarnings() : invalid parameter"); + return "error"; +} + + + + + + + + +////////////////////////////////////////////////////////////////////////////// +// +// Messages +// + + +bool static AlreadyHave(CTxDB& txdb, const CInv& inv) +{ + switch (inv.type) + { + case MSG_TX: + { + bool txInMap = false; + txInMap = mempool.exists(inv.hash); + return txInMap || + mapOrphanTransactions.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; +} + + + + +// The message start string is designed to be unlikely to occur in normal data. +// The characters are rarely used upper ASCII, not valid as UTF-8, and produce +// a large 4-byte int at any alignment. +unsigned char pchMessageStart[4] = { 0xb6, 0x60, 0x02, 0xf5 }; + +bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv) +{ + static map mapReuseKey; + RandAddSeedPerfmon(); + if (fDebug) + printf("received: %s (%" PRIszu" bytes)\n", strCommand.c_str(), vRecv.size()); + if (mapArgs.count("-dropmessagestest") && GetRand(atoi(mapArgs["-dropmessagestest"])) == 0) + { + printf("dropmessagestest DROPPING RECV MESSAGE\n"); + return true; + } + + if (strCommand == "version") + { + // Each connection can only send one version message + if (pfrom->nVersion != 0) + { + pfrom->Misbehaving(1); + return false; + } + + int64_t nTime; + CAddress addrMe; + CAddress addrFrom; + uint64_t nNonce = 1; + vRecv >> pfrom->nVersion >> pfrom->nServices >> nTime >> addrMe; + if (pfrom->nVersion < MIN_PEER_PROTO_VERSION) + { + // disconnect from peers older than this proto version + printf("partner %s using obsolete version %i; disconnecting\n", pfrom->addr.ToString().c_str(), pfrom->nVersion); + pfrom->fDisconnect = true; + return false; + } + + if (pfrom->nVersion == 10300) + pfrom->nVersion = 300; + if (!vRecv.empty()) + vRecv >> addrFrom >> nNonce; + if (!vRecv.empty()) + vRecv >> pfrom->strSubVer; + if (!vRecv.empty()) + vRecv >> pfrom->nStartingHeight; + + if (pfrom->fInbound && addrMe.IsRoutable()) + { + pfrom->addrLocal = addrMe; + SeenLocal(addrMe); + } + + // Disconnect if we connected to ourself + if (nNonce == nLocalHostNonce && nNonce > 1) + { + printf("connected to self at %s, disconnecting\n", pfrom->addr.ToString().c_str()); + pfrom->fDisconnect = true; + return true; + } + + // record my external IP reported by peer + if (addrFrom.IsRoutable() && addrMe.IsRoutable()) { + if (addrFrom.IsIPv4()) { + addrSeenByPeerIpv4 = addrMe; + } + + if (addrFrom.IsIPv6()) { + addrSeenByPeerIpv6 = addrMe; + } + addrSeenByPeerIp = addrMe; + } + + // Be shy and don't send version until we hear + if (pfrom->fInbound) + pfrom->PushVersion(); + + pfrom->fClient = !(pfrom->nServices & NODE_NETWORK); + + if (GetBoolArg("-synctime", true)) + AddTimeData(pfrom->addr, nTime); + + // Change version + pfrom->PushMessage("verack"); + pfrom->ssSend.SetVersion(min(pfrom->nVersion, PROTOCOL_VERSION)); + + if (!pfrom->fInbound) + { + // Advertise our address + if (!fNoListen && !IsInitialBlockDownload()) + { + CAddress addr = GetLocalAddress(&pfrom->addr); + if (addr.IsRoutable()) + pfrom->PushAddress(addr); + } + + // Get recent addresses + if (pfrom->fOneShot || pfrom->nVersion >= CADDR_TIME_VERSION || addrman.size() < 1000) + { + pfrom->PushMessage("getaddr"); + pfrom->fGetAddr = true; + } + addrman.Good(pfrom->addr); + } else { + if (((CNetAddr)pfrom->addr) == (CNetAddr)addrFrom) + { + addrman.Add(addrFrom, addrFrom); + addrman.Good(addrFrom); + } + } + + // Ask the first connected node for block updates + static int nAskedForBlocks = 0; + if (!pfrom->fClient && !pfrom->fOneShot && + (pfrom->nStartingHeight > (nBestHeight - 144)) && + (pfrom->nVersion < NOBLKS_VERSION_START || + pfrom->nVersion >= NOBLKS_VERSION_END) && + (nAskedForBlocks < 1 || vNodes.size() <= 1)) + { + nAskedForBlocks++; + pfrom->PushGetBlocks(pindexBest, uint256(0)); + } + + // Relay alerts + { + LOCK(cs_mapAlerts); + BOOST_FOREACH(PAIRTYPE(const uint256, CAlert)& item, mapAlerts) + item.second.RelayTo(pfrom); + } + + // Relay sync-checkpoint + { + LOCK(Checkpoints::cs_hashSyncCheckpoint); + if (!Checkpoints::checkpointMessage.IsNull()) + Checkpoints::checkpointMessage.RelayTo(pfrom); + } + + pfrom->fSuccessfullyConnected = true; + + printf("receive version message: version %d, blocks=%d, us=%s, them=%s, peer=%s\n", pfrom->nVersion, pfrom->nStartingHeight, addrMe.ToString().c_str(), addrFrom.ToString().c_str(), pfrom->addr.ToString().c_str()); + + cPeerBlockCounts.input(pfrom->nStartingHeight); + + // ppcoin: ask for pending sync-checkpoint if any + if (!IsInitialBlockDownload()) + Checkpoints::AskForPendingSyncCheckpoint(pfrom); + } + + + else if (pfrom->nVersion == 0) + { + // Must have a version message before anything else + pfrom->Misbehaving(1); + return false; + } + + + else if (strCommand == "verack") + { + pfrom->SetRecvVersion(min(pfrom->nVersion, PROTOCOL_VERSION)); + } + + + else if (strCommand == "addr") + { + vector vAddr; + vRecv >> vAddr; + + // Don't want addr from older versions unless seeding + if (pfrom->nVersion < CADDR_TIME_VERSION && addrman.size() > 1000) + return true; + if (vAddr.size() > 1000) + { + pfrom->Misbehaving(20); + return error("message addr size() = %" PRIszu"", vAddr.size()); + } + + // Store the new addresses + vector vAddrOk; + int64_t nNow = GetAdjustedTime(); + int64_t nSince = nNow - 10 * 60; + BOOST_FOREACH(CAddress& addr, vAddr) + { + if (fShutdown) + return true; + if (addr.nTime <= 100000000 || addr.nTime > nNow + 10 * 60) + addr.nTime = nNow - 5 * 24 * 60 * 60; + pfrom->AddAddressKnown(addr); + bool fReachable = IsReachable(addr); + if (addr.nTime > nSince && !pfrom->fGetAddr && vAddr.size() <= 10 && addr.IsRoutable()) + { + // Relay to a limited number of other nodes + { + LOCK(cs_vNodes); + // Use deterministic randomness to send to the same nodes for 24 hours + // at a time so the setAddrKnowns of the chosen nodes prevent repeats + static uint256 hashSalt; + if (hashSalt == 0) + hashSalt = GetRandHash(); + uint64_t hashAddr = addr.GetHash(); + uint256 hashRand = hashSalt ^ (hashAddr<<32) ^ ((GetTime()+hashAddr)/(24*60*60)); + hashRand = Hash(BEGIN(hashRand), END(hashRand)); + multimap mapMix; + BOOST_FOREACH(CNode* pnode, vNodes) + { + if (pnode->nVersion < CADDR_TIME_VERSION) + continue; + unsigned int nPointer; + memcpy(&nPointer, &pnode, sizeof(nPointer)); + uint256 hashKey = hashRand ^ nPointer; + hashKey = Hash(BEGIN(hashKey), END(hashKey)); + mapMix.insert(make_pair(hashKey, pnode)); + } + int nRelayNodes = fReachable ? 2 : 1; // limited relaying of addresses outside our network(s) + for (multimap::iterator mi = mapMix.begin(); mi != mapMix.end() && nRelayNodes-- > 0; ++mi) + ((*mi).second)->PushAddress(addr); + } + } + // Do not store addresses outside our network + if (fReachable) + vAddrOk.push_back(addr); + } + addrman.Add(vAddrOk, pfrom->addr, 2 * 60 * 60); + if (vAddr.size() < 1000) + pfrom->fGetAddr = false; + if (pfrom->fOneShot) + pfrom->fDisconnect = true; + } + + else if (strCommand == "inv") + { + vector vInv; + vRecv >> vInv; + if (vInv.size() > MAX_INV_SZ) + { + pfrom->Misbehaving(20); + return error("message inv size() = %" PRIszu"", vInv.size()); + } + + // find last block in inv vector + unsigned int nLastBlock = (unsigned int)(-1); + for (unsigned int nInv = 0; nInv < vInv.size(); nInv++) { + if (vInv[vInv.size() - 1 - nInv].type == MSG_BLOCK) { + nLastBlock = vInv.size() - 1 - nInv; + break; + } + } + CTxDB txdb("r"); + for (unsigned int nInv = 0; nInv < vInv.size(); nInv++) + { + const CInv &inv = vInv[nInv]; + + if (fShutdown) + return true; + pfrom->AddInventoryKnown(inv); + + bool fAlreadyHave = AlreadyHave(txdb, inv); + if (fDebug) + printf(" got inventory: %s %s\n", inv.ToString().c_str(), fAlreadyHave ? "have" : "new"); + + if (!fAlreadyHave) + pfrom->AskFor(inv); + else if (inv.type == MSG_BLOCK && mapOrphanBlocks.count(inv.hash)) { + pfrom->PushGetBlocks(pindexBest, GetOrphanRoot(mapOrphanBlocks[inv.hash])); + } else if (nInv == nLastBlock) { + // In case we are on a very long side-chain, it is possible that we already have + // the last block in an inv bundle sent in response to getblocks. Try to detect + // this situation and push another getblocks to continue. + pfrom->PushGetBlocks(mapBlockIndex[inv.hash], uint256(0)); + if (fDebug) + printf("force request: %s\n", inv.ToString().c_str()); + } + + // Track requests for our stuff + Inventory(inv.hash); + } + } + + + else if (strCommand == "getdata") + { + vector vInv; + vRecv >> vInv; + if (vInv.size() > MAX_INV_SZ) + { + pfrom->Misbehaving(20); + return error("message getdata size() = %" PRIszu"", vInv.size()); + } + + if (fDebugNet || (vInv.size() != 1)) + printf("received getdata (%" PRIszu" invsz)\n", vInv.size()); + + BOOST_FOREACH(const CInv& inv, vInv) + { + if (fShutdown) + return true; + if (fDebugNet || (vInv.size() == 1)) + printf("received getdata for: %s\n", inv.ToString().c_str()); + + if (inv.type == MSG_BLOCK) + { + // Send block from disk + map::iterator mi = mapBlockIndex.find(inv.hash); + if (mi != mapBlockIndex.end()) + { + CBlock block; + block.ReadFromDisk((*mi).second); + pfrom->PushMessage("block", block); + + // Trigger them to send a getblocks request for the next batch of inventory + if (inv.hash == pfrom->hashContinue) + { + // ppcoin: send latest proof-of-work block to allow the + // download node to accept as orphan (proof-of-stake + // block might be rejected by stake connection check) + vector vInv; + vInv.push_back(CInv(MSG_BLOCK, GetLastBlockIndex(pindexBest, false)->GetBlockHash())); + pfrom->PushMessage("inv", vInv); + pfrom->hashContinue = 0; + } + } + } + else if (inv.IsKnownType()) + { + // Send stream from relay memory + bool pushed = false; + { + LOCK(cs_mapRelay); + map::iterator mi = mapRelay.find(inv); + if (mi != mapRelay.end()) { + pfrom->PushMessage(inv.GetCommand(), (*mi).second); + pushed = true; + } + } + if (!pushed && inv.type == MSG_TX) { + CTransaction tx; + if (mempool.lookup(inv.hash, tx)) { + CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); + ss.reserve(1000); + ss << tx; + pfrom->PushMessage("tx", ss); + } + } + } + + // Track requests for our stuff + Inventory(inv.hash); + } + } + + + else if (strCommand == "getblocks") + { + CBlockLocator locator; + uint256 hashStop; + vRecv >> locator >> hashStop; + + // Find the last block the caller has in the main chain + CBlockIndex* pindex = locator.GetBlockIndex(); + + // Send the rest of the chain + if (pindex) + pindex = pindex->pnext; + int nLimit = 500; + printf("getblocks %d to %s limit %d\n", (pindex ? pindex->nHeight : -1), hashStop.ToString().substr(0,20).c_str(), nLimit); + for (; pindex; pindex = pindex->pnext) + { + if (pindex->GetBlockHash() == hashStop) + { + printf(" getblocks stopping at %d %s\n", pindex->nHeight, pindex->GetBlockHash().ToString().substr(0,20).c_str()); + // ppcoin: tell downloading node about the latest block if it's + // without risk being rejected due to stake connection check + if (hashStop != hashBestChain && pindex->GetBlockTime() + nStakeMinAge > pindexBest->GetBlockTime()) + pfrom->PushInventory(CInv(MSG_BLOCK, hashBestChain)); + break; + } + pfrom->PushInventory(CInv(MSG_BLOCK, pindex->GetBlockHash())); + if (--nLimit <= 0) + { + // When this block is requested, we'll send an inv that'll make them + // getblocks the next batch of inventory. + printf(" getblocks stopping at limit %d %s\n", pindex->nHeight, pindex->GetBlockHash().ToString().substr(0,20).c_str()); + pfrom->hashContinue = pindex->GetBlockHash(); + break; + } + } + } + else if (strCommand == "checkpoint") + { + CSyncCheckpoint checkpoint; + vRecv >> checkpoint; + + if (checkpoint.ProcessSyncCheckpoint(pfrom)) + { + // Relay + pfrom->hashCheckpointKnown = checkpoint.hashCheckpoint; + LOCK(cs_vNodes); + BOOST_FOREACH(CNode* pnode, vNodes) + checkpoint.RelayTo(pnode); + } + } + + else if (strCommand == "getheaders") + { + CBlockLocator locator; + uint256 hashStop; + vRecv >> locator >> hashStop; + + CBlockIndex* pindex = NULL; + if (locator.IsNull()) + { + // If locator is null, return the hashStop block + map::iterator mi = mapBlockIndex.find(hashStop); + if (mi == mapBlockIndex.end()) + return true; + pindex = (*mi).second; + } + else + { + // Find the last block the caller has in the main chain + pindex = locator.GetBlockIndex(); + if (pindex) + pindex = pindex->pnext; + } + + vector vHeaders; + int nLimit = 2000; + printf("getheaders %d to %s\n", (pindex ? pindex->nHeight : -1), hashStop.ToString().substr(0,20).c_str()); + for (; pindex; pindex = pindex->pnext) + { + vHeaders.push_back(pindex->GetBlockHeader()); + if (--nLimit <= 0 || pindex->GetBlockHash() == hashStop) + break; + } + pfrom->PushMessage("headers", vHeaders); + } + + + else if (strCommand == "tx") + { + vector vWorkQueue; + vector vEraseQueue; + CTransaction tx; + vRecv >> tx; + + CInv inv(MSG_TX, tx.GetHash()); + pfrom->AddInventoryKnown(inv); + + bool fMissingInputs = false; + if (AcceptToMemoryPool(mempool, tx, &fMissingInputs)) + { + SyncWithWallets(tx, NULL, true); + RelayTransaction(tx, inv.hash); + mapAlreadyAskedFor.erase(inv); + vWorkQueue.push_back(inv.hash); + vEraseQueue.push_back(inv.hash); + + // Recursively process any orphan transactions that depended on this one + for (unsigned int i = 0; i < vWorkQueue.size(); i++) + { + uint256 hashPrev = vWorkQueue[i]; + for (set::iterator mi = mapOrphanTransactionsByPrev[hashPrev].begin(); + mi != mapOrphanTransactionsByPrev[hashPrev].end(); + ++mi) + { + const uint256& orphanTxHash = *mi; + CTransaction& orphanTx = mapOrphanTransactions[orphanTxHash]; + bool fMissingInputs2 = false; + + if (AcceptToMemoryPool(mempool, orphanTx, &fMissingInputs2)) + { + printf(" accepted orphan tx %s\n", orphanTxHash.ToString().substr(0,10).c_str()); + SyncWithWallets(tx, NULL, true); + RelayTransaction(orphanTx, orphanTxHash); + mapAlreadyAskedFor.erase(CInv(MSG_TX, orphanTxHash)); + vWorkQueue.push_back(orphanTxHash); + vEraseQueue.push_back(orphanTxHash); + } + else if (!fMissingInputs2) + { + // invalid orphan + vEraseQueue.push_back(orphanTxHash); + printf(" removed invalid orphan tx %s\n", orphanTxHash.ToString().substr(0,10).c_str()); + } + } + } + + BOOST_FOREACH(uint256 hash, vEraseQueue) + EraseOrphanTx(hash); + } + else if (fMissingInputs) + { + AddOrphanTx(tx); + + // DoS prevention: do not allow mapOrphanTransactions to grow unbounded + unsigned int nEvicted = LimitOrphanTxSize(MAX_ORPHAN_TRANSACTIONS); + if (nEvicted > 0) + printf("mapOrphan overflow, removed %u tx\n", nEvicted); + } + if (tx.nDoS) pfrom->Misbehaving(tx.nDoS); + } + + + else if (strCommand == "block") + { + CBlock block; + vRecv >> block; + uint256 hashBlock = block.GetHash(); + + printf("received block %s\n", hashBlock.ToString().substr(0,20).c_str()); + + CInv inv(MSG_BLOCK, hashBlock); + pfrom->AddInventoryKnown(inv); + + if (ProcessBlock(pfrom, &block)) + mapAlreadyAskedFor.erase(inv); + if (block.nDoS) pfrom->Misbehaving(block.nDoS); + } + + + else if (strCommand == "getaddr") + { + // Don't return addresses older than nCutOff timestamp + int64_t nCutOff = GetTime() - (nNodeLifespan * 24 * 60 * 60); + pfrom->vAddrToSend.clear(); + vector vAddr = addrman.GetAddr(); + BOOST_FOREACH(const CAddress &addr, vAddr) + if(addr.nTime > nCutOff) + pfrom->PushAddress(addr); + } + + + else if (strCommand == "mempool") + { + std::vector vtxid; + mempool.queryHashes(vtxid); + vector vInv; + for (unsigned int i = 0; i < vtxid.size(); i++) { + CInv inv(MSG_TX, vtxid[i]); + vInv.push_back(inv); + if (i == (MAX_INV_SZ - 1)) + break; + } + if (vInv.size() > 0) + pfrom->PushMessage("inv", vInv); + } + + + else if (strCommand == "checkorder") + { + uint256 hashReply; + vRecv >> hashReply; + + if (!GetBoolArg("-allowreceivebyip")) + { + pfrom->PushMessage("reply", hashReply, (int)2, string("")); + return true; + } + + CWalletTx order; + vRecv >> order; + + /// we have a chance to check the order here + + // Keep giving the same key to the same ip until they use it + if (!mapReuseKey.count(pfrom->addr)) + pwalletMain->GetKeyFromPool(mapReuseKey[pfrom->addr], true); + + // Send back approval of order and pubkey to use + CScript scriptPubKey; + scriptPubKey << mapReuseKey[pfrom->addr] << OP_CHECKSIG; + pfrom->PushMessage("reply", hashReply, (int)0, scriptPubKey); + } + + + else if (strCommand == "reply") + { + uint256 hashReply; + vRecv >> hashReply; + + CRequestTracker tracker; + { + LOCK(pfrom->cs_mapRequests); + map::iterator mi = pfrom->mapRequests.find(hashReply); + if (mi != pfrom->mapRequests.end()) + { + tracker = (*mi).second; + pfrom->mapRequests.erase(mi); + } + } + if (!tracker.IsNull()) + tracker.fn(tracker.param1, vRecv); + } + + + else if (strCommand == "ping") + { + if (pfrom->nVersion > BIP0031_VERSION) + { + uint64_t nonce = 0; + vRecv >> nonce; + // Echo the message back with the nonce. This allows for two useful features: + // + // 1) A remote node can quickly check if the connection is operational + // 2) Remote nodes can measure the latency of the network thread. If this node + // is overloaded it won't respond to pings quickly and the remote node can + // avoid sending us more work, like chain download requests. + // + // The nonce stops the remote getting confused between different pings: without + // it, if the remote node sends a ping once per second and this node takes 5 + // seconds to respond to each, the 5th ping the remote sends would appear to + // return very quickly. + pfrom->PushMessage("pong", nonce); + } + } + + + else if (strCommand == "alert") + { + CAlert alert; + vRecv >> alert; + + uint256 alertHash = alert.GetHash(); + if (pfrom->setKnown.count(alertHash) == 0) + { + if (alert.ProcessAlert()) + { + // Relay + pfrom->setKnown.insert(alertHash); + { + LOCK(cs_vNodes); + BOOST_FOREACH(CNode* pnode, vNodes) + alert.RelayTo(pnode); + } + } + else { + // Small DoS penalty so peers that send us lots of + // duplicate/expired/invalid-signature/whatever alerts + // eventually get banned. + // This isn't a Misbehaving(100) (immediate ban) because the + // peer might be an older or different implementation with + // a different signature key, etc. + pfrom->Misbehaving(10); + } + } + } + + + else + { + // Ignore unknown commands for extensibility + } + + + // Update the last seen time for this node's address + if (pfrom->fNetworkNode) + if (strCommand == "version" || strCommand == "addr" || strCommand == "inv" || strCommand == "getdata" || strCommand == "ping") + AddressCurrentlyConnected(pfrom->addr); + + + return true; +} + +// requires LOCK(cs_vRecvMsg) +bool ProcessMessages(CNode* pfrom) +{ + //if (fDebug) + // printf("ProcessMessages(%zu messages)\n", pfrom->vRecvMsg.size()); + + // + // Message format + // (4) message start + // (12) command + // (4) size + // (4) checksum + // (x) data + // + bool fOk = true; + + std::deque::iterator it = pfrom->vRecvMsg.begin(); + while (!pfrom->fDisconnect && it != pfrom->vRecvMsg.end()) { + // Don't bother if send buffer is too full to respond anyway + if (pfrom->nSendSize >= SendBufferSize()) + break; + + // get next message + CNetMessage& msg = *it; + + //if (fDebug) + // printf("ProcessMessages(message %u msgsz, %zu bytes, complete:%s)\n", + // msg.hdr.nMessageSize, msg.vRecv.size(), + // msg.complete() ? "Y" : "N"); + + // end, if an incomplete message is found + if (!msg.complete()) + break; + + // at this point, any failure means we can delete the current message + it++; + + // Scan for message start + if (memcmp(msg.hdr.pchMessageStart, pchMessageStart, sizeof(pchMessageStart)) != 0) { + printf("\n\nPROCESSMESSAGE: INVALID MESSAGESTART\n\n"); + fOk = false; + break; + } + + // Read header + CMessageHeader& hdr = msg.hdr; + if (!hdr.IsValid()) + { + printf("\n\nPROCESSMESSAGE: ERRORS IN HEADER %s\n\n\n", hdr.GetCommand().c_str()); + continue; + } + string strCommand = hdr.GetCommand(); + + // Message size + unsigned int nMessageSize = hdr.nMessageSize; + + // Checksum + CDataStream& vRecv = msg.vRecv; + uint256 hash = Hash(vRecv.begin(), vRecv.begin() + nMessageSize); + unsigned int nChecksum = 0; + memcpy(&nChecksum, &hash, sizeof(nChecksum)); + if (nChecksum != hdr.nChecksum) + { + printf("ProcessMessages(%s, %u bytes) : CHECKSUM ERROR nChecksum=%08x hdr.nChecksum=%08x\n", + strCommand.c_str(), nMessageSize, nChecksum, hdr.nChecksum); + continue; + } + + // Process message + bool fRet = false; + try + { + { + LOCK(cs_main); + fRet = ProcessMessage(pfrom, strCommand, vRecv); + } + if (fShutdown) + break; + } + catch (std::ios_base::failure& e) + { + if (strstr(e.what(), "end of data")) + { + // Allow exceptions from under-length message on vRecv + printf("ProcessMessages(%s, %u 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 over-long size + printf("ProcessMessages(%s, %u bytes) : Exception '%s' caught\n", strCommand.c_str(), nMessageSize, e.what()); + } + else + { + PrintExceptionContinue(&e, "ProcessMessages()"); + } + } + catch (std::exception& e) { + PrintExceptionContinue(&e, "ProcessMessages()"); + } catch (...) { + PrintExceptionContinue(NULL, "ProcessMessages()"); + } + + if (!fRet) + printf("ProcessMessage(%s, %u bytes) FAILED\n", strCommand.c_str(), nMessageSize); + } + + // In case the connection got shut down, its receive buffer was wiped + if (!pfrom->fDisconnect) + pfrom->vRecvMsg.erase(pfrom->vRecvMsg.begin(), it); + + return fOk; +} + + +bool SendMessages(CNode* pto, bool fSendTrickle) +{ + TRY_LOCK(cs_main, lockMain); + if (lockMain) { + // Don't send anything until we get their version message + if (pto->nVersion == 0) + return true; + + // Keep-alive ping. We send a nonce of zero because we don't use it anywhere + // right now. + if (pto->nLastSend && GetTime() - pto->nLastSend > 30 * 60 && pto->vSendMsg.empty()) { + uint64_t nonce = 0; + if (pto->nVersion > BIP0031_VERSION) + pto->PushMessage("ping", nonce); + else + pto->PushMessage("ping"); + } + + // Resend wallet transactions that haven't gotten in a block yet + ResendWalletTransactions(); + + // Address refresh broadcast + static int64_t nLastRebroadcast; + if (!IsInitialBlockDownload() && (GetTime() - nLastRebroadcast > 24 * 60 * 60)) + { + { + LOCK(cs_vNodes); + BOOST_FOREACH(CNode* pnode, vNodes) + { + // Periodically clear setAddrKnown to allow refresh broadcasts + if (nLastRebroadcast) + pnode->setAddrKnown.clear(); + + // Rebroadcast our address + if (!fNoListen) + { + CAddress addr = GetLocalAddress(&pnode->addr); + if (addr.IsRoutable()) + pnode->PushAddress(addr); + } + } + } + nLastRebroadcast = GetTime(); + } + + // + // Message: addr + // + if (fSendTrickle) + { + vector vAddr; + vAddr.reserve(pto->vAddrToSend.size()); + BOOST_FOREACH(const CAddress& addr, pto->vAddrToSend) + { + // returns true if wasn't already contained in the set + if (pto->setAddrKnown.insert(addr).second) + { + vAddr.push_back(addr); + // receiver rejects addr messages larger than 1000 + if (vAddr.size() >= 1000) + { + pto->PushMessage("addr", vAddr); + vAddr.clear(); + } + } + } + pto->vAddrToSend.clear(); + if (!vAddr.empty()) + pto->PushMessage("addr", vAddr); + } + + + // + // Message: inventory + // + vector vInv; + vector vInvWait; + { + LOCK(pto->cs_inventory); + vInv.reserve(pto->vInventoryToSend.size()); + vInvWait.reserve(pto->vInventoryToSend.size()); + BOOST_FOREACH(const CInv& inv, pto->vInventoryToSend) + { + if (pto->setInventoryKnown.count(inv)) + continue; + + // trickle out tx inv to protect privacy + if (inv.type == MSG_TX && !fSendTrickle) + { + // 1/4 of tx invs blast to all immediately + static uint256 hashSalt; + if (hashSalt == 0) + hashSalt = GetRandHash(); + uint256 hashRand = inv.hash ^ hashSalt; + hashRand = Hash(BEGIN(hashRand), END(hashRand)); + bool fTrickleWait = ((hashRand & 3) != 0); + + // always trickle our own transactions + if (!fTrickleWait) + { + CWalletTx wtx; + if (GetTransaction(inv.hash, wtx)) + if (wtx.fFromMe) + fTrickleWait = true; + } + + if (fTrickleWait) + { + vInvWait.push_back(inv); + continue; + } + } + + // returns true if wasn't already contained in the set + if (pto->setInventoryKnown.insert(inv).second) + { + vInv.push_back(inv); + if (vInv.size() >= 1000) + { + pto->PushMessage("inv", vInv); + vInv.clear(); + } + } + } + pto->vInventoryToSend = vInvWait; + } + if (!vInv.empty()) + pto->PushMessage("inv", vInv); + + + // + // Message: getdata + // + vector vGetData; + int64_t nNow = GetTime() * 1000000; + CTxDB txdb("r"); + while (!pto->mapAskFor.empty() && (*pto->mapAskFor.begin()).first <= nNow) + { + const CInv& inv = (*pto->mapAskFor.begin()).second; + if (!AlreadyHave(txdb, inv)) + { + if (fDebugNet) + printf("sending getdata: %s\n", inv.ToString().c_str()); + vGetData.push_back(inv); + if (vGetData.size() >= 1000) + { + pto->PushMessage("getdata", vGetData); + vGetData.clear(); + } + mapAlreadyAskedFor[inv] = nNow; + } + pto->mapAskFor.erase(pto->mapAskFor.begin()); + } + if (!vGetData.empty()) + pto->PushMessage("getdata", vGetData); + + } + return true; +} diff --git a/src/main.h b/src/main.h new file mode 100644 index 0000000..cac2e42 --- /dev/null +++ b/src/main.h @@ -0,0 +1,1596 @@ +// Copyright (c) 2009-2010 Satoshi Nakamoto +// Copyright (c) 2009-2012 The Bitcoin developers +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. +#ifndef BITCOIN_MAIN_H +#define BITCOIN_MAIN_H + +#include "bignum.h" +#include "sync.h" +#include "net.h" +#include "script.h" +#include "scrypt.h" +#include "zerocoin/Zerocoin.h" + +#include + +class CWallet; +class CBlock; +class CBlockIndex; +class CKeyItem; +class CReserveKey; +class COutPoint; + +class CAddress; +class CInv; +class CRequestTracker; +class CNode; + +class CTxMemPool; + +static const int LAST_POW_BLOCK = 100000000; + +/** The maximum allowed size for a serialized block, in bytes (network rule) */ +static const unsigned int MAX_BLOCK_SIZE = 1000000; +/** The maximum size for mined blocks */ +static const unsigned int MAX_BLOCK_SIZE_GEN = MAX_BLOCK_SIZE/2; +/** The maximum size for transactions we're willing to relay/mine **/ +static const unsigned int MAX_STANDARD_TX_SIZE = MAX_BLOCK_SIZE_GEN/5; +/** The maximum allowed number of signature check operations in a block (network rule) */ +static const unsigned int MAX_BLOCK_SIGOPS = MAX_BLOCK_SIZE/50; +/** The maximum number of orphan transactions kept in memory */ +static const unsigned int MAX_ORPHAN_TRANSACTIONS = MAX_BLOCK_SIZE/100; +/** The maximum number of entries in an 'inv' protocol message */ +static const unsigned int MAX_INV_SZ = 50000; +/** Fees smaller than this (in satoshi) are considered zero fee (for transaction creation) */ +static const int64_t MIN_TX_FEE = 10000; +/** Fees smaller than this (in satoshi) are considered zero fee (for relaying) */ +static const int64_t MIN_RELAY_TX_FEE = MIN_TX_FEE; +/** No amount larger than this (in satoshi) is valid */ +static const int64_t MAX_MONEY = 60000000 * COIN; +inline bool MoneyRange(int64_t nValue) { return (nValue >= 0 && nValue <= MAX_MONEY); } +/** Threshold for nLockTime: below this value it is interpreted as block number, otherwise as UNIX timestamp. */ +static const unsigned int LOCKTIME_THRESHOLD = 500000000; // Tue Nov 5 00:53:20 1985 UTC +static const int nCoinbaseMaturity = 6; // 6 blocks +static const int nCoinbaseMaturityADJ = 150; // 150 blocks + +static const int64_t COIN_YEAR_REWARD = 3 * CENT; + +static const uint256 hashGenesisBlock("0x000002cac270a01e29300abaaeb7d412ca00fa7f43f0d547a57b9ff9c85d95e8"); +static const uint256 hashGenesisBlockTestNet("0x000002cac270a01e29300abaaeb7d412ca00fa7f43f0d547a57b9ff9c85d95e8"); + +inline int64_t PastDrift(int64_t nTime) { return nTime - 10 * 60; } // up to 10 minutes from the past +inline int64_t FutureDrift(int64_t nTime) { return nTime + 10 * 60; } // up to 10 minutes from the future + +extern libzerocoin::Params* ZCParams; +extern CScript COINBASE_FLAGS; +extern CCriticalSection cs_main; +extern std::map mapBlockIndex; +extern std::set > setStakeSeen; +extern CBlockIndex* pindexGenesisBlock; +extern unsigned int nTargetSpacing; +extern unsigned int nStakeMinAge; +extern unsigned int nStakeMaxAge; +extern unsigned int nNodeLifespan; +extern int nBestHeight; +extern uint256 nBestChainTrust; +extern uint256 nBestInvalidTrust; +extern uint256 hashBestChain; +extern CBlockIndex* pindexBest; +extern unsigned int nTransactionsUpdated; +extern uint64_t nLastBlockTx; +extern uint64_t nLastBlockSize; +extern int64_t nLastCoinStakeSearchInterval; +extern const std::string strMessageMagic; +extern int64_t nTimeBestReceived; +extern CCriticalSection cs_setpwalletRegistered; +extern std::set setpwalletRegistered; +extern unsigned char pchMessageStart[4]; +extern std::map mapOrphanBlocks; + +// Settings +extern int64_t nTransactionFee; +extern int64_t nReserveBalance; +extern int64_t nMinimumInputValue; +extern bool fUseFastIndex; +extern unsigned int nDerivationMethodIndex; + +extern bool fEnforceCanonical; + +// Minimum disk space required - used in CheckDiskSpace() +static const uint64_t nMinDiskSpace = 52428800; + +class CReserveKey; +class CTxDB; +class CTxIndex; + +void RegisterWallet(CWallet* pwalletIn); +void UnregisterWallet(CWallet* pwalletIn); +void SyncWithWallets(const CTransaction& tx, const CBlock* pblock = NULL, bool fUpdate = false, bool fConnect = true); +bool ProcessBlock(CNode* pfrom, CBlock* pblock); +bool CheckDiskSpace(uint64_t nAdditionalBytes=0); +FILE* OpenBlockFile(unsigned int nFile, unsigned int nBlockPos, const char* pszMode="rb"); +FILE* AppendBlockFile(unsigned int& nFileRet); +bool LoadBlockIndex(bool fAllowNew=true); +void PrintBlockTree(); +CBlockIndex* FindBlockByHeight(int nHeight); +bool ProcessMessages(CNode* pfrom); +bool SendMessages(CNode* pto, bool fSendTrickle); +bool LoadExternalBlockFile(FILE* fileIn); + +bool CheckProofOfWork(uint256 hash, unsigned int nBits); +unsigned int GetNextTargetRequired(const CBlockIndex* pindexLast, bool fProofOfStake); +int64_t GetProofOfWorkReward(int64_t nFees); +int64_t GetProofOfStakeReward(int64_t nCoinAge, int64_t nFees); +unsigned int ComputeMinWork(unsigned int nBase, int64_t nTime); +unsigned int ComputeMinStake(unsigned int nBase, int64_t nTime, unsigned int nBlockTime); +int GetNumBlocksOfPeers(); +bool IsInitialBlockDownload(); +std::string GetWarnings(std::string strFor); +bool GetTransaction(const uint256 &hash, CTransaction &tx, uint256 &hashBlock); +uint256 WantedByOrphan(const CBlock* pblockOrphan); +const CBlockIndex* GetLastBlockIndex(const CBlockIndex* pindex, bool fProofOfStake); +void StakeMiner(CWallet *pwallet); +void ResendWalletTransactions(bool fForce = false); +int GetCoinbaseMaturity(int nHeight); + + +/** (try to) add transaction to memory pool **/ +bool AcceptToMemoryPool(CTxMemPool& pool, CTransaction &tx, + bool* pfMissingInputs); + + + + + + + + +bool GetWalletFile(CWallet* pwallet, std::string &strWalletFileOut); + +/** Position on disk for a particular transaction. */ +class CDiskTxPos +{ +public: + unsigned int nFile; + unsigned int nBlockPos; + unsigned int nTxPos; + + CDiskTxPos() + { + SetNull(); + } + + CDiskTxPos(unsigned int nFileIn, unsigned int nBlockPosIn, unsigned int nTxPosIn) + { + nFile = nFileIn; + nBlockPos = nBlockPosIn; + nTxPos = nTxPosIn; + } + + IMPLEMENT_SERIALIZE( READWRITE(FLATDATA(*this)); ) + void SetNull() { nFile = (unsigned int) -1; nBlockPos = 0; nTxPos = 0; } + bool IsNull() const { return (nFile == (unsigned int) -1); } + + friend bool operator==(const CDiskTxPos& a, const CDiskTxPos& b) + { + return (a.nFile == b.nFile && + a.nBlockPos == b.nBlockPos && + a.nTxPos == b.nTxPos); + } + + friend bool operator!=(const CDiskTxPos& a, const CDiskTxPos& b) + { + return !(a == b); + } + + + std::string ToString() const + { + if (IsNull()) + return "null"; + else + return strprintf("(nFile=%u, nBlockPos=%u, nTxPos=%u)", nFile, nBlockPos, nTxPos); + } + + void print() const + { + printf("%s", ToString().c_str()); + } +}; + + + +/** An inpoint - a combination of a transaction and an index n into its vin */ +class CInPoint +{ +public: + CTransaction* ptx; + unsigned int n; + + CInPoint() { SetNull(); } + CInPoint(CTransaction* ptxIn, unsigned int nIn) { ptx = ptxIn; n = nIn; } + void SetNull() { ptx = NULL; n = (unsigned int) -1; } + bool IsNull() const { return (ptx == NULL && n == (unsigned int) -1); } +}; + + + +/** An outpoint - a combination of a transaction hash and an index n into its vout */ +class COutPoint +{ +public: + uint256 hash; + unsigned int n; + + COutPoint() { SetNull(); } + COutPoint(uint256 hashIn, unsigned int nIn) { hash = hashIn; n = nIn; } + IMPLEMENT_SERIALIZE( READWRITE(FLATDATA(*this)); ) + void SetNull() { hash = 0; n = (unsigned int) -1; } + bool IsNull() const { return (hash == 0 && n == (unsigned int) -1); } + + friend bool operator<(const COutPoint& a, const COutPoint& b) + { + return (a.hash < b.hash || (a.hash == b.hash && a.n < b.n)); + } + + friend bool operator==(const COutPoint& a, const COutPoint& b) + { + return (a.hash == b.hash && a.n == b.n); + } + + friend bool operator!=(const COutPoint& a, const COutPoint& b) + { + return !(a == b); + } + + std::string ToString() const + { + return strprintf("COutPoint(%s, %u)", hash.ToString().substr(0,10).c_str(), n); + } + + void print() const + { + printf("%s\n", ToString().c_str()); + } +}; + + + + +/** An input of a transaction. It contains the location of the previous + * transaction's output that it claims and a signature that matches the + * output's public key. + */ +class CTxIn +{ +public: + COutPoint prevout; + CScript scriptSig; + unsigned int nSequence; + + CTxIn() + { + nSequence = std::numeric_limits::max(); + } + + explicit CTxIn(COutPoint prevoutIn, CScript scriptSigIn=CScript(), unsigned int nSequenceIn=std::numeric_limits::max()) + { + prevout = prevoutIn; + scriptSig = scriptSigIn; + nSequence = nSequenceIn; + } + + CTxIn(uint256 hashPrevTx, unsigned int nOut, CScript scriptSigIn=CScript(), unsigned int nSequenceIn=std::numeric_limits::max()) + { + prevout = COutPoint(hashPrevTx, nOut); + scriptSig = scriptSigIn; + nSequence = nSequenceIn; + } + + IMPLEMENT_SERIALIZE + ( + READWRITE(prevout); + READWRITE(scriptSig); + READWRITE(nSequence); + ) + + bool IsFinal() const + { + return (nSequence == std::numeric_limits::max()); + } + + friend bool operator==(const CTxIn& a, const CTxIn& b) + { + return (a.prevout == b.prevout && + a.scriptSig == b.scriptSig && + a.nSequence == b.nSequence); + } + + friend bool operator!=(const CTxIn& a, const CTxIn& b) + { + return !(a == b); + } + + std::string ToStringShort() const + { + return strprintf(" %s %d", prevout.hash.ToString().c_str(), prevout.n); + } + + std::string ToString() const + { + std::string str; + str += "CTxIn("; + str += prevout.ToString(); + if (prevout.IsNull()) + str += strprintf(", coinbase %s", HexStr(scriptSig).c_str()); + else + str += strprintf(", scriptSig=%s", scriptSig.ToString().substr(0,24).c_str()); + if (nSequence != std::numeric_limits::max()) + str += strprintf(", nSequence=%u", nSequence); + str += ")"; + return str; + } + + void print() const + { + printf("%s\n", ToString().c_str()); + } +}; + + + + +/** An output of a transaction. It contains the public key that the next input + * must be able to sign with to claim it. + */ +class CTxOut +{ +public: + int64_t nValue; + CScript scriptPubKey; + + CTxOut() + { + SetNull(); + } + + CTxOut(int64_t nValueIn, CScript scriptPubKeyIn) + { + nValue = nValueIn; + scriptPubKey = scriptPubKeyIn; + } + + IMPLEMENT_SERIALIZE + ( + READWRITE(nValue); + READWRITE(scriptPubKey); + ) + + void SetNull() + { + nValue = -1; + scriptPubKey.clear(); + } + + bool IsNull() + { + return (nValue == -1); + } + + void SetEmpty() + { + nValue = 0; + scriptPubKey.clear(); + } + + bool IsEmpty() const + { + return (nValue == 0 && scriptPubKey.empty()); + } + + uint256 GetHash() const + { + return SerializeHash(*this); + } + + friend bool operator==(const CTxOut& a, const CTxOut& b) + { + return (a.nValue == b.nValue && + a.scriptPubKey == b.scriptPubKey); + } + + friend bool operator!=(const CTxOut& a, const CTxOut& b) + { + return !(a == b); + } + + std::string ToStringShort() const + { + return strprintf(" out %s %s", FormatMoney(nValue).c_str(), scriptPubKey.ToString(true).c_str()); + } + + std::string ToString() const + { + if (IsEmpty()) return "CTxOut(empty)"; + return strprintf("CTxOut(nValue=%s, scriptPubKey=%s)", FormatMoney(nValue).c_str(), scriptPubKey.ToString().c_str()); + } + + void print() const + { + printf("%s\n", ToString().c_str()); + } +}; + + + + +enum GetMinFee_mode +{ + GMF_BLOCK, + GMF_RELAY, + GMF_SEND, +}; + +typedef std::map > MapPrevTx; + +/** The basic transaction that is broadcasted on the network and contained in + * blocks. A transaction can contain multiple inputs and outputs. + */ +class CTransaction +{ +public: + static const int CURRENT_VERSION=1; + int nVersion; + unsigned int nTime; + std::vector vin; + std::vector vout; + unsigned int nLockTime; + + // Denial-of-service detection: + mutable int nDoS; + bool DoS(int nDoSIn, bool fIn) const { nDoS += nDoSIn; return fIn; } + + CTransaction() + { + SetNull(); + } + + IMPLEMENT_SERIALIZE + ( + READWRITE(this->nVersion); + nVersion = this->nVersion; + READWRITE(nTime); + READWRITE(vin); + READWRITE(vout); + READWRITE(nLockTime); + ) + + void SetNull() + { + nVersion = CTransaction::CURRENT_VERSION; + nTime = GetAdjustedTime(); + vin.clear(); + vout.clear(); + nLockTime = 0; + nDoS = 0; // Denial-of-service prevention + } + + bool IsNull() const + { + return (vin.empty() && vout.empty()); + } + + uint256 GetHash() const + { + return SerializeHash(*this); + } + + bool IsNewerThan(const CTransaction& old) const + { + if (vin.size() != old.vin.size()) + return false; + for (unsigned int i = 0; i < vin.size(); i++) + if (vin[i].prevout != old.vin[i].prevout) + return false; + + bool fNewer = false; + unsigned int nLowest = std::numeric_limits::max(); + for (unsigned int i = 0; i < vin.size(); i++) + { + if (vin[i].nSequence != old.vin[i].nSequence) + { + if (vin[i].nSequence <= nLowest) + { + fNewer = false; + nLowest = vin[i].nSequence; + } + if (old.vin[i].nSequence < nLowest) + { + fNewer = true; + nLowest = old.vin[i].nSequence; + } + } + } + return fNewer; + } + + bool IsCoinBase() const + { + return (vin.size() == 1 && vin[0].prevout.IsNull() && vout.size() >= 1); + } + + bool IsCoinStake() const + { + // ppcoin: the coin stake transaction is marked with the first output empty + return (vin.size() > 0 && (!vin[0].prevout.IsNull()) && vout.size() >= 2 && vout[0].IsEmpty()); + } + + /** Check for standard transaction types + @param[in] mapInputs Map of previous transactions that have outputs we're spending + @return True if all inputs (scriptSigs) use only standard transaction forms + @see CTransaction::FetchInputs + */ + bool AreInputsStandard(const MapPrevTx& mapInputs) const; + + /** Count ECDSA signature operations the old-fashioned (pre-0.6) way + @return number of sigops this transaction's outputs will produce when spent + @see CTransaction::FetchInputs + */ + unsigned int GetLegacySigOpCount() const; + + /** Count ECDSA signature operations in pay-to-script-hash inputs. + + @param[in] mapInputs Map of previous transactions that have outputs we're spending + @return maximum number of sigops required to validate this transaction's inputs + @see CTransaction::FetchInputs + */ + unsigned int GetP2SHSigOpCount(const MapPrevTx& mapInputs) const; + + /** Amount of bitcoins spent by this transaction. + @return sum of all outputs (note: does not include fees) + */ + int64_t GetValueOut() const + { + int64_t nValueOut = 0; + BOOST_FOREACH(const CTxOut& txout, vout) + { + nValueOut += txout.nValue; + if (!MoneyRange(txout.nValue) || !MoneyRange(nValueOut)) + throw std::runtime_error("CTransaction::GetValueOut() : value out of range"); + } + return nValueOut; + } + + /** Amount of bitcoins coming in to this transaction + Note that lightweight clients may not know anything besides the hash of previous transactions, + so may not be able to calculate this. + + @param[in] mapInputs Map of previous transactions that have outputs we're spending + @return Sum of value of all inputs (scriptSigs) + @see CTransaction::FetchInputs + */ + int64_t GetValueIn(const MapPrevTx& mapInputs) const; + + int64_t GetMinFee(unsigned int nBlockSize=1, enum GetMinFee_mode mode=GMF_BLOCK, unsigned int nBytes = 0) const; + + bool ReadFromDisk(CDiskTxPos pos, FILE** pfileRet=NULL) + { + CAutoFile filein = CAutoFile(OpenBlockFile(pos.nFile, 0, pfileRet ? "rb+" : "rb"), SER_DISK, CLIENT_VERSION); + if (!filein) + return error("CTransaction::ReadFromDisk() : OpenBlockFile failed"); + + // Read transaction + if (fseek(filein, pos.nTxPos, SEEK_SET) != 0) + return error("CTransaction::ReadFromDisk() : fseek failed"); + + try { + filein >> *this; + } + catch (std::exception &e) { + return error("%s() : deserialize or I/O error", __PRETTY_FUNCTION__); + } + + // Return file pointer + if (pfileRet) + { + if (fseek(filein, pos.nTxPos, SEEK_SET) != 0) + return error("CTransaction::ReadFromDisk() : second fseek failed"); + *pfileRet = filein.release(); + } + return true; + } + + friend bool operator==(const CTransaction& a, const CTransaction& b) + { + return (a.nVersion == b.nVersion && + a.nTime == b.nTime && + a.vin == b.vin && + a.vout == b.vout && + a.nLockTime == b.nLockTime); + } + + friend bool operator!=(const CTransaction& a, const CTransaction& b) + { + return !(a == b); + } + + std::string ToStringShort() const + { + std::string str; + str += strprintf("%s %s", GetHash().ToString().c_str(), IsCoinBase()? "base" : (IsCoinStake()? "stake" : "user")); + return str; + } + + std::string ToString() const + { + std::string str; + str += IsCoinBase()? "Coinbase" : (IsCoinStake()? "Coinstake" : "CTransaction"); + str += strprintf("(hash=%s, nTime=%d, ver=%d, vin.size=%" PRIszu", vout.size=%" PRIszu", nLockTime=%d)\n", + GetHash().ToString().substr(0,10).c_str(), + nTime, + nVersion, + vin.size(), + vout.size(), + nLockTime); + for (unsigned int i = 0; i < vin.size(); i++) + str += " " + vin[i].ToString() + "\n"; + for (unsigned int i = 0; i < vout.size(); i++) + str += " " + vout[i].ToString() + "\n"; + return str; + } + + void print() const + { + printf("%s", ToString().c_str()); + } + + + bool ReadFromDisk(CTxDB& txdb, COutPoint prevout, CTxIndex& txindexRet); + bool ReadFromDisk(CTxDB& txdb, COutPoint prevout); + bool ReadFromDisk(COutPoint prevout); + bool DisconnectInputs(CTxDB& txdb); + + /** Fetch from memory and/or disk. inputsRet keys are transaction hashes. + + @param[in] txdb Transaction database + @param[in] mapTestPool List of pending changes to the transaction index database + @param[in] fBlock True if being called to add a new best-block to the chain + @param[in] fMiner True if being called by CreateNewBlock + @param[out] inputsRet Pointers to this transaction's inputs + @param[out] fInvalid returns true if transaction is invalid + @return Returns true if all inputs are in txdb or mapTestPool + */ + bool FetchInputs(CTxDB& txdb, const std::map& mapTestPool, + bool fBlock, bool fMiner, MapPrevTx& inputsRet, bool& fInvalid); + + /** Sanity check previous transactions, then, if all checks succeed, + mark them as spent by this transaction. + + @param[in] inputs Previous transactions (from FetchInputs) + @param[out] mapTestPool Keeps track of inputs that need to be updated on disk + @param[in] posThisTx Position of this transaction on disk + @param[in] pindexBlock + @param[in] fBlock true if called from ConnectBlock + @param[in] fMiner true if called from CreateNewBlock + @return Returns true if all checks succeed + */ + bool ConnectInputs(CTxDB& txdb, MapPrevTx inputs, + std::map& mapTestPool, const CDiskTxPos& posThisTx, + const CBlockIndex* pindexBlock, bool fBlock, bool fMiner); + bool CheckTransaction() const; + bool GetCoinAge(CTxDB& txdb, uint64_t& nCoinAge) const; // ppcoin: get transaction coin age + +protected: + const CTxOut& GetOutputFor(const CTxIn& input, const MapPrevTx& inputs) const; +}; + +/** Check for standard transaction types + @return True if all outputs (scriptPubKeys) use only standard transaction forms +*/ +bool IsStandardTx(const CTransaction& tx); + +bool IsFinalTx(const CTransaction &tx, int nBlockHeight = 0, int64_t nBlockTime = 0); + + + +/** A transaction with a merkle branch linking it to the block chain. */ +class CMerkleTx : public CTransaction +{ +private: + int GetDepthInMainChainINTERNAL(CBlockIndex* &pindexRet) const; +public: + uint256 hashBlock; + std::vector vMerkleBranch; + int nIndex; + + // memory only + mutable bool fMerkleVerified; + + + CMerkleTx() + { + Init(); + } + + CMerkleTx(const CTransaction& txIn) : CTransaction(txIn) + { + Init(); + } + + void Init() + { + hashBlock = 0; + nIndex = -1; + fMerkleVerified = false; + } + + + IMPLEMENT_SERIALIZE + ( + nSerSize += SerReadWrite(s, *(CTransaction*)this, nType, nVersion, ser_action); + nVersion = this->nVersion; + READWRITE(hashBlock); + READWRITE(vMerkleBranch); + READWRITE(nIndex); + ) + + + int SetMerkleBranch(const CBlock* pblock=NULL); + + // Return depth of transaction in blockchain: + // -1 : not in blockchain, and not in memory pool (conflicted transaction) + // 0 : in memory pool, waiting to be included in a block + // >=1 : this many blocks deep in the main chain + int GetDepthInMainChain(CBlockIndex* &pindexRet) const; + int GetDepthInMainChain() const { CBlockIndex *pindexRet; return GetDepthInMainChain(pindexRet); } + int GetHeightInMainChain(CBlockIndex* &pindexRet) const; + int GetHeightInMainChain() const { CBlockIndex *pindexRet; return GetHeightInMainChain(pindexRet); } + bool IsInMainChain() const { CBlockIndex *pindexRet; return GetDepthInMainChainINTERNAL(pindexRet) > 0; } + int GetBlocksToMaturity() const; + bool AcceptToMemoryPool(); +}; + + + + +/** A txdb record that contains the disk location of a transaction and the + * locations of transactions that spend its outputs. vSpent is really only + * used as a flag, but having the location is very helpful for debugging. + */ +class CTxIndex +{ +public: + CDiskTxPos pos; + std::vector vSpent; + + CTxIndex() + { + SetNull(); + } + + CTxIndex(const CDiskTxPos& posIn, unsigned int nOutputs) + { + pos = posIn; + vSpent.resize(nOutputs); + } + + IMPLEMENT_SERIALIZE + ( + if (!(nType & SER_GETHASH)) + READWRITE(nVersion); + READWRITE(pos); + READWRITE(vSpent); + ) + + void SetNull() + { + pos.SetNull(); + vSpent.clear(); + } + + bool IsNull() + { + return pos.IsNull(); + } + + friend bool operator==(const CTxIndex& a, const CTxIndex& b) + { + return (a.pos == b.pos && + a.vSpent == b.vSpent); + } + + friend bool operator!=(const CTxIndex& a, const CTxIndex& b) + { + return !(a == b); + } + int GetDepthInMainChain() const; + +}; + + + + + +/** Nodes collect new transactions into a block, hash them into a hash tree, + * and scan through nonce values to make the block's hash satisfy proof-of-work + * requirements. When they solve the proof-of-work, they broadcast the block + * to everyone and the block is added to the block chain. The first transaction + * in the block is a special one that creates a new coin owned by the creator + * of the block. + * + * Blocks are appended to blk0001.dat files on disk. Their location on disk + * is indexed by CBlockIndex objects in memory. + */ +class CBlock +{ +public: + // header + static const int CURRENT_VERSION=6; + int nVersion; + uint256 hashPrevBlock; + uint256 hashMerkleRoot; + unsigned int nTime; + unsigned int nBits; + unsigned int nNonce; + + // network and disk + std::vector vtx; + + // ppcoin: block signature - signed by one of the coin base txout[N]'s owner + std::vector vchBlockSig; + + // memory only + mutable std::vector vMerkleTree; + + // Denial-of-service detection: + mutable int nDoS; + bool DoS(int nDoSIn, bool fIn) const { nDoS += nDoSIn; return fIn; } + + CBlock() + { + SetNull(); + } + + IMPLEMENT_SERIALIZE + ( + READWRITE(this->nVersion); + nVersion = this->nVersion; + READWRITE(hashPrevBlock); + READWRITE(hashMerkleRoot); + READWRITE(nTime); + READWRITE(nBits); + READWRITE(nNonce); + + // ConnectBlock depends on vtx following header to generate CDiskTxPos + if (!(nType & (SER_GETHASH|SER_BLOCKHEADERONLY))) + { + READWRITE(vtx); + READWRITE(vchBlockSig); + } + else if (fRead) + { + const_cast(this)->vtx.clear(); + const_cast(this)->vchBlockSig.clear(); + } + ) + + void SetNull() + { + nVersion = CBlock::CURRENT_VERSION; + hashPrevBlock = 0; + hashMerkleRoot = 0; + nTime = 0; + nBits = 0; + nNonce = 0; + vtx.clear(); + vchBlockSig.clear(); + vMerkleTree.clear(); + nDoS = 0; + } + + bool IsNull() const + { + return (nBits == 0); + } + + uint256 GetHash() const + { + return GetPoWHash(); + } + + uint256 GetPoWHash() const + { + return scrypt_blockhash(CVOIDBEGIN(nVersion)); + } + + int64_t GetBlockTime() const + { + return (int64_t)nTime; + } + + void UpdateTime(const CBlockIndex* pindexPrev); + + // entropy bit for stake modifier if chosen by modifier + unsigned int GetStakeEntropyBit() const + { + // Take last bit of block hash as entropy bit + unsigned int nEntropyBit = ((GetHash().Get64()) & 1llu); + if (fDebug && GetBoolArg("-printstakemodifier")) + printf("GetStakeEntropyBit: hashBlock=%s nEntropyBit=%u\n", GetHash().ToString().c_str(), nEntropyBit); + return nEntropyBit; + } + + // ppcoin: two types of block: proof-of-work or proof-of-stake + bool IsProofOfStake() const + { + return (vtx.size() > 1 && vtx[1].IsCoinStake()); + } + + bool IsProofOfWork() const + { + return !IsProofOfStake(); + } + + std::pair GetProofOfStake() const + { + return IsProofOfStake()? std::make_pair(vtx[1].vin[0].prevout, vtx[1].nTime) : std::make_pair(COutPoint(), (unsigned int)0); + } + + // ppcoin: get max transaction timestamp + int64_t GetMaxTransactionTime() const + { + int64_t maxTransactionTime = 0; + BOOST_FOREACH(const CTransaction& tx, vtx) + maxTransactionTime = std::max(maxTransactionTime, (int64_t)tx.nTime); + return maxTransactionTime; + } + + uint256 BuildMerkleTree() const + { + vMerkleTree.clear(); + BOOST_FOREACH(const CTransaction& tx, vtx) + vMerkleTree.push_back(tx.GetHash()); + int j = 0; + for (int nSize = vtx.size(); nSize > 1; nSize = (nSize + 1) / 2) + { + for (int i = 0; i < nSize; i += 2) + { + int i2 = std::min(i+1, nSize-1); + vMerkleTree.push_back(Hash(BEGIN(vMerkleTree[j+i]), END(vMerkleTree[j+i]), + BEGIN(vMerkleTree[j+i2]), END(vMerkleTree[j+i2]))); + } + j += nSize; + } + return (vMerkleTree.empty() ? 0 : vMerkleTree.back()); + } + + std::vector GetMerkleBranch(int nIndex) const + { + if (vMerkleTree.empty()) + BuildMerkleTree(); + std::vector vMerkleBranch; + int j = 0; + for (int nSize = vtx.size(); nSize > 1; nSize = (nSize + 1) / 2) + { + int i = std::min(nIndex^1, nSize-1); + vMerkleBranch.push_back(vMerkleTree[j+i]); + nIndex >>= 1; + j += nSize; + } + return vMerkleBranch; + } + + static uint256 CheckMerkleBranch(uint256 hash, const std::vector& vMerkleBranch, int nIndex) + { + if (nIndex == -1) + return 0; + BOOST_FOREACH(const uint256& otherside, vMerkleBranch) + { + if (nIndex & 1) + hash = Hash(BEGIN(otherside), END(otherside), BEGIN(hash), END(hash)); + else + hash = Hash(BEGIN(hash), END(hash), BEGIN(otherside), END(otherside)); + nIndex >>= 1; + } + return hash; + } + + + bool WriteToDisk(unsigned int& nFileRet, unsigned int& nBlockPosRet) + { + // Open history file to append + CAutoFile fileout = CAutoFile(AppendBlockFile(nFileRet), SER_DISK, CLIENT_VERSION); + if (!fileout) + return error("CBlock::WriteToDisk() : AppendBlockFile failed"); + + // Write index header + unsigned int nSize = fileout.GetSerializeSize(*this); + fileout << FLATDATA(pchMessageStart) << nSize; + + // Write block + long fileOutPos = ftell(fileout); + if (fileOutPos < 0) + return error("CBlock::WriteToDisk() : ftell failed"); + nBlockPosRet = fileOutPos; + fileout << *this; + + // Flush stdio buffers and commit to disk before returning + fflush(fileout); + if (!IsInitialBlockDownload() || (nBestHeight+1) % 500 == 0) + FileCommit(fileout); + + return true; + } + + bool ReadFromDisk(unsigned int nFile, unsigned int nBlockPos, bool fReadTransactions=true) + { + SetNull(); + + // Open history file to read + CAutoFile filein = CAutoFile(OpenBlockFile(nFile, nBlockPos, "rb"), SER_DISK, CLIENT_VERSION); + if (!filein) + return error("CBlock::ReadFromDisk() : OpenBlockFile failed"); + if (!fReadTransactions) + filein.nType |= SER_BLOCKHEADERONLY; + + // Read block + try { + filein >> *this; + } + catch (std::exception &e) { + return error("%s() : deserialize or I/O error", __PRETTY_FUNCTION__); + } + + // Check the header + if (fReadTransactions && IsProofOfWork() && !CheckProofOfWork(GetPoWHash(), nBits)) + return error("CBlock::ReadFromDisk() : errors in block header"); + + return true; + } + + + + void print() const + { + printf("CBlock(hash=%s, ver=%d, hashPrevBlock=%s, hashMerkleRoot=%s, nTime=%u, nBits=%08x, nNonce=%u, vtx=%" PRIszu", vchBlockSig=%s)\n", + GetHash().ToString().c_str(), + nVersion, + hashPrevBlock.ToString().c_str(), + hashMerkleRoot.ToString().c_str(), + nTime, nBits, nNonce, + vtx.size(), + HexStr(vchBlockSig.begin(), vchBlockSig.end()).c_str()); + for (unsigned int i = 0; i < vtx.size(); i++) + { + printf(" "); + vtx[i].print(); + } + printf(" vMerkleTree: "); + for (unsigned int i = 0; i < vMerkleTree.size(); i++) + printf("%s ", vMerkleTree[i].ToString().substr(0,10).c_str()); + printf("\n"); + } + + + bool DisconnectBlock(CTxDB& txdb, CBlockIndex* pindex); + bool ConnectBlock(CTxDB& txdb, CBlockIndex* pindex, bool fJustCheck=false); + bool ReadFromDisk(const CBlockIndex* pindex, bool fReadTransactions=true); + bool SetBestChain(CTxDB& txdb, CBlockIndex* pindexNew); + bool AddToBlockIndex(unsigned int nFile, unsigned int nBlockPos, const uint256& hashProof); + bool CheckBlock(bool fCheckPOW=true, bool fCheckMerkleRoot=true, bool fCheckSig=true) const; + bool AcceptBlock(); + bool GetCoinAge(uint64_t& nCoinAge) const; // ppcoin: calculate total coin age spent in block + bool SignBlock(CWallet& keystore, int64_t nFees); + bool CheckBlockSignature() const; + +private: + bool SetBestChainInner(CTxDB& txdb, CBlockIndex *pindexNew); +}; + + + + + + +/** The block chain is a tree shaped structure starting with the + * genesis block at the root, with each block potentially having multiple + * candidates to be the next block. pprev and pnext link a path through the + * main/longest chain. A blockindex may have multiple pprev pointing back + * to it, but pnext will only point forward to the longest branch, or will + * be null if the block is not part of the longest chain. + */ +class CBlockIndex +{ +public: + const uint256* phashBlock; + CBlockIndex* pprev; + CBlockIndex* pnext; + unsigned int nFile; + unsigned int nBlockPos; + uint256 nChainTrust; // ppcoin: trust score of block chain + int nHeight; + + int64_t nMint; + int64_t nMoneySupply; + + unsigned int nFlags; // ppcoin: block index flags + enum + { + BLOCK_PROOF_OF_STAKE = (1 << 0), // is proof-of-stake block + BLOCK_STAKE_ENTROPY = (1 << 1), // entropy bit for stake modifier + BLOCK_STAKE_MODIFIER = (1 << 2), // regenerated stake modifier + }; + + uint64_t nStakeModifier; // hash modifier for proof-of-stake + unsigned int nStakeModifierChecksum; // checksum of index; in-memeory only + + // proof-of-stake specific fields + COutPoint prevoutStake; + unsigned int nStakeTime; + + uint256 hashProof; + + // block header + int nVersion; + uint256 hashMerkleRoot; + unsigned int nTime; + unsigned int nBits; + unsigned int nNonce; + + CBlockIndex() + { + phashBlock = NULL; + pprev = NULL; + pnext = NULL; + nFile = 0; + nBlockPos = 0; + nHeight = 0; + nChainTrust = 0; + nMint = 0; + nMoneySupply = 0; + nFlags = 0; + nStakeModifier = 0; + nStakeModifierChecksum = 0; + hashProof = 0; + prevoutStake.SetNull(); + nStakeTime = 0; + + nVersion = 0; + hashMerkleRoot = 0; + nTime = 0; + nBits = 0; + nNonce = 0; + } + + CBlockIndex(unsigned int nFileIn, unsigned int nBlockPosIn, CBlock& block) + { + phashBlock = NULL; + pprev = NULL; + pnext = NULL; + nFile = nFileIn; + nBlockPos = nBlockPosIn; + nHeight = 0; + nChainTrust = 0; + nMint = 0; + nMoneySupply = 0; + nFlags = 0; + nStakeModifier = 0; + nStakeModifierChecksum = 0; + hashProof = 0; + if (block.IsProofOfStake()) + { + SetProofOfStake(); + prevoutStake = block.vtx[1].vin[0].prevout; + nStakeTime = block.vtx[1].nTime; + } + else + { + prevoutStake.SetNull(); + nStakeTime = 0; + } + + nVersion = block.nVersion; + hashMerkleRoot = block.hashMerkleRoot; + nTime = block.nTime; + nBits = block.nBits; + nNonce = block.nNonce; + } + + CBlock GetBlockHeader() const + { + CBlock block; + block.nVersion = nVersion; + if (pprev) + block.hashPrevBlock = pprev->GetBlockHash(); + block.hashMerkleRoot = hashMerkleRoot; + block.nTime = nTime; + block.nBits = nBits; + block.nNonce = nNonce; + return block; + } + + uint256 GetBlockHash() const + { + return *phashBlock; + } + + int64_t GetBlockTime() const + { + return (int64_t)nTime; + } + + uint256 GetBlockTrust() const; + + bool IsInMainChain() const + { + return (pnext || this == pindexBest); + } + + bool CheckIndex() const + { + return true; + } + + int64_t GetPastTimeLimit() const + { + return GetMedianTimePast(); + } + + enum { nMedianTimeSpan=11 }; + + int64_t GetMedianTimePast() const + { + int64_t pmedian[nMedianTimeSpan]; + int64_t* pbegin = &pmedian[nMedianTimeSpan]; + int64_t* pend = &pmedian[nMedianTimeSpan]; + + const CBlockIndex* pindex = this; + for (int i = 0; i < nMedianTimeSpan && pindex; i++, pindex = pindex->pprev) + *(--pbegin) = pindex->GetBlockTime(); + + std::sort(pbegin, pend); + return pbegin[(pend - pbegin)/2]; + } + + /** + * Returns true if there are nRequired or more blocks of minVersion or above + * in the last nToCheck blocks, starting at pstart and going backwards. + */ + static bool IsSuperMajority(int minVersion, const CBlockIndex* pstart, + unsigned int nRequired, unsigned int nToCheck); + + + bool IsProofOfWork() const + { + return !(nFlags & BLOCK_PROOF_OF_STAKE); + } + + bool IsProofOfStake() const + { + return (nFlags & BLOCK_PROOF_OF_STAKE); + } + + void SetProofOfStake() + { + nFlags |= BLOCK_PROOF_OF_STAKE; + } + + unsigned int GetStakeEntropyBit() const + { + return ((nFlags & BLOCK_STAKE_ENTROPY) >> 1); + } + + bool SetStakeEntropyBit(unsigned int nEntropyBit) + { + if (nEntropyBit > 1) + return false; + nFlags |= (nEntropyBit? BLOCK_STAKE_ENTROPY : 0); + return true; + } + + bool GeneratedStakeModifier() const + { + return (nFlags & BLOCK_STAKE_MODIFIER); + } + + void SetStakeModifier(uint64_t nModifier, bool fGeneratedStakeModifier) + { + nStakeModifier = nModifier; + if (fGeneratedStakeModifier) + nFlags |= BLOCK_STAKE_MODIFIER; + } + + std::string ToString() const + { + return strprintf("CBlockIndex(nprev=%p, pnext=%p, nFile=%u, nBlockPos=%-6d nHeight=%d, nMint=%s, nMoneySupply=%s, nFlags=(%s)(%d)(%s), nStakeModifier=%016" PRIx64", nStakeModifierChecksum=%08x, hashProof=%s, prevoutStake=(%s), nStakeTime=%d merkle=%s, hashBlock=%s)", + pprev, pnext, nFile, nBlockPos, nHeight, + FormatMoney(nMint).c_str(), FormatMoney(nMoneySupply).c_str(), + GeneratedStakeModifier() ? "MOD" : "-", GetStakeEntropyBit(), IsProofOfStake()? "PoS" : "PoW", + nStakeModifier, nStakeModifierChecksum, + hashProof.ToString().c_str(), + prevoutStake.ToString().c_str(), nStakeTime, + hashMerkleRoot.ToString().c_str(), + GetBlockHash().ToString().c_str()); + } + + void print() const + { + printf("%s\n", ToString().c_str()); + } +}; + + + +/** Used to marshal pointers into hashes for db storage. */ +class CDiskBlockIndex : public CBlockIndex +{ +private: + uint256 blockHash; + +public: + uint256 hashPrev; + uint256 hashNext; + + CDiskBlockIndex() + { + hashPrev = 0; + hashNext = 0; + blockHash = 0; + } + + explicit CDiskBlockIndex(CBlockIndex* pindex) : CBlockIndex(*pindex) + { + hashPrev = (pprev ? pprev->GetBlockHash() : 0); + hashNext = (pnext ? pnext->GetBlockHash() : 0); + } + + IMPLEMENT_SERIALIZE + ( + if (!(nType & SER_GETHASH)) + READWRITE(nVersion); + + READWRITE(hashNext); + READWRITE(nFile); + READWRITE(nBlockPos); + READWRITE(nHeight); + READWRITE(nMint); + READWRITE(nMoneySupply); + READWRITE(nFlags); + READWRITE(nStakeModifier); + if (IsProofOfStake()) + { + READWRITE(prevoutStake); + READWRITE(nStakeTime); + } + else if (fRead) + { + const_cast(this)->prevoutStake.SetNull(); + const_cast(this)->nStakeTime = 0; + } + READWRITE(hashProof); + + // block header + READWRITE(this->nVersion); + READWRITE(hashPrev); + READWRITE(hashMerkleRoot); + READWRITE(nTime); + READWRITE(nBits); + READWRITE(nNonce); + READWRITE(blockHash); + ) + + uint256 GetBlockHash() const + { + if (fUseFastIndex && (nTime < GetAdjustedTime() - 24 * 60 * 60) && blockHash != 0) + return blockHash; + + CBlock block; + block.nVersion = nVersion; + block.hashPrevBlock = hashPrev; + block.hashMerkleRoot = hashMerkleRoot; + block.nTime = nTime; + block.nBits = nBits; + block.nNonce = nNonce; + + const_cast(this)->blockHash = block.GetHash(); + + return blockHash; + } + + std::string ToString() const + { + std::string str = "CDiskBlockIndex("; + str += CBlockIndex::ToString(); + str += strprintf("\n hashBlock=%s, hashPrev=%s, hashNext=%s)", + GetBlockHash().ToString().c_str(), + hashPrev.ToString().c_str(), + hashNext.ToString().c_str()); + return str; + } + + void print() const + { + printf("%s\n", ToString().c_str()); + } +}; + + + + + + + + +/** Describes a place in the block chain to another node such that if the + * other node doesn't have the same branch, it can find a recent common trunk. + * The further back it is, the further before the fork it may be. + */ +class CBlockLocator +{ +protected: + std::vector vHave; +public: + + CBlockLocator() + { + } + + explicit CBlockLocator(const CBlockIndex* pindex) + { + Set(pindex); + } + + explicit CBlockLocator(uint256 hashBlock) + { + std::map::iterator mi = mapBlockIndex.find(hashBlock); + if (mi != mapBlockIndex.end()) + Set((*mi).second); + } + + CBlockLocator(const std::vector& vHaveIn) + { + vHave = vHaveIn; + } + + IMPLEMENT_SERIALIZE + ( + if (!(nType & SER_GETHASH)) + READWRITE(nVersion); + READWRITE(vHave); + ) + + void SetNull() + { + vHave.clear(); + } + + bool IsNull() + { + return vHave.empty(); + } + + void Set(const CBlockIndex* pindex) + { + vHave.clear(); + int nStep = 1; + while (pindex) + { + vHave.push_back(pindex->GetBlockHash()); + + // Exponentially larger steps back + for (int i = 0; pindex && i < nStep; i++) + pindex = pindex->pprev; + if (vHave.size() > 10) + nStep *= 2; + } + vHave.push_back((!fTestNet ? hashGenesisBlock : hashGenesisBlockTestNet)); + } + + int GetDistanceBack() + { + // Retrace how far back it was in the sender's branch + int nDistance = 0; + int nStep = 1; + BOOST_FOREACH(const uint256& hash, vHave) + { + std::map::iterator mi = mapBlockIndex.find(hash); + if (mi != mapBlockIndex.end()) + { + CBlockIndex* pindex = (*mi).second; + if (pindex->IsInMainChain()) + return nDistance; + } + nDistance += nStep; + if (nDistance > 10) + nStep *= 2; + } + return nDistance; + } + + CBlockIndex* GetBlockIndex() + { + // Find the first block the caller has in the main chain + BOOST_FOREACH(const uint256& hash, vHave) + { + std::map::iterator mi = mapBlockIndex.find(hash); + if (mi != mapBlockIndex.end()) + { + CBlockIndex* pindex = (*mi).second; + if (pindex->IsInMainChain()) + return pindex; + } + } + return pindexGenesisBlock; + } + + uint256 GetBlockHash() + { + // Find the first block the caller has in the main chain + BOOST_FOREACH(const uint256& hash, vHave) + { + std::map::iterator mi = mapBlockIndex.find(hash); + if (mi != mapBlockIndex.end()) + { + CBlockIndex* pindex = (*mi).second; + if (pindex->IsInMainChain()) + return hash; + } + } + return (!fTestNet ? hashGenesisBlock : hashGenesisBlockTestNet); + } + + int GetHeight() + { + CBlockIndex* pindex = GetBlockIndex(); + if (!pindex) + return 0; + return pindex->nHeight; + } +}; + + + + + + + + +class CTxMemPool +{ +public: + mutable CCriticalSection cs; + std::map mapTx; + std::map mapNextTx; + + bool addUnchecked(const uint256& hash, CTransaction &tx); + bool remove(const CTransaction &tx, bool fRecursive = false); + bool removeConflicts(const CTransaction &tx); + void clear(); + void queryHashes(std::vector& vtxid); + + unsigned long size() const + { + LOCK(cs); + return mapTx.size(); + } + + bool exists(uint256 hash) const + { + LOCK(cs); + return (mapTx.count(hash) != 0); + } + + bool lookup(uint256 hash, CTransaction& result) const + { + LOCK(cs); + std::map::const_iterator i = mapTx.find(hash); + if (i == mapTx.end()) return false; + result = i->second; + return true; + } +}; + +extern CTxMemPool mempool; + +#endif diff --git a/src/makefile.bsd b/src/makefile.bsd new file mode 100644 index 0000000..ab71a3e --- /dev/null +++ b/src/makefile.bsd @@ -0,0 +1,192 @@ +# Copyright (c) 2009-2010 Satoshi Nakamoto +# Distributed under the MIT/X11 software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. + +USE_UPNP:=0 + +LINK:=$(CXX) + +DEFS=-DBOOST_SPIRIT_THREADSAFE + +DEFS += $(addprefix -I,$(CURDIR) $(CURDIR)/obj $(BOOST_INCLUDE_PATH) $(BDB_INCLUDE_PATH) $(OPENSSL_INCLUDE_PATH)) +LIBS = $(addprefix -L,$(BOOST_LIB_PATH) $(BDB_LIB_PATH) $(OPENSSL_LIB_PATH)) + +LMODE = dynamic +LMODE2 = dynamic +ifdef STATIC + LMODE = static + ifeq (${STATIC}, all) + LMODE2 = static + endif +endif + +# for boost 1.37, add -mt to the boost libraries +LIBS += \ + -Wl,-B$(LMODE) \ + -l boost_system$(BOOST_LIB_SUFFIX) \ + -l boost_filesystem$(BOOST_LIB_SUFFIX) \ + -l boost_program_options$(BOOST_LIB_SUFFIX) \ + -l boost_thread$(BOOST_LIB_SUFFIX) \ + -l db_cxx$(BDB_LIB_SUFFIX) \ + -l ssl \ + -l crypto \ + -l execinfo + +ifndef USE_UPNP + override USE_UPNP = - +endif +ifneq (${USE_UPNP}, -) + LIBS += -l miniupnpc + DEFS += -DUSE_UPNP=$(USE_UPNP) +endif + +LIBS+= \ + -Wl,-B$(LMODE2) \ + -l z \ + -l dl \ + -l pthread + + +# Hardening +# Make some classes of vulnerabilities unexploitable in case one is discovered. +# + # This is a workaround for Ubuntu bug #691722, the default -fstack-protector causes + # -fstack-protector-all to be ignored unless -fno-stack-protector is used first. + # see: https://bugs.launchpad.net/ubuntu/+source/gcc-4.5/+bug/691722 + HARDENING=-fno-stack-protector + + # Stack Canaries + # Put numbers at the beginning of each stack frame and check that they are the same. + # If a stack buffer if overflowed, it writes over the canary number and then on return + # when that number is checked, it won't be the same and the program will exit with + # a "Stack smashing detected" error instead of being exploited. + HARDENING+=-fstack-protector-all -Wstack-protector + + # Make some important things such as the global offset table read only as soon as + # the dynamic linker is finished building it. This will prevent overwriting of addresses + # which would later be jumped to. + LDHARDENING+=-Wl,-z,relro -Wl,-z,now + + # Build position independent code to take advantage of Address Space Layout Randomization + # offered by some kernels. + # see doc/build-unix.txt for more information. + ifdef PIE + HARDENING+=-fPIE + LDHARDENING+=-pie + endif + + # -D_FORTIFY_SOURCE=2 does some checking for potentially exploitable code patterns in + # the source such overflowing a statically defined buffer. + HARDENING+=-D_FORTIFY_SOURCE=2 +# + + +DEBUGFLAGS=-g + +# CXXFLAGS can be specified on the make command line, so we use xCXXFLAGS that only +# adds some defaults in front. Unfortunately, CXXFLAGS=... $(CXXFLAGS) does not work. +xCXXFLAGS=-O0 -msse2 -pthread -Wall -Wextra -Wno-ignored-qualifiers -Wformat -Wformat-security -Wno-unused-parameter \ + $(DEBUGFLAGS) $(DEFS) $(HARDENING) $(CXXFLAGS) + +# LDFLAGS can be specified on the make command line, so we use xLDFLAGS that only +# adds some defaults in front. Unfortunately, LDFLAGS=... $(LDFLAGS) does not work. +xLDFLAGS=$(LDHARDENING) $(LDFLAGS) + +OBJS= \ + obj/alert.o \ + obj/version.o \ + obj/checkpoints.o \ + obj/netbase.o \ + obj/addrman.o \ + obj/crypter.o \ + obj/key.o \ + obj/db.o \ + obj/init.o \ + obj/keystore.o \ + obj/main.o \ + obj/miner.o \ + obj/net.o \ + obj/protocol.o \ + obj/bitcoinrpc.o \ + obj/rpcdump.o \ + obj/rpcnet.o \ + obj/rpcmining.o \ + obj/rpcwallet.o \ + obj/rpcblockchain.o \ + obj/rpcrawtransaction.o \ + obj/script.o \ + obj/sync.o \ + obj/util.o \ + obj/wallet.o \ + obj/walletdb.o \ + obj/noui.o \ + obj/kernel.o \ + obj/pbkdf2.o \ + obj/scrypt.o \ + obj/scrypt-arm.o \ + obj/scrypt-x86.o \ + obj/scrypt-x86_64.o \ + obj/zerocoin/Accumulator.o \ + obj/zerocoin/AccumulatorProofOfKnowledge.o \ + obj/zerocoin/Coin.o \ + obj/zerocoin/CoinSpend.o \ + obj/zerocoin/Commitment.o \ + obj/zerocoin/ParamGeneration.o \ + obj/zerocoin/Params.o \ + obj/zerocoin/SerialNumberSignatureOfKnowledge.o \ + obj/zerocoin/SpendMetaData.o \ + obj/zerocoin/ZeroTest.o + +all: arepacoind + +LIBS += $(CURDIR)/leveldb/libleveldb.a $(CURDIR)/leveldb/libmemenv.a +DEFS += $(addprefix -I,$(CURDIR)/leveldb/include) +DEFS += $(addprefix -I,$(CURDIR)/leveldb/helpers) +OBJS += obj/txdb-leveldb.o +leveldb/libleveldb.a: + @echo "Building LevelDB ..."; cd leveldb; make libleveldb.a libmemenv.a; cd ..; +obj/txdb-leveldb.o: leveldb/libleveldb.a + +# auto-generated dependencies: +-include obj/*.P + +obj/build.h: FORCE + /bin/sh ../share/genbuild.sh obj/build.h +version.cpp: obj/build.h +DEFS += -DHAVE_BUILD_INFO + +obj/scrypt-x86.o: scrypt-x86.S + $(CXX) -c $(xCXXFLAGS) -MMD -o $@ $< + +obj/scrypt-x86_64.o: scrypt-x86_64.S + $(CXX) -c $(xCXXFLAGS) -MMD -o $@ $< + +obj/scrypt-arm.o: scrypt-arm.S + $(CXX) -c $(xCXXFLAGS) -MMD -o $@ $< + +obj/%.o: %.cpp + $(CXX) -c $(xCXXFLAGS) -MMD -MF $(@:%.o=%.d) -o $@ $< + @cp $(@:%.o=%.d) $(@:%.o=%.P); \ + sed -e 's/#.*//' -e 's/^[^:]*: *//' -e 's/ *\\$$//' \ + -e '/^$$/ d' -e 's/$$/ :/' < $(@:%.o=%.d) >> $(@:%.o=%.P); \ + rm -f $(@:%.o=%.d) + +obj/zerocoin/%.o: zerocoin/%.cpp + $(CXX) -c $(xCXXFLAGS) -MMD -MF $(@:%.o=%.d) -o $@ $< + @cp $(@:%.o=%.d) $(@:%.o=%.P); \ + sed -e 's/#.*//' -e 's/^[^:]*: *//' -e 's/ *\\$$//' \ + -e '/^$$/ d' -e 's/$$/ :/' < $(@:%.o=%.d) >> $(@:%.o=%.P); \ + rm -f $(@:%.o=%.d) + +arepacoind: $(OBJS:obj/%=obj/%) + $(LINK) $(xCXXFLAGS) -o $@ $^ $(xLDFLAGS) $(LIBS) + +clean: + -rm -f arepacoind + -rm -f obj/*.o + -rm -f obj/zerocoin/*.o + -rm -f obj/*.P + -rm -f obj/zerocoin/*.P + -rm -f obj/build.h + +FORCE: diff --git a/src/makefile.linux-mingw b/src/makefile.linux-mingw new file mode 100644 index 0000000..04903aa --- /dev/null +++ b/src/makefile.linux-mingw @@ -0,0 +1,141 @@ +# Copyright (c) 2009-2010 Satoshi Nakamoto +# Distributed under the MIT/X11 software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. + +TARGET_PLATFORM:=i686 +#TARGET_PLATFORM:=x86_64 + +DEPSDIR:=/usr/$(TARGET_PLATFORM)-w64-mingw32 +CC:=$(TARGET_PLATFORM)-w64-mingw32-gcc +CXX:=$(TARGET_PLATFORM)-w64-mingw32-g++ +RANLIB=$(TARGET_PLATFORM)-w64-mingw32-ranlib +STRIP=$(TARGET_PLATFORM)-w64-mingw32-strip + +USE_UPNP:=0 + +INCLUDEPATHS= \ + -I"$(CURDIR)" \ + -I"$(CURDIR)"/obj \ + -I"$(DEPSDIR)/boost_1_55_0" \ + -I"$(DEPSDIR)/db-6.0.20/build_unix" \ + -I"$(DEPSDIR)/openssl-1.0.1f/include" \ + -I"$(DEPSDIR)" + +LIBPATHS= \ + -L"$(DEPSDIR)/boost_1_55_0/stage/lib" \ + -L"$(DEPSDIR)/db-6.0.20/build_unix" \ + -L"$(DEPSDIR)/openssl-1.0.1f" + +LIBS= \ + -l boost_system-mt \ + -l boost_filesystem-mt \ + -l boost_program_options-mt \ + -l boost_thread_win32-mt \ + -l boost_chrono-mt \ + -l db_cxx \ + -l ssl \ + -l crypto \ + -l z + +DEFS=-D_MT -DWIN32 -D_WINDOWS -DBOOST_THREAD_USE_LIB -DBOOST_SPIRIT_THREADSAFE +DEBUGFLAGS=-g +CFLAGS=-O3 -msse2 -w -Wall -Wextra -Wno-ignored-qualifiers -Wformat -Wformat-security -Wno-unused-parameter $(DEBUGFLAGS) $(DEFS) $(INCLUDEPATHS) +LDFLAGS=-Wl,--dynamicbase -Wl,--nxcompat -static-libgcc -static-libstdc++ + +ifndef USE_UPNP + override USE_UPNP = - +endif +ifneq (${USE_UPNP}, -) + LIBPATHS += -L"$(DEPSDIR)/miniupnpc" + LIBS += -l miniupnpc -l iphlpapi + DEFS += -DSTATICLIB -DUSE_UPNP=$(USE_UPNP) +endif + +LIBS += -l mingwthrd -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 mswsock -l shlwapi + +# TODO: make the mingw builds smarter about dependencies, like the linux/osx builds are +HEADERS = $(wildcard *.h) + +OBJS= \ + obj/alert.o \ + obj/version.o \ + obj/checkpoints.o \ + obj/netbase.o \ + obj/addrman.o \ + obj/crypter.o \ + obj/key.o \ + obj/db.o \ + obj/init.o \ + obj/keystore.o \ + obj/main.o \ + obj/miner.o \ + obj/net.o \ + obj/protocol.o \ + obj/bitcoinrpc.o \ + obj/rpcdump.o \ + obj/rpcnet.o \ + obj/rpcmining.o \ + obj/rpcwallet.o \ + obj/rpcblockchain.o \ + obj/rpcrawtransaction.o \ + obj/script.o \ + obj/sync.o \ + obj/util.o \ + obj/wallet.o \ + obj/walletdb.o \ + obj/noui.o \ + obj/kernel.o \ + obj/pbkdf2.o \ + obj/scrypt.o \ + obj/scrypt-x86.o \ + obj/scrypt-x86_64.o \ + obj/zerocoin/Accumulator.o \ + obj/zerocoin/AccumulatorProofOfKnowledge.o \ + obj/zerocoin/Coin.o \ + obj/zerocoin/CoinSpend.o \ + obj/zerocoin/Commitment.o \ + obj/zerocoin/ParamGeneration.o \ + obj/zerocoin/Params.o \ + obj/zerocoin/SerialNumberSignatureOfKnowledge.o \ + obj/zerocoin/SpendMetaData.o \ + obj/zerocoin/ZeroTest.o + +all: arepacoind.exe + +LIBS += $(CURDIR)/leveldb/libleveldb.a $(CURDIR)/leveldb/libmemenv.a +DEFS += -I"$(CURDIR)/leveldb/include" +DEFS += -I"$(CURDIR)/leveldb/helpers" +OBJS += obj/txdb-leveldb.o +leveldb/libleveldb.a: + @echo "Building LevelDB ..." && cd leveldb && CC=$(CC) CXX=$(CXX) TARGET_OS=OS_WINDOWS_CROSSCOMPILE CXXFLAGS="-I$(INCLUDEPATHS)" LDFLAGS="-L$(LIBPATHS)" $(MAKE) libleveldb.a libmemenv.a && $(RANLIB) libleveldb.a && $(RANLIB) libmemenv.a && cd .. +obj/txdb-leveldb.o: leveldb/libleveldb.a + +obj/build.h: FORCE + /bin/sh ../share/genbuild.sh obj/build.h +version.cpp: obj/build.h +DEFS += -DHAVE_BUILD_INFO + +obj/%.o: %.cpp $(HEADERS) + $(CXX) -c $(CFLAGS) -o $@ $< + +obj/zerocoin/%.o: zerocoin/%.cpp $(HEADERS) + $(CXX) -c $(CFLAGS) -o $@ $< + +arepacoind.exe: $(OBJS:obj/%=obj/%) + $(CXX) $(CFLAGS) $(LDFLAGS) -o $@ $(LIBPATHS) $^ $(LIBS) -lshlwapi + $(STRIP) arepacoind.exe + +obj/scrypt-x86.o: scrypt-x86.S + $(CXX) -c $(CFLAGS) -MMD -o $@ $< + +obj/scrypt-x86_64.o: scrypt-x86_64.S + $(CXX) -c $(CFLAGS) -MMD -o $@ $< + +clean: + -rm -f obj/*.o + -rm -f obj/zerocoin/*.o + -rm -f arepacoind.exe + -rm -f obj/build.h + cd leveldb && TARGET_OS=OS_WINDOWS_CROSSCOMPILE $(MAKE) clean && cd .. + +FORCE: diff --git a/src/makefile.mingw b/src/makefile.mingw new file mode 100644 index 0000000..66af269 --- /dev/null +++ b/src/makefile.mingw @@ -0,0 +1,123 @@ +# Copyright (c) 2009-2010 Satoshi Nakamoto +# Distributed under the MIT/X11 software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. + +USE_UPNP:=0 + +INCLUDEPATHS= \ + -I"C:\boost-1.50.0-mgw" \ + -I"C:\db-4.8.30.NC-mgw\build_unix" \ + -I"C:\openssl-1.0.1c-mgw\include" + +LIBPATHS= \ + -L"C:\boost-1.50.0-mgw\stage\lib" \ + -L"C:\db-4.8.30.NC-mgw\build_unix" \ + -L"C:\openssl-1.0.1c-mgw" + +LIBS= \ + -l boost_system-mgw44-mt-1_53 \ + -l boost_filesystem-mgw44-mt-1_53 \ + -l boost_program_options-mgw44-mt-1_53 \ + -l boost_thread-mgw44-mt-1_53 \ + -l boost_chrono-mgw44-mt-1_53 \ + -l db_cxx \ + -l ssl \ + -l crypto + +DEFS=-DWIN32 -D_WINDOWS -DBOOST_THREAD_USE_LIB -DBOOST_SPIRIT_THREADSAFE +DEBUGFLAGS=-g +CFLAGS=-mthreads -O3 -msse2 -w -Wall -Wextra -Wno-ignored-qualifiers -Wformat -Wformat-security -Wno-unused-parameter $(DEBUGFLAGS) $(DEFS) $(INCLUDEPATHS) +LDFLAGS=-Wl,--dynamicbase -Wl,--nxcompat + +TESTDEFS = -DTEST_DATA_DIR=$(abspath test/data) + +ifndef USE_UPNP + override USE_UPNP = - +endif +ifneq (${USE_UPNP}, -) + INCLUDEPATHS += -I"C:\miniupnpc-1.6-mgw" + LIBPATHS += -L"C:\miniupnpc-1.6-mgw" + LIBS += -l miniupnpc -l iphlpapi + DEFS += -DSTATICLIB -DUSE_UPNP=$(USE_UPNP) +endif + +LIBS += -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 mswsock -l shlwapi + +# TODO: make the mingw builds smarter about dependencies, like the linux/osx builds are +HEADERS = $(wildcard *.h) + +OBJS= \ + obj/alert.o \ + obj/version.o \ + obj/checkpoints.o \ + obj/netbase.o \ + obj/addrman.o \ + obj/crypter.o \ + obj/key.o \ + obj/db.o \ + obj/init.o \ + obj/keystore.o \ + obj/main.o \ + obj/miner.o \ + obj/net.o \ + obj/protocol.o \ + obj/bitcoinrpc.o \ + obj/rpcdump.o \ + obj/rpcnet.o \ + obj/rpcmining.o \ + obj/rpcwallet.o \ + obj/rpcblockchain.o \ + obj/rpcrawtransaction.o \ + obj/script.o \ + obj/sync.o \ + obj/util.o \ + obj/wallet.o \ + obj/walletdb.o \ + obj/noui.o \ + obj/kernel.o \ + obj/pbkdf2.o \ + obj/scrypt.o \ + obj/scrypt-x86.o \ + obj/scrypt-x86_64.o \ + obj/zerocoin/Accumulator.o \ + obj/zerocoin/AccumulatorProofOfKnowledge.o \ + obj/zerocoin/Coin.o \ + obj/zerocoin/CoinSpend.o \ + obj/zerocoin/Commitment.o \ + obj/zerocoin/ParamGeneration.o \ + obj/zerocoin/Params.o \ + obj/zerocoin/SerialNumberSignatureOfKnowledge.o \ + obj/zerocoin/SpendMetaData.o \ + obj/zerocoin/ZeroTest.o + +all: arepacoind.exe + +LIBS += $(CURDIR)/leveldb/libleveldb.a $(CURDIR)/leveldb/libmemenv.a +DEFS += $(addprefix -I,$(CURDIR)/leveldb/include) +DEFS += $(addprefix -I,$(CURDIR)/leveldb/helpers) +OBJS += obj/txdb-leveldb.o +leveldb/libleveldb.a: + cd leveldb; make; cd .. +obj/txdb-leveldb.o: leveldb/libleveldb.a + +obj/%.o: %.cpp $(HEADERS) + g++ -c $(CFLAGS) -o $@ $< + +obj/zerocoin/%.o: zerocoin/%.cpp + g++ -c $(CFLAGS) -o $@ $< + +obj/scrypt-x86.o: scrypt-x86.S + $(CXX) -c $(xCXXFLAGS) -MMD -o $@ $< + +obj/scrypt-x86_64.o: scrypt-x86_64.S + $(CXX) -c $(xCXXFLAGS) -MMD -o $@ $< + +arepacoind.exe: $(OBJS:obj/%=obj/%) + g++ $(CFLAGS) $(LDFLAGS) -o $@ $(LIBPATHS) $^ $(LIBS) + +clean: + -del /Q arepacoind + -del /Q obj\* + -del /Q obj\zerocoin\* + +FORCE: diff --git a/src/makefile.osx b/src/makefile.osx new file mode 100644 index 0000000..2111ad9 --- /dev/null +++ b/src/makefile.osx @@ -0,0 +1,169 @@ +# -*- mode: Makefile; -*- +# Copyright (c) 2011 Bitcoin Developers +# Distributed under the MIT/X11 software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. + +# Mac OS X makefile for arepacoin +# Originally by Laszlo Hanyecz (solar@heliacal.net) + +CXX=llvm-g++ +DEPSDIR=/opt/local + +INCLUDEPATHS= \ + -I"$(CURDIR)" \ + -I"$(CURDIR)"/obj \ + -I"$(DEPSDIR)/include" \ + -I"$(DEPSDIR)/include/db48" + +LIBPATHS= \ + -L"$(DEPSDIR)/lib" \ + -L"$(DEPSDIR)/lib/db48" + +USE_UPNP:=1 + +LIBS= -dead_strip + +ifdef STATIC +# Build STATIC if you are redistributing the arepacoind binary +LIBS += \ + $(DEPSDIR)/lib/db48/libdb_cxx-4.8.a \ + $(DEPSDIR)/lib/libboost_system-mt.a \ + $(DEPSDIR)/lib/libboost_filesystem-mt.a \ + $(DEPSDIR)/lib/libboost_program_options-mt.a \ + $(DEPSDIR)/lib/libboost_thread-mt.a \ + $(DEPSDIR)/lib/libssl.a \ + $(DEPSDIR)/lib/libcrypto.a \ + -lz +else +LIBS += \ + -ldb_cxx-4.8 \ + -lboost_system-mt \ + -lboost_filesystem-mt \ + -lboost_program_options-mt \ + -lboost_thread-mt \ + -lssl \ + -lcrypto \ + -lz +endif + +DEFS=-DMAC_OSX -DMSG_NOSIGNAL=0 -DBOOST_SPIRIT_THREADSAFE + +ifdef RELEASE +# Compile for maximum compatibility and smallest size. +# This requires that dependencies are compiled +# the same way. +CFLAGS = -mmacosx-version-min=10.5 -arch x86_64 -O3 -msse2 +else +CFLAGS = -g -msse2 +endif + +# ppc doesn't work because we don't support big-endian +CFLAGS += -Wall -Wextra -Wformat -Wno-ignored-qualifiers -Wformat-security -Wno-unused-parameter \ + $(DEBUGFLAGS) $(DEFS) $(INCLUDEPATHS) + +OBJS= \ + obj/alert.o \ + obj/version.o \ + obj/checkpoints.o \ + obj/netbase.o \ + obj/addrman.o \ + obj/crypter.o \ + obj/key.o \ + obj/db.o \ + obj/init.o \ + obj/keystore.o \ + obj/main.o \ + obj/miner.o \ + obj/net.o \ + obj/protocol.o \ + obj/bitcoinrpc.o \ + obj/rpcdump.o \ + obj/rpcnet.o \ + obj/rpcmining.o \ + obj/rpcwallet.o \ + obj/rpcblockchain.o \ + obj/rpcrawtransaction.o \ + obj/script.o \ + obj/sync.o \ + obj/util.o \ + obj/wallet.o \ + obj/walletdb.o \ + obj/noui.o \ + obj/pbkdf2.o \ + obj/kernel.o \ + obj/scrypt.o \ + obj/scrypt-x86.o \ + obj/scrypt-x86_64.o \ + obj/zerocoin/Accumulator.o \ + obj/zerocoin/AccumulatorProofOfKnowledge.o \ + obj/zerocoin/Coin.o \ + obj/zerocoin/CoinSpend.o \ + obj/zerocoin/Commitment.o \ + obj/zerocoin/ParamGeneration.o \ + obj/zerocoin/Params.o \ + obj/zerocoin/SerialNumberSignatureOfKnowledge.o \ + obj/zerocoin/SpendMetaData.o \ + obj/zerocoin/ZeroTest.o + +ifndef USE_UPNP + override USE_UPNP = - +endif +ifneq (${USE_UPNP}, -) + DEFS += -DUSE_UPNP=$(USE_UPNP) +ifdef STATIC + LIBS += $(DEPSDIR)/lib/libminiupnpc.a +else + LIBS += -lminiupnpc +endif +endif + +all: arepacoind + +LIBS += $(CURDIR)/leveldb/libleveldb.a $(CURDIR)/leveldb/libmemenv.a +DEFS += $(addprefix -I,$(CURDIR)/leveldb/include) +DEFS += $(addprefix -I,$(CURDIR)/leveldb/helpers) +OBJS += obj/txdb-leveldb.o +leveldb/libleveldb.a: + @echo "Building LevelDB ..."; cd leveldb; make libleveldb.a libmemenv.a; cd .. +obj/txdb-leveldb.o: leveldb/libleveldb.a + +# auto-generated dependencies: +-include obj/*.P + +obj/build.h: FORCE + /bin/sh ../share/genbuild.sh obj/build.h +version.cpp: obj/build.h +DEFS += -DHAVE_BUILD_INFO + +obj/%.o: %.cpp + $(CXX) -c $(CFLAGS) -MMD -MF $(@:%.o=%.d) -o $@ $< + @cp $(@:%.o=%.d) $(@:%.o=%.P); \ + sed -e 's/#.*//' -e 's/^[^:]*: *//' -e 's/ *\\$$//' \ + -e '/^$$/ d' -e 's/$$/ :/' < $(@:%.o=%.d) >> $(@:%.o=%.P); \ + rm -f $(@:%.o=%.d) + +obj/zerocoin/%.o: zerocoin/%.cpp + $(CXX) -c $(xCXXFLAGS) -MMD -MF $(@:%.o=%.d) -o $@ $< + @cp $(@:%.o=%.d) $(@:%.o=%.P); \ + sed -e 's/#.*//' -e 's/^[^:]*: *//' -e 's/ *\\$$//' \ + -e '/^$$/ d' -e 's/$$/ :/' < $(@:%.o=%.d) >> $(@:%.o=%.P); \ + rm -f $(@:%.o=%.d) + +obj/scrypt-x86.o: scrypt-x86.S + $(CXX) -c $(xCXXFLAGS) -MMD -o $@ $< + +obj/scrypt-x86_64.o: scrypt-x86_64.S + $(CXX) -c $(xCXXFLAGS) -MMD -o $@ $< + +arepacoind: $(OBJS:obj/%=obj/%) + $(CXX) $(CFLAGS) -o $@ $(LIBPATHS) $^ $(LIBS) + +clean: + -rm -f arepacoind + -rm -f obj/*.o + -rm -f obj/zerocoin/*.o + -rm -f obj/*.P + -rm -f obj/zerocoin/*.P + -rm -f obj/build.h + +FORCE: diff --git a/src/makefile.unix b/src/makefile.unix new file mode 100644 index 0000000..eb3d87f --- /dev/null +++ b/src/makefile.unix @@ -0,0 +1,198 @@ +# Copyright (c) 2009-2010 Satoshi Nakamoto +# Distributed under the MIT/X11 software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. + +USE_UPNP:=0 + +LINK:=$(CXX) +ARCH:=$(system lscpu | head -n 1 | awk '{print $2}') + +DEFS=-DBOOST_SPIRIT_THREADSAFE + +DEFS += $(addprefix -I,$(CURDIR) $(CURDIR)/obj $(BOOST_INCLUDE_PATH) $(BDB_INCLUDE_PATH) $(OPENSSL_INCLUDE_PATH)) +LIBS = $(addprefix -L,$(BOOST_LIB_PATH) $(BDB_LIB_PATH) $(OPENSSL_LIB_PATH)) + +LMODE = dynamic +LMODE2 = dynamic +ifdef STATIC + LMODE = static + ifeq (${STATIC}, all) + LMODE2 = static + endif +endif + +# for boost 1.37, add -mt to the boost libraries +LIBS += \ + -Wl,-B$(LMODE) \ + -l boost_system$(BOOST_LIB_SUFFIX) \ + -l boost_filesystem$(BOOST_LIB_SUFFIX) \ + -l boost_program_options$(BOOST_LIB_SUFFIX) \ + -l boost_thread$(BOOST_LIB_SUFFIX) \ + -l db_cxx$(BDB_LIB_SUFFIX) \ + -l ssl \ + -l crypto + +ifndef USE_UPNP + override USE_UPNP = - +endif +ifneq (${USE_UPNP}, -) + LIBS += -l miniupnpc + DEFS += -DUSE_UPNP=$(USE_UPNP) +endif + +LIBS+= \ + -Wl,-B$(LMODE2) \ + -l z \ + -l dl \ + -l pthread + + +# Hardening +# Make some classes of vulnerabilities unexploitable in case one is discovered. +# + # This is a workaround for Ubuntu bug #691722, the default -fstack-protector causes + # -fstack-protector-all to be ignored unless -fno-stack-protector is used first. + # see: https://bugs.launchpad.net/ubuntu/+source/gcc-4.5/+bug/691722 + HARDENING=-fno-stack-protector + + # Stack Canaries + # Put numbers at the beginning of each stack frame and check that they are the same. + # If a stack buffer if overflowed, it writes over the canary number and then on return + # when that number is checked, it won't be the same and the program will exit with + # a "Stack smashing detected" error instead of being exploited. + HARDENING+=-fstack-protector-all -Wstack-protector + + # Make some important things such as the global offset table read only as soon as + # the dynamic linker is finished building it. This will prevent overwriting of addresses + # which would later be jumped to. + LDHARDENING+=-Wl,-z,relro -Wl,-z,now + + # Build position independent code to take advantage of Address Space Layout Randomization + # offered by some kernels. + # see doc/build-unix.txt for more information. + ifdef PIE + HARDENING+=-fPIE + LDHARDENING+=-pie + endif + + # -D_FORTIFY_SOURCE=2 does some checking for potentially exploitable code patterns in + # the source such overflowing a statically defined buffer. + HARDENING+=-D_FORTIFY_SOURCE=2 +# + + +DEBUGFLAGS=-g + + +ifeq (${ARCH}, i686) + EXT_OPTIONS=-msse2 +endif + + +# CXXFLAGS can be specified on the make command line, so we use xCXXFLAGS that only +# adds some defaults in front. Unfortunately, CXXFLAGS=... $(CXXFLAGS) does not work. +xCXXFLAGS=-O2 $(EXT_OPTIONS) -pthread -Wall -Wextra -Wno-ignored-qualifiers -Wformat -Wformat-security -Wno-unused-parameter \ + $(DEBUGFLAGS) $(DEFS) $(HARDENING) $(CXXFLAGS) + +# LDFLAGS can be specified on the make command line, so we use xLDFLAGS that only +# adds some defaults in front. Unfortunately, LDFLAGS=... $(LDFLAGS) does not work. +xLDFLAGS=$(LDHARDENING) $(LDFLAGS) + +OBJS= \ + obj/alert.o \ + obj/version.o \ + obj/checkpoints.o \ + obj/netbase.o \ + obj/addrman.o \ + obj/crypter.o \ + obj/key.o \ + obj/db.o \ + obj/init.o \ + obj/keystore.o \ + obj/miner.o \ + obj/main.o \ + obj/net.o \ + obj/protocol.o \ + obj/bitcoinrpc.o \ + obj/rpcdump.o \ + obj/rpcnet.o \ + obj/rpcmining.o \ + obj/rpcwallet.o \ + obj/rpcblockchain.o \ + obj/rpcrawtransaction.o \ + obj/script.o \ + obj/sync.o \ + obj/util.o \ + obj/wallet.o \ + obj/walletdb.o \ + obj/noui.o \ + obj/kernel.o \ + obj/pbkdf2.o \ + obj/scrypt.o \ + obj/scrypt-arm.o \ + obj/scrypt-x86.o \ + obj/scrypt-x86_64.o \ + obj/zerocoin/Accumulator.o \ + obj/zerocoin/AccumulatorProofOfKnowledge.o \ + obj/zerocoin/Coin.o \ + obj/zerocoin/CoinSpend.o \ + obj/zerocoin/Commitment.o \ + obj/zerocoin/ParamGeneration.o \ + obj/zerocoin/Params.o \ + obj/zerocoin/SerialNumberSignatureOfKnowledge.o \ + obj/zerocoin/SpendMetaData.o \ + obj/zerocoin/ZeroTest.o + +all: arepacoind + +LIBS += $(CURDIR)/leveldb/libleveldb.a $(CURDIR)/leveldb/libmemenv.a +DEFS += $(addprefix -I,$(CURDIR)/leveldb/include) +DEFS += $(addprefix -I,$(CURDIR)/leveldb/helpers) +OBJS += obj/txdb-leveldb.o +leveldb/libleveldb.a: + @echo "Building LevelDB ..."; cd leveldb; make libleveldb.a libmemenv.a; cd ..; +obj/txdb-leveldb.o: leveldb/libleveldb.a + +# auto-generated dependencies: +-include obj/*.P + +obj/build.h: FORCE + /bin/sh ../share/genbuild.sh obj/build.h +version.cpp: obj/build.h +DEFS += -DHAVE_BUILD_INFO + +obj/scrypt-x86.o: scrypt-x86.S + $(CXX) -c $(xCXXFLAGS) -MMD -o $@ $< + +obj/scrypt-x86_64.o: scrypt-x86_64.S + $(CXX) -c $(xCXXFLAGS) -MMD -o $@ $< + +obj/scrypt-arm.o: scrypt-arm.S + $(CXX) -c $(xCXXFLAGS) -MMD -o $@ $< + +obj/%.o: %.cpp + $(CXX) -c $(xCXXFLAGS) -MMD -MF $(@:%.o=%.d) -o $@ $< + @cp $(@:%.o=%.d) $(@:%.o=%.P); \ + sed -e 's/#.*//' -e 's/^[^:]*: *//' -e 's/ *\\$$//' \ + -e '/^$$/ d' -e 's/$$/ :/' < $(@:%.o=%.d) >> $(@:%.o=%.P); \ + rm -f $(@:%.o=%.d) + +obj/zerocoin/%.o: zerocoin/%.cpp + $(CXX) -c $(xCXXFLAGS) -MMD -MF $(@:%.o=%.d) -o $@ $< + @cp $(@:%.o=%.d) $(@:%.o=%.P); \ + sed -e 's/#.*//' -e 's/^[^:]*: *//' -e 's/ *\\$$//' \ + -e '/^$$/ d' -e 's/$$/ :/' < $(@:%.o=%.d) >> $(@:%.o=%.P); \ + rm -f $(@:%.o=%.d) + +arepacoind: $(OBJS:obj/%=obj/%) + $(LINK) $(xCXXFLAGS) -o $@ $^ $(xLDFLAGS) $(LIBS) + +clean: + -rm -f arepacoind + -rm -f obj/*.o + -rm -f obj/zerocoin/*.o + -rm -f obj/*.P + -rm -f obj/zerocoin/*.P + -rm -f obj/build.h + +FORCE: diff --git a/src/miner.cpp b/src/miner.cpp new file mode 100644 index 0000000..a608833 --- /dev/null +++ b/src/miner.cpp @@ -0,0 +1,582 @@ +// Copyright (c) 2009-2010 Satoshi Nakamoto +// Copyright (c) 2009-2012 The Bitcoin developers +// Copyright (c) 2013 The NovaCoin developers +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include "txdb.h" +#include "miner.h" +#include "kernel.h" + +using namespace std; + +////////////////////////////////////////////////////////////////////////////// +// +// BitcoinMiner +// + +extern unsigned int nMinerSleep; + +int static FormatHashBlocks(void* pbuffer, unsigned int len) +{ + unsigned char* pdata = (unsigned char*)pbuffer; + unsigned int blocks = 1 + ((len + 8) / 64); + unsigned char* pend = pdata + 64 * blocks; + memset(pdata + len, 0, 64 * blocks - len); + pdata[len] = 0x80; + unsigned int bits = len * 8; + pend[-1] = (bits >> 0) & 0xff; + pend[-2] = (bits >> 8) & 0xff; + pend[-3] = (bits >> 16) & 0xff; + pend[-4] = (bits >> 24) & 0xff; + return blocks; +} + +static const unsigned int pSHA256InitState[8] = +{0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19}; + +void SHA256Transform(void* pstate, void* pinput, const void* pinit) +{ + SHA256_CTX ctx; + unsigned char data[64]; + + SHA256_Init(&ctx); + + for (int i = 0; i < 16; i++) + ((uint32_t*)data)[i] = ByteReverse(((uint32_t*)pinput)[i]); + + for (int i = 0; i < 8; i++) + ctx.h[i] = ((uint32_t*)pinit)[i]; + + SHA256_Update(&ctx, data, sizeof(data)); + for (int i = 0; i < 8; i++) + ((uint32_t*)pstate)[i] = ctx.h[i]; +} + +// Some explaining would be appreciated +class COrphan +{ +public: + CTransaction* ptx; + set setDependsOn; + double dPriority; + double dFeePerKb; + + COrphan(CTransaction* ptxIn) + { + ptx = ptxIn; + dPriority = dFeePerKb = 0; + } + + void print() const + { + printf("COrphan(hash=%s, dPriority=%.1f, dFeePerKb=%.1f)\n", + ptx->GetHash().ToString().substr(0,10).c_str(), dPriority, dFeePerKb); + BOOST_FOREACH(uint256 hash, setDependsOn) + printf(" setDependsOn %s\n", hash.ToString().substr(0,10).c_str()); + } +}; + + +uint64_t nLastBlockTx = 0; +uint64_t nLastBlockSize = 0; +int64_t nLastCoinStakeSearchInterval = 0; + +// We want to sort transactions by priority and fee, so: +typedef boost::tuple TxPriority; +class TxPriorityCompare +{ + bool byFee; +public: + TxPriorityCompare(bool _byFee) : byFee(_byFee) { } + bool operator()(const TxPriority& a, const TxPriority& b) + { + if (byFee) + { + if (a.get<1>() == b.get<1>()) + return a.get<0>() < b.get<0>(); + return a.get<1>() < b.get<1>(); + } + else + { + if (a.get<0>() == b.get<0>()) + return a.get<1>() < b.get<1>(); + return a.get<0>() < b.get<0>(); + } + } +}; + +// CreateNewBlock: create new block (without proof-of-work/proof-of-stake) +CBlock* CreateNewBlock(CWallet* pwallet, bool fProofOfStake, int64_t* pFees) +{ + // Create new block + auto_ptr pblock(new CBlock()); + if (!pblock.get()) + return NULL; + + CBlockIndex* pindexPrev = pindexBest; + + // Create coinbase tx + CTransaction txNew; + txNew.vin.resize(1); + txNew.vin[0].prevout.SetNull(); + txNew.vout.resize(1); + + if (!fProofOfStake) + { + CReserveKey reservekey(pwallet); + CPubKey pubkey; + if (!reservekey.GetReservedKey(pubkey)) + return NULL; + txNew.vout[0].scriptPubKey.SetDestination(pubkey.GetID()); + } + else + { + // Height first in coinbase required for block.version=2 + txNew.vin[0].scriptSig = (CScript() << pindexPrev->nHeight+1) + COINBASE_FLAGS; + assert(txNew.vin[0].scriptSig.size() <= 100); + + txNew.vout[0].SetEmpty(); + } + + // Add our coinbase tx as first transaction + pblock->vtx.push_back(txNew); + + // Largest block you're willing to create: + unsigned int nBlockMaxSize = GetArg("-blockmaxsize", MAX_BLOCK_SIZE_GEN/2); + // Limit to betweeen 1K and MAX_BLOCK_SIZE-1K for sanity: + nBlockMaxSize = std::max((unsigned int)1000, std::min((unsigned int)(MAX_BLOCK_SIZE-1000), nBlockMaxSize)); + + // How much of the block should be dedicated to high-priority transactions, + // included regardless of the fees they pay + unsigned int nBlockPrioritySize = GetArg("-blockprioritysize", 27000); + nBlockPrioritySize = std::min(nBlockMaxSize, nBlockPrioritySize); + + // Minimum block size you want to create; block will be filled with free transactions + // until there are no more or the block reaches this size: + unsigned int nBlockMinSize = GetArg("-blockminsize", 0); + nBlockMinSize = std::min(nBlockMaxSize, nBlockMinSize); + + // Fee-per-kilobyte amount considered the same as "free" + // Be careful setting this: if you set it to zero then + // a transaction spammer can cheaply fill blocks using + // 1-satoshi-fee transactions. It should be set above the real + // cost to you of processing a transaction. + int64_t nMinTxFee = MIN_TX_FEE; + if (mapArgs.count("-mintxfee")) + ParseMoney(mapArgs["-mintxfee"], nMinTxFee); + + pblock->nBits = GetNextTargetRequired(pindexPrev, fProofOfStake); + + // Collect memory pool transactions into the block + int64_t nFees = 0; + { + LOCK2(cs_main, mempool.cs); + CTxDB txdb("r"); + + // Priority order to process transactions + list vOrphan; // list memory doesn't move + map > mapDependers; + + // This vector will be sorted into a priority queue: + vector vecPriority; + vecPriority.reserve(mempool.mapTx.size()); + for (map::iterator mi = mempool.mapTx.begin(); mi != mempool.mapTx.end(); ++mi) + { + CTransaction& tx = (*mi).second; + if (tx.IsCoinBase() || tx.IsCoinStake() || !IsFinalTx(tx, pindexPrev->nHeight + 1)) + continue; + + COrphan* porphan = NULL; + double dPriority = 0; + int64_t nTotalIn = 0; + bool fMissingInputs = false; + BOOST_FOREACH(const CTxIn& txin, tx.vin) + { + // Read prev transaction + CTransaction txPrev; + CTxIndex txindex; + if (!txPrev.ReadFromDisk(txdb, txin.prevout, txindex)) + { + // This should never happen; all transactions in the memory + // pool should connect to either transactions in the chain + // or other transactions in the memory pool. + if (!mempool.mapTx.count(txin.prevout.hash)) + { + printf("ERROR: mempool transaction missing input\n"); + if (fDebug) assert("mempool transaction missing input" == 0); + fMissingInputs = true; + if (porphan) + vOrphan.pop_back(); + break; + } + + // Has to wait for dependencies + if (!porphan) + { + // Use list for automatic deletion + vOrphan.push_back(COrphan(&tx)); + porphan = &vOrphan.back(); + } + mapDependers[txin.prevout.hash].push_back(porphan); + porphan->setDependsOn.insert(txin.prevout.hash); + nTotalIn += mempool.mapTx[txin.prevout.hash].vout[txin.prevout.n].nValue; + continue; + } + int64_t nValueIn = txPrev.vout[txin.prevout.n].nValue; + nTotalIn += nValueIn; + + int nConf = txindex.GetDepthInMainChain(); + dPriority += (double)nValueIn * nConf; + } + if (fMissingInputs) continue; + + // Priority is sum(valuein * age) / txsize + unsigned int nTxSize = ::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION); + dPriority /= nTxSize; + + // This is a more accurate fee-per-kilobyte than is used by the client code, because the + // client code rounds up the size to the nearest 1K. That's good, because it gives an + // incentive to create smaller transactions. + double dFeePerKb = double(nTotalIn-tx.GetValueOut()) / (double(nTxSize)/1000.0); + + if (porphan) + { + porphan->dPriority = dPriority; + porphan->dFeePerKb = dFeePerKb; + } + else + vecPriority.push_back(TxPriority(dPriority, dFeePerKb, &(*mi).second)); + } + + // Collect transactions into block + map mapTestPool; + uint64_t nBlockSize = 1000; + uint64_t nBlockTx = 0; + int nBlockSigOps = 100; + bool fSortedByFee = (nBlockPrioritySize <= 0); + + TxPriorityCompare comparer(fSortedByFee); + std::make_heap(vecPriority.begin(), vecPriority.end(), comparer); + + while (!vecPriority.empty()) + { + // Take highest priority transaction off the priority queue: + double dPriority = vecPriority.front().get<0>(); + double dFeePerKb = vecPriority.front().get<1>(); + CTransaction& tx = *(vecPriority.front().get<2>()); + + std::pop_heap(vecPriority.begin(), vecPriority.end(), comparer); + vecPriority.pop_back(); + + // Size limits + unsigned int nTxSize = ::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION); + if (nBlockSize + nTxSize >= nBlockMaxSize) + continue; + + // Legacy limits on sigOps: + unsigned int nTxSigOps = tx.GetLegacySigOpCount(); + if (nBlockSigOps + nTxSigOps >= MAX_BLOCK_SIGOPS) + continue; + + // Timestamp limit + if (tx.nTime > GetAdjustedTime() || (fProofOfStake && tx.nTime > pblock->vtx[0].nTime)) + continue; + + // Transaction fee + int64_t nMinFee = tx.GetMinFee(nBlockSize, GMF_BLOCK); + + // Skip free transactions if we're past the minimum block size: + if (fSortedByFee && (dFeePerKb < nMinTxFee) && (nBlockSize + nTxSize >= nBlockMinSize)) + continue; + + // Prioritize by fee once past the priority size or we run out of high-priority + // transactions: + if (!fSortedByFee && + ((nBlockSize + nTxSize >= nBlockPrioritySize) || (dPriority < COIN * 144 / 250))) + { + fSortedByFee = true; + comparer = TxPriorityCompare(fSortedByFee); + std::make_heap(vecPriority.begin(), vecPriority.end(), comparer); + } + + // Connecting shouldn't fail due to dependency on other memory pool transactions + // because we're already processing them in order of dependency + map mapTestPoolTmp(mapTestPool); + MapPrevTx mapInputs; + bool fInvalid; + if (!tx.FetchInputs(txdb, mapTestPoolTmp, false, true, mapInputs, fInvalid)) + continue; + + int64_t nTxFees = tx.GetValueIn(mapInputs)-tx.GetValueOut(); + if (nTxFees < nMinFee) + continue; + + nTxSigOps += tx.GetP2SHSigOpCount(mapInputs); + if (nBlockSigOps + nTxSigOps >= MAX_BLOCK_SIGOPS) + continue; + + if (!tx.ConnectInputs(txdb, mapInputs, mapTestPoolTmp, CDiskTxPos(1,1,1), pindexPrev, false, true)) + continue; + mapTestPoolTmp[tx.GetHash()] = CTxIndex(CDiskTxPos(1,1,1), tx.vout.size()); + swap(mapTestPool, mapTestPoolTmp); + + // Added + pblock->vtx.push_back(tx); + nBlockSize += nTxSize; + ++nBlockTx; + nBlockSigOps += nTxSigOps; + nFees += nTxFees; + + if (fDebug && GetBoolArg("-printpriority")) + { + printf("priority %.1f feeperkb %.1f txid %s\n", + dPriority, dFeePerKb, tx.GetHash().ToString().c_str()); + } + + // Add transactions that depend on this one to the priority queue + uint256 hash = tx.GetHash(); + if (mapDependers.count(hash)) + { + BOOST_FOREACH(COrphan* porphan, mapDependers[hash]) + { + if (!porphan->setDependsOn.empty()) + { + porphan->setDependsOn.erase(hash); + if (porphan->setDependsOn.empty()) + { + vecPriority.push_back(TxPriority(porphan->dPriority, porphan->dFeePerKb, porphan->ptx)); + std::push_heap(vecPriority.begin(), vecPriority.end(), comparer); + } + } + } + } + } + + nLastBlockTx = nBlockTx; + nLastBlockSize = nBlockSize; + + if (fDebug && GetBoolArg("-printpriority")) + printf("CreateNewBlock(): total size %" PRIu64"\n", nBlockSize); + + if (!fProofOfStake) + pblock->vtx[0].vout[0].nValue = GetProofOfWorkReward(nFees); + + if (pFees) + *pFees = nFees; + + // Fill in header + pblock->hashPrevBlock = pindexPrev->GetBlockHash(); + pblock->nTime = max(pindexPrev->GetPastTimeLimit()+1, pblock->GetMaxTransactionTime()); + pblock->nTime = max(pblock->GetBlockTime(), PastDrift(pindexPrev->GetBlockTime())); + if (!fProofOfStake) + pblock->UpdateTime(pindexPrev); + pblock->nNonce = 0; + } + + return pblock.release(); +} + + +void IncrementExtraNonce(CBlock* pblock, CBlockIndex* pindexPrev, unsigned int& nExtraNonce) +{ + // Update nExtraNonce + static uint256 hashPrevBlock; + if (hashPrevBlock != pblock->hashPrevBlock) + { + nExtraNonce = 0; + hashPrevBlock = pblock->hashPrevBlock; + } + ++nExtraNonce; + + unsigned int nHeight = pindexPrev->nHeight+1; // Height first in coinbase required for block.version=2 + pblock->vtx[0].vin[0].scriptSig = (CScript() << nHeight << CBigNum(nExtraNonce)) + COINBASE_FLAGS; + assert(pblock->vtx[0].vin[0].scriptSig.size() <= 100); + + pblock->hashMerkleRoot = pblock->BuildMerkleTree(); +} + + +void FormatHashBuffers(CBlock* pblock, char* pmidstate, char* pdata, char* phash1) +{ + // + // Pre-build hash buffers + // + struct + { + struct unnamed2 + { + int nVersion; + uint256 hashPrevBlock; + uint256 hashMerkleRoot; + unsigned int nTime; + unsigned int nBits; + unsigned int nNonce; + } + block; + unsigned char pchPadding0[64]; + uint256 hash1; + unsigned char pchPadding1[64]; + } + tmp; + memset(&tmp, 0, sizeof(tmp)); + + tmp.block.nVersion = pblock->nVersion; + tmp.block.hashPrevBlock = pblock->hashPrevBlock; + tmp.block.hashMerkleRoot = pblock->hashMerkleRoot; + tmp.block.nTime = pblock->nTime; + tmp.block.nBits = pblock->nBits; + tmp.block.nNonce = pblock->nNonce; + + FormatHashBlocks(&tmp.block, sizeof(tmp.block)); + FormatHashBlocks(&tmp.hash1, sizeof(tmp.hash1)); + + // Byte swap all the input buffer + for (unsigned int i = 0; i < sizeof(tmp)/4; i++) + ((unsigned int*)&tmp)[i] = ByteReverse(((unsigned int*)&tmp)[i]); + + // Precalc the first half of the first hash, which stays constant + SHA256Transform(pmidstate, &tmp.block, pSHA256InitState); + + memcpy(pdata, &tmp.block, 128); + memcpy(phash1, &tmp.hash1, 64); +} + + +bool CheckWork(CBlock* pblock, CWallet& wallet, CReserveKey& reservekey) +{ + uint256 hashBlock = pblock->GetHash(); + uint256 hashTarget = CBigNum().SetCompact(pblock->nBits).getuint256(); + + if(!pblock->IsProofOfWork()) + return error("CheckWork() : %s is not a proof-of-work block", hashBlock.GetHex().c_str()); + + if (hashBlock > hashTarget) + return error("CheckWork() : proof-of-work not meeting target"); + + //// debug print + printf("CheckWork() : new proof-of-work block found \n hash: %s \ntarget: %s\n", hashBlock.GetHex().c_str(), hashTarget.GetHex().c_str()); + pblock->print(); + printf("generated %s\n", FormatMoney(pblock->vtx[0].vout[0].nValue).c_str()); + + // Found a solution + { + LOCK(cs_main); + if (pblock->hashPrevBlock != hashBestChain) + return error("CheckWork() : generated block is stale"); + + // Remove key from key pool + reservekey.KeepKey(); + + // Track how many getdata requests this block gets + { + LOCK(wallet.cs_wallet); + wallet.mapRequestCount[hashBlock] = 0; + } + + // Process this block the same as if we had received it from another node + if (!ProcessBlock(NULL, pblock)) + return error("CheckWork() : ProcessBlock, block not accepted"); + } + + return true; +} + +bool CheckStake(CBlock* pblock, CWallet& wallet) +{ + uint256 proofHash = 0, hashTarget = 0; + uint256 hashBlock = pblock->GetHash(); + + if(!pblock->IsProofOfStake()) + return error("CheckStake() : %s is not a proof-of-stake block", hashBlock.GetHex().c_str()); + + // verify hash target and signature of coinstake tx + if (!CheckProofOfStake(pblock->vtx[1], pblock->nBits, proofHash, hashTarget)) + return error("CheckStake() : proof-of-stake checking failed"); + + //// debug print + printf("CheckStake() : new proof-of-stake block found \n hash: %s \nproofhash: %s \ntarget: %s\n", hashBlock.GetHex().c_str(), proofHash.GetHex().c_str(), hashTarget.GetHex().c_str()); + pblock->print(); + printf("out %s\n", FormatMoney(pblock->vtx[1].GetValueOut()).c_str()); + + // Found a solution + { + LOCK(cs_main); + if (pblock->hashPrevBlock != hashBestChain) + return error("CheckStake() : generated block is stale"); + + // Track how many getdata requests this block gets + { + LOCK(wallet.cs_wallet); + wallet.mapRequestCount[hashBlock] = 0; + } + + // Process this block the same as if we had received it from another node + if (!ProcessBlock(NULL, pblock)) + return error("CheckStake() : ProcessBlock, block not accepted"); + } + + return true; +} + +void StakeMiner(CWallet *pwallet) +{ + SetThreadPriority(THREAD_PRIORITY_LOWEST); + + // Make this thread recognisable as the mining thread + RenameThread("arepacoin-miner"); + + bool fTryToSync = true; + + while (true) + { + if (fShutdown) + return; + + while (pwallet->IsLocked()) + { + nLastCoinStakeSearchInterval = 0; + MilliSleep(1000); + if (fShutdown) + return; + } + + while (vNodes.empty() || IsInitialBlockDownload()) + { + nLastCoinStakeSearchInterval = 0; + fTryToSync = true; + MilliSleep(1000); + if (fShutdown) + return; + } + + if (fTryToSync) + { + fTryToSync = false; + if (vNodes.size() < 3 || nBestHeight < GetNumBlocksOfPeers()) + { + MilliSleep(60000); + continue; + } + } + + // + // Create new block + // + int64_t nFees; + auto_ptr pblock(CreateNewBlock(pwallet, true, &nFees)); + if (!pblock.get()) + return; + + // Trying to sign a block + if (pblock->SignBlock(*pwallet, nFees)) + { + SetThreadPriority(THREAD_PRIORITY_NORMAL); + CheckStake(pblock.get(), *pwallet); + SetThreadPriority(THREAD_PRIORITY_LOWEST); + MilliSleep(500); + } + else + MilliSleep(nMinerSleep); + } +} diff --git a/src/miner.h b/src/miner.h new file mode 100644 index 0000000..597e08a --- /dev/null +++ b/src/miner.h @@ -0,0 +1,30 @@ +// Copyright (c) 2009-2010 Satoshi Nakamoto +// Copyright (c) 2009-2012 The Bitcoin developers +// Copyright (c) 2013 The NovaCoin developers +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. +#ifndef NOVACOIN_MINER_H +#define NOVACOIN_MINER_H + +#include "main.h" +#include "wallet.h" + +/* Generate a new block, without valid proof-of-work */ +CBlock* CreateNewBlock(CWallet* pwallet, bool fProofOfStake=false, int64_t* pFees = 0); + +/** Modify the extranonce in a block */ +void IncrementExtraNonce(CBlock* pblock, CBlockIndex* pindexPrev, unsigned int& nExtraNonce); + +/** Do mining precalculation */ +void FormatHashBuffers(CBlock* pblock, char* pmidstate, char* pdata, char* phash1); + +/** Check mined proof-of-work block */ +bool CheckWork(CBlock* pblock, CWallet& wallet, CReserveKey& reservekey); + +/** Check mined proof-of-stake block */ +bool CheckStake(CBlock* pblock, CWallet& wallet); + +/** Base sha256 mining transform */ +void SHA256Transform(void* pstate, void* pinput, const void* pinit); + +#endif // NOVACOIN_MINER_H diff --git a/src/mruset.h b/src/mruset.h new file mode 100644 index 0000000..3b8c30a --- /dev/null +++ b/src/mruset.h @@ -0,0 +1,65 @@ +// Copyright (c) 2012 The Bitcoin developers +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. +#ifndef BITCOIN_MRUSET_H +#define BITCOIN_MRUSET_H + +#include +#include + +/** STL-like set container that only keeps the most recent N elements. */ +template class mruset +{ +public: + typedef T key_type; + typedef T value_type; + typedef typename std::set::iterator iterator; + typedef typename std::set::const_iterator const_iterator; + typedef typename std::set::size_type size_type; + +protected: + std::set set; + std::deque queue; + size_type nMaxSize; + +public: + mruset(size_type nMaxSizeIn = 0) { nMaxSize = nMaxSizeIn; } + iterator begin() const { return set.begin(); } + iterator end() const { return set.end(); } + size_type size() const { return set.size(); } + bool empty() const { return set.empty(); } + iterator find(const key_type& k) const { return set.find(k); } + size_type count(const key_type& k) const { return set.count(k); } + void clear() { set.clear(); queue.clear(); } + bool inline friend operator==(const mruset& a, const mruset& b) { return a.set == b.set; } + bool inline friend operator==(const mruset& a, const std::set& b) { return a.set == b; } + bool inline friend operator<(const mruset& a, const mruset& b) { return a.set < b.set; } + std::pair insert(const key_type& x) + { + std::pair ret = set.insert(x); + if (ret.second) + { + if (nMaxSize && queue.size() == nMaxSize) + { + set.erase(queue.front()); + queue.pop_front(); + } + queue.push_back(x); + } + return ret; + } + size_type max_size() const { return nMaxSize; } + size_type max_size(size_type s) + { + if (s) + while (queue.size() > s) + { + set.erase(queue.front()); + queue.pop_front(); + } + nMaxSize = s; + return nMaxSize; + } +}; + +#endif diff --git a/src/net.cpp b/src/net.cpp new file mode 100644 index 0000000..60b2721 --- /dev/null +++ b/src/net.cpp @@ -0,0 +1,2105 @@ +// Copyright (c) 2009-2010 Satoshi Nakamoto +// Copyright (c) 2009-2012 The Bitcoin developers +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include "db.h" +#include "net.h" +#include "init.h" +#include "strlcpy.h" +#include "addrman.h" +#include "ui_interface.h" + +#ifdef WIN32 +#include +#endif + +#ifdef USE_UPNP +#include +#include +#include +#include +#endif + +using namespace std; +using namespace boost; + +static const int MAX_OUTBOUND_CONNECTIONS = 16; + +void ThreadMessageHandler2(void* parg); +void ThreadSocketHandler2(void* parg); +void ThreadOpenConnections2(void* parg); +void ThreadOpenAddedConnections2(void* parg); +#ifdef USE_UPNP +void ThreadMapPort2(void* parg); +#endif +void ThreadDNSAddressSeed2(void* parg); +bool OpenNetworkConnection(const CAddress& addrConnect, CSemaphoreGrant *grantOutbound = NULL, const char *strDest = NULL, bool fOneShot = false); + + +struct LocalServiceInfo { + int nScore; + int nPort; +}; + +// +// Global state variables +// +bool fDiscover = true; +bool fUseUPnP = false; +uint64_t nLocalServices = NODE_NETWORK; +static CCriticalSection cs_mapLocalHost; +static map mapLocalHost; +static bool vfReachable[NET_MAX] = {}; +static bool vfLimited[NET_MAX] = {}; +static CNode* pnodeLocalHost = NULL; +CAddress addrSeenByPeerIp(CService("0.0.0.0", 0), nLocalServices); +CAddress addrSeenByPeerIpv4(CService("0.0.0.0", 0), nLocalServices); +CAddress addrSeenByPeerIpv6(CService("0.0.0.0", 0), nLocalServices); +uint64_t nLocalHostNonce = 0; +boost::array vnThreadsRunning; +static std::vector vhListenSocket; +CAddrMan addrman; + +vector vNodes; +CCriticalSection cs_vNodes; +map mapRelay; +deque > vRelayExpiration; +CCriticalSection cs_mapRelay; +map mapAlreadyAskedFor; + +static deque vOneShots; +CCriticalSection cs_vOneShots; + +set setservAddNodeAddresses; +CCriticalSection cs_setservAddNodeAddresses; + +vector vAddedNodes; +CCriticalSection cs_vAddedNodes; + +static CSemaphore *semOutbound = NULL; + +void AddOneShot(string strDest) +{ + LOCK(cs_vOneShots); + vOneShots.push_back(strDest); +} + +unsigned short GetListenPort() +{ + return (unsigned short)(GetArg("-port", GetDefaultPort())); +} + +void CNode::PushGetBlocks(CBlockIndex* pindexBegin, uint256 hashEnd) +{ + // Filter out duplicate requests + if (pindexBegin == pindexLastGetBlocksBegin && hashEnd == hashLastGetBlocksEnd) + return; + pindexLastGetBlocksBegin = pindexBegin; + hashLastGetBlocksEnd = hashEnd; + + PushMessage("getblocks", CBlockLocator(pindexBegin), hashEnd); +} + +// find 'best' local address for a particular peer +bool GetLocal(CService& addr, const CNetAddr *paddrPeer) +{ + if (fNoListen) + return false; + + int nBestScore = -1; + int nBestReachability = -1; + { + LOCK(cs_mapLocalHost); + for (map::iterator it = mapLocalHost.begin(); it != mapLocalHost.end(); it++) + { + int nScore = (*it).second.nScore; + int nReachability = (*it).first.GetReachabilityFrom(paddrPeer); + if (nReachability > nBestReachability || (nReachability == nBestReachability && nScore > nBestScore)) + { + addr = CService((*it).first, (*it).second.nPort); + nBestReachability = nReachability; + nBestScore = nScore; + } + } + } + return nBestScore >= 0; +} + +// get best local address for a particular peer as a CAddress +CAddress GetLocalAddress(const CNetAddr *paddrPeer) +{ + CAddress ret(CService("0.0.0.0",0),0); + CService addr; + if (GetLocal(addr, paddrPeer)) + { + ret = CAddress(addr); + ret.nServices = nLocalServices; + ret.nTime = GetAdjustedTime(); + } + return ret; +} + +bool RecvLine(SOCKET hSocket, string& strLine) +{ + strLine = ""; + while (true) + { + char c; + int nBytes = recv(hSocket, &c, 1, 0); + if (nBytes > 0) + { + if (c == '\n') + continue; + if (c == '\r') + return true; + strLine += c; + if (strLine.size() >= 9000) + return true; + } + else if (nBytes <= 0) + { + if (fShutdown) + return false; + if (nBytes < 0) + { + int nErr = WSAGetLastError(); + if (nErr == WSAEMSGSIZE) + continue; + if (nErr == WSAEWOULDBLOCK || nErr == WSAEINTR || nErr == WSAEINPROGRESS) + { + MilliSleep(10); + continue; + } + } + if (!strLine.empty()) + return true; + if (nBytes == 0) + { + // socket closed + printf("socket closed\n"); + return false; + } + else + { + // socket error + int nErr = WSAGetLastError(); + printf("recv failed: %d\n", nErr); + return false; + } + } + } +} + +// used when scores of local addresses may have changed +// pushes better local address to peers +void static AdvertizeLocal() +{ + LOCK(cs_vNodes); + BOOST_FOREACH(CNode* pnode, vNodes) + { + if (pnode->fSuccessfullyConnected) + { + CAddress addrLocal = GetLocalAddress(&pnode->addr); + if (addrLocal.IsRoutable() && (CService)addrLocal != (CService)pnode->addrLocal) + { + pnode->PushAddress(addrLocal); + pnode->addrLocal = addrLocal; + } + } + } +} + +void SetReachable(enum Network net, bool fFlag) +{ + LOCK(cs_mapLocalHost); + vfReachable[net] = fFlag; + if (net == NET_IPV6 && fFlag) + vfReachable[NET_IPV4] = true; +} + +// learn a new local address +bool AddLocal(const CService& addr, int nScore) +{ + if (!addr.IsRoutable()) + return false; + + if (!fDiscover && nScore < LOCAL_MANUAL) + return false; + + if (IsLimited(addr)) + return false; + + printf("AddLocal(%s,%i)\n", addr.ToString().c_str(), nScore); + + { + LOCK(cs_mapLocalHost); + bool fAlready = mapLocalHost.count(addr) > 0; + LocalServiceInfo &info = mapLocalHost[addr]; + if (!fAlready || nScore >= info.nScore) { + info.nScore = nScore + (fAlready ? 1 : 0); + info.nPort = addr.GetPort(); + } + SetReachable(addr.GetNetwork()); + } + + AdvertizeLocal(); + + return true; +} + +bool AddLocal(const CNetAddr &addr, int nScore) +{ + return AddLocal(CService(addr, GetListenPort()), nScore); +} + +/** Make a particular network entirely off-limits (no automatic connects to it) */ +void SetLimited(enum Network net, bool fLimited) +{ + if (net == NET_UNROUTABLE) + return; + LOCK(cs_mapLocalHost); + vfLimited[net] = fLimited; +} + +bool IsLimited(enum Network net) +{ + LOCK(cs_mapLocalHost); + return vfLimited[net]; +} + +bool IsLimited(const CNetAddr &addr) +{ + return IsLimited(addr.GetNetwork()); +} + +/** vote for a local address */ +bool SeenLocal(const CService& addr) +{ + { + LOCK(cs_mapLocalHost); + if (mapLocalHost.count(addr) == 0) + return false; + mapLocalHost[addr].nScore++; + } + + AdvertizeLocal(); + + return true; +} + +/** check whether a given address is potentially local */ +bool IsLocal(const CService& addr) +{ + LOCK(cs_mapLocalHost); + return mapLocalHost.count(addr) > 0; +} + +/** check whether a given address is in a network we can probably connect to */ +bool IsReachable(const CNetAddr& addr) +{ + LOCK(cs_mapLocalHost); + enum Network net = addr.GetNetwork(); + return vfReachable[net] && !vfLimited[net]; +} + +bool GetMyExternalIP2(const CService& addrConnect, const char* pszGet, const char* pszKeyword, CNetAddr& ipRet) +{ + SOCKET hSocket; + if (!ConnectSocket(addrConnect, hSocket)) + return error("GetMyExternalIP() : connection to %s failed", addrConnect.ToString().c_str()); + + send(hSocket, pszGet, strlen(pszGet), MSG_NOSIGNAL); + + string strLine; + while (RecvLine(hSocket, strLine)) + { + if (strLine.empty()) // HTTP response is separated from headers by blank line + { + while (true) + { + if (!RecvLine(hSocket, strLine)) + { + closesocket(hSocket); + return false; + } + if (pszKeyword == NULL) + break; + if (strLine.find(pszKeyword) != string::npos) + { + strLine = strLine.substr(strLine.find(pszKeyword) + strlen(pszKeyword)); + break; + } + } + closesocket(hSocket); + if (strLine.find("<") != string::npos) + strLine = strLine.substr(0, strLine.find("<")); + strLine = strLine.substr(strspn(strLine.c_str(), " \t\n\r")); + while (strLine.size() > 0 && isspace(strLine[strLine.size()-1])) + strLine.resize(strLine.size()-1); + CService addr(strLine,0,true); + printf("GetMyExternalIP() received [%s] %s\n", strLine.c_str(), addr.ToString().c_str()); + if (!addr.IsValid() || !addr.IsRoutable()) + return false; + ipRet.SetIP(addr); + return true; + } + } + closesocket(hSocket); + return error("GetMyExternalIP() : connection closed"); +} + +bool GetMyExternalIP(CNetAddr& ipRet) +{ + CService addrConnect; + const char* pszGet; + const char* pszKeyword; + + for (int nLookup = 0; nLookup <= 1; nLookup++) + for (int nHost = 1; nHost <= 2; nHost++) + { + // We should be phasing out our use of sites like these. If we need + // replacements, we should ask for volunteers to put this simple + // php file on their web server that prints the client IP: + // + if (nHost == 1) + { + addrConnect = CService("216.146.43.70",80); // checkip.dyndns.org + + if (nLookup == 1) + { + CService addrIP("checkip.dyndns.org", 80, true); + if (addrIP.IsValid()) + addrConnect = addrIP; + } + + pszGet = "GET / HTTP/1.1\r\n" + "Host: checkip.dyndns.org\r\n" + "User-Agent: arepacoin\r\n" + "Connection: close\r\n" + "\r\n"; + + pszKeyword = "Address:"; + } + else if (nHost == 2) + { + addrConnect = CService("74.208.43.192", 80); // www.showmyip.com + + if (nLookup == 1) + { + CService addrIP("www.showmyip.com", 80, true); + if (addrIP.IsValid()) + addrConnect = addrIP; + } + + pszGet = "GET /simple/ HTTP/1.1\r\n" + "Host: www.showmyip.com\r\n" + "User-Agent: arepacoin\r\n" + "Connection: close\r\n" + "\r\n"; + + pszKeyword = NULL; // Returns just IP address + } + + if (GetMyExternalIP2(addrConnect, pszGet, pszKeyword, ipRet)) + return true; + } + + return false; +} + +void ThreadGetMyExternalIP(void* parg) +{ + // Make this thread recognisable as the external IP detection thread + RenameThread("arepacoin-ext-ip"); + + CNetAddr addrLocalHost; + if (GetMyExternalIP(addrLocalHost)) + { + printf("GetMyExternalIP() returned %s\n", addrLocalHost.ToStringIP().c_str()); + AddLocal(addrLocalHost, LOCAL_HTTP); + } +} + + + + + +void AddressCurrentlyConnected(const CService& addr) +{ + addrman.Connected(addr); +} + +uint64_t CNode::nTotalBytesRecv = 0; +uint64_t CNode::nTotalBytesSent = 0; +CCriticalSection CNode::cs_totalBytesRecv; +CCriticalSection CNode::cs_totalBytesSent; + +CNode* FindNode(const CNetAddr& ip) +{ + { + LOCK(cs_vNodes); + BOOST_FOREACH(CNode* pnode, vNodes) + if ((CNetAddr)pnode->addr == ip) + return (pnode); + } + return NULL; +} + +CNode* FindNode(std::string addrName) +{ + LOCK(cs_vNodes); + BOOST_FOREACH(CNode* pnode, vNodes) + if (pnode->addrName == addrName) + return (pnode); + return NULL; +} + +CNode* FindNode(const CService& addr) +{ + { + LOCK(cs_vNodes); + BOOST_FOREACH(CNode* pnode, vNodes) + if ((CService)pnode->addr == addr) + return (pnode); + } + return NULL; +} + +CNode* ConnectNode(CAddress addrConnect, const char *pszDest) +{ + if (pszDest == NULL) { + if (IsLocal(addrConnect)) + return NULL; + + // Look for an existing connection + CNode* pnode = FindNode((CService)addrConnect); + if (pnode) + { + pnode->AddRef(); + return pnode; + } + } + + + /// debug print + printf("trying connection %s lastseen=%.1fhrs\n", + pszDest ? pszDest : addrConnect.ToString().c_str(), + pszDest ? 0 : (double)(GetAdjustedTime() - addrConnect.nTime)/3600.0); + + // Connect + SOCKET hSocket; + if (pszDest ? ConnectSocketByName(addrConnect, hSocket, pszDest, GetDefaultPort()) : ConnectSocket(addrConnect, hSocket)) + { + addrman.Attempt(addrConnect); + + /// debug print + printf("connected %s\n", pszDest ? pszDest : addrConnect.ToString().c_str()); + + // Set to non-blocking +#ifdef WIN32 + u_long nOne = 1; + if (ioctlsocket(hSocket, FIONBIO, &nOne) == SOCKET_ERROR) + printf("ConnectSocket() : ioctlsocket non-blocking setting failed, error %d\n", WSAGetLastError()); +#else + if (fcntl(hSocket, F_SETFL, O_NONBLOCK) == SOCKET_ERROR) + printf("ConnectSocket() : fcntl non-blocking setting failed, error %d\n", errno); +#endif + + // Add node + CNode* pnode = new CNode(hSocket, addrConnect, pszDest ? pszDest : "", false); + pnode->AddRef(); + + { + LOCK(cs_vNodes); + vNodes.push_back(pnode); + } + + pnode->nTimeConnected = GetTime(); + return pnode; + } + else + { + return NULL; + } +} + +void CNode::CloseSocketDisconnect() +{ + fDisconnect = true; + if (hSocket != INVALID_SOCKET) + { + printf("disconnecting node %s\n", addrName.c_str()); + closesocket(hSocket); + hSocket = INVALID_SOCKET; + + // in case this fails, we'll empty the recv buffer when the CNode is deleted + TRY_LOCK(cs_vRecvMsg, lockRecv); + if (lockRecv) + vRecvMsg.clear(); + } +} + +void CNode::PushVersion() +{ + /// when NTP implemented, change to just nTime = GetAdjustedTime() + int64_t nTime = (fInbound ? GetAdjustedTime() : GetTime()); + CAddress addrYou = (addr.IsRoutable() && !IsProxy(addr) ? addr : CAddress(CService("0.0.0.0",0))); + CAddress addrMe = GetLocalAddress(&addr); + RAND_bytes((unsigned char*)&nLocalHostNonce, sizeof(nLocalHostNonce)); + printf("send version message: version %d, blocks=%d, us=%s, them=%s, peer=%s\n", PROTOCOL_VERSION, nBestHeight, addrMe.ToString().c_str(), addrYou.ToString().c_str(), addr.ToString().c_str()); + PushMessage("version", PROTOCOL_VERSION, nLocalServices, nTime, addrYou, addrMe, + nLocalHostNonce, FormatSubVersion(CLIENT_NAME, CLIENT_VERSION, std::vector()), nBestHeight); +} + + + + + +std::map CNode::setBanned; +CCriticalSection CNode::cs_setBanned; + +void CNode::ClearBanned() +{ + setBanned.clear(); +} + +bool CNode::IsBanned(CNetAddr ip) +{ + bool fResult = false; + { + LOCK(cs_setBanned); + std::map::iterator i = setBanned.find(ip); + if (i != setBanned.end()) + { + int64_t t = (*i).second; + if (GetTime() < t) + fResult = true; + } + } + return fResult; +} + +bool CNode::Misbehaving(int howmuch) +{ + if (addr.IsLocal()) + { + printf("Warning: Local node %s misbehaving (delta: %d)!\n", addrName.c_str(), howmuch); + return false; + } + + nMisbehavior += howmuch; + if (nMisbehavior >= GetArg("-banscore", 100)) + { + int64_t banTime = GetTime()+GetArg("-bantime", 60*60*24); // Default 24-hour ban + printf("Misbehaving: %s (%d -> %d) DISCONNECTING\n", addr.ToString().c_str(), nMisbehavior-howmuch, nMisbehavior); + { + LOCK(cs_setBanned); + if (setBanned[addr] < banTime) + setBanned[addr] = banTime; + } + CloseSocketDisconnect(); + return true; + } else + printf("Misbehaving: %s (%d -> %d)\n", addr.ToString().c_str(), nMisbehavior-howmuch, nMisbehavior); + return false; +} + +#undef X +#define X(name) stats.name = name +void CNode::copyStats(CNodeStats &stats) +{ + X(nServices); + X(nLastSend); + X(nLastRecv); + X(nTimeConnected); + X(addrName); + X(nVersion); + X(strSubVer); + X(fInbound); + X(nStartingHeight); + X(nMisbehavior); +} +#undef X + +// requires LOCK(cs_vRecvMsg) +bool CNode::ReceiveMsgBytes(const char *pch, unsigned int nBytes) +{ + while (nBytes > 0) { + + // get current incomplete message, or create a new one + if (vRecvMsg.empty() || + vRecvMsg.back().complete()) + vRecvMsg.push_back(CNetMessage(SER_NETWORK, nRecvVersion)); + + CNetMessage& msg = vRecvMsg.back(); + + // absorb network data + int handled; + if (!msg.in_data) + handled = msg.readHeader(pch, nBytes); + else + handled = msg.readData(pch, nBytes); + + if (handled < 0) + return false; + + pch += handled; + nBytes -= handled; + } + + return true; +} + +int CNetMessage::readHeader(const char *pch, unsigned int nBytes) +{ + // copy data to temporary parsing buffer + unsigned int nRemaining = 24 - nHdrPos; + unsigned int nCopy = std::min(nRemaining, nBytes); + + memcpy(&hdrbuf[nHdrPos], pch, nCopy); + nHdrPos += nCopy; + + // if header incomplete, exit + if (nHdrPos < 24) + return nCopy; + + // deserialize to CMessageHeader + try { + hdrbuf >> hdr; + } + catch (std::exception &e) { + return -1; + } + + // reject messages larger than MAX_SIZE + if (hdr.nMessageSize > MAX_SIZE) + return -1; + + // switch state to reading message data + in_data = true; + + return nCopy; +} + +int CNetMessage::readData(const char *pch, unsigned int nBytes) +{ + unsigned int nRemaining = hdr.nMessageSize - nDataPos; + unsigned int nCopy = std::min(nRemaining, nBytes); + + if (vRecv.size() < nDataPos + nCopy) { + // Allocate up to 256 KiB ahead, but never more than the total message size. + vRecv.resize(std::min(hdr.nMessageSize, nDataPos + nCopy + 256 * 1024)); + } + + memcpy(&vRecv[nDataPos], pch, nCopy); + nDataPos += nCopy; + + return nCopy; +} + + + + + + + + + +// requires LOCK(cs_vSend) +void SocketSendData(CNode *pnode) +{ + std::deque::iterator it = pnode->vSendMsg.begin(); + + while (it != pnode->vSendMsg.end()) { + const CSerializeData &data = *it; + assert(data.size() > pnode->nSendOffset); + int nBytes = send(pnode->hSocket, &data[pnode->nSendOffset], data.size() - pnode->nSendOffset, MSG_NOSIGNAL | MSG_DONTWAIT); + if (nBytes > 0) { + pnode->nLastSend = GetTime(); + pnode->nSendOffset += nBytes; + pnode->RecordBytesSent(nBytes); + if (pnode->nSendOffset == data.size()) { + pnode->nSendOffset = 0; + pnode->nSendSize -= data.size(); + it++; + } else { + // could not send full message; stop sending more + break; + } + } else { + if (nBytes < 0) { + // error + int nErr = WSAGetLastError(); + if (nErr != WSAEWOULDBLOCK && nErr != WSAEMSGSIZE && nErr != WSAEINTR && nErr != WSAEINPROGRESS) + { + printf("socket send error %d\n", nErr); + pnode->CloseSocketDisconnect(); + } + } + // couldn't send anything at all + break; + } + } + + if (it == pnode->vSendMsg.end()) { + assert(pnode->nSendOffset == 0); + assert(pnode->nSendSize == 0); + } + pnode->vSendMsg.erase(pnode->vSendMsg.begin(), it); +} + +void ThreadSocketHandler(void* parg) +{ + // Make this thread recognisable as the networking thread + RenameThread("arepacoin-net"); + + try + { + vnThreadsRunning[THREAD_SOCKETHANDLER]++; + ThreadSocketHandler2(parg); + vnThreadsRunning[THREAD_SOCKETHANDLER]--; + } + catch (std::exception& e) { + vnThreadsRunning[THREAD_SOCKETHANDLER]--; + PrintException(&e, "ThreadSocketHandler()"); + } catch (...) { + vnThreadsRunning[THREAD_SOCKETHANDLER]--; + throw; // support pthread_cancel() + } + printf("ThreadSocketHandler exited\n"); +} + +void ThreadSocketHandler2(void* parg) +{ + printf("ThreadSocketHandler started\n"); + list vNodesDisconnected; + unsigned int nPrevNodeCount = 0; + + while (true) + { + // + // Disconnect nodes + // + { + LOCK(cs_vNodes); + // Disconnect unused nodes + vector vNodesCopy = vNodes; + BOOST_FOREACH(CNode* pnode, vNodesCopy) + { + if (pnode->fDisconnect || + (pnode->GetRefCount() <= 0 && pnode->vRecvMsg.empty() && pnode->nSendSize == 0 && pnode->ssSend.empty())) + { + // remove from vNodes + vNodes.erase(remove(vNodes.begin(), vNodes.end(), pnode), vNodes.end()); + + // release outbound grant (if any) + pnode->grantOutbound.Release(); + + // close socket and cleanup + pnode->CloseSocketDisconnect(); + + // hold in disconnected pool until all refs are released + if (pnode->fNetworkNode || pnode->fInbound) + pnode->Release(); + vNodesDisconnected.push_back(pnode); + } + } + + // Delete disconnected nodes + list vNodesDisconnectedCopy = vNodesDisconnected; + BOOST_FOREACH(CNode* pnode, vNodesDisconnectedCopy) + { + // wait until threads are done using it + if (pnode->GetRefCount() <= 0) + { + bool fDelete = false; + { + TRY_LOCK(pnode->cs_vSend, lockSend); + if (lockSend) + { + TRY_LOCK(pnode->cs_vRecvMsg, lockRecv); + if (lockRecv) + { + TRY_LOCK(pnode->cs_mapRequests, lockReq); + if (lockReq) + { + TRY_LOCK(pnode->cs_inventory, lockInv); + if (lockInv) + fDelete = true; + } + } + } + } + if (fDelete) + { + vNodesDisconnected.remove(pnode); + delete pnode; + } + } + } + } + if (vNodes.size() != nPrevNodeCount) + { + nPrevNodeCount = vNodes.size(); + uiInterface.NotifyNumConnectionsChanged(nPrevNodeCount); + } + + + // + // Find which sockets have data to receive + // + struct timeval timeout; + timeout.tv_sec = 0; + timeout.tv_usec = 50000; // frequency to poll pnode->vSend + + fd_set fdsetRecv; + fd_set fdsetSend; + fd_set fdsetError; + FD_ZERO(&fdsetRecv); + FD_ZERO(&fdsetSend); + FD_ZERO(&fdsetError); + SOCKET hSocketMax = 0; + bool have_fds = false; + + BOOST_FOREACH(SOCKET hListenSocket, vhListenSocket) { + FD_SET(hListenSocket, &fdsetRecv); + hSocketMax = max(hSocketMax, hListenSocket); + have_fds = true; + } + { + LOCK(cs_vNodes); + BOOST_FOREACH(CNode* pnode, vNodes) + { + if (pnode->hSocket == INVALID_SOCKET) + continue; + { + TRY_LOCK(pnode->cs_vSend, lockSend); + if (lockSend) { + // do not read, if draining write queue + if (!pnode->vSendMsg.empty()) + FD_SET(pnode->hSocket, &fdsetSend); + else + FD_SET(pnode->hSocket, &fdsetRecv); + FD_SET(pnode->hSocket, &fdsetError); + hSocketMax = max(hSocketMax, pnode->hSocket); + have_fds = true; + } + } + } + } + + vnThreadsRunning[THREAD_SOCKETHANDLER]--; + int nSelect = select(have_fds ? hSocketMax + 1 : 0, + &fdsetRecv, &fdsetSend, &fdsetError, &timeout); + vnThreadsRunning[THREAD_SOCKETHANDLER]++; + if (fShutdown) + return; + if (nSelect == SOCKET_ERROR) + { + if (have_fds) + { + int nErr = WSAGetLastError(); + printf("socket select error %d\n", nErr); + for (unsigned int i = 0; i <= hSocketMax; i++) + FD_SET(i, &fdsetRecv); + } + FD_ZERO(&fdsetSend); + FD_ZERO(&fdsetError); + MilliSleep(timeout.tv_usec/1000); + } + + + // + // Accept new connections + // + BOOST_FOREACH(SOCKET hListenSocket, vhListenSocket) + if (hListenSocket != INVALID_SOCKET && FD_ISSET(hListenSocket, &fdsetRecv)) + { + struct sockaddr_storage sockaddr; + socklen_t len = sizeof(sockaddr); + SOCKET hSocket = accept(hListenSocket, (struct sockaddr*)&sockaddr, &len); + CAddress addr; + int nInbound = 0; + + if (hSocket != INVALID_SOCKET) + if (!addr.SetSockAddr((const struct sockaddr*)&sockaddr)) + printf("Warning: Unknown socket family\n"); + + { + LOCK(cs_vNodes); + BOOST_FOREACH(CNode* pnode, vNodes) + if (pnode->fInbound) + nInbound++; + } + + if (hSocket == INVALID_SOCKET) + { + int nErr = WSAGetLastError(); + if (nErr != WSAEWOULDBLOCK) + printf("socket error accept failed: %d\n", nErr); + } + else if (nInbound >= GetArg("-maxconnections", 125) - MAX_OUTBOUND_CONNECTIONS) + { + closesocket(hSocket); + } + else if (CNode::IsBanned(addr)) + { + printf("connection from %s dropped (banned)\n", addr.ToString().c_str()); + closesocket(hSocket); + } + else + { + printf("accepted connection %s\n", addr.ToString().c_str()); + CNode* pnode = new CNode(hSocket, addr, "", true); + pnode->AddRef(); + { + LOCK(cs_vNodes); + vNodes.push_back(pnode); + } + } + } + + + // + // Service each socket + // + vector vNodesCopy; + { + LOCK(cs_vNodes); + vNodesCopy = vNodes; + BOOST_FOREACH(CNode* pnode, vNodesCopy) + pnode->AddRef(); + } + BOOST_FOREACH(CNode* pnode, vNodesCopy) + { + if (fShutdown) + return; + + // + // Receive + // + if (pnode->hSocket == INVALID_SOCKET) + continue; + if (FD_ISSET(pnode->hSocket, &fdsetRecv) || FD_ISSET(pnode->hSocket, &fdsetError)) + { + TRY_LOCK(pnode->cs_vRecvMsg, lockRecv); + if (lockRecv) + { + if (pnode->GetTotalRecvSize() > ReceiveFloodSize()) { + if (!pnode->fDisconnect) + printf("socket recv flood control disconnect (%u bytes)\n", pnode->GetTotalRecvSize()); + pnode->CloseSocketDisconnect(); + } + else { + // typical socket buffer is 8K-64K + char pchBuf[0x10000]; + int nBytes = recv(pnode->hSocket, pchBuf, sizeof(pchBuf), MSG_DONTWAIT); + if (nBytes > 0) + { + if (!pnode->ReceiveMsgBytes(pchBuf, nBytes)) + pnode->CloseSocketDisconnect(); + pnode->nLastRecv = GetTime(); + pnode->RecordBytesRecv(nBytes); + } + else if (nBytes == 0) + { + // socket closed gracefully + if (!pnode->fDisconnect) + printf("socket closed\n"); + pnode->CloseSocketDisconnect(); + } + else if (nBytes < 0) + { + // error + int nErr = WSAGetLastError(); + if (nErr != WSAEWOULDBLOCK && nErr != WSAEMSGSIZE && nErr != WSAEINTR && nErr != WSAEINPROGRESS) + { + if (!pnode->fDisconnect) + printf("socket recv error %d\n", nErr); + pnode->CloseSocketDisconnect(); + } + } + } + } + } + + // + // Send + // + if (pnode->hSocket == INVALID_SOCKET) + continue; + if (FD_ISSET(pnode->hSocket, &fdsetSend)) + { + TRY_LOCK(pnode->cs_vSend, lockSend); + if (lockSend) + SocketSendData(pnode); + } + + // + // Inactivity checking + // + if (pnode->vSendMsg.empty()) + pnode->nLastSendEmpty = GetTime(); + if (GetTime() - pnode->nTimeConnected > 60) + { + if (pnode->nLastRecv == 0 || pnode->nLastSend == 0) + { + printf("socket no message in first 60 seconds, %d %d\n", pnode->nLastRecv != 0, pnode->nLastSend != 0); + pnode->fDisconnect = true; + } + else if (GetTime() - pnode->nLastSend > 90*60 && GetTime() - pnode->nLastSendEmpty > 90*60) + { + printf("socket not sending\n"); + pnode->fDisconnect = true; + } + else if (GetTime() - pnode->nLastRecv > 90*60) + { + printf("socket inactivity timeout\n"); + pnode->fDisconnect = true; + } + } + } + { + LOCK(cs_vNodes); + BOOST_FOREACH(CNode* pnode, vNodesCopy) + pnode->Release(); + } + + MilliSleep(10); + } +} + + + + + + + + + +#ifdef USE_UPNP +void ThreadMapPort(void* parg) +{ + // Make this thread recognisable as the UPnP thread + RenameThread("arepacoin-UPnP"); + + try + { + vnThreadsRunning[THREAD_UPNP]++; + ThreadMapPort2(parg); + vnThreadsRunning[THREAD_UPNP]--; + } + catch (std::exception& e) { + vnThreadsRunning[THREAD_UPNP]--; + PrintException(&e, "ThreadMapPort()"); + } catch (...) { + vnThreadsRunning[THREAD_UPNP]--; + PrintException(NULL, "ThreadMapPort()"); + } + printf("ThreadMapPort exited\n"); +} + +void ThreadMapPort2(void* parg) +{ + printf("ThreadMapPort started\n"); + + std::string port = strprintf("%u", GetListenPort()); + const char * multicastif = 0; + const char * minissdpdpath = 0; + struct UPNPDev * devlist = 0; + char lanaddr[64]; + +#ifndef UPNPDISCOVER_SUCCESS + /* miniupnpc 1.5 */ + devlist = upnpDiscover(2000, multicastif, minissdpdpath, 0); +#elif MINIUPNPC_API_VERSION < 14 + /* miniupnpc 1.6 */ + int error = 0; + devlist = upnpDiscover(2000, multicastif, minissdpdpath, 0, 0, &error); +#else + /* miniupnpc 1.9.20150730 */ + int error = 0; + devlist = upnpDiscover(2000, multicastif, minissdpdpath, 0, 0, 2, &error); +#endif + + struct UPNPUrls urls; + struct IGDdatas data; + int r; + + r = UPNP_GetValidIGD(devlist, &urls, &data, lanaddr, sizeof(lanaddr)); + if (r == 1) + { + if (fDiscover) { + char externalIPAddress[40]; + r = UPNP_GetExternalIPAddress(urls.controlURL, data.first.servicetype, externalIPAddress); + if(r != UPNPCOMMAND_SUCCESS) + printf("UPnP: GetExternalIPAddress() returned %d\n", r); + else + { + if(externalIPAddress[0]) + { + printf("UPnP: ExternalIPAddress = %s\n", externalIPAddress); + AddLocal(CNetAddr(externalIPAddress), LOCAL_UPNP); + } + else + printf("UPnP: GetExternalIPAddress failed.\n"); + } + } + + string strDesc = "arepacoin " + FormatFullVersion(); +#ifndef UPNPDISCOVER_SUCCESS + /* miniupnpc 1.5 */ + r = UPNP_AddPortMapping(urls.controlURL, data.first.servicetype, + port.c_str(), port.c_str(), lanaddr, strDesc.c_str(), "TCP", 0); +#else + /* miniupnpc 1.6 */ + r = UPNP_AddPortMapping(urls.controlURL, data.first.servicetype, + port.c_str(), port.c_str(), lanaddr, strDesc.c_str(), "TCP", 0, "0"); +#endif + + if(r!=UPNPCOMMAND_SUCCESS) + printf("AddPortMapping(%s, %s, %s) failed with code %d (%s)\n", + port.c_str(), port.c_str(), lanaddr, r, strupnperror(r)); + else + printf("UPnP Port Mapping successful.\n"); + int i = 1; + while (true) + { + if (fShutdown || !fUseUPnP) + { + r = UPNP_DeletePortMapping(urls.controlURL, data.first.servicetype, port.c_str(), "TCP", 0); + printf("UPNP_DeletePortMapping() returned : %d\n", r); + freeUPNPDevlist(devlist); devlist = 0; + FreeUPNPUrls(&urls); + return; + } + if (i % 600 == 0) // Refresh every 20 minutes + { +#ifndef UPNPDISCOVER_SUCCESS + /* miniupnpc 1.5 */ + r = UPNP_AddPortMapping(urls.controlURL, data.first.servicetype, + port.c_str(), port.c_str(), lanaddr, strDesc.c_str(), "TCP", 0); +#else + /* miniupnpc 1.6 */ + r = UPNP_AddPortMapping(urls.controlURL, data.first.servicetype, + port.c_str(), port.c_str(), lanaddr, strDesc.c_str(), "TCP", 0, "0"); +#endif + + if(r!=UPNPCOMMAND_SUCCESS) + printf("AddPortMapping(%s, %s, %s) failed with code %d (%s)\n", + port.c_str(), port.c_str(), lanaddr, r, strupnperror(r)); + else + printf("UPnP Port Mapping successful.\n");; + } + MilliSleep(2000); + i++; + } + } else { + printf("No valid UPnP IGDs found\n"); + freeUPNPDevlist(devlist); devlist = 0; + if (r != 0) + FreeUPNPUrls(&urls); + while (true) + { + if (fShutdown || !fUseUPnP) + return; + MilliSleep(2000); + } + } +} + +void MapPort() +{ + if (fUseUPnP && vnThreadsRunning[THREAD_UPNP] < 1) + { + if (!NewThread(ThreadMapPort, NULL)) + printf("Error: ThreadMapPort(ThreadMapPort) failed\n"); + } +} +#else +void MapPort() +{ + // Intentionally left blank. +} +#endif + + + + + + + + + +// DNS seeds +// Each pair gives a source name and a seed name. +// The first name is used as information source for addrman. +// The second name should resolve to a list of seed addresses. +static const char *strMainNetDNSSeed[] = { + "node.arepacripto.org", + "node2.arepacripto.org", + "node3.arepacripto.org" +}; + +static const char *strTestNetDNSSeed[] = { + "dnsseedtest.arepacripto.org", +}; + +void ThreadDNSAddressSeed(void* parg) +{ + // Make this thread recognisable as the DNS seeding thread + RenameThread("arepacoin-dnsseed"); + + try + { + vnThreadsRunning[THREAD_DNSSEED]++; + ThreadDNSAddressSeed2(parg); + vnThreadsRunning[THREAD_DNSSEED]--; + } + catch (std::exception& e) { + vnThreadsRunning[THREAD_DNSSEED]--; + PrintException(&e, "ThreadDNSAddressSeed()"); + } catch (...) { + vnThreadsRunning[THREAD_DNSSEED]--; + throw; // support pthread_cancel() + } + printf("ThreadDNSAddressSeed exited\n"); +} + +void ThreadDNSAddressSeed2(void* parg) +{ + printf("ThreadDNSAddressSeed started\n"); + + static const char **strDNSSeed = fTestNet ? strTestNetDNSSeed : strMainNetDNSSeed; + static const unsigned long int nbSeeds = ARRAYLEN(fTestNet ? strTestNetDNSSeed : strMainNetDNSSeed); + + unsigned int found = 0; + + printf("Loading addresses from DNS seeds (could take a while)\n"); + + for (unsigned int seed_idx = 0; seed_idx < nbSeeds; seed_idx++) { + if (HaveNameProxy()) { + AddOneShot(strDNSSeed[seed_idx]); + } else { + vector vaddr; + vector vAdd; + if (LookupHost(strDNSSeed[seed_idx], vaddr)) + { + BOOST_FOREACH(CNetAddr& ip, vaddr) + { + int nOneDay = 24*3600; + CAddress addr = CAddress(CService(ip, GetDefaultPort())); + addr.nTime = GetTime() - 3*nOneDay - GetRand(4*nOneDay); // use a random age between 3 and 7 days old + vAdd.push_back(addr); + found++; + } + } + addrman.Add(vAdd, CNetAddr(strDNSSeed[seed_idx], true)); + } + } + + printf("%u addresses found from %lu DNS seed(s)\n", found, nbSeeds); +} + + + + + + + + + + + + +unsigned int pnSeed[] = +{ +}; + +void DumpAddresses() +{ + int64_t nStart = GetTimeMillis(); + + CAddrDB adb; + adb.Write(addrman); + + printf("Flushed %d addresses to peers.dat %" PRId64"ms\n", + addrman.size(), GetTimeMillis() - nStart); +} + +void ThreadDumpAddress2(void* parg) +{ + vnThreadsRunning[THREAD_DUMPADDRESS]++; + while (!fShutdown) + { + DumpAddresses(); + vnThreadsRunning[THREAD_DUMPADDRESS]--; + MilliSleep(600000); + vnThreadsRunning[THREAD_DUMPADDRESS]++; + } + vnThreadsRunning[THREAD_DUMPADDRESS]--; +} + +void ThreadDumpAddress(void* parg) +{ + // Make this thread recognisable as the address dumping thread + RenameThread("arepacoin-adrdump"); + + try + { + ThreadDumpAddress2(parg); + } + catch (std::exception& e) { + PrintException(&e, "ThreadDumpAddress()"); + } + printf("ThreadDumpAddress exited\n"); +} + +void ThreadOpenConnections(void* parg) +{ + // Make this thread recognisable as the connection opening thread + RenameThread("arepacoin-opencon"); + + try + { + vnThreadsRunning[THREAD_OPENCONNECTIONS]++; + ThreadOpenConnections2(parg); + vnThreadsRunning[THREAD_OPENCONNECTIONS]--; + } + catch (std::exception& e) { + vnThreadsRunning[THREAD_OPENCONNECTIONS]--; + PrintException(&e, "ThreadOpenConnections()"); + } catch (...) { + vnThreadsRunning[THREAD_OPENCONNECTIONS]--; + PrintException(NULL, "ThreadOpenConnections()"); + } + printf("ThreadOpenConnections exited\n"); +} + +void static ProcessOneShot() +{ + string strDest; + { + LOCK(cs_vOneShots); + if (vOneShots.empty()) + return; + strDest = vOneShots.front(); + vOneShots.pop_front(); + } + CAddress addr; + CSemaphoreGrant grant(*semOutbound, true); + if (grant) { + if (!OpenNetworkConnection(addr, &grant, strDest.c_str(), true)) + AddOneShot(strDest); + } +} + +void static ThreadStakeMiner(void* parg) +{ + printf("ThreadStakeMiner started\n"); + CWallet* pwallet = (CWallet*)parg; + try + { + vnThreadsRunning[THREAD_STAKE_MINER]++; + StakeMiner(pwallet); + vnThreadsRunning[THREAD_STAKE_MINER]--; + } + catch (std::exception& e) { + vnThreadsRunning[THREAD_STAKE_MINER]--; + PrintException(&e, "ThreadStakeMiner()"); + } catch (...) { + vnThreadsRunning[THREAD_STAKE_MINER]--; + PrintException(NULL, "ThreadStakeMiner()"); + } + printf("ThreadStakeMiner exiting, %d threads remaining\n", vnThreadsRunning[THREAD_STAKE_MINER]); +} + +void ThreadOpenConnections2(void* parg) +{ + printf("ThreadOpenConnections started\n"); + + // Connect to specific addresses + if (mapArgs.count("-connect") && mapMultiArgs["-connect"].size() > 0) + { + for (int64_t nLoop = 0;; nLoop++) + { + ProcessOneShot(); + BOOST_FOREACH(string strAddr, mapMultiArgs["-connect"]) + { + CAddress addr; + OpenNetworkConnection(addr, NULL, strAddr.c_str()); + for (int i = 0; i < 10 && i < nLoop; i++) + { + MilliSleep(500); + if (fShutdown) + return; + } + } + MilliSleep(500); + } + } + + // Initiate network connections + int64_t nStart = GetTime(); + while (true) + { + ProcessOneShot(); + + vnThreadsRunning[THREAD_OPENCONNECTIONS]--; + MilliSleep(500); + vnThreadsRunning[THREAD_OPENCONNECTIONS]++; + if (fShutdown) + return; + + + vnThreadsRunning[THREAD_OPENCONNECTIONS]--; + CSemaphoreGrant grant(*semOutbound); + vnThreadsRunning[THREAD_OPENCONNECTIONS]++; + if (fShutdown) + return; + + // Add seed nodes if IRC isn't working + if (addrman.size()==0 && (GetTime() - nStart > 60) && !fTestNet) + { + std::vector vAdd; + for (unsigned int i = 0; i < ARRAYLEN(pnSeed); i++) + { + // It'll only connect to one or two seed nodes because once it connects, + // it'll get a pile of addresses with newer timestamps. + // Seed nodes are given a random 'last seen time' of between one and two + // weeks ago. + const int64_t nOneWeek = 7*24*60*60; + struct in_addr ip; + memcpy(&ip, &pnSeed[i], sizeof(ip)); + CAddress addr(CService(ip, GetDefaultPort())); + addr.nTime = GetTime()-GetRand(nOneWeek)-nOneWeek; + vAdd.push_back(addr); + } + addrman.Add(vAdd, CNetAddr("127.0.0.1")); + } + + // + // Choose an address to connect to based on most recently seen + // + CAddress addrConnect; + + // Only connect out to one peer per network group (/16 for IPv4). + // Do this here so we don't have to critsect vNodes inside mapAddresses critsect. + int nOutbound = 0; + set > setConnected; + { + LOCK(cs_vNodes); + BOOST_FOREACH(CNode* pnode, vNodes) { + if (!pnode->fInbound) { + setConnected.insert(pnode->addr.GetGroup()); + nOutbound++; + } + } + } + + int64_t nANow = GetAdjustedTime(); + + int nTries = 0; + while (true) + { + // use an nUnkBias between 10 (no outgoing connections) and 90 (8 outgoing connections) + CAddress addr = addrman.Select(10 + min(nOutbound,8)*10); + + // if we selected an invalid address, restart + if (!addr.IsValid() || setConnected.count(addr.GetGroup()) || IsLocal(addr)) + break; + + // If we didn't find an appropriate destination after trying 100 addresses fetched from addrman, + // stop this loop, and let the outer loop run again (which sleeps, adds seed nodes, recalculates + // already-connected network ranges, ...) before trying new addrman addresses. + nTries++; + if (nTries > 100) + break; + + if (IsLimited(addr)) + continue; + + // only consider very recently tried nodes after 30 failed attempts + if (nANow - addr.nLastTry < 600 && nTries < 30) + continue; + + // do not allow non-default ports, unless after 50 invalid addresses selected already + if (addr.GetPort() != GetDefaultPort() && nTries < 50) + continue; + + addrConnect = addr; + break; + } + + if (addrConnect.IsValid()) + OpenNetworkConnection(addrConnect, &grant); + } +} + +void ThreadOpenAddedConnections(void* parg) +{ + // Make this thread recognisable as the connection opening thread + RenameThread("arepacoin-opencon"); + + try + { + vnThreadsRunning[THREAD_ADDEDCONNECTIONS]++; + ThreadOpenAddedConnections2(parg); + vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--; + } + catch (std::exception& e) { + vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--; + PrintException(&e, "ThreadOpenAddedConnections()"); + } catch (...) { + vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--; + PrintException(NULL, "ThreadOpenAddedConnections()"); + } + printf("ThreadOpenAddedConnections exited\n"); +} + +void ThreadOpenAddedConnections2(void* parg) +{ + printf("ThreadOpenAddedConnections started\n"); + + { + LOCK(cs_vAddedNodes); + vAddedNodes = mapMultiArgs["-addnode"]; + } + + if (HaveNameProxy()) { + while(!fShutdown) { + list lAddresses(0); + { + LOCK(cs_vAddedNodes); + BOOST_FOREACH(string& strAddNode, vAddedNodes) + lAddresses.push_back(strAddNode); + } + BOOST_FOREACH(string& strAddNode, lAddresses) { + CAddress addr; + CSemaphoreGrant grant(*semOutbound); + OpenNetworkConnection(addr, &grant, strAddNode.c_str()); + MilliSleep(500); + if (fShutdown) + return; + } + vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--; + MilliSleep(120000); // Retry every 2 minutes + vnThreadsRunning[THREAD_ADDEDCONNECTIONS]++; + } + return; + } + + while (true) + { + list lAddresses(0); + { + LOCK(cs_vAddedNodes); + BOOST_FOREACH(string& strAddNode, vAddedNodes) + lAddresses.push_back(strAddNode); + } + + list > lservAddressesToAdd(0); + BOOST_FOREACH(string& strAddNode, lAddresses) + { + vector vservNode(0); + if(Lookup(strAddNode.c_str(), vservNode, GetDefaultPort(), fNameLookup, 0)) + { + lservAddressesToAdd.push_back(vservNode); + { + LOCK(cs_setservAddNodeAddresses); + BOOST_FOREACH(CService& serv, vservNode) + setservAddNodeAddresses.insert(serv); + } + } + } + // Attempt to connect to each IP for each addnode entry until at least one is successful per addnode entry + // (keeping in mind that addnode entries can have many IPs if fNameLookup) + { + LOCK(cs_vNodes); + BOOST_FOREACH(CNode* pnode, vNodes) + for (list >::iterator it = lservAddressesToAdd.begin(); it != lservAddressesToAdd.end(); it++) + BOOST_FOREACH(CService& addrNode, *(it)) + if (pnode->addr == addrNode) + { + it = lservAddressesToAdd.erase(it); + it--; + break; + } + } + BOOST_FOREACH(vector& vserv, lservAddressesToAdd) + { + CSemaphoreGrant grant(*semOutbound); + OpenNetworkConnection(CAddress(*(vserv.begin())), &grant); + MilliSleep(500); + if (fShutdown) + return; + } + if (fShutdown) + return; + vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--; + MilliSleep(120000); // Retry every 2 minutes + vnThreadsRunning[THREAD_ADDEDCONNECTIONS]++; + if (fShutdown) + return; + } +} + +// if successful, this moves the passed grant to the constructed node +bool OpenNetworkConnection(const CAddress& addrConnect, CSemaphoreGrant *grantOutbound, const char *strDest, bool fOneShot) +{ + // + // Initiate outbound network connection + // + if (fShutdown) + return false; + if (!strDest) + if (IsLocal(addrConnect) || + FindNode((CNetAddr)addrConnect) || CNode::IsBanned(addrConnect) || + FindNode(addrConnect.ToStringIPPort().c_str())) + return false; + if (strDest && FindNode(strDest)) + return false; + + vnThreadsRunning[THREAD_OPENCONNECTIONS]--; + CNode* pnode = ConnectNode(addrConnect, strDest); + vnThreadsRunning[THREAD_OPENCONNECTIONS]++; + if (fShutdown) + return false; + if (!pnode) + return false; + if (grantOutbound) + grantOutbound->MoveTo(pnode->grantOutbound); + pnode->fNetworkNode = true; + if (fOneShot) + pnode->fOneShot = true; + + return true; +} + + + + + + + + +void ThreadMessageHandler(void* parg) +{ + // Make this thread recognisable as the message handling thread + RenameThread("arepacoin-msghand"); + + try + { + vnThreadsRunning[THREAD_MESSAGEHANDLER]++; + ThreadMessageHandler2(parg); + vnThreadsRunning[THREAD_MESSAGEHANDLER]--; + } + catch (std::exception& e) { + vnThreadsRunning[THREAD_MESSAGEHANDLER]--; + PrintException(&e, "ThreadMessageHandler()"); + } catch (...) { + vnThreadsRunning[THREAD_MESSAGEHANDLER]--; + PrintException(NULL, "ThreadMessageHandler()"); + } + printf("ThreadMessageHandler exited\n"); +} + +void ThreadMessageHandler2(void* parg) +{ + printf("ThreadMessageHandler started\n"); + SetThreadPriority(THREAD_PRIORITY_BELOW_NORMAL); + while (!fShutdown) + { + vector vNodesCopy; + { + LOCK(cs_vNodes); + vNodesCopy = vNodes; + BOOST_FOREACH(CNode* pnode, vNodesCopy) + pnode->AddRef(); + } + + // Poll the connected nodes for messages + CNode* pnodeTrickle = NULL; + if (!vNodesCopy.empty()) + pnodeTrickle = vNodesCopy[GetRand(vNodesCopy.size())]; + BOOST_FOREACH(CNode* pnode, vNodesCopy) + { + if (pnode->fDisconnect) + continue; + + // Receive messages + { + TRY_LOCK(pnode->cs_vRecvMsg, lockRecv); + if (lockRecv) + if (!ProcessMessages(pnode)) + pnode->CloseSocketDisconnect(); + } + if (fShutdown) + return; + + // Send messages + { + TRY_LOCK(pnode->cs_vSend, lockSend); + if (lockSend) + SendMessages(pnode, pnode == pnodeTrickle); + } + if (fShutdown) + return; + } + + { + LOCK(cs_vNodes); + BOOST_FOREACH(CNode* pnode, vNodesCopy) + pnode->Release(); + } + + // Wait and allow messages to bunch up. + // Reduce vnThreadsRunning so StopNode has permission to exit while + // we're sleeping, but we must always check fShutdown after doing this. + vnThreadsRunning[THREAD_MESSAGEHANDLER]--; + MilliSleep(100); + if (fRequestShutdown) + StartShutdown(); + vnThreadsRunning[THREAD_MESSAGEHANDLER]++; + if (fShutdown) + return; + } +} + + + + + + +bool BindListenPort(const CService &addrBind, string& strError) +{ + strError = ""; + int nOne = 1; + +#ifdef WIN32 + // Initialize Windows Sockets + WSADATA wsadata; + int ret = WSAStartup(MAKEWORD(2,2), &wsadata); + if (ret != NO_ERROR) + { + strError = strprintf("Error: TCP/IP socket library failed to start (WSAStartup returned error %d)", ret); + printf("%s\n", strError.c_str()); + return false; + } +#endif + + // Create socket for listening for incoming connections + struct sockaddr_storage sockaddr; + socklen_t len = sizeof(sockaddr); + if (!addrBind.GetSockAddr((struct sockaddr*)&sockaddr, &len)) + { + strError = strprintf("Error: bind address family for %s not supported", addrBind.ToString().c_str()); + printf("%s\n", strError.c_str()); + return false; + } + + SOCKET hListenSocket = socket(((struct sockaddr*)&sockaddr)->sa_family, SOCK_STREAM, IPPROTO_TCP); + if (hListenSocket == INVALID_SOCKET) + { + strError = strprintf("Error: Couldn't open socket for incoming connections (socket returned error %d)", WSAGetLastError()); + printf("%s\n", strError.c_str()); + return false; + } + +#ifdef SO_NOSIGPIPE + // Different way of disabling SIGPIPE on BSD + setsockopt(hListenSocket, SOL_SOCKET, SO_NOSIGPIPE, (void*)&nOne, sizeof(int)); +#endif + +#ifndef WIN32 + // Allow binding if the port is still in TIME_WAIT state after + // the program was closed and restarted. Not an issue on windows. + setsockopt(hListenSocket, SOL_SOCKET, SO_REUSEADDR, (void*)&nOne, sizeof(int)); +#endif + + +#ifdef WIN32 + // Set to non-blocking, incoming connections will also inherit this + if (ioctlsocket(hListenSocket, FIONBIO, (u_long*)&nOne) == SOCKET_ERROR) +#else + if (fcntl(hListenSocket, F_SETFL, O_NONBLOCK) == SOCKET_ERROR) +#endif + { + strError = strprintf("Error: Couldn't set properties on socket for incoming connections (error %d)", WSAGetLastError()); + printf("%s\n", strError.c_str()); + return false; + } + + // some systems don't have IPV6_V6ONLY but are always v6only; others do have the option + // and enable it by default or not. Try to enable it, if possible. + if (addrBind.IsIPv6()) { +#ifdef IPV6_V6ONLY +#ifdef WIN32 + setsockopt(hListenSocket, IPPROTO_IPV6, IPV6_V6ONLY, (const char*)&nOne, sizeof(int)); +#else + setsockopt(hListenSocket, IPPROTO_IPV6, IPV6_V6ONLY, (void*)&nOne, sizeof(int)); +#endif +#endif +#ifdef WIN32 + int nProtLevel = 10 /* PROTECTION_LEVEL_UNRESTRICTED */; + int nParameterId = 23 /* IPV6_PROTECTION_LEVEl */; + // this call is allowed to fail + setsockopt(hListenSocket, IPPROTO_IPV6, nParameterId, (const char*)&nProtLevel, sizeof(int)); +#endif + } + + if (::bind(hListenSocket, (struct sockaddr*)&sockaddr, len) == SOCKET_ERROR) + { + int nErr = WSAGetLastError(); + if (nErr == WSAEADDRINUSE) + strError = strprintf(_("Unable to bind to %s on this computer. arepacoin is probably already running."), addrBind.ToString().c_str()); + else + strError = strprintf(_("Unable to bind to %s on this computer (bind returned error %d, %s)"), addrBind.ToString().c_str(), nErr, strerror(nErr)); + printf("%s\n", strError.c_str()); + return false; + } + printf("Bound to %s\n", addrBind.ToString().c_str()); + + // Listen for incoming connections + if (listen(hListenSocket, SOMAXCONN) == SOCKET_ERROR) + { + strError = strprintf("Error: Listening for incoming connections failed (listen returned error %d)", WSAGetLastError()); + printf("%s\n", strError.c_str()); + return false; + } + + vhListenSocket.push_back(hListenSocket); + + if (addrBind.IsRoutable() && fDiscover) + AddLocal(addrBind, LOCAL_BIND); + + return true; +} + +void static Discover() +{ + if (!fDiscover) + return; + +#ifdef WIN32 + // Get local host IP + char pszHostName[1000] = ""; + if (gethostname(pszHostName, sizeof(pszHostName)) != SOCKET_ERROR) + { + vector vaddr; + if (LookupHost(pszHostName, vaddr)) + { + BOOST_FOREACH (const CNetAddr &addr, vaddr) + { + AddLocal(addr, LOCAL_IF); + } + } + } +#else + // Get local host ip + struct ifaddrs* myaddrs; + if (getifaddrs(&myaddrs) == 0) + { + for (struct ifaddrs* ifa = myaddrs; ifa != NULL; ifa = ifa->ifa_next) + { + if (ifa->ifa_addr == NULL) continue; + if ((ifa->ifa_flags & IFF_UP) == 0) continue; + if (strcmp(ifa->ifa_name, "lo") == 0) continue; + if (strcmp(ifa->ifa_name, "lo0") == 0) continue; + if (ifa->ifa_addr->sa_family == AF_INET) + { + struct sockaddr_in* s4 = (struct sockaddr_in*)(ifa->ifa_addr); + CNetAddr addr(s4->sin_addr); + if (AddLocal(addr, LOCAL_IF)) + printf("IPv4 %s: %s\n", ifa->ifa_name, addr.ToString().c_str()); + } + else if (ifa->ifa_addr->sa_family == AF_INET6) + { + struct sockaddr_in6* s6 = (struct sockaddr_in6*)(ifa->ifa_addr); + CNetAddr addr(s6->sin6_addr); + if (AddLocal(addr, LOCAL_IF)) + printf("IPv6 %s: %s\n", ifa->ifa_name, addr.ToString().c_str()); + } + } + freeifaddrs(myaddrs); + } +#endif + + // Don't use external IPv4 discovery, when -onlynet="IPv6" + if (!IsLimited(NET_IPV4)) + NewThread(ThreadGetMyExternalIP, NULL); +} + +void StartNode(void* parg) +{ + // Make this thread recognisable as the startup thread + RenameThread("arepacoin-start"); + + if (semOutbound == NULL) { + // initialize semaphore + int nMaxOutbound = min(MAX_OUTBOUND_CONNECTIONS, (int)GetArg("-maxconnections", 125)); + semOutbound = new CSemaphore(nMaxOutbound); + } + + if (pnodeLocalHost == NULL) + pnodeLocalHost = new CNode(INVALID_SOCKET, CAddress(CService("127.0.0.1", 0), nLocalServices)); + + Discover(); + + // + // Start threads + // + + if (!GetBoolArg("-dnsseed", true)) + printf("DNS seeding disabled\n"); + else if (!NewThread(ThreadDNSAddressSeed, NULL)) + printf("Error: NewThread(ThreadDNSAddressSeed) failed\n"); + + // Map ports with UPnP + if (fUseUPnP) + MapPort(); + + // Send and receive from sockets, accept connections + if (!NewThread(ThreadSocketHandler, NULL)) + printf("Error: NewThread(ThreadSocketHandler) failed\n"); + + // Initiate outbound connections from -addnode + if (!NewThread(ThreadOpenAddedConnections, NULL)) + printf("Error: NewThread(ThreadOpenAddedConnections) failed\n"); + + // Initiate outbound connections + if (!NewThread(ThreadOpenConnections, NULL)) + printf("Error: NewThread(ThreadOpenConnections) failed\n"); + + // Process messages + if (!NewThread(ThreadMessageHandler, NULL)) + printf("Error: NewThread(ThreadMessageHandler) failed\n"); + + // Dump network addresses + if (!NewThread(ThreadDumpAddress, NULL)) + printf("Error; NewThread(ThreadDumpAddress) failed\n"); + + // Mine proof-of-stake blocks in the background + if (!GetBoolArg("-staking", true)) + printf("Staking disabled\n"); + else + if (!NewThread(ThreadStakeMiner, pwalletMain)) + printf("Error: NewThread(ThreadStakeMiner) failed\n"); +} + +bool StopNode() +{ + printf("StopNode()\n"); + fShutdown = true; + nTransactionsUpdated++; + int64_t nStart = GetTime(); + if (semOutbound) + for (int i=0; ipost(); + do + { + int nThreadsRunning = 0; + for (int n = 0; n < THREAD_MAX; n++) + nThreadsRunning += vnThreadsRunning[n]; + if (nThreadsRunning == 0) + break; + if (GetTime() - nStart > 20) + break; + MilliSleep(20); + } while(true); + if (vnThreadsRunning[THREAD_SOCKETHANDLER] > 0) printf("ThreadSocketHandler still running\n"); + if (vnThreadsRunning[THREAD_OPENCONNECTIONS] > 0) printf("ThreadOpenConnections still running\n"); + if (vnThreadsRunning[THREAD_MESSAGEHANDLER] > 0) printf("ThreadMessageHandler still running\n"); + if (vnThreadsRunning[THREAD_RPCLISTENER] > 0) printf("ThreadRPCListener still running\n"); + if (vnThreadsRunning[THREAD_RPCHANDLER] > 0) printf("ThreadsRPCServer still running\n"); +#ifdef USE_UPNP + if (vnThreadsRunning[THREAD_UPNP] > 0) printf("ThreadMapPort still running\n"); +#endif + if (vnThreadsRunning[THREAD_DNSSEED] > 0) printf("ThreadDNSAddressSeed still running\n"); + if (vnThreadsRunning[THREAD_ADDEDCONNECTIONS] > 0) printf("ThreadOpenAddedConnections still running\n"); + if (vnThreadsRunning[THREAD_DUMPADDRESS] > 0) printf("ThreadDumpAddresses still running\n"); + if (vnThreadsRunning[THREAD_STAKE_MINER] > 0) printf("ThreadStakeMiner still running\n"); + while (vnThreadsRunning[THREAD_MESSAGEHANDLER] > 0 || vnThreadsRunning[THREAD_RPCHANDLER] > 0) + MilliSleep(20); + MilliSleep(50); + DumpAddresses(); + return true; +} + +class CNetCleanup +{ +public: + CNetCleanup() + { + } + ~CNetCleanup() + { + // Close sockets + BOOST_FOREACH(CNode* pnode, vNodes) + if (pnode->hSocket != INVALID_SOCKET) + closesocket(pnode->hSocket); + BOOST_FOREACH(SOCKET hListenSocket, vhListenSocket) + if (hListenSocket != INVALID_SOCKET) + if (closesocket(hListenSocket) == SOCKET_ERROR) + printf("closesocket(hListenSocket) failed with error %d\n", WSAGetLastError()); + +#ifdef WIN32 + // Shutdown Windows Sockets + WSACleanup(); +#endif + } +} +instance_of_cnetcleanup; + +void RelayTransaction(const CTransaction& tx, const uint256& hash) +{ + CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); + ss.reserve(10000); + ss << tx; + RelayTransaction(tx, hash, ss); +} + +void RelayTransaction(const CTransaction& tx, const uint256& hash, const CDataStream& ss) +{ + CInv inv(MSG_TX, hash); + { + LOCK(cs_mapRelay); + // Expire old relay messages + while (!vRelayExpiration.empty() && vRelayExpiration.front().first < GetTime()) + { + mapRelay.erase(vRelayExpiration.front().second); + vRelayExpiration.pop_front(); + } + + // Save original serialized message so newer versions are preserved + mapRelay.insert(std::make_pair(inv, ss)); + vRelayExpiration.push_back(std::make_pair(GetTime() + 15 * 60, inv)); + } + + RelayInventory(inv); +} + +void CNode::RecordBytesRecv(uint64_t bytes) +{ + LOCK(cs_totalBytesRecv); + nTotalBytesRecv += bytes; +} + +void CNode::RecordBytesSent(uint64_t bytes) +{ + LOCK(cs_totalBytesSent); + nTotalBytesSent += bytes; +} + +uint64_t CNode::GetTotalBytesRecv() +{ + LOCK(cs_totalBytesRecv); + return nTotalBytesRecv; +} + +uint64_t CNode::GetTotalBytesSent() +{ + LOCK(cs_totalBytesSent); + return nTotalBytesSent; +} \ No newline at end of file diff --git a/src/net.h b/src/net.h new file mode 100644 index 0000000..0d562c8 --- /dev/null +++ b/src/net.h @@ -0,0 +1,720 @@ +// Copyright (c) 2009-2010 Satoshi Nakamoto +// Copyright (c) 2009-2012 The Bitcoin developers +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. +#ifndef BITCOIN_NET_H +#define BITCOIN_NET_H + +#include +#include +#include +#include + +#ifndef WIN32 +#include +#endif + +#include "mruset.h" +#include "netbase.h" +#include "protocol.h" +#include "addrman.h" + +class CRequestTracker; +class CNode; +class CBlockIndex; +extern int nBestHeight; + + + +inline unsigned int ReceiveFloodSize() { return 1000*GetArg("-maxreceivebuffer", 5*1000); } +inline unsigned int SendBufferSize() { return 1000*GetArg("-maxsendbuffer", 1*1000); } + +void AddOneShot(std::string strDest); +bool RecvLine(SOCKET hSocket, std::string& strLine); +bool GetMyExternalIP(CNetAddr& ipRet); +void AddressCurrentlyConnected(const CService& addr); +CNode* FindNode(const CNetAddr& ip); +CNode* FindNode(const CService& ip); +CNode* ConnectNode(CAddress addrConnect, const char *strDest = NULL); +void MapPort(); +unsigned short GetListenPort(); +bool BindListenPort(const CService &bindAddr, std::string& strError=REF(std::string())); +void StartNode(void* parg); +bool StopNode(); +void SocketSendData(CNode *pnode); + +enum +{ + LOCAL_NONE, // unknown + LOCAL_IF, // address a local interface listens on + LOCAL_BIND, // address explicit bound to + LOCAL_UPNP, // address reported by UPnP + LOCAL_IRC, // address reported by IRC (deprecated) + LOCAL_HTTP, // address reported by whatismyip.com and similar + LOCAL_MANUAL, // address explicitly specified (-externalip=) + + LOCAL_MAX +}; + +void SetLimited(enum Network net, bool fLimited = true); +bool IsLimited(enum Network net); +bool IsLimited(const CNetAddr& addr); +bool AddLocal(const CService& addr, int nScore = LOCAL_NONE); +bool AddLocal(const CNetAddr& addr, int nScore = LOCAL_NONE); +bool SeenLocal(const CService& addr); +bool IsLocal(const CService& addr); +bool GetLocal(CService &addr, const CNetAddr *paddrPeer = NULL); +bool IsReachable(const CNetAddr &addr); +void SetReachable(enum Network net, bool fFlag = true); +CAddress GetLocalAddress(const CNetAddr *paddrPeer = NULL); + + +enum +{ + MSG_TX = 1, + MSG_BLOCK, +}; + +class CRequestTracker +{ +public: + void (*fn)(void*, CDataStream&); + void* param1; + + explicit CRequestTracker(void (*fnIn)(void*, CDataStream&)=NULL, void* param1In=NULL) + { + fn = fnIn; + param1 = param1In; + } + + bool IsNull() + { + return fn == NULL; + } +}; + + +/** Thread types */ +enum threadId +{ + THREAD_SOCKETHANDLER, + THREAD_OPENCONNECTIONS, + THREAD_MESSAGEHANDLER, + THREAD_RPCLISTENER, + THREAD_UPNP, + THREAD_DNSSEED, + THREAD_ADDEDCONNECTIONS, + THREAD_DUMPADDRESS, + THREAD_RPCHANDLER, + THREAD_STAKE_MINER, + + THREAD_MAX +}; + +extern bool fDiscover; +extern bool fUseUPnP; +extern uint64_t nLocalServices; +extern uint64_t nLocalHostNonce; +extern CAddress addrSeenByPeerIp; +extern CAddress addrSeenByPeerIpv4; +extern CAddress addrSeenByPeerIpv6; +extern CAddress addrSeenByPeer; +extern boost::array vnThreadsRunning; +extern CAddrMan addrman; + +extern std::vector vNodes; +extern CCriticalSection cs_vNodes; +extern std::map mapRelay; +extern std::deque > vRelayExpiration; +extern CCriticalSection cs_mapRelay; +extern std::map mapAlreadyAskedFor; + +extern std::vector vAddedNodes; +extern CCriticalSection cs_vAddedNodes; + + +class CNodeStats +{ +public: + uint64_t nServices; + int64_t nLastSend; + int64_t nLastRecv; + int64_t nTimeConnected; + std::string addrName; + int nVersion; + std::string strSubVer; + bool fInbound; + int nStartingHeight; + int nMisbehavior; +}; + + + + +class CNetMessage { +public: + bool in_data; // parsing header (false) or data (true) + + CDataStream hdrbuf; // partially received header + CMessageHeader hdr; // complete header + unsigned int nHdrPos; + + CDataStream vRecv; // received message data + unsigned int nDataPos; + + CNetMessage(int nTypeIn, int nVersionIn) : hdrbuf(nTypeIn, nVersionIn), vRecv(nTypeIn, nVersionIn) { + hdrbuf.resize(24); + in_data = false; + nHdrPos = 0; + nDataPos = 0; + } + + bool complete() const + { + if (!in_data) + return false; + return (hdr.nMessageSize == nDataPos); + } + + void SetVersion(int nVersionIn) + { + hdrbuf.SetVersion(nVersionIn); + vRecv.SetVersion(nVersionIn); + } + + int readHeader(const char *pch, unsigned int nBytes); + int readData(const char *pch, unsigned int nBytes); +}; + + + + + +/** Information about a peer */ +class CNode +{ +public: + // socket + uint64_t nServices; + SOCKET hSocket; + CDataStream ssSend; + size_t nSendSize; // total size of all vSendMsg entries + size_t nSendOffset; // offset inside the first vSendMsg already sent + std::deque vSendMsg; + CCriticalSection cs_vSend; + + std::deque vRecvMsg; + CCriticalSection cs_vRecvMsg; + int nRecvVersion; + + int64_t nLastSend; + int64_t nLastRecv; + int64_t nLastSendEmpty; + int64_t nTimeConnected; + CAddress addr; + std::string addrName; + CService addrLocal; + int nVersion; + std::string strSubVer; + bool fOneShot; + bool fClient; + bool fInbound; + bool fNetworkNode; + bool fSuccessfullyConnected; + bool fDisconnect; + CSemaphoreGrant grantOutbound; + int nRefCount; +protected: + + // Denial-of-service detection/prevention + // Key is IP address, value is banned-until-time + static std::map setBanned; + static CCriticalSection cs_setBanned; + int nMisbehavior; + +public: + std::map mapRequests; + CCriticalSection cs_mapRequests; + uint256 hashContinue; + CBlockIndex* pindexLastGetBlocksBegin; + uint256 hashLastGetBlocksEnd; + int nStartingHeight; + + // flood relay + std::vector vAddrToSend; + mruset setAddrKnown; + bool fGetAddr; + std::set setKnown; + uint256 hashCheckpointKnown; // ppcoin: known sent sync-checkpoint + + // inventory based relay + mruset setInventoryKnown; + std::vector vInventoryToSend; + CCriticalSection cs_inventory; + std::multimap mapAskFor; + + CNode(SOCKET hSocketIn, CAddress addrIn, std::string addrNameIn = "", bool fInboundIn=false) : ssSend(SER_NETWORK, INIT_PROTO_VERSION), setAddrKnown(5000) + { + nServices = 0; + hSocket = hSocketIn; + nRecvVersion = INIT_PROTO_VERSION; + nLastSend = 0; + nLastRecv = 0; + nLastSendEmpty = GetTime(); + nTimeConnected = GetTime(); + addr = addrIn; + addrName = addrNameIn == "" ? addr.ToStringIPPort() : addrNameIn; + nVersion = 0; + strSubVer = ""; + fOneShot = false; + fClient = false; // set by version message + fInbound = fInboundIn; + fNetworkNode = false; + fSuccessfullyConnected = false; + fDisconnect = false; + nRefCount = 0; + nSendSize = 0; + nSendOffset = 0; + hashContinue = 0; + pindexLastGetBlocksBegin = 0; + hashLastGetBlocksEnd = 0; + nStartingHeight = -1; + fGetAddr = false; + nMisbehavior = 0; + hashCheckpointKnown = 0; + setInventoryKnown.max_size(SendBufferSize() / 1000); + + // Be shy and don't send version until we hear + if (hSocket != INVALID_SOCKET && !fInbound) + PushVersion(); + } + + ~CNode() + { + if (hSocket != INVALID_SOCKET) + { + closesocket(hSocket); + hSocket = INVALID_SOCKET; + } + } + +private: + // Network usage totals + static CCriticalSection cs_totalBytesRecv; + static CCriticalSection cs_totalBytesSent; + static uint64_t nTotalBytesRecv; + static uint64_t nTotalBytesSent; + + CNode(const CNode&); + void operator=(const CNode&); + +public: + + + int GetRefCount() + { + assert(nRefCount >= 0); + return nRefCount; + } + + // requires LOCK(cs_vRecvMsg) + unsigned int GetTotalRecvSize() + { + unsigned int total = 0; + BOOST_FOREACH(const CNetMessage &msg, vRecvMsg) + total += msg.vRecv.size() + 24; + return total; + } + + // requires LOCK(cs_vRecvMsg) + bool ReceiveMsgBytes(const char *pch, unsigned int nBytes); + + // requires LOCK(cs_vRecvMsg) + void SetRecvVersion(int nVersionIn) + { + nRecvVersion = nVersionIn; + BOOST_FOREACH(CNetMessage &msg, vRecvMsg) + msg.SetVersion(nVersionIn); + } + + CNode* AddRef() + { + nRefCount++; + return this; + } + + void Release() + { + nRefCount--; + } + + + + void AddAddressKnown(const CAddress& addr) + { + setAddrKnown.insert(addr); + } + + void PushAddress(const CAddress& addr) + { + // Known checking here is only to save space from duplicates. + // SendMessages will filter it again for knowns that were added + // after addresses were pushed. + if (addr.IsValid() && !setAddrKnown.count(addr)) + vAddrToSend.push_back(addr); + } + + + void AddInventoryKnown(const CInv& inv) + { + { + LOCK(cs_inventory); + setInventoryKnown.insert(inv); + } + } + + void PushInventory(const CInv& inv) + { + { + LOCK(cs_inventory); + if (!setInventoryKnown.count(inv)) + vInventoryToSend.push_back(inv); + } + } + + void AskFor(const CInv& inv) + { + // We're using mapAskFor as a priority queue, + // the key is the earliest time the request can be sent + int64_t& nRequestTime = mapAlreadyAskedFor[inv]; + if (fDebugNet) + printf("askfor %s %" PRId64" (%s)\n", inv.ToString().c_str(), nRequestTime, DateTimeStrFormat("%H:%M:%S", nRequestTime/1000000).c_str()); + + // Make sure not to reuse time indexes to keep things in the same order + int64_t nNow = (GetTime() - 1) * 1000000; + static int64_t nLastTime; + ++nLastTime; + nNow = std::max(nNow, nLastTime); + nLastTime = nNow; + + // Each retry is 2 minutes after the last + nRequestTime = std::max(nRequestTime + 2 * 60 * 1000000, nNow); + mapAskFor.insert(std::make_pair(nRequestTime, inv)); + } + + + + void BeginMessage(const char* pszCommand) + { + ENTER_CRITICAL_SECTION(cs_vSend); + assert(ssSend.size() == 0); + ssSend << CMessageHeader(pszCommand, 0); + if (fDebug) + printf("sending: %s ", pszCommand); + } + + void AbortMessage() + { + ssSend.clear(); + + LEAVE_CRITICAL_SECTION(cs_vSend); + + if (fDebug) + printf("(aborted)\n"); + } + + void EndMessage() + { + if (mapArgs.count("-dropmessagestest") && GetRand(atoi(mapArgs["-dropmessagestest"])) == 0) + { + printf("dropmessages DROPPING SEND MESSAGE\n"); + AbortMessage(); + return; + } + + if (ssSend.size() == 0) + return; + + // Set the size + unsigned int nSize = ssSend.size() - CMessageHeader::HEADER_SIZE; + memcpy((char*)&ssSend[CMessageHeader::MESSAGE_SIZE_OFFSET], &nSize, sizeof(nSize)); + + // Set the checksum + uint256 hash = Hash(ssSend.begin() + CMessageHeader::HEADER_SIZE, ssSend.end()); + unsigned int nChecksum = 0; + memcpy(&nChecksum, &hash, sizeof(nChecksum)); + assert(ssSend.size () >= CMessageHeader::CHECKSUM_OFFSET + sizeof(nChecksum)); + memcpy((char*)&ssSend[CMessageHeader::CHECKSUM_OFFSET], &nChecksum, sizeof(nChecksum)); + + if (fDebug) { + printf("(%d bytes)\n", nSize); + } + + std::deque::iterator it = vSendMsg.insert(vSendMsg.end(), CSerializeData()); + ssSend.GetAndClear(*it); + nSendSize += (*it).size(); + + // If write queue empty, attempt "optimistic write" + if (it == vSendMsg.begin()) + SocketSendData(this); + + LEAVE_CRITICAL_SECTION(cs_vSend); + } + + void PushVersion(); + + + void PushMessage(const char* pszCommand) + { + try + { + BeginMessage(pszCommand); + EndMessage(); + } + catch (...) + { + AbortMessage(); + throw; + } + } + + template + void PushMessage(const char* pszCommand, const T1& a1) + { + try + { + BeginMessage(pszCommand); + ssSend << a1; + EndMessage(); + } + catch (...) + { + AbortMessage(); + throw; + } + } + + template + void PushMessage(const char* pszCommand, const T1& a1, const T2& a2) + { + try + { + BeginMessage(pszCommand); + ssSend << a1 << a2; + EndMessage(); + } + catch (...) + { + AbortMessage(); + throw; + } + } + + template + void PushMessage(const char* pszCommand, const T1& a1, const T2& a2, const T3& a3) + { + try + { + BeginMessage(pszCommand); + ssSend << a1 << a2 << a3; + EndMessage(); + } + catch (...) + { + AbortMessage(); + throw; + } + } + + template + void PushMessage(const char* pszCommand, const T1& a1, const T2& a2, const T3& a3, const T4& a4) + { + try + { + BeginMessage(pszCommand); + ssSend << a1 << a2 << a3 << a4; + EndMessage(); + } + catch (...) + { + AbortMessage(); + throw; + } + } + + template + void PushMessage(const char* pszCommand, const T1& a1, const T2& a2, const T3& a3, const T4& a4, const T5& a5) + { + try + { + BeginMessage(pszCommand); + ssSend << a1 << a2 << a3 << a4 << a5; + EndMessage(); + } + catch (...) + { + AbortMessage(); + throw; + } + } + + template + void PushMessage(const char* pszCommand, const T1& a1, const T2& a2, const T3& a3, const T4& a4, const T5& a5, const T6& a6) + { + try + { + BeginMessage(pszCommand); + ssSend << a1 << a2 << a3 << a4 << a5 << a6; + EndMessage(); + } + catch (...) + { + AbortMessage(); + throw; + } + } + + template + void PushMessage(const char* pszCommand, const T1& a1, const T2& a2, const T3& a3, const T4& a4, const T5& a5, const T6& a6, const T7& a7) + { + try + { + BeginMessage(pszCommand); + ssSend << a1 << a2 << a3 << a4 << a5 << a6 << a7; + EndMessage(); + } + catch (...) + { + AbortMessage(); + throw; + } + } + + template + void PushMessage(const char* pszCommand, const T1& a1, const T2& a2, const T3& a3, const T4& a4, const T5& a5, const T6& a6, const T7& a7, const T8& a8) + { + try + { + BeginMessage(pszCommand); + ssSend << a1 << a2 << a3 << a4 << a5 << a6 << a7 << a8; + EndMessage(); + } + catch (...) + { + AbortMessage(); + throw; + } + } + + template + void PushMessage(const char* pszCommand, const T1& a1, const T2& a2, const T3& a3, const T4& a4, const T5& a5, const T6& a6, const T7& a7, const T8& a8, const T9& a9) + { + try + { + BeginMessage(pszCommand); + ssSend << a1 << a2 << a3 << a4 << a5 << a6 << a7 << a8 << a9; + EndMessage(); + } + catch (...) + { + AbortMessage(); + throw; + } + } + + + void PushRequest(const char* pszCommand, + void (*fn)(void*, CDataStream&), void* param1) + { + uint256 hashReply; + RAND_bytes((unsigned char*)&hashReply, sizeof(hashReply)); + + { + LOCK(cs_mapRequests); + mapRequests[hashReply] = CRequestTracker(fn, param1); + } + + PushMessage(pszCommand, hashReply); + } + + template + void PushRequest(const char* pszCommand, const T1& a1, + void (*fn)(void*, CDataStream&), void* param1) + { + uint256 hashReply; + RAND_bytes((unsigned char*)&hashReply, sizeof(hashReply)); + + { + LOCK(cs_mapRequests); + mapRequests[hashReply] = CRequestTracker(fn, param1); + } + + PushMessage(pszCommand, hashReply, a1); + } + + template + void PushRequest(const char* pszCommand, const T1& a1, const T2& a2, + void (*fn)(void*, CDataStream&), void* param1) + { + uint256 hashReply; + RAND_bytes((unsigned char*)&hashReply, sizeof(hashReply)); + + { + LOCK(cs_mapRequests); + mapRequests[hashReply] = CRequestTracker(fn, param1); + } + + PushMessage(pszCommand, hashReply, a1, a2); + } + + + + void PushGetBlocks(CBlockIndex* pindexBegin, uint256 hashEnd); + bool IsSubscribed(unsigned int nChannel); + void Subscribe(unsigned int nChannel, unsigned int nHops=0); + void CancelSubscribe(unsigned int nChannel); + void CloseSocketDisconnect(); + + // Denial-of-service detection/prevention + // The idea is to detect peers that are behaving + // badly and disconnect/ban them, but do it in a + // one-coding-mistake-won't-shatter-the-entire-network + // way. + // IMPORTANT: There should be nothing I can give a + // node that it will forward on that will make that + // node's peers drop it. If there is, an attacker + // can isolate a node and/or try to split the network. + // Dropping a node for sending stuff that is invalid + // now but might be valid in a later version is also + // dangerous, because it can cause a network split + // between nodes running old code and nodes running + // new code. + static void ClearBanned(); // needed for unit testing + static bool IsBanned(CNetAddr ip); + bool Misbehaving(int howmuch); // 1 == a little, 100 == a lot + void copyStats(CNodeStats &stats); + + // Network stats + static void RecordBytesRecv(uint64_t bytes); + static void RecordBytesSent(uint64_t bytes); + + static uint64_t GetTotalBytesRecv(); + static uint64_t GetTotalBytesSent(); +}; + +inline void RelayInventory(const CInv& inv) +{ + // Put on lists to offer to the other nodes + { + LOCK(cs_vNodes); + BOOST_FOREACH(CNode* pnode, vNodes) + pnode->PushInventory(inv); + } +} + +class CTransaction; +void RelayTransaction(const CTransaction& tx, const uint256& hash); +void RelayTransaction(const CTransaction& tx, const uint256& hash, const CDataStream& ss); + + +#endif diff --git a/src/netbase.cpp b/src/netbase.cpp new file mode 100644 index 0000000..ef5f4b5 --- /dev/null +++ b/src/netbase.cpp @@ -0,0 +1,1151 @@ +// Copyright (c) 2009-2010 Satoshi Nakamoto +// Copyright (c) 2009-2012 The Bitcoin developers +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include "netbase.h" +#include "util.h" +#include "sync.h" + +#ifndef WIN32 +#include +#endif + +#include "strlcpy.h" +#include // for to_lower() + +using namespace std; + +// Settings +static proxyType proxyInfo[NET_MAX]; +static proxyType nameproxyInfo; +static CCriticalSection cs_proxyInfos; +int nConnectTimeout = 5000; +bool fNameLookup = false; + +static const unsigned char pchIPv4[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff }; + +enum Network ParseNetwork(std::string net) { + boost::to_lower(net); + if (net == "ipv4") return NET_IPV4; + if (net == "ipv6") return NET_IPV6; + if (net == "tor") return NET_TOR; + if (net == "i2p") return NET_I2P; + return NET_UNROUTABLE; +} + +void SplitHostPort(std::string in, int &portOut, std::string &hostOut) { + size_t colon = in.find_last_of(':'); + // if a : is found, and it either follows a [...], or no other : is in the string, treat it as port separator + bool fHaveColon = colon != in.npos; + bool fBracketed = fHaveColon && (in[0]=='[' && in[colon-1]==']'); // if there is a colon, and in[0]=='[', colon is not 0, so in[colon-1] is safe + bool fMultiColon = fHaveColon && (in.find_last_of(':',colon-1) != in.npos); + if (fHaveColon && (colon==0 || fBracketed || !fMultiColon)) { + char *endp = NULL; + int n = strtol(in.c_str() + colon + 1, &endp, 10); + if (endp && *endp == 0 && n >= 0) { + in = in.substr(0, colon); + if (n > 0 && n < 0x10000) + portOut = n; + } + } + if (in.size()>0 && in[0] == '[' && in[in.size()-1] == ']') + hostOut = in.substr(1, in.size()-2); + else + hostOut = in; +} + +bool static LookupIntern(const char *pszName, std::vector& vIP, unsigned int nMaxSolutions, bool fAllowLookup) +{ + vIP.clear(); + + { + CNetAddr addr; + if (addr.SetSpecial(std::string(pszName))) { + vIP.push_back(addr); + return true; + } + } + + struct addrinfo aiHint; + memset(&aiHint, 0, sizeof(struct addrinfo)); + + aiHint.ai_socktype = SOCK_STREAM; + aiHint.ai_protocol = IPPROTO_TCP; +#ifdef WIN32 + aiHint.ai_family = AF_UNSPEC; + aiHint.ai_flags = fAllowLookup ? 0 : AI_NUMERICHOST; +#else + aiHint.ai_family = AF_UNSPEC; + aiHint.ai_flags = fAllowLookup ? AI_ADDRCONFIG : AI_NUMERICHOST; +#endif + struct addrinfo *aiRes = NULL; + int nErr = getaddrinfo(pszName, NULL, &aiHint, &aiRes); + if (nErr) + return false; + + struct addrinfo *aiTrav = aiRes; + while (aiTrav != NULL && (nMaxSolutions == 0 || vIP.size() < nMaxSolutions)) + { + if (aiTrav->ai_family == AF_INET) + { + assert(aiTrav->ai_addrlen >= sizeof(sockaddr_in)); + vIP.push_back(CNetAddr(((struct sockaddr_in*)(aiTrav->ai_addr))->sin_addr)); + } + + if (aiTrav->ai_family == AF_INET6) + { + assert(aiTrav->ai_addrlen >= sizeof(sockaddr_in6)); + vIP.push_back(CNetAddr(((struct sockaddr_in6*)(aiTrav->ai_addr))->sin6_addr)); + } + + aiTrav = aiTrav->ai_next; + } + + freeaddrinfo(aiRes); + + return (vIP.size() > 0); +} + +bool LookupHost(const char *pszName, std::vector& vIP, unsigned int nMaxSolutions, bool fAllowLookup) +{ + if (pszName[0] == 0) + return false; + char psz[256]; + char *pszHost = psz; + strlcpy(psz, pszName, sizeof(psz)); + if (psz[0] == '[' && psz[strlen(psz)-1] == ']') + { + pszHost = psz+1; + psz[strlen(psz)-1] = 0; + } + + return LookupIntern(pszHost, vIP, nMaxSolutions, fAllowLookup); +} + +bool Lookup(const char *pszName, std::vector& vAddr, int portDefault, bool fAllowLookup, unsigned int nMaxSolutions) +{ + if (pszName[0] == 0) + return false; + int port = portDefault; + std::string hostname = ""; + SplitHostPort(std::string(pszName), port, hostname); + + std::vector vIP; + bool fRet = LookupIntern(hostname.c_str(), vIP, nMaxSolutions, fAllowLookup); + if (!fRet) + return false; + vAddr.resize(vIP.size()); + for (unsigned int i = 0; i < vIP.size(); i++) + vAddr[i] = CService(vIP[i], port); + return true; +} + +bool Lookup(const char *pszName, CService& addr, int portDefault, bool fAllowLookup) +{ + std::vector vService; + bool fRet = Lookup(pszName, vService, portDefault, fAllowLookup, 1); + if (!fRet) + return false; + addr = vService[0]; + return true; +} + +bool LookupNumeric(const char *pszName, CService& addr, int portDefault) +{ + return Lookup(pszName, addr, portDefault, false); +} + +bool static Socks4(const CService &addrDest, SOCKET& hSocket) +{ + printf("SOCKS4 connecting %s\n", addrDest.ToString().c_str()); + if (!addrDest.IsIPv4()) + { + closesocket(hSocket); + return error("Proxy destination is not IPv4"); + } + char pszSocks4IP[] = "\4\1\0\0\0\0\0\0user"; + struct sockaddr_in addr; + socklen_t len = sizeof(addr); + if (!addrDest.GetSockAddr((struct sockaddr*)&addr, &len) || addr.sin_family != AF_INET) + { + closesocket(hSocket); + return error("Cannot get proxy destination address"); + } + memcpy(pszSocks4IP + 2, &addr.sin_port, 2); + memcpy(pszSocks4IP + 4, &addr.sin_addr, 4); + char* pszSocks4 = pszSocks4IP; + int nSize = sizeof(pszSocks4IP); + + int ret = send(hSocket, pszSocks4, nSize, MSG_NOSIGNAL); + if (ret != nSize) + { + closesocket(hSocket); + return error("Error sending to proxy"); + } + char pchRet[8]; + if (recv(hSocket, pchRet, 8, 0) != 8) + { + closesocket(hSocket); + return error("Error reading proxy response"); + } + if (pchRet[1] != 0x5a) + { + closesocket(hSocket); + if (pchRet[1] != 0x5b) + printf("ERROR: Proxy returned error %d\n", pchRet[1]); + return false; + } + printf("SOCKS4 connected %s\n", addrDest.ToString().c_str()); + return true; +} + +bool static Socks5(string strDest, int port, SOCKET& hSocket) +{ + printf("SOCKS5 connecting %s\n", strDest.c_str()); + if (strDest.size() > 255) + { + closesocket(hSocket); + return error("Hostname too long"); + } + char pszSocks5Init[] = "\5\1\0"; + char *pszSocks5 = pszSocks5Init; + ssize_t nSize = sizeof(pszSocks5Init) - 1; + + ssize_t ret = send(hSocket, pszSocks5, nSize, MSG_NOSIGNAL); + if (ret != nSize) + { + closesocket(hSocket); + return error("Error sending to proxy"); + } + char pchRet1[2]; + if (recv(hSocket, pchRet1, 2, 0) != 2) + { + closesocket(hSocket); + return error("Error reading proxy response"); + } + if (pchRet1[0] != 0x05 || pchRet1[1] != 0x00) + { + closesocket(hSocket); + return error("Proxy failed to initialize"); + } + string strSocks5("\5\1"); + strSocks5 += '\000'; strSocks5 += '\003'; + strSocks5 += static_cast(std::min((int)strDest.size(), 255)); + strSocks5 += strDest; + strSocks5 += static_cast((port >> 8) & 0xFF); + strSocks5 += static_cast((port >> 0) & 0xFF); + ret = send(hSocket, strSocks5.c_str(), strSocks5.size(), MSG_NOSIGNAL); + if (ret != (ssize_t)strSocks5.size()) + { + closesocket(hSocket); + return error("Error sending to proxy"); + } + char pchRet2[4]; + if (recv(hSocket, pchRet2, 4, 0) != 4) + { + closesocket(hSocket); + return error("Error reading proxy response"); + } + if (pchRet2[0] != 0x05) + { + closesocket(hSocket); + return error("Proxy failed to accept request"); + } + if (pchRet2[1] != 0x00) + { + closesocket(hSocket); + switch (pchRet2[1]) + { + case 0x01: return error("Proxy error: general failure"); + case 0x02: return error("Proxy error: connection not allowed"); + case 0x03: return error("Proxy error: network unreachable"); + case 0x04: return error("Proxy error: host unreachable"); + case 0x05: return error("Proxy error: connection refused"); + case 0x06: return error("Proxy error: TTL expired"); + case 0x07: return error("Proxy error: protocol error"); + case 0x08: return error("Proxy error: address type not supported"); + default: return error("Proxy error: unknown"); + } + } + if (pchRet2[2] != 0x00) + { + closesocket(hSocket); + return error("Error: malformed proxy response"); + } + char pchRet3[256]; + switch (pchRet2[3]) + { + case 0x01: ret = recv(hSocket, pchRet3, 4, 0) != 4; break; + case 0x04: ret = recv(hSocket, pchRet3, 16, 0) != 16; break; + case 0x03: + { + ret = recv(hSocket, pchRet3, 1, 0) != 1; + if (ret) { + closesocket(hSocket); + return error("Error reading from proxy"); + } + int nRecv = pchRet3[0]; + ret = recv(hSocket, pchRet3, nRecv, 0) != nRecv; + break; + } + default: closesocket(hSocket); return error("Error: malformed proxy response"); + } + if (ret) + { + closesocket(hSocket); + return error("Error reading from proxy"); + } + if (recv(hSocket, pchRet3, 2, 0) != 2) + { + closesocket(hSocket); + return error("Error reading from proxy"); + } + printf("SOCKS5 connected %s\n", strDest.c_str()); + return true; +} + +bool static ConnectSocketDirectly(const CService &addrConnect, SOCKET& hSocketRet, int nTimeout) +{ + hSocketRet = INVALID_SOCKET; + + struct sockaddr_storage sockaddr; + socklen_t len = sizeof(sockaddr); + if (!addrConnect.GetSockAddr((struct sockaddr*)&sockaddr, &len)) { + printf("Cannot connect to %s: unsupported network\n", addrConnect.ToString().c_str()); + return false; + } + + SOCKET hSocket = socket(((struct sockaddr*)&sockaddr)->sa_family, SOCK_STREAM, IPPROTO_TCP); + if (hSocket == INVALID_SOCKET) + return false; +#ifdef SO_NOSIGPIPE + int set = 1; + setsockopt(hSocket, SOL_SOCKET, SO_NOSIGPIPE, (void*)&set, sizeof(int)); +#endif + +#ifdef WIN32 + u_long fNonblock = 1; + if (ioctlsocket(hSocket, FIONBIO, &fNonblock) == SOCKET_ERROR) +#else + int fFlags = fcntl(hSocket, F_GETFL, 0); + if (fcntl(hSocket, F_SETFL, fFlags | O_NONBLOCK) == -1) +#endif + { + closesocket(hSocket); + return false; + } + + if (connect(hSocket, (struct sockaddr*)&sockaddr, len) == SOCKET_ERROR) + { + int nErr = WSAGetLastError(); + // WSAEINVAL is here because some legacy version of winsock uses it + if (nErr == WSAEINPROGRESS || nErr == WSAEWOULDBLOCK || nErr == WSAEINVAL) + { + struct timeval timeout; + timeout.tv_sec = nTimeout / 1000; + timeout.tv_usec = (nTimeout % 1000) * 1000; + + fd_set fdset; + FD_ZERO(&fdset); + FD_SET(hSocket, &fdset); + int nRet = select(hSocket + 1, NULL, &fdset, NULL, &timeout); + if (nRet == 0) + { + printf("connection timeout\n"); + closesocket(hSocket); + return false; + } + if (nRet == SOCKET_ERROR) + { + printf("select() for connection failed: %i\n",WSAGetLastError()); + closesocket(hSocket); + return false; + } + socklen_t nRetSize = sizeof(nRet); +#ifdef WIN32 + if (getsockopt(hSocket, SOL_SOCKET, SO_ERROR, (char*)(&nRet), &nRetSize) == SOCKET_ERROR) +#else + if (getsockopt(hSocket, SOL_SOCKET, SO_ERROR, &nRet, &nRetSize) == SOCKET_ERROR) +#endif + { + printf("getsockopt() for connection failed: %i\n",WSAGetLastError()); + closesocket(hSocket); + return false; + } + if (nRet != 0) + { + printf("connect() failed after select(): %s\n",strerror(nRet)); + closesocket(hSocket); + return false; + } + } +#ifdef WIN32 + else if (WSAGetLastError() != WSAEISCONN) +#else + else +#endif + { + printf("connect() failed: %i\n",WSAGetLastError()); + closesocket(hSocket); + return false; + } + } + + // this isn't even strictly necessary + // CNode::ConnectNode immediately turns the socket back to non-blocking + // but we'll turn it back to blocking just in case +#ifdef WIN32 + fNonblock = 0; + if (ioctlsocket(hSocket, FIONBIO, &fNonblock) == SOCKET_ERROR) +#else + fFlags = fcntl(hSocket, F_GETFL, 0); + if (fcntl(hSocket, F_SETFL, fFlags & !O_NONBLOCK) == SOCKET_ERROR) +#endif + { + closesocket(hSocket); + return false; + } + + hSocketRet = hSocket; + return true; +} + +bool SetProxy(enum Network net, CService addrProxy, int nSocksVersion) { + assert(net >= 0 && net < NET_MAX); + if (nSocksVersion != 0 && nSocksVersion != 4 && nSocksVersion != 5) + return false; + if (nSocksVersion != 0 && !addrProxy.IsValid()) + return false; + LOCK(cs_proxyInfos); + proxyInfo[net] = std::make_pair(addrProxy, nSocksVersion); + return true; +} + +bool GetProxy(enum Network net, proxyType &proxyInfoOut) { + assert(net >= 0 && net < NET_MAX); + LOCK(cs_proxyInfos); + if (!proxyInfo[net].second) + return false; + proxyInfoOut = proxyInfo[net]; + return true; +} + +bool SetNameProxy(CService addrProxy, int nSocksVersion) { + if (nSocksVersion != 0 && nSocksVersion != 5) + return false; + if (nSocksVersion != 0 && !addrProxy.IsValid()) + return false; + LOCK(cs_proxyInfos); + nameproxyInfo = std::make_pair(addrProxy, nSocksVersion); + return true; +} + +bool GetNameProxy(proxyType &nameproxyInfoOut) { + LOCK(cs_proxyInfos); + if (!nameproxyInfo.second) + return false; + nameproxyInfoOut = nameproxyInfo; + return true; +} + +bool HaveNameProxy() { + LOCK(cs_proxyInfos); + return nameproxyInfo.second != 0; +} + +bool IsProxy(const CNetAddr &addr) { + LOCK(cs_proxyInfos); + for (int i = 0; i < NET_MAX; i++) { + if (proxyInfo[i].second && (addr == (CNetAddr)proxyInfo[i].first)) + return true; + } + return false; +} + +bool ConnectSocket(const CService &addrDest, SOCKET& hSocketRet, int nTimeout) +{ + proxyType proxy; + + // no proxy needed + if (!GetProxy(addrDest.GetNetwork(), proxy)) + return ConnectSocketDirectly(addrDest, hSocketRet, nTimeout); + + SOCKET hSocket = INVALID_SOCKET; + + // first connect to proxy server + if (!ConnectSocketDirectly(proxy.first, hSocket, nTimeout)) + return false; + + // do socks negotiation + switch (proxy.second) { + case 4: + if (!Socks4(addrDest, hSocket)) + return false; + break; + case 5: + if (!Socks5(addrDest.ToStringIP(), addrDest.GetPort(), hSocket)) + return false; + break; + default: + closesocket(hSocket); + return false; + } + + hSocketRet = hSocket; + return true; +} + +bool ConnectSocketByName(CService &addr, SOCKET& hSocketRet, const char *pszDest, int portDefault, int nTimeout) +{ + string strDest; + int port = portDefault; + SplitHostPort(string(pszDest), port, strDest); + + SOCKET hSocket = INVALID_SOCKET; + + proxyType nameproxy; + GetNameProxy(nameproxy); + + CService addrResolved(CNetAddr(strDest, fNameLookup && !nameproxy.second), port); + if (addrResolved.IsValid()) { + addr = addrResolved; + return ConnectSocket(addr, hSocketRet, nTimeout); + } + addr = CService("0.0.0.0:0"); + if (!nameproxy.second) + return false; + if (!ConnectSocketDirectly(nameproxy.first, hSocket, nTimeout)) + return false; + + switch(nameproxy.second) { + default: + case 4: + closesocket(hSocket); + return false; + case 5: + if (!Socks5(strDest, port, hSocket)) + return false; + break; + } + + hSocketRet = hSocket; + return true; +} + +void CNetAddr::Init() +{ + memset(ip, 0, sizeof(ip)); +} + +void CNetAddr::SetIP(const CNetAddr& ipIn) +{ + memcpy(ip, ipIn.ip, sizeof(ip)); +} + +static const unsigned char pchOnionCat[] = {0xFD,0x87,0xD8,0x7E,0xEB,0x43}; +static const unsigned char pchGarliCat[] = {0xFD,0x60,0xDB,0x4D,0xDD,0xB5}; + +bool CNetAddr::SetSpecial(const std::string &strName) +{ + if (strName.size()>6 && strName.substr(strName.size() - 6, 6) == ".onion") { + std::vector vchAddr = DecodeBase32(strName.substr(0, strName.size() - 6).c_str()); + if (vchAddr.size() != 16-sizeof(pchOnionCat)) + return false; + memcpy(ip, pchOnionCat, sizeof(pchOnionCat)); + for (unsigned int i=0; i<16-sizeof(pchOnionCat); i++) + ip[i + sizeof(pchOnionCat)] = vchAddr[i]; + return true; + } + if (strName.size()>11 && strName.substr(strName.size() - 11, 11) == ".oc.b32.i2p") { + std::vector vchAddr = DecodeBase32(strName.substr(0, strName.size() - 11).c_str()); + if (vchAddr.size() != 16-sizeof(pchGarliCat)) + return false; + memcpy(ip, pchOnionCat, sizeof(pchGarliCat)); + for (unsigned int i=0; i<16-sizeof(pchGarliCat); i++) + ip[i + sizeof(pchGarliCat)] = vchAddr[i]; + return true; + } + return false; +} + +CNetAddr::CNetAddr() +{ + Init(); +} + +CNetAddr::CNetAddr(const struct in_addr& ipv4Addr) +{ + memcpy(ip, pchIPv4, 12); + memcpy(ip+12, &ipv4Addr, 4); +} + +CNetAddr::CNetAddr(const struct in6_addr& ipv6Addr) +{ + memcpy(ip, &ipv6Addr, 16); +} + +CNetAddr::CNetAddr(const char *pszIp, bool fAllowLookup) +{ + Init(); + std::vector vIP; + if (LookupHost(pszIp, vIP, 1, fAllowLookup)) + *this = vIP[0]; +} + +CNetAddr::CNetAddr(const std::string &strIp, bool fAllowLookup) +{ + Init(); + std::vector vIP; + if (LookupHost(strIp.c_str(), vIP, 1, fAllowLookup)) + *this = vIP[0]; +} + +unsigned int CNetAddr::GetByte(int n) const +{ + return ip[15-n]; +} + +bool CNetAddr::IsIPv4() const +{ + return (memcmp(ip, pchIPv4, sizeof(pchIPv4)) == 0); +} + +bool CNetAddr::IsIPv6() const +{ + return (!IsIPv4() && !IsTor() && !IsI2P()); +} + +bool CNetAddr::IsRFC1918() const +{ + return IsIPv4() && ( + GetByte(3) == 10 || + (GetByte(3) == 192 && GetByte(2) == 168) || + (GetByte(3) == 172 && (GetByte(2) >= 16 && GetByte(2) <= 31))); +} + +bool CNetAddr::IsRFC3927() const +{ + return IsIPv4() && (GetByte(3) == 169 && GetByte(2) == 254); +} + +bool CNetAddr::IsRFC3849() const +{ + return GetByte(15) == 0x20 && GetByte(14) == 0x01 && GetByte(13) == 0x0D && GetByte(12) == 0xB8; +} + +bool CNetAddr::IsRFC3964() const +{ + return (GetByte(15) == 0x20 && GetByte(14) == 0x02); +} + +bool CNetAddr::IsRFC6052() const +{ + static const unsigned char pchRFC6052[] = {0,0x64,0xFF,0x9B,0,0,0,0,0,0,0,0}; + return (memcmp(ip, pchRFC6052, sizeof(pchRFC6052)) == 0); +} + +bool CNetAddr::IsRFC4380() const +{ + return (GetByte(15) == 0x20 && GetByte(14) == 0x01 && GetByte(13) == 0 && GetByte(12) == 0); +} + +bool CNetAddr::IsRFC4862() const +{ + static const unsigned char pchRFC4862[] = {0xFE,0x80,0,0,0,0,0,0}; + return (memcmp(ip, pchRFC4862, sizeof(pchRFC4862)) == 0); +} + +bool CNetAddr::IsRFC4193() const +{ + return ((GetByte(15) & 0xFE) == 0xFC); +} + +bool CNetAddr::IsRFC6145() const +{ + static const unsigned char pchRFC6145[] = {0,0,0,0,0,0,0,0,0xFF,0xFF,0,0}; + return (memcmp(ip, pchRFC6145, sizeof(pchRFC6145)) == 0); +} + +bool CNetAddr::IsRFC4843() const +{ + return (GetByte(15) == 0x20 && GetByte(14) == 0x01 && GetByte(13) == 0x00 && (GetByte(12) & 0xF0) == 0x10); +} + +bool CNetAddr::IsTor() const +{ + return (memcmp(ip, pchOnionCat, sizeof(pchOnionCat)) == 0); +} + +bool CNetAddr::IsI2P() const +{ + return (memcmp(ip, pchGarliCat, sizeof(pchGarliCat)) == 0); +} + +bool CNetAddr::IsLocal() const +{ + // IPv4 loopback + if (IsIPv4() && (GetByte(3) == 127 || GetByte(3) == 0)) + return true; + + // IPv6 loopback (::1/128) + static const unsigned char pchLocal[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1}; + if (memcmp(ip, pchLocal, 16) == 0) + return true; + + return false; +} + +bool CNetAddr::IsMulticast() const +{ + return (IsIPv4() && (GetByte(3) & 0xF0) == 0xE0) + || (GetByte(15) == 0xFF); +} + +bool CNetAddr::IsValid() const +{ + // Cleanup 3-byte shifted addresses caused by garbage in size field + // of addr messages from versions before 0.2.9 checksum. + // Two consecutive addr messages look like this: + // header20 vectorlen3 addr26 addr26 addr26 header20 vectorlen3 addr26 addr26 addr26... + // so if the first length field is garbled, it reads the second batch + // of addr misaligned by 3 bytes. + if (memcmp(ip, pchIPv4+3, sizeof(pchIPv4)-3) == 0) + return false; + + // unspecified IPv6 address (::/128) + unsigned char ipNone[16] = {}; + if (memcmp(ip, ipNone, 16) == 0) + return false; + + // documentation IPv6 address + if (IsRFC3849()) + return false; + + if (IsIPv4()) + { + // INADDR_NONE + uint32_t ipNone = INADDR_NONE; + if (memcmp(ip+12, &ipNone, 4) == 0) + return false; + + // 0 + ipNone = 0; + if (memcmp(ip+12, &ipNone, 4) == 0) + return false; + } + + return true; +} + +bool CNetAddr::IsRoutable() const +{ + return IsValid() && !(IsRFC1918() || IsRFC3927() || IsRFC4862() || (IsRFC4193() && !IsTor() && !IsI2P()) || IsRFC4843() || IsLocal()); +} + +enum Network CNetAddr::GetNetwork() const +{ + if (!IsRoutable()) + return NET_UNROUTABLE; + + if (IsIPv4()) + return NET_IPV4; + + if (IsTor()) + return NET_TOR; + + if (IsI2P()) + return NET_I2P; + + return NET_IPV6; +} + +std::string CNetAddr::ToStringIP() const +{ + if (IsTor()) + return EncodeBase32(&ip[6], 10) + ".onion"; + if (IsI2P()) + return EncodeBase32(&ip[6], 10) + ".oc.b32.i2p"; + CService serv(*this, 0); + struct sockaddr_storage sockaddr; + socklen_t socklen = sizeof(sockaddr); + if (serv.GetSockAddr((struct sockaddr*)&sockaddr, &socklen)) { + char name[1025] = ""; + if (!getnameinfo((const struct sockaddr*)&sockaddr, socklen, name, sizeof(name), NULL, 0, NI_NUMERICHOST)) + return std::string(name); + } + if (IsIPv4()) + return strprintf("%u.%u.%u.%u", GetByte(3), GetByte(2), GetByte(1), GetByte(0)); + else + return strprintf("%x:%x:%x:%x:%x:%x:%x:%x", + GetByte(15) << 8 | GetByte(14), GetByte(13) << 8 | GetByte(12), + GetByte(11) << 8 | GetByte(10), GetByte(9) << 8 | GetByte(8), + GetByte(7) << 8 | GetByte(6), GetByte(5) << 8 | GetByte(4), + GetByte(3) << 8 | GetByte(2), GetByte(1) << 8 | GetByte(0)); +} + +std::string CNetAddr::ToString() const +{ + return ToStringIP(); +} + +bool operator==(const CNetAddr& a, const CNetAddr& b) +{ + return (memcmp(a.ip, b.ip, 16) == 0); +} + +bool operator!=(const CNetAddr& a, const CNetAddr& b) +{ + return (memcmp(a.ip, b.ip, 16) != 0); +} + +bool operator<(const CNetAddr& a, const CNetAddr& b) +{ + return (memcmp(a.ip, b.ip, 16) < 0); +} + +bool CNetAddr::GetInAddr(struct in_addr* pipv4Addr) const +{ + if (!IsIPv4()) + return false; + memcpy(pipv4Addr, ip+12, 4); + return true; +} + +bool CNetAddr::GetIn6Addr(struct in6_addr* pipv6Addr) const +{ + memcpy(pipv6Addr, ip, 16); + return true; +} + +// get canonical identifier of an address' group +// no two connections will be attempted to addresses with the same group +std::vector CNetAddr::GetGroup() const +{ + std::vector vchRet; + int nClass = NET_IPV6; + int nStartByte = 0; + int nBits = 16; + + // all local addresses belong to the same group + if (IsLocal()) + { + nClass = 255; + nBits = 0; + } + + // all unroutable addresses belong to the same group + if (!IsRoutable()) + { + nClass = NET_UNROUTABLE; + nBits = 0; + } + // for IPv4 addresses, '1' + the 16 higher-order bits of the IP + // includes mapped IPv4, SIIT translated IPv4, and the well-known prefix + else if (IsIPv4() || IsRFC6145() || IsRFC6052()) + { + nClass = NET_IPV4; + nStartByte = 12; + } + // for 6to4 tunnelled addresses, use the encapsulated IPv4 address + else if (IsRFC3964()) + { + nClass = NET_IPV4; + nStartByte = 2; + } + // for Teredo-tunnelled IPv6 addresses, use the encapsulated IPv4 address + else if (IsRFC4380()) + { + vchRet.push_back(NET_IPV4); + vchRet.push_back(GetByte(3) ^ 0xFF); + vchRet.push_back(GetByte(2) ^ 0xFF); + return vchRet; + } + else if (IsTor()) + { + nClass = NET_TOR; + nStartByte = 6; + nBits = 4; + } + else if (IsI2P()) + { + nClass = NET_I2P; + nStartByte = 6; + nBits = 4; + } + // for he.net, use /36 groups + else if (GetByte(15) == 0x20 && GetByte(14) == 0x11 && GetByte(13) == 0x04 && GetByte(12) == 0x70) + nBits = 36; + // for the rest of the IPv6 network, use /32 groups + else + nBits = 32; + + vchRet.push_back(nClass); + while (nBits >= 8) + { + vchRet.push_back(GetByte(15 - nStartByte)); + nStartByte++; + nBits -= 8; + } + if (nBits > 0) + vchRet.push_back(GetByte(15 - nStartByte) | ((1 << nBits) - 1)); + + return vchRet; +} + +uint64_t CNetAddr::GetHash() const +{ + uint256 hash = Hash(&ip[0], &ip[16]); + uint64_t nRet; + memcpy(&nRet, &hash, sizeof(nRet)); + return nRet; +} + +void CNetAddr::print() const +{ + printf("CNetAddr(%s)\n", ToString().c_str()); +} + +// private extensions to enum Network, only returned by GetExtNetwork, +// and only used in GetReachabilityFrom +static const int NET_UNKNOWN = NET_MAX + 0; +static const int NET_TEREDO = NET_MAX + 1; +int static GetExtNetwork(const CNetAddr *addr) +{ + if (addr == NULL) + return NET_UNKNOWN; + if (addr->IsRFC4380()) + return NET_TEREDO; + return addr->GetNetwork(); +} + +/** Calculates a metric for how reachable (*this) is from a given partner */ +int CNetAddr::GetReachabilityFrom(const CNetAddr *paddrPartner) const +{ + enum Reachability { + REACH_UNREACHABLE, + REACH_DEFAULT, + REACH_TEREDO, + REACH_IPV6_WEAK, + REACH_IPV4, + REACH_IPV6_STRONG, + REACH_PRIVATE + }; + + if (!IsRoutable()) + return REACH_UNREACHABLE; + + int ourNet = GetExtNetwork(this); + int theirNet = GetExtNetwork(paddrPartner); + bool fTunnel = IsRFC3964() || IsRFC6052() || IsRFC6145(); + + switch(theirNet) { + case NET_IPV4: + switch(ourNet) { + default: return REACH_DEFAULT; + case NET_IPV4: return REACH_IPV4; + } + case NET_IPV6: + switch(ourNet) { + default: return REACH_DEFAULT; + case NET_TEREDO: return REACH_TEREDO; + case NET_IPV4: return REACH_IPV4; + case NET_IPV6: return fTunnel ? REACH_IPV6_WEAK : REACH_IPV6_STRONG; // only prefer giving our IPv6 address if it's not tunnelled + } + case NET_TOR: + switch(ourNet) { + default: return REACH_DEFAULT; + case NET_IPV4: return REACH_IPV4; // Tor users can connect to IPv4 as well + case NET_TOR: return REACH_PRIVATE; + } + case NET_I2P: + switch(ourNet) { + default: return REACH_DEFAULT; + case NET_I2P: return REACH_PRIVATE; + } + case NET_TEREDO: + switch(ourNet) { + default: return REACH_DEFAULT; + case NET_TEREDO: return REACH_TEREDO; + case NET_IPV6: return REACH_IPV6_WEAK; + case NET_IPV4: return REACH_IPV4; + } + case NET_UNKNOWN: + case NET_UNROUTABLE: + default: + switch(ourNet) { + default: return REACH_DEFAULT; + case NET_TEREDO: return REACH_TEREDO; + case NET_IPV6: return REACH_IPV6_WEAK; + case NET_IPV4: return REACH_IPV4; + case NET_I2P: return REACH_PRIVATE; // assume connections from unroutable addresses are + case NET_TOR: return REACH_PRIVATE; // either from Tor/I2P, or don't care about our address + } + } +} + +void CService::Init() +{ + port = 0; +} + +CService::CService() +{ + Init(); +} + +CService::CService(const CNetAddr& cip, unsigned short portIn) : CNetAddr(cip), port(portIn) +{ +} + +CService::CService(const struct in_addr& ipv4Addr, unsigned short portIn) : CNetAddr(ipv4Addr), port(portIn) +{ +} + +CService::CService(const struct in6_addr& ipv6Addr, unsigned short portIn) : CNetAddr(ipv6Addr), port(portIn) +{ +} + +CService::CService(const struct sockaddr_in& addr) : CNetAddr(addr.sin_addr), port(ntohs(addr.sin_port)) +{ + assert(addr.sin_family == AF_INET); +} + +CService::CService(const struct sockaddr_in6 &addr) : CNetAddr(addr.sin6_addr), port(ntohs(addr.sin6_port)) +{ + assert(addr.sin6_family == AF_INET6); +} + +bool CService::SetSockAddr(const struct sockaddr *paddr) +{ + switch (paddr->sa_family) { + case AF_INET: + *this = CService(*(const struct sockaddr_in*)paddr); + return true; + case AF_INET6: + *this = CService(*(const struct sockaddr_in6*)paddr); + return true; + default: + return false; + } +} + +CService::CService(const char *pszIpPort, bool fAllowLookup) +{ + Init(); + CService ip; + if (Lookup(pszIpPort, ip, 0, fAllowLookup)) + *this = ip; +} + +CService::CService(const char *pszIpPort, int portDefault, bool fAllowLookup) +{ + Init(); + CService ip; + if (Lookup(pszIpPort, ip, portDefault, fAllowLookup)) + *this = ip; +} + +CService::CService(const std::string &strIpPort, bool fAllowLookup) +{ + Init(); + CService ip; + if (Lookup(strIpPort.c_str(), ip, 0, fAllowLookup)) + *this = ip; +} + +CService::CService(const std::string &strIpPort, int portDefault, bool fAllowLookup) +{ + Init(); + CService ip; + if (Lookup(strIpPort.c_str(), ip, portDefault, fAllowLookup)) + *this = ip; +} + +unsigned short CService::GetPort() const +{ + return port; +} + +bool operator==(const CService& a, const CService& b) +{ + return (CNetAddr)a == (CNetAddr)b && a.port == b.port; +} + +bool operator!=(const CService& a, const CService& b) +{ + return (CNetAddr)a != (CNetAddr)b || a.port != b.port; +} + +bool operator<(const CService& a, const CService& b) +{ + return (CNetAddr)a < (CNetAddr)b || ((CNetAddr)a == (CNetAddr)b && a.port < b.port); +} + +bool CService::GetSockAddr(struct sockaddr* paddr, socklen_t *addrlen) const +{ + if (IsIPv4()) { + if (*addrlen < (socklen_t)sizeof(struct sockaddr_in)) + return false; + *addrlen = sizeof(struct sockaddr_in); + struct sockaddr_in *paddrin = (struct sockaddr_in*)paddr; + memset(paddrin, 0, *addrlen); + if (!GetInAddr(&paddrin->sin_addr)) + return false; + paddrin->sin_family = AF_INET; + paddrin->sin_port = htons(port); + return true; + } + if (IsIPv6()) { + if (*addrlen < (socklen_t)sizeof(struct sockaddr_in6)) + return false; + *addrlen = sizeof(struct sockaddr_in6); + struct sockaddr_in6 *paddrin6 = (struct sockaddr_in6*)paddr; + memset(paddrin6, 0, *addrlen); + if (!GetIn6Addr(&paddrin6->sin6_addr)) + return false; + paddrin6->sin6_family = AF_INET6; + paddrin6->sin6_port = htons(port); + return true; + } + return false; +} + +std::vector CService::GetKey() const +{ + std::vector vKey; + vKey.resize(18); + memcpy(&vKey[0], ip, 16); + vKey[16] = port / 0x100; + vKey[17] = port & 0x0FF; + return vKey; +} + +std::string CService::ToStringPort() const +{ + return strprintf("%u", port); +} + +std::string CService::ToStringIPPort() const +{ + if (IsIPv4() || IsTor() || IsI2P()) { + return ToStringIP() + ":" + ToStringPort(); + } else { + return "[" + ToStringIP() + "]:" + ToStringPort(); + } +} + +std::string CService::ToString() const +{ + return ToStringIPPort(); +} + +void CService::print() const +{ + printf("CService(%s)\n", ToString().c_str()); +} + +void CService::SetPort(unsigned short portIn) +{ + port = portIn; +} diff --git a/src/netbase.h b/src/netbase.h new file mode 100644 index 0000000..e052e80 --- /dev/null +++ b/src/netbase.h @@ -0,0 +1,146 @@ +// Copyright (c) 2009-2012 The Bitcoin developers +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. +#ifndef BITCOIN_NETBASE_H +#define BITCOIN_NETBASE_H + +#include +#include + +#include "serialize.h" +#include "compat.h" + +extern int nConnectTimeout; +extern bool fNameLookup; + +#ifdef WIN32 +// In MSVC, this is defined as a macro, undefine it to prevent a compile and link error +#undef SetPort +#endif + +enum Network +{ + NET_UNROUTABLE, + NET_IPV4, + NET_IPV6, + NET_TOR, + NET_I2P, + + NET_MAX, +}; + +/** IP address (IPv6, or IPv4 using mapped IPv6 range (::FFFF:0:0/96)) */ +class CNetAddr +{ + protected: + unsigned char ip[16]; // in network byte order + + public: + CNetAddr(); + CNetAddr(const struct in_addr& ipv4Addr); + explicit CNetAddr(const char *pszIp, bool fAllowLookup = false); + explicit CNetAddr(const std::string &strIp, bool fAllowLookup = false); + void Init(); + void SetIP(const CNetAddr& ip); + bool SetSpecial(const std::string &strName); // for Tor and I2P addresses + bool IsIPv4() const; // IPv4 mapped address (::FFFF:0:0/96, 0.0.0.0/0) + bool IsIPv6() const; // IPv6 address (not mapped IPv4, not Tor/I2P) + bool IsRFC1918() const; // IPv4 private networks (10.0.0.0/8, 192.168.0.0/16, 172.16.0.0/12) + bool IsRFC3849() const; // IPv6 documentation address (2001:0DB8::/32) + bool IsRFC3927() const; // IPv4 autoconfig (169.254.0.0/16) + bool IsRFC3964() const; // IPv6 6to4 tunnelling (2002::/16) + bool IsRFC4193() const; // IPv6 unique local (FC00::/15) + bool IsRFC4380() const; // IPv6 Teredo tunnelling (2001::/32) + bool IsRFC4843() const; // IPv6 ORCHID (2001:10::/28) + bool IsRFC4862() const; // IPv6 autoconfig (FE80::/64) + bool IsRFC6052() const; // IPv6 well-known prefix (64:FF9B::/96) + bool IsRFC6145() const; // IPv6 IPv4-translated address (::FFFF:0:0:0/96) + bool IsTor() const; + bool IsI2P() const; + bool IsLocal() const; + bool IsRoutable() const; + bool IsValid() const; + bool IsMulticast() const; + enum Network GetNetwork() const; + std::string ToString() const; + std::string ToStringIP() const; + unsigned int GetByte(int n) const; + uint64_t GetHash() const; + bool GetInAddr(struct in_addr* pipv4Addr) const; + std::vector GetGroup() const; + int GetReachabilityFrom(const CNetAddr *paddrPartner = NULL) const; + void print() const; + + CNetAddr(const struct in6_addr& pipv6Addr); + bool GetIn6Addr(struct in6_addr* pipv6Addr) const; + + friend bool operator==(const CNetAddr& a, const CNetAddr& b); + friend bool operator!=(const CNetAddr& a, const CNetAddr& b); + friend bool operator<(const CNetAddr& a, const CNetAddr& b); + + IMPLEMENT_SERIALIZE + ( + READWRITE(FLATDATA(ip)); + ) +}; + +/** A combination of a network address (CNetAddr) and a (TCP) port */ +class CService : public CNetAddr +{ + protected: + unsigned short port; // host order + + public: + CService(); + CService(const CNetAddr& ip, unsigned short port); + CService(const struct in_addr& ipv4Addr, unsigned short port); + CService(const struct sockaddr_in& addr); + explicit CService(const char *pszIpPort, int portDefault, bool fAllowLookup = false); + explicit CService(const char *pszIpPort, bool fAllowLookup = false); + explicit CService(const std::string& strIpPort, int portDefault, bool fAllowLookup = false); + explicit CService(const std::string& strIpPort, bool fAllowLookup = false); + void Init(); + void SetPort(unsigned short portIn); + unsigned short GetPort() const; + bool GetSockAddr(struct sockaddr* paddr, socklen_t *addrlen) const; + bool SetSockAddr(const struct sockaddr* paddr); + friend bool operator==(const CService& a, const CService& b); + friend bool operator!=(const CService& a, const CService& b); + friend bool operator<(const CService& a, const CService& b); + std::vector GetKey() const; + std::string ToString() const; + std::string ToStringPort() const; + std::string ToStringIPPort() const; + void print() const; + + CService(const struct in6_addr& ipv6Addr, unsigned short port); + CService(const struct sockaddr_in6& addr); + + IMPLEMENT_SERIALIZE + ( + CService* pthis = const_cast(this); + READWRITE(FLATDATA(ip)); + unsigned short portN = htons(port); + READWRITE(portN); + if (fRead) + pthis->port = ntohs(portN); + ) +}; + +typedef std::pair proxyType; + +enum Network ParseNetwork(std::string net); +void SplitHostPort(std::string in, int &portOut, std::string &hostOut); +bool SetProxy(enum Network net, CService addrProxy, int nSocksVersion = 5); +bool GetProxy(enum Network net, proxyType &proxyInfoOut); +bool IsProxy(const CNetAddr &addr); +bool SetNameProxy(CService addrProxy, int nSocksVersion = 5); +bool HaveNameProxy(); +bool LookupHost(const char *pszName, std::vector& vIP, unsigned int nMaxSolutions = 0, bool fAllowLookup = true); +bool Lookup(const char *pszName, CService& addr, int portDefault = 0, bool fAllowLookup = true); +bool Lookup(const char *pszName, std::vector& vAddr, int portDefault = 0, bool fAllowLookup = true, unsigned int nMaxSolutions = 0); +bool LookupNumeric(const char *pszName, CService& addr, int portDefault = 0); +bool ConnectSocket(const CService &addr, SOCKET& hSocketRet, int nTimeout = nConnectTimeout); +bool ConnectSocketByName(CService &addr, SOCKET& hSocketRet, const char *pszDest, int portDefault = 0, int nTimeout = nConnectTimeout); + +#endif diff --git a/src/noui.cpp b/src/noui.cpp new file mode 100644 index 0000000..965b39d --- /dev/null +++ b/src/noui.cpp @@ -0,0 +1,28 @@ +// Copyright (c) 2010 Satoshi Nakamoto +// Copyright (c) 2009-2012 The Bitcoin developers +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. +#include "ui_interface.h" +#include "init.h" +#include "bitcoinrpc.h" + +#include + +static int noui_ThreadSafeMessageBox(const std::string& message, const std::string& caption, int style) +{ + printf("%s: %s\n", caption.c_str(), message.c_str()); + fprintf(stderr, "%s: %s\n", caption.c_str(), message.c_str()); + return 4; +} + +static bool noui_ThreadSafeAskFee(int64_t nFeeRequired, const std::string& strCaption) +{ + return true; +} + +void noui_connect() +{ + // Connect bitcoind signal handlers + uiInterface.ThreadSafeMessageBox.connect(noui_ThreadSafeMessageBox); + uiInterface.ThreadSafeAskFee.connect(noui_ThreadSafeAskFee); +} diff --git a/src/obj/zerocoin/.gitignore b/src/obj/zerocoin/.gitignore new file mode 100644 index 0000000..d6b7ef3 --- /dev/null +++ b/src/obj/zerocoin/.gitignore @@ -0,0 +1,2 @@ +* +!.gitignore diff --git a/src/pbkdf2.cpp b/src/pbkdf2.cpp new file mode 100644 index 0000000..6d3f3dc --- /dev/null +++ b/src/pbkdf2.cpp @@ -0,0 +1,148 @@ +// Copyright (c) 2013 NovaCoin Developers + +#include +#include "pbkdf2.h" + +static inline uint32_t +be32dec(const void *pp) +{ + const uint8_t *p = (uint8_t const *)pp; + + return ((uint32_t)(p[3]) + ((uint32_t)(p[2]) << 8) + + ((uint32_t)(p[1]) << 16) + ((uint32_t)(p[0]) << 24)); +} + +static inline void +be32enc(void *pp, uint32_t x) +{ + uint8_t * p = (uint8_t *)pp; + + p[3] = x & 0xff; + p[2] = (x >> 8) & 0xff; + p[1] = (x >> 16) & 0xff; + p[0] = (x >> 24) & 0xff; +} + + + +/* Initialize an HMAC-SHA256 operation with the given key. */ +void +HMAC_SHA256_Init(HMAC_SHA256_CTX * ctx, const void * _K, size_t Klen) +{ + unsigned char pad[64]; + unsigned char khash[32]; + const unsigned char * K = (const unsigned char *)_K; + size_t i; + + /* If Klen > 64, the key is really SHA256(K). */ + if (Klen > 64) { + SHA256_Init(&ctx->ictx); + SHA256_Update(&ctx->ictx, K, Klen); + SHA256_Final(khash, &ctx->ictx); + K = khash; + Klen = 32; + } + + /* Inner SHA256 operation is SHA256(K xor [block of 0x36] || data). */ + SHA256_Init(&ctx->ictx); + memset(pad, 0x36, 64); + for (i = 0; i < Klen; i++) + pad[i] ^= K[i]; + SHA256_Update(&ctx->ictx, pad, 64); + + /* Outer SHA256 operation is SHA256(K xor [block of 0x5c] || hash). */ + SHA256_Init(&ctx->octx); + memset(pad, 0x5c, 64); + for (i = 0; i < Klen; i++) + pad[i] ^= K[i]; + SHA256_Update(&ctx->octx, pad, 64); + + /* Clean the stack. */ + memset(khash, 0, 32); +} + +/* Add bytes to the HMAC-SHA256 operation. */ +void +HMAC_SHA256_Update(HMAC_SHA256_CTX * ctx, const void *in, size_t len) +{ + + /* Feed data to the inner SHA256 operation. */ + SHA256_Update(&ctx->ictx, in, len); +} + +/* Finish an HMAC-SHA256 operation. */ +void +HMAC_SHA256_Final(unsigned char digest[32], HMAC_SHA256_CTX * ctx) +{ + unsigned char ihash[32]; + + /* Finish the inner SHA256 operation. */ + SHA256_Final(ihash, &ctx->ictx); + + /* Feed the inner hash to the outer SHA256 operation. */ + SHA256_Update(&ctx->octx, ihash, 32); + + /* Finish the outer SHA256 operation. */ + SHA256_Final(digest, &ctx->octx); + + /* Clean the stack. */ + memset(ihash, 0, 32); +} + +/** + * PBKDF2_SHA256(passwd, passwdlen, salt, saltlen, c, buf, dkLen): + * Compute PBKDF2(passwd, salt, c, dkLen) using HMAC-SHA256 as the PRF, and + * write the output to buf. The value dkLen must be at most 32 * (2^32 - 1). + */ +void +PBKDF2_SHA256(const uint8_t * passwd, size_t passwdlen, const uint8_t * salt, + size_t saltlen, uint64_t c, uint8_t * buf, size_t dkLen) +{ + HMAC_SHA256_CTX PShctx, hctx; + size_t i; + uint8_t ivec[4]; + uint8_t U[32]; + uint8_t T[32]; + uint64_t j; + int k; + size_t clen; + + /* Compute HMAC state after processing P and S. */ + HMAC_SHA256_Init(&PShctx, passwd, passwdlen); + HMAC_SHA256_Update(&PShctx, salt, saltlen); + + /* Iterate through the blocks. */ + for (i = 0; i * 32 < dkLen; i++) { + /* Generate INT(i + 1). */ + be32enc(ivec, (uint32_t)(i + 1)); + + /* Compute U_1 = PRF(P, S || INT(i)). */ + memcpy(&hctx, &PShctx, sizeof(HMAC_SHA256_CTX)); + HMAC_SHA256_Update(&hctx, ivec, 4); + HMAC_SHA256_Final(U, &hctx); + + /* T_i = U_1 ... */ + memcpy(T, U, 32); + + for (j = 2; j <= c; j++) { + /* Compute U_j. */ + HMAC_SHA256_Init(&hctx, passwd, passwdlen); + HMAC_SHA256_Update(&hctx, U, 32); + HMAC_SHA256_Final(U, &hctx); + + /* ... xor U_j ... */ + for (k = 0; k < 32; k++) + T[k] ^= U[k]; + } + + /* Copy as many bytes as necessary into buf. */ + clen = dkLen - i * 32; + if (clen > 32) + clen = 32; + memcpy(&buf[i * 32], T, clen); + } + + /* Clean PShctx, since we never called _Final on it. */ + memset(&PShctx, 0, sizeof(HMAC_SHA256_CTX)); +} + diff --git a/src/pbkdf2.h b/src/pbkdf2.h new file mode 100644 index 0000000..4c55fd9 --- /dev/null +++ b/src/pbkdf2.h @@ -0,0 +1,27 @@ +// Copyright (c) 2013 NovaCoin Developers + +#ifndef PBKDF2_H +#define PBKDF2_H + +#include +#include + +typedef struct HMAC_SHA256Context { + SHA256_CTX ictx; + SHA256_CTX octx; +} HMAC_SHA256_CTX; + +void +HMAC_SHA256_Init(HMAC_SHA256_CTX * ctx, const void * _K, size_t Klen); + +void +HMAC_SHA256_Update(HMAC_SHA256_CTX * ctx, const void *in, size_t len); + +void +HMAC_SHA256_Final(unsigned char digest[32], HMAC_SHA256_CTX * ctx); + +void +PBKDF2_SHA256(const uint8_t * passwd, size_t passwdlen, const uint8_t * salt, + size_t saltlen, uint64_t c, uint8_t * buf, size_t dkLen); + +#endif // PBKDF2_H diff --git a/src/protocol.cpp b/src/protocol.cpp new file mode 100644 index 0000000..1bb578c --- /dev/null +++ b/src/protocol.cpp @@ -0,0 +1,150 @@ +// Copyright (c) 2009-2010 Satoshi Nakamoto +// Copyright (c) 2009-2012 The Bitcoin developers +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include "protocol.h" +#include "util.h" +#include "netbase.h" + +#ifndef WIN32 +# include +#endif + +static const char* ppszTypeName[] = +{ + "ERROR", + "tx", + "block", +}; + +CMessageHeader::CMessageHeader() +{ + memcpy(pchMessageStart, ::pchMessageStart, sizeof(pchMessageStart)); + memset(pchCommand, 0, sizeof(pchCommand)); + pchCommand[1] = 1; + nMessageSize = -1; + nChecksum = 0; +} + +CMessageHeader::CMessageHeader(const char* pszCommand, unsigned int nMessageSizeIn) +{ + memcpy(pchMessageStart, ::pchMessageStart, sizeof(pchMessageStart)); + strncpy(pchCommand, pszCommand, COMMAND_SIZE); + nMessageSize = nMessageSizeIn; + nChecksum = 0; +} + +std::string CMessageHeader::GetCommand() const +{ + if (pchCommand[COMMAND_SIZE-1] == 0) + return std::string(pchCommand, pchCommand + strlen(pchCommand)); + else + return std::string(pchCommand, pchCommand + COMMAND_SIZE); +} + +bool CMessageHeader::IsValid() const +{ + // Check start string + if (memcmp(pchMessageStart, ::pchMessageStart, sizeof(pchMessageStart)) != 0) + return false; + + // Check the command string for errors + for (const char* p1 = pchCommand; p1 < pchCommand + COMMAND_SIZE; p1++) + { + if (*p1 == 0) + { + // Must be all zeros after the first zero + for (; p1 < pchCommand + COMMAND_SIZE; p1++) + if (*p1 != 0) + return false; + } + else if (*p1 < ' ' || *p1 > 0x7E) + return false; + } + + // Message size + if (nMessageSize > MAX_SIZE) + { + printf("CMessageHeader::IsValid() : (%s, %u bytes) nMessageSize > MAX_SIZE\n", GetCommand().c_str(), nMessageSize); + return false; + } + + return true; +} + + + +CAddress::CAddress() : CService() +{ + Init(); +} + +CAddress::CAddress(CService ipIn, uint64_t nServicesIn) : CService(ipIn) +{ + Init(); + nServices = nServicesIn; +} + +void CAddress::Init() +{ + nServices = NODE_NETWORK; + nTime = 100000000; + nLastTry = 0; +} + +CInv::CInv() +{ + type = 0; + hash = 0; +} + +CInv::CInv(int typeIn, const uint256& hashIn) +{ + type = typeIn; + hash = hashIn; +} + +CInv::CInv(const std::string& strType, const uint256& hashIn) +{ + unsigned int i; + for (i = 1; i < ARRAYLEN(ppszTypeName); i++) + { + if (strType == ppszTypeName[i]) + { + type = i; + break; + } + } + if (i == ARRAYLEN(ppszTypeName)) + throw std::out_of_range(strprintf("CInv::CInv(string, uint256) : unknown type '%s'", strType.c_str())); + hash = hashIn; +} + +bool operator<(const CInv& a, const CInv& b) +{ + return (a.type < b.type || (a.type == b.type && a.hash < b.hash)); +} + +bool CInv::IsKnownType() const +{ + return (type >= 1 && type < (int)ARRAYLEN(ppszTypeName)); +} + +const char* CInv::GetCommand() const +{ + if (!IsKnownType()) + throw std::out_of_range(strprintf("CInv::GetCommand() : type=%d unknown type", type)); + return ppszTypeName[type]; +} + +std::string CInv::ToString() const +{ + return strprintf("%s %s", GetCommand(), hash.ToString().substr(0,20).c_str()); +} + +void CInv::print() const +{ + printf("CInv(%s)\n", ToString().c_str()); +} + diff --git a/src/protocol.h b/src/protocol.h new file mode 100644 index 0000000..ac01cab --- /dev/null +++ b/src/protocol.h @@ -0,0 +1,138 @@ +// Copyright (c) 2009-2010 Satoshi Nakamoto +// Copyright (c) 2009-2012 The Bitcoin developers +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifndef __cplusplus +# error This header can only be compiled as C++. +#endif + +#ifndef __INCLUDED_PROTOCOL_H__ +#define __INCLUDED_PROTOCOL_H__ + +#include "serialize.h" +#include "netbase.h" +#include +#include "uint256.h" + +extern bool fTestNet; +static inline unsigned short GetDefaultPort(const bool testnet = fTestNet) +{ + return testnet ? 18585 : 8585; +} + + +extern unsigned char pchMessageStart[4]; + +/** Message header. + * (4) message start. + * (12) command. + * (4) size. + * (4) checksum. + */ +class CMessageHeader +{ + public: + CMessageHeader(); + CMessageHeader(const char* pszCommand, unsigned int nMessageSizeIn); + + std::string GetCommand() const; + bool IsValid() const; + + IMPLEMENT_SERIALIZE + ( + READWRITE(FLATDATA(pchMessageStart)); + READWRITE(FLATDATA(pchCommand)); + READWRITE(nMessageSize); + READWRITE(nChecksum); + ) + + // TODO: make private (improves encapsulation) + public: + enum { + MESSAGE_START_SIZE=sizeof(::pchMessageStart), + COMMAND_SIZE=12, + MESSAGE_SIZE_SIZE=sizeof(int), + CHECKSUM_SIZE=sizeof(int), + + MESSAGE_SIZE_OFFSET=MESSAGE_START_SIZE+COMMAND_SIZE, + CHECKSUM_OFFSET=MESSAGE_SIZE_OFFSET+MESSAGE_SIZE_SIZE, + HEADER_SIZE=MESSAGE_START_SIZE+COMMAND_SIZE+MESSAGE_SIZE_SIZE+CHECKSUM_SIZE + }; + char pchMessageStart[MESSAGE_START_SIZE]; + char pchCommand[COMMAND_SIZE]; + unsigned int nMessageSize; + unsigned int nChecksum; +}; + +/** nServices flags */ +enum +{ + NODE_NETWORK = (1 << 0), +}; + +/** A CService with information about it as peer */ +class CAddress : public CService +{ + public: + CAddress(); + explicit CAddress(CService ipIn, uint64_t nServicesIn=NODE_NETWORK); + + void Init(); + + IMPLEMENT_SERIALIZE + ( + CAddress* pthis = const_cast(this); + CService* pip = (CService*)pthis; + if (fRead) + pthis->Init(); + if (nType & SER_DISK) + READWRITE(nVersion); + if ((nType & SER_DISK) || + (nVersion >= CADDR_TIME_VERSION && !(nType & SER_GETHASH))) + READWRITE(nTime); + READWRITE(nServices); + READWRITE(*pip); + ) + + void print() const; + + // TODO: make private (improves encapsulation) + public: + uint64_t nServices; + + // disk and network only + unsigned int nTime; + + // memory only + int64_t nLastTry; +}; + +/** inv message data */ +class CInv +{ + public: + CInv(); + CInv(int typeIn, const uint256& hashIn); + CInv(const std::string& strType, const uint256& hashIn); + + IMPLEMENT_SERIALIZE + ( + READWRITE(type); + READWRITE(hash); + ) + + friend bool operator<(const CInv& a, const CInv& b); + + bool IsKnownType() const; + const char* GetCommand() const; + std::string ToString() const; + void print() const; + + // TODO: make private (improves encapsulation) + public: + int type; + uint256 hash; +}; + +#endif // __INCLUDED_PROTOCOL_H__ diff --git a/src/qt/aboutdialog.cpp b/src/qt/aboutdialog.cpp new file mode 100755 index 0000000..0b98bef --- /dev/null +++ b/src/qt/aboutdialog.cpp @@ -0,0 +1,30 @@ +#include "aboutdialog.h" +#include "ui_aboutdialog.h" +#include "clientmodel.h" + +#include "version.h" + +AboutDialog::AboutDialog(QWidget *parent) : + QDialog(parent), + ui(new Ui::AboutDialog) +{ + ui->setupUi(this); +} + +void AboutDialog::setModel(ClientModel *model) +{ + if(model) + { + ui->versionLabel->setText(model->formatFullVersion()); + } +} + +AboutDialog::~AboutDialog() +{ + delete ui; +} + +void AboutDialog::on_buttonBox_accepted() +{ + close(); +} diff --git a/src/qt/aboutdialog.h b/src/qt/aboutdialog.h new file mode 100755 index 0000000..2ed9e9e --- /dev/null +++ b/src/qt/aboutdialog.h @@ -0,0 +1,28 @@ +#ifndef ABOUTDIALOG_H +#define ABOUTDIALOG_H + +#include + +namespace Ui { + class AboutDialog; +} +class ClientModel; + +/** "About" dialog box */ +class AboutDialog : public QDialog +{ + Q_OBJECT + +public: + explicit AboutDialog(QWidget *parent = 0); + ~AboutDialog(); + + void setModel(ClientModel *model); +private: + Ui::AboutDialog *ui; + +private slots: + void on_buttonBox_accepted(); +}; + +#endif // ABOUTDIALOG_H diff --git a/src/qt/addressbookpage.cpp b/src/qt/addressbookpage.cpp new file mode 100755 index 0000000..e20358c --- /dev/null +++ b/src/qt/addressbookpage.cpp @@ -0,0 +1,374 @@ +#include "addressbookpage.h" +#include "ui_addressbookpage.h" + +#include "addresstablemodel.h" +#include "optionsmodel.h" +#include "bitcoingui.h" +#include "editaddressdialog.h" +#include "csvmodelwriter.h" +#include "guiutil.h" + +#include +#include +#include +#include + +#ifdef USE_QRCODE +#include "qrcodedialog.h" +#endif + +AddressBookPage::AddressBookPage(Mode mode, Tabs tab, QWidget *parent) : + QDialog(parent), + ui(new Ui::AddressBookPage), + model(0), + optionsModel(0), + mode(mode), + tab(tab) +{ + ui->setupUi(this); + +#ifdef Q_OS_MAC // Icons on push buttons are very uncommon on Mac + ui->newAddressButton->setIcon(QIcon()); + ui->copyToClipboard->setIcon(QIcon()); + ui->deleteButton->setIcon(QIcon()); +#endif + +#ifndef USE_QRCODE + ui->showQRCode->setVisible(false); +#endif + + switch(mode) + { + case ForSending: + connect(ui->tableView, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(accept())); + ui->tableView->setEditTriggers(QAbstractItemView::NoEditTriggers); + ui->tableView->setFocus(); + break; + case ForEditing: + ui->buttonBox->setVisible(false); + break; + } + switch(tab) + { + case SendingTab: + ui->labelExplanation->setVisible(false); + ui->deleteButton->setVisible(true); + ui->signMessage->setVisible(false); + break; + case ReceivingTab: + ui->deleteButton->setVisible(false); + ui->signMessage->setVisible(true); + break; + } + + // Context menu actions + QAction *copyLabelAction = new QAction(tr("Copy &Label"), this); + QAction *copyAddressAction = new QAction(ui->copyToClipboard->text(), this); + QAction *editAction = new QAction(tr("&Edit"), this); + QAction *showQRCodeAction = new QAction(ui->showQRCode->text(), this); + QAction *signMessageAction = new QAction(ui->signMessage->text(), this); + QAction *verifyMessageAction = new QAction(ui->verifyMessage->text(), this); + deleteAction = new QAction(ui->deleteButton->text(), this); + + // Build context menu + contextMenu = new QMenu(); + contextMenu->addAction(copyAddressAction); + contextMenu->addAction(copyLabelAction); + contextMenu->addAction(editAction); + if(tab == SendingTab) + contextMenu->addAction(deleteAction); + contextMenu->addSeparator(); + contextMenu->addAction(showQRCodeAction); + if(tab == ReceivingTab) + contextMenu->addAction(signMessageAction); + else if(tab == SendingTab) + contextMenu->addAction(verifyMessageAction); + + // Connect signals for context menu actions + connect(copyAddressAction, SIGNAL(triggered()), this, SLOT(on_copyToClipboard_clicked())); + connect(copyLabelAction, SIGNAL(triggered()), this, SLOT(onCopyLabelAction())); + connect(editAction, SIGNAL(triggered()), this, SLOT(onEditAction())); + connect(deleteAction, SIGNAL(triggered()), this, SLOT(on_deleteButton_clicked())); + connect(showQRCodeAction, SIGNAL(triggered()), this, SLOT(on_showQRCode_clicked())); + connect(signMessageAction, SIGNAL(triggered()), this, SLOT(on_signMessage_clicked())); + connect(verifyMessageAction, SIGNAL(triggered()), this, SLOT(on_verifyMessage_clicked())); + + connect(ui->tableView, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(contextualMenu(QPoint))); + + // Pass through accept action from button box + connect(ui->buttonBox, SIGNAL(accepted()), this, SLOT(accept())); +} + +AddressBookPage::~AddressBookPage() +{ + delete ui; +} + +void AddressBookPage::setModel(AddressTableModel *model) +{ + this->model = model; + if(!model) + return; + + proxyModel = new QSortFilterProxyModel(this); + proxyModel->setSourceModel(model); + proxyModel->setDynamicSortFilter(true); + proxyModel->setSortCaseSensitivity(Qt::CaseInsensitive); + proxyModel->setFilterCaseSensitivity(Qt::CaseInsensitive); + switch(tab) + { + case ReceivingTab: + // Receive filter + proxyModel->setFilterRole(AddressTableModel::TypeRole); + proxyModel->setFilterFixedString(AddressTableModel::Receive); + break; + case SendingTab: + // Send filter + proxyModel->setFilterRole(AddressTableModel::TypeRole); + proxyModel->setFilterFixedString(AddressTableModel::Send); + break; + } + ui->tableView->setModel(proxyModel); + ui->tableView->sortByColumn(0, Qt::AscendingOrder); + + // Set column widths + ui->tableView->horizontalHeader()->resizeSection( + AddressTableModel::Address, 320); + ui->tableView->horizontalHeader()->setResizeMode( + AddressTableModel::Label, QHeaderView::Stretch); + + connect(ui->tableView->selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)), + this, SLOT(selectionChanged())); + + // Select row for newly created address + connect(model, SIGNAL(rowsInserted(QModelIndex,int,int)), + this, SLOT(selectNewAddress(QModelIndex,int,int))); + + selectionChanged(); +} + +void AddressBookPage::setOptionsModel(OptionsModel *optionsModel) +{ + this->optionsModel = optionsModel; +} + +void AddressBookPage::on_copyToClipboard_clicked() +{ + GUIUtil::copyEntryData(ui->tableView, AddressTableModel::Address); +} + +void AddressBookPage::onCopyLabelAction() +{ + GUIUtil::copyEntryData(ui->tableView, AddressTableModel::Label); +} + +void AddressBookPage::onEditAction() +{ + if(!ui->tableView->selectionModel()) + return; + QModelIndexList indexes = ui->tableView->selectionModel()->selectedRows(); + if(indexes.isEmpty()) + return; + + EditAddressDialog dlg( + tab == SendingTab ? + EditAddressDialog::EditSendingAddress : + EditAddressDialog::EditReceivingAddress); + dlg.setModel(model); + QModelIndex origIndex = proxyModel->mapToSource(indexes.at(0)); + dlg.loadRow(origIndex.row()); + dlg.exec(); +} + +void AddressBookPage::on_signMessage_clicked() +{ + QTableView *table = ui->tableView; + QModelIndexList indexes = table->selectionModel()->selectedRows(AddressTableModel::Address); + QString addr; + + foreach (QModelIndex index, indexes) + { + QVariant address = index.data(); + addr = address.toString(); + } + + emit signMessage(addr); +} + +void AddressBookPage::on_verifyMessage_clicked() +{ + QTableView *table = ui->tableView; + QModelIndexList indexes = table->selectionModel()->selectedRows(AddressTableModel::Address); + QString addr; + + foreach (QModelIndex index, indexes) + { + QVariant address = index.data(); + addr = address.toString(); + } + + emit verifyMessage(addr); +} + +void AddressBookPage::on_newAddressButton_clicked() +{ + if(!model) + return; + EditAddressDialog dlg( + tab == SendingTab ? + EditAddressDialog::NewSendingAddress : + EditAddressDialog::NewReceivingAddress, this); + dlg.setModel(model); + if(dlg.exec()) + { + newAddressToSelect = dlg.getAddress(); + } +} + +void AddressBookPage::on_deleteButton_clicked() +{ + QTableView *table = ui->tableView; + if(!table->selectionModel()) + return; + QModelIndexList indexes = table->selectionModel()->selectedRows(); + if(!indexes.isEmpty()) + { + table->model()->removeRow(indexes.at(0).row()); + } +} + +void AddressBookPage::selectionChanged() +{ + // Set button states based on selected tab and selection + QTableView *table = ui->tableView; + if(!table->selectionModel()) + return; + + if(table->selectionModel()->hasSelection()) + { + switch(tab) + { + case SendingTab: + // In sending tab, allow deletion of selection + ui->deleteButton->setEnabled(true); + ui->deleteButton->setVisible(true); + deleteAction->setEnabled(true); + ui->signMessage->setEnabled(false); + ui->signMessage->setVisible(false); + ui->verifyMessage->setEnabled(true); + ui->verifyMessage->setVisible(true); + break; + case ReceivingTab: + // Deleting receiving addresses, however, is not allowed + ui->deleteButton->setEnabled(false); + ui->deleteButton->setVisible(false); + deleteAction->setEnabled(false); + ui->signMessage->setEnabled(true); + ui->signMessage->setVisible(true); + ui->verifyMessage->setEnabled(false); + ui->verifyMessage->setVisible(false); + break; + } + ui->copyToClipboard->setEnabled(true); + ui->showQRCode->setEnabled(true); + } + else + { + ui->deleteButton->setEnabled(false); + ui->showQRCode->setEnabled(false); + ui->copyToClipboard->setEnabled(false); + ui->signMessage->setEnabled(false); + ui->verifyMessage->setEnabled(false); + } +} + +void AddressBookPage::done(int retval) +{ + QTableView *table = ui->tableView; + if(!table->selectionModel() || !table->model()) + return; + // When this is a tab/widget and not a model dialog, ignore "done" + if(mode == ForEditing) + return; + + // Figure out which address was selected, and return it + QModelIndexList indexes = table->selectionModel()->selectedRows(AddressTableModel::Address); + + foreach (QModelIndex index, indexes) + { + QVariant address = table->model()->data(index); + returnValue = address.toString(); + } + + if(returnValue.isEmpty()) + { + // If no address entry selected, return rejected + retval = Rejected; + } + + QDialog::done(retval); +} + +void AddressBookPage::exportClicked() +{ + // CSV is currently the only supported format + QString filename = GUIUtil::getSaveFileName( + this, + tr("Export Address Book Data"), QString(), + tr("Comma separated file (*.csv)")); + + if (filename.isNull()) return; + + CSVModelWriter writer(filename); + + // name, column, role + writer.setModel(proxyModel); + writer.addColumn("Label", AddressTableModel::Label, Qt::EditRole); + writer.addColumn("Address", AddressTableModel::Address, Qt::EditRole); + + if(!writer.write()) + { + QMessageBox::critical(this, tr("Error exporting"), tr("Could not write to file %1.").arg(filename), + QMessageBox::Abort, QMessageBox::Abort); + } +} + +void AddressBookPage::on_showQRCode_clicked() +{ +#ifdef USE_QRCODE + QTableView *table = ui->tableView; + QModelIndexList indexes = table->selectionModel()->selectedRows(AddressTableModel::Address); + + foreach (QModelIndex index, indexes) + { + QString address = index.data().toString(), label = index.sibling(index.row(), 0).data(Qt::EditRole).toString(); + + QRCodeDialog *dialog = new QRCodeDialog(address, label, tab == ReceivingTab, this); + if(optionsModel) + dialog->setModel(optionsModel); + dialog->setAttribute(Qt::WA_DeleteOnClose); + dialog->show(); + } +#endif +} + +void AddressBookPage::contextualMenu(const QPoint &point) +{ + QModelIndex index = ui->tableView->indexAt(point); + if(index.isValid()) + { + contextMenu->exec(QCursor::pos()); + } +} + +void AddressBookPage::selectNewAddress(const QModelIndex &parent, int begin, int end) +{ + QModelIndex idx = proxyModel->mapFromSource(model->index(begin, AddressTableModel::Address, parent)); + if(idx.isValid() && (idx.data(Qt::EditRole).toString() == newAddressToSelect)) + { + // Select row of newly created address, once + ui->tableView->setFocus(); + ui->tableView->selectRow(idx.row()); + newAddressToSelect.clear(); + } +} diff --git a/src/qt/addressbookpage.h b/src/qt/addressbookpage.h new file mode 100755 index 0000000..df87486 --- /dev/null +++ b/src/qt/addressbookpage.h @@ -0,0 +1,85 @@ +#ifndef ADDRESSBOOKPAGE_H +#define ADDRESSBOOKPAGE_H + +#include + +namespace Ui { + class AddressBookPage; +} +class AddressTableModel; +class OptionsModel; + +QT_BEGIN_NAMESPACE +class QTableView; +class QItemSelection; +class QSortFilterProxyModel; +class QMenu; +class QModelIndex; +QT_END_NAMESPACE + +/** Widget that shows a list of sending or receiving addresses. + */ +class AddressBookPage : public QDialog +{ + Q_OBJECT + +public: + enum Tabs { + SendingTab = 0, + ReceivingTab = 1 + }; + + enum Mode { + ForSending, /**< Open address book to pick address for sending */ + ForEditing /**< Open address book for editing */ + }; + + explicit AddressBookPage(Mode mode, Tabs tab, QWidget *parent = 0); + ~AddressBookPage(); + + void setModel(AddressTableModel *model); + void setOptionsModel(OptionsModel *optionsModel); + const QString &getReturnValue() const { return returnValue; } + +public slots: + void done(int retval); + void exportClicked(); + +private: + Ui::AddressBookPage *ui; + AddressTableModel *model; + OptionsModel *optionsModel; + Mode mode; + Tabs tab; + QString returnValue; + QSortFilterProxyModel *proxyModel; + QMenu *contextMenu; + QAction *deleteAction; + QString newAddressToSelect; + +private slots: + void on_deleteButton_clicked(); + void on_newAddressButton_clicked(); + /** Copy address of currently selected address entry to clipboard */ + void on_copyToClipboard_clicked(); + void on_signMessage_clicked(); + void on_verifyMessage_clicked(); + void selectionChanged(); + void on_showQRCode_clicked(); + /** Spawn contextual menu (right mouse menu) for address book entry */ + void contextualMenu(const QPoint &point); + + /** Copy label of currently selected address entry to clipboard */ + void onCopyLabelAction(); + /** Edit currently selected address entry */ + void onEditAction(); + + /** New entry/entries were added to address table */ + void selectNewAddress(const QModelIndex &parent, int begin, int end); + +signals: + void signMessage(QString addr); + void verifyMessage(QString addr); +}; + +#endif // ADDRESSBOOKDIALOG_H diff --git a/src/qt/addresstablemodel.cpp b/src/qt/addresstablemodel.cpp new file mode 100755 index 0000000..491e60e --- /dev/null +++ b/src/qt/addresstablemodel.cpp @@ -0,0 +1,426 @@ +#include "addresstablemodel.h" +#include "guiutil.h" +#include "walletmodel.h" + +#include "wallet.h" +#include "base58.h" + +#include +#include + +const QString AddressTableModel::Send = "S"; +const QString AddressTableModel::Receive = "R"; + +struct AddressTableEntry +{ + enum Type { + Sending, + Receiving + }; + + Type type; + QString label; + QString address; + + AddressTableEntry() {} + AddressTableEntry(Type type, const QString &label, const QString &address): + type(type), label(label), address(address) {} +}; + +struct AddressTableEntryLessThan +{ + bool operator()(const AddressTableEntry &a, const AddressTableEntry &b) const + { + return a.address < b.address; + } + bool operator()(const AddressTableEntry &a, const QString &b) const + { + return a.address < b; + } + bool operator()(const QString &a, const AddressTableEntry &b) const + { + return a < b.address; + } +}; + +// Private implementation +class AddressTablePriv +{ +public: + CWallet *wallet; + QList cachedAddressTable; + AddressTableModel *parent; + + AddressTablePriv(CWallet *wallet, AddressTableModel *parent): + wallet(wallet), parent(parent) {} + + void refreshAddressTable() + { + cachedAddressTable.clear(); + { + LOCK(wallet->cs_wallet); + BOOST_FOREACH(const PAIRTYPE(CTxDestination, std::string)& item, wallet->mapAddressBook) + { + const CBitcoinAddress& address = item.first; + const std::string& strName = item.second; + bool fMine = IsMine(*wallet, address.Get()); + cachedAddressTable.append(AddressTableEntry(fMine ? AddressTableEntry::Receiving : AddressTableEntry::Sending, + QString::fromStdString(strName), + QString::fromStdString(address.ToString()))); + } + } + // qLowerBound() and qUpperBound() require our cachedAddressTable list to be sorted in asc order + qSort(cachedAddressTable.begin(), cachedAddressTable.end(), AddressTableEntryLessThan()); + } + + void updateEntry(const QString &address, const QString &label, bool isMine, int status) + { + // Find address / label in model + QList::iterator lower = qLowerBound( + cachedAddressTable.begin(), cachedAddressTable.end(), address, AddressTableEntryLessThan()); + QList::iterator upper = qUpperBound( + cachedAddressTable.begin(), cachedAddressTable.end(), address, AddressTableEntryLessThan()); + int lowerIndex = (lower - cachedAddressTable.begin()); + int upperIndex = (upper - cachedAddressTable.begin()); + bool inModel = (lower != upper); + AddressTableEntry::Type newEntryType = isMine ? AddressTableEntry::Receiving : AddressTableEntry::Sending; + + switch(status) + { + case CT_NEW: + if(inModel) + { + OutputDebugStringF("Warning: AddressTablePriv::updateEntry: Got CT_NEW, but entry is already in model\n"); + break; + } + parent->beginInsertRows(QModelIndex(), lowerIndex, lowerIndex); + cachedAddressTable.insert(lowerIndex, AddressTableEntry(newEntryType, label, address)); + parent->endInsertRows(); + break; + case CT_UPDATED: + if(!inModel) + { + OutputDebugStringF("Warning: AddressTablePriv::updateEntry: Got CT_UPDATED, but entry is not in model\n"); + break; + } + lower->type = newEntryType; + lower->label = label; + parent->emitDataChanged(lowerIndex); + break; + case CT_DELETED: + if(!inModel) + { + OutputDebugStringF("Warning: AddressTablePriv::updateEntry: Got CT_DELETED, but entry is not in model\n"); + break; + } + parent->beginRemoveRows(QModelIndex(), lowerIndex, upperIndex-1); + cachedAddressTable.erase(lower, upper); + parent->endRemoveRows(); + break; + } + } + + int size() + { + return cachedAddressTable.size(); + } + + AddressTableEntry *index(int idx) + { + if(idx >= 0 && idx < cachedAddressTable.size()) + { + return &cachedAddressTable[idx]; + } + else + { + return 0; + } + } +}; + +AddressTableModel::AddressTableModel(CWallet *wallet, WalletModel *parent) : + QAbstractTableModel(parent),walletModel(parent),wallet(wallet),priv(0) +{ + columns << tr("Label") << tr("Address"); + priv = new AddressTablePriv(wallet, this); + priv->refreshAddressTable(); +} + +AddressTableModel::~AddressTableModel() +{ + delete priv; +} + +int AddressTableModel::rowCount(const QModelIndex &parent) const +{ + Q_UNUSED(parent); + return priv->size(); +} + +int AddressTableModel::columnCount(const QModelIndex &parent) const +{ + Q_UNUSED(parent); + return columns.length(); +} + +QVariant AddressTableModel::data(const QModelIndex &index, int role) const +{ + if(!index.isValid()) + return QVariant(); + + AddressTableEntry *rec = static_cast(index.internalPointer()); + + if(role == Qt::DisplayRole || role == Qt::EditRole) + { + switch(index.column()) + { + case Label: + if(rec->label.isEmpty() && role == Qt::DisplayRole) + { + return tr("(no label)"); + } + else + { + return rec->label; + } + case Address: + return rec->address; + } + } + else if (role == Qt::FontRole) + { + QFont font; + if(index.column() == Address) + { + font = GUIUtil::bitcoinAddressFont(); + } + return font; + } + else if (role == TypeRole) + { + switch(rec->type) + { + case AddressTableEntry::Sending: + return Send; + case AddressTableEntry::Receiving: + return Receive; + default: break; + } + } + return QVariant(); +} + +bool AddressTableModel::setData(const QModelIndex &index, const QVariant &value, int role) +{ + if(!index.isValid()) + return false; + AddressTableEntry *rec = static_cast(index.internalPointer()); + + editStatus = OK; + + if(role == Qt::EditRole) + { + switch(index.column()) + { + case Label: + // Do nothing, if old label == new label + if(rec->label == value.toString()) + { + editStatus = NO_CHANGES; + return false; + } + wallet->SetAddressBookName(CBitcoinAddress(rec->address.toStdString()).Get(), value.toString().toStdString()); + break; + case Address: + // Do nothing, if old address == new address + if(CBitcoinAddress(rec->address.toStdString()) == CBitcoinAddress(value.toString().toStdString())) + { + editStatus = NO_CHANGES; + return false; + } + // Refuse to set invalid address, set error status and return false + else if(!walletModel->validateAddress(value.toString())) + { + editStatus = INVALID_ADDRESS; + return false; + } + // Check for duplicate addresses to prevent accidental deletion of addresses, if you try + // to paste an existing address over another address (with a different label) + else if(wallet->mapAddressBook.count(CBitcoinAddress(value.toString().toStdString()).Get())) + { + editStatus = DUPLICATE_ADDRESS; + return false; + } + // Double-check that we're not overwriting a receiving address + else if(rec->type == AddressTableEntry::Sending) + { + { + LOCK(wallet->cs_wallet); + // Remove old entry + wallet->DelAddressBookName(CBitcoinAddress(rec->address.toStdString()).Get()); + // Add new entry with new address + wallet->SetAddressBookName(CBitcoinAddress(value.toString().toStdString()).Get(), rec->label.toStdString()); + } + } + break; + } + return true; + } + return false; +} + +QVariant AddressTableModel::headerData(int section, Qt::Orientation orientation, int role) const +{ + if(orientation == Qt::Horizontal) + { + if(role == Qt::DisplayRole) + { + return columns[section]; + } + } + return QVariant(); +} + +Qt::ItemFlags AddressTableModel::flags(const QModelIndex &index) const +{ + if(!index.isValid()) + return 0; + AddressTableEntry *rec = static_cast(index.internalPointer()); + + Qt::ItemFlags retval = Qt::ItemIsSelectable | Qt::ItemIsEnabled; + // Can edit address and label for sending addresses, + // and only label for receiving addresses. + if(rec->type == AddressTableEntry::Sending || + (rec->type == AddressTableEntry::Receiving && index.column()==Label)) + { + retval |= Qt::ItemIsEditable; + } + return retval; +} + +QModelIndex AddressTableModel::index(int row, int column, const QModelIndex &parent) const +{ + Q_UNUSED(parent); + AddressTableEntry *data = priv->index(row); + if(data) + { + return createIndex(row, column, priv->index(row)); + } + else + { + return QModelIndex(); + } +} + +void AddressTableModel::updateEntry(const QString &address, const QString &label, bool isMine, int status) +{ + // Update address book model from Bitcoin core + priv->updateEntry(address, label, isMine, status); +} + +QString AddressTableModel::addRow(const QString &type, const QString &label, const QString &address) +{ + std::string strLabel = label.toStdString(); + std::string strAddress = address.toStdString(); + + editStatus = OK; + + if(type == Send) + { + if(!walletModel->validateAddress(address)) + { + editStatus = INVALID_ADDRESS; + return QString(); + } + // Check for duplicate addresses + { + LOCK(wallet->cs_wallet); + if(wallet->mapAddressBook.count(CBitcoinAddress(strAddress).Get())) + { + editStatus = DUPLICATE_ADDRESS; + return QString(); + } + } + } + else if(type == Receive) + { + // Generate a new address to associate with given label + WalletModel::UnlockContext ctx(walletModel->requestUnlock()); + if(!ctx.isValid()) + { + // Unlock wallet failed or was cancelled + editStatus = WALLET_UNLOCK_FAILURE; + return QString(); + } + CPubKey newKey; + if(!wallet->GetKeyFromPool(newKey, true)) + { + editStatus = KEY_GENERATION_FAILURE; + return QString(); + } + strAddress = CBitcoinAddress(newKey.GetID()).ToString(); + } + else + { + return QString(); + } + + // Add entry + { + LOCK(wallet->cs_wallet); + wallet->SetAddressBookName(CBitcoinAddress(strAddress).Get(), strLabel); + } + return QString::fromStdString(strAddress); +} + +bool AddressTableModel::removeRows(int row, int count, const QModelIndex &parent) +{ + Q_UNUSED(parent); + AddressTableEntry *rec = priv->index(row); + if(count != 1 || !rec || rec->type == AddressTableEntry::Receiving) + { + // Can only remove one row at a time, and cannot remove rows not in model. + // Also refuse to remove receiving addresses. + return false; + } + { + LOCK(wallet->cs_wallet); + wallet->DelAddressBookName(CBitcoinAddress(rec->address.toStdString()).Get()); + } + return true; +} + +/* Look up label for address in address book, if not found return empty string. + */ +QString AddressTableModel::labelForAddress(const QString &address) const +{ + { + LOCK(wallet->cs_wallet); + CBitcoinAddress address_parsed(address.toStdString()); + std::map::iterator mi = wallet->mapAddressBook.find(address_parsed.Get()); + if (mi != wallet->mapAddressBook.end()) + { + return QString::fromStdString(mi->second); + } + } + return QString(); +} + +int AddressTableModel::lookupAddress(const QString &address) const +{ + QModelIndexList lst = match(index(0, Address, QModelIndex()), + Qt::EditRole, address, 1, Qt::MatchExactly); + if(lst.isEmpty()) + { + return -1; + } + else + { + return lst.at(0).row(); + } +} + +void AddressTableModel::emitDataChanged(int idx) +{ + emit dataChanged(index(idx, 0, QModelIndex()), index(idx, columns.length()-1, QModelIndex())); +} diff --git a/src/qt/addresstablemodel.h b/src/qt/addresstablemodel.h new file mode 100755 index 0000000..ae3e3b2 --- /dev/null +++ b/src/qt/addresstablemodel.h @@ -0,0 +1,92 @@ +#ifndef ADDRESSTABLEMODEL_H +#define ADDRESSTABLEMODEL_H + +#include +#include + +class AddressTablePriv; +class CWallet; +class WalletModel; + +/** + Qt model of the address book in the core. This allows views to access and modify the address book. + */ +class AddressTableModel : public QAbstractTableModel +{ + Q_OBJECT +public: + explicit AddressTableModel(CWallet *wallet, WalletModel *parent = 0); + ~AddressTableModel(); + + enum ColumnIndex { + Label = 0, /**< User specified label */ + Address = 1 /**< Bitcoin address */ + }; + + enum RoleIndex { + TypeRole = Qt::UserRole /**< Type of address (#Send or #Receive) */ + }; + + /** Return status of edit/insert operation */ + enum EditStatus { + OK, /**< Everything ok */ + NO_CHANGES, /**< No changes were made during edit operation */ + INVALID_ADDRESS, /**< Unparseable address */ + DUPLICATE_ADDRESS, /**< Address already in address book */ + WALLET_UNLOCK_FAILURE, /**< Wallet could not be unlocked to create new receiving address */ + KEY_GENERATION_FAILURE /**< Generating a new public key for a receiving address failed */ + }; + + static const QString Send; /**< Specifies send address */ + static const QString Receive; /**< Specifies receive address */ + + /** @name Methods overridden from QAbstractTableModel + @{*/ + int rowCount(const QModelIndex &parent) const; + int columnCount(const QModelIndex &parent) const; + QVariant data(const QModelIndex &index, int role) const; + bool setData(const QModelIndex &index, const QVariant &value, int role); + QVariant headerData(int section, Qt::Orientation orientation, int role) const; + QModelIndex index(int row, int column, const QModelIndex &parent) const; + bool removeRows(int row, int count, const QModelIndex &parent = QModelIndex()); + Qt::ItemFlags flags(const QModelIndex &index) const; + /*@}*/ + + /* Add an address to the model. + Returns the added address on success, and an empty string otherwise. + */ + QString addRow(const QString &type, const QString &label, const QString &address); + + /* Look up label for address in address book, if not found return empty string. + */ + QString labelForAddress(const QString &address) const; + + /* Look up row index of an address in the model. + Return -1 if not found. + */ + int lookupAddress(const QString &address) const; + + EditStatus getEditStatus() const { return editStatus; } + +private: + WalletModel *walletModel; + CWallet *wallet; + AddressTablePriv *priv; + QStringList columns; + EditStatus editStatus; + + /** Notify listeners that data changed. */ + void emitDataChanged(int index); + +signals: + void defaultAddressChanged(const QString &address); + +public slots: + /* Update address list from core. + */ + void updateEntry(const QString &address, const QString &label, bool isMine, int status); + + friend class AddressTablePriv; +}; + +#endif // ADDRESSTABLEMODEL_H diff --git a/src/qt/askpassphrasedialog.cpp b/src/qt/askpassphrasedialog.cpp new file mode 100755 index 0000000..64042c1 --- /dev/null +++ b/src/qt/askpassphrasedialog.cpp @@ -0,0 +1,270 @@ +#include "askpassphrasedialog.h" +#include "ui_askpassphrasedialog.h" + +#include "guiconstants.h" +#include "walletmodel.h" + +#include +#include +#include + +extern bool fWalletUnlockStakingOnly; + +AskPassphraseDialog::AskPassphraseDialog(Mode mode, QWidget *parent) : + QDialog(parent), + ui(new Ui::AskPassphraseDialog), + mode(mode), + model(0), + fCapsLock(false) +{ + ui->setupUi(this); + ui->passEdit1->setMaxLength(MAX_PASSPHRASE_SIZE); + ui->passEdit2->setMaxLength(MAX_PASSPHRASE_SIZE); + ui->passEdit3->setMaxLength(MAX_PASSPHRASE_SIZE); + + // Setup Caps Lock detection. + ui->passEdit1->installEventFilter(this); + ui->passEdit2->installEventFilter(this); + ui->passEdit3->installEventFilter(this); + + ui->stakingCheckBox->setChecked(fWalletUnlockStakingOnly); + + switch(mode) + { + case Encrypt: // Ask passphrase x2 + ui->passLabel1->hide(); + ui->passEdit1->hide(); + ui->warningLabel->setText(tr("Enter the new passphrase to the wallet.
Please use a passphrase of ten or more random characters, or eight or more words.")); + setWindowTitle(tr("Encrypt wallet")); + break; + case UnlockStaking: + ui->stakingCheckBox->setChecked(true); + ui->stakingCheckBox->show(); + // fallthru + case Unlock: // Ask passphrase + ui->warningLabel->setText(tr("This operation needs your wallet passphrase to unlock the wallet.")); + ui->passLabel2->hide(); + ui->passEdit2->hide(); + ui->passLabel3->hide(); + ui->passEdit3->hide(); + setWindowTitle(tr("Unlock wallet")); + break; + case Decrypt: // Ask passphrase + ui->warningLabel->setText(tr("This operation needs your wallet passphrase to decrypt the wallet.")); + ui->passLabel2->hide(); + ui->passEdit2->hide(); + ui->passLabel3->hide(); + ui->passEdit3->hide(); + setWindowTitle(tr("Decrypt wallet")); + break; + case ChangePass: // Ask old passphrase + new passphrase x2 + setWindowTitle(tr("Change passphrase")); + ui->warningLabel->setText(tr("Enter the old and new passphrase to the wallet.")); + break; + } + + textChanged(); + connect(ui->passEdit1, SIGNAL(textChanged(QString)), this, SLOT(textChanged())); + connect(ui->passEdit2, SIGNAL(textChanged(QString)), this, SLOT(textChanged())); + connect(ui->passEdit3, SIGNAL(textChanged(QString)), this, SLOT(textChanged())); +} + +AskPassphraseDialog::~AskPassphraseDialog() +{ + secureClearPassFields(); + delete ui; +} + +void AskPassphraseDialog::setModel(WalletModel *model) +{ + this->model = model; +} + +void AskPassphraseDialog::accept() +{ + SecureString oldpass, newpass1, newpass2; + if(!model) + return; + oldpass.reserve(MAX_PASSPHRASE_SIZE); + newpass1.reserve(MAX_PASSPHRASE_SIZE); + newpass2.reserve(MAX_PASSPHRASE_SIZE); + // TODO: get rid of this .c_str() by implementing SecureString::operator=(std::string) + // Alternately, find a way to make this input mlock()'d to begin with. + oldpass.assign(ui->passEdit1->text().toStdString().c_str()); + newpass1.assign(ui->passEdit2->text().toStdString().c_str()); + newpass2.assign(ui->passEdit3->text().toStdString().c_str()); + + secureClearPassFields(); + + switch(mode) + { + case Encrypt: { + if(newpass1.empty() || newpass2.empty()) + { + // Cannot encrypt with empty passphrase + break; + } + QMessageBox::StandardButton retval = QMessageBox::question(this, tr("Confirm wallet encryption"), + tr("Warning: If you encrypt your wallet and lose your passphrase, you will LOSE ALL OF YOUR COINS!") + "

" + tr("Are you sure you wish to encrypt your wallet?"), + QMessageBox::Yes|QMessageBox::Cancel, + QMessageBox::Cancel); + if(retval == QMessageBox::Yes) + { + if(newpass1 == newpass2) + { + if(model->setWalletEncrypted(true, newpass1)) + { + QMessageBox::warning(this, tr("Wallet encrypted"), + "" + + tr("Arepacoin will close now to finish the encryption process. " + "Remember that encrypting your wallet cannot fully protect " + "your coins from being stolen by malware infecting your computer.") + + "

" + + tr("IMPORTANT: Any previous backups you have made of your wallet file " + "should be replaced with the newly generated, encrypted wallet file. " + "For security reasons, previous backups of the unencrypted wallet file " + "will become useless as soon as you start using the new, encrypted wallet.") + + "
"); + QApplication::quit(); + } + else + { + QMessageBox::critical(this, tr("Wallet encryption failed"), + tr("Wallet encryption failed due to an internal error. Your wallet was not encrypted.")); + } + QDialog::accept(); // Success + } + else + { + QMessageBox::critical(this, tr("Wallet encryption failed"), + tr("The supplied passphrases do not match.")); + } + } + else + { + QDialog::reject(); // Cancelled + } + } break; + case UnlockStaking: + case Unlock: + if(!model->setWalletLocked(false, oldpass)) + { + QMessageBox::critical(this, tr("Wallet unlock failed"), + tr("The passphrase entered for the wallet decryption was incorrect.")); + } + else + { + fWalletUnlockStakingOnly = ui->stakingCheckBox->isChecked(); + QDialog::accept(); // Success + } + break; + case Decrypt: + if(!model->setWalletEncrypted(false, oldpass)) + { + QMessageBox::critical(this, tr("Wallet decryption failed"), + tr("The passphrase entered for the wallet decryption was incorrect.")); + } + else + { + QDialog::accept(); // Success + } + break; + case ChangePass: + if(newpass1 == newpass2) + { + if(model->changePassphrase(oldpass, newpass1)) + { + QMessageBox::information(this, tr("Wallet encrypted"), + tr("Wallet passphrase was successfully changed.")); + QDialog::accept(); // Success + } + else + { + QMessageBox::critical(this, tr("Wallet encryption failed"), + tr("The passphrase entered for the wallet decryption was incorrect.")); + } + } + else + { + QMessageBox::critical(this, tr("Wallet encryption failed"), + tr("The supplied passphrases do not match.")); + } + break; + } +} + +void AskPassphraseDialog::textChanged() +{ + // Validate input, set Ok button to enabled when acceptable + bool acceptable = false; + switch(mode) + { + case Encrypt: // New passphrase x2 + acceptable = !ui->passEdit2->text().isEmpty() && !ui->passEdit3->text().isEmpty(); + break; + case UnlockStaking: + case Unlock: // Old passphrase x1 + case Decrypt: + acceptable = !ui->passEdit1->text().isEmpty(); + break; + case ChangePass: // Old passphrase x1, new passphrase x2 + acceptable = !ui->passEdit1->text().isEmpty() && !ui->passEdit2->text().isEmpty() && !ui->passEdit3->text().isEmpty(); + break; + } + ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(acceptable); +} + +bool AskPassphraseDialog::event(QEvent *event) +{ + // Detect Caps Lock key press. + if (event->type() == QEvent::KeyPress) { + QKeyEvent *ke = static_cast(event); + if (ke->key() == Qt::Key_CapsLock) { + fCapsLock = !fCapsLock; + } + if (fCapsLock) { + ui->capsLabel->setText(tr("Warning: The Caps Lock key is on!")); + } else { + ui->capsLabel->clear(); + } + } + return QWidget::event(event); +} + +bool AskPassphraseDialog::eventFilter(QObject *object, QEvent *event) +{ + /* Detect Caps Lock. + * There is no good OS-independent way to check a key state in Qt, but we + * can detect Caps Lock by checking for the following condition: + * Shift key is down and the result is a lower case character, or + * Shift key is not down and the result is an upper case character. + */ + if (event->type() == QEvent::KeyPress) { + QKeyEvent *ke = static_cast(event); + QString str = ke->text(); + if (str.length() != 0) { + const QChar *psz = str.unicode(); + bool fShift = (ke->modifiers() & Qt::ShiftModifier) != 0; + if ((fShift && psz->isLower()) || (!fShift && psz->isUpper())) { + fCapsLock = true; + ui->capsLabel->setText(tr("Warning: The Caps Lock key is on!")); + } else if (psz->isLetter()) { + fCapsLock = false; + ui->capsLabel->clear(); + } + } + } + return QDialog::eventFilter(object, event); +} + +void AskPassphraseDialog::secureClearPassFields() +{ + // Attempt to overwrite text so that they do not linger around in memory + ui->passEdit1->setText(QString(" ").repeated(ui->passEdit1->text().size())); + ui->passEdit2->setText(QString(" ").repeated(ui->passEdit2->text().size())); + ui->passEdit3->setText(QString(" ").repeated(ui->passEdit3->text().size())); + + ui->passEdit1->clear(); + ui->passEdit2->clear(); + ui->passEdit3->clear(); +} diff --git a/src/qt/askpassphrasedialog.h b/src/qt/askpassphrasedialog.h new file mode 100755 index 0000000..f604ffe --- /dev/null +++ b/src/qt/askpassphrasedialog.h @@ -0,0 +1,47 @@ +#ifndef ASKPASSPHRASEDIALOG_H +#define ASKPASSPHRASEDIALOG_H + +#include + +namespace Ui { + class AskPassphraseDialog; +} + +class WalletModel; + +/** Multifunctional dialog to ask for passphrases. Used for encryption, unlocking, and changing the passphrase. + */ +class AskPassphraseDialog : public QDialog +{ + Q_OBJECT + +public: + enum Mode { + Encrypt, /**< Ask passphrase twice and encrypt */ + UnlockStaking, /**< Ask passphrase and unlock */ + Unlock, /**< Ask passphrase and unlock */ + ChangePass, /**< Ask old passphrase + new passphrase twice */ + Decrypt /**< Ask passphrase and decrypt wallet */ + }; + + explicit AskPassphraseDialog(Mode mode, QWidget *parent = 0); + ~AskPassphraseDialog(); + + void accept(); + + void setModel(WalletModel *model); + +private: + Ui::AskPassphraseDialog *ui; + Mode mode; + WalletModel *model; + bool fCapsLock; + +private slots: + void textChanged(); + bool event(QEvent *event); + bool eventFilter(QObject *, QEvent *event); + void secureClearPassFields(); +}; + +#endif // ASKPASSPHRASEDIALOG_H diff --git a/src/qt/bitcoin.cpp b/src/qt/bitcoin.cpp new file mode 100755 index 0000000..3359edc --- /dev/null +++ b/src/qt/bitcoin.cpp @@ -0,0 +1,272 @@ +/* + * W.J. van der Laan 2011-2012 + */ +#include "bitcoingui.h" +#include "clientmodel.h" +#include "walletmodel.h" +#include "optionsmodel.h" +#include "guiutil.h" +#include "guiconstants.h" + +#include "init.h" +#include "ui_interface.h" +#include "qtipcserver.h" + +#include +#include +#include +#include +#include +#include +#include + +#if defined(BITCOIN_NEED_QT_PLUGINS) && !defined(_BITCOIN_QT_PLUGINS_INCLUDED) +#define _BITCOIN_QT_PLUGINS_INCLUDED +#define __INSURE__ +#include +Q_IMPORT_PLUGIN(qcncodecs) +Q_IMPORT_PLUGIN(qjpcodecs) +Q_IMPORT_PLUGIN(qtwcodecs) +Q_IMPORT_PLUGIN(qkrcodecs) +Q_IMPORT_PLUGIN(qtaccessiblewidgets) +#endif + +// Need a global reference for the notifications to find the GUI +static BitcoinGUI *guiref; +static QSplashScreen *splashref; + +static void ThreadSafeMessageBox(const std::string& message, const std::string& caption, int style) +{ + // Message from network thread + if(guiref) + { + bool modal = (style & CClientUIInterface::MODAL); + // in case of modal message, use blocking connection to wait for user to click OK + QMetaObject::invokeMethod(guiref, "error", + modal ? GUIUtil::blockingGUIThreadConnection() : Qt::QueuedConnection, + Q_ARG(QString, QString::fromStdString(caption)), + Q_ARG(QString, QString::fromStdString(message)), + Q_ARG(bool, modal)); + } + else + { + printf("%s: %s\n", caption.c_str(), message.c_str()); + fprintf(stderr, "%s: %s\n", caption.c_str(), message.c_str()); + } +} + +static bool ThreadSafeAskFee(int64_t nFeeRequired, const std::string& strCaption) +{ + if(!guiref) + return false; + if(nFeeRequired < MIN_TX_FEE || nFeeRequired <= nTransactionFee || fDaemon) + return true; + bool payFee = false; + + QMetaObject::invokeMethod(guiref, "askFee", GUIUtil::blockingGUIThreadConnection(), + Q_ARG(qint64, nFeeRequired), + Q_ARG(bool*, &payFee)); + + return payFee; +} + +static void ThreadSafeHandleURI(const std::string& strURI) +{ + if(!guiref) + return; + + QMetaObject::invokeMethod(guiref, "handleURI", GUIUtil::blockingGUIThreadConnection(), + Q_ARG(QString, QString::fromStdString(strURI))); +} + +static void InitMessage(const std::string &message) +{ + if(splashref) + { + splashref->showMessage(QString::fromStdString(message), Qt::AlignBottom|Qt::AlignHCenter, QColor(255,255,255)); + QApplication::instance()->processEvents(); + } +} + +static void QueueShutdown() +{ + QMetaObject::invokeMethod(QCoreApplication::instance(), "quit", Qt::QueuedConnection); +} + +/* + Translate string to current locale using Qt. + */ +static std::string Translate(const char* psz) +{ + return QCoreApplication::translate("bitcoin-core", psz).toStdString(); +} + +/* Handle runaway exceptions. Shows a message box with the problem and quits the program. + */ +static void handleRunawayException(std::exception *e) +{ + PrintExceptionContinue(e, "Runaway exception"); + QMessageBox::critical(0, "Runaway exception", BitcoinGUI::tr("A fatal error occurred. Arepacoin can no longer continue safely and will quit.") + QString("\n\n") + QString::fromStdString(strMiscWarning)); + exit(1); +} + +#ifndef BITCOIN_QT_TEST +int main(int argc, char *argv[]) +{ + // Do this early as we don't want to bother initializing if we are just calling IPC + ipcScanRelay(argc, argv); + +#if QT_VERSION < 0x050000 + // Internal string conversion is all UTF-8 + QTextCodec::setCodecForTr(QTextCodec::codecForName("UTF-8")); + QTextCodec::setCodecForCStrings(QTextCodec::codecForTr()); +#endif + + Q_INIT_RESOURCE(bitcoin); + QApplication app(argc, argv); + + // Install global event filter that makes sure that long tooltips can be word-wrapped + app.installEventFilter(new GUIUtil::ToolTipToRichTextFilter(TOOLTIP_WRAP_THRESHOLD, &app)); + + // Command-line options take precedence: + ParseParameters(argc, argv); + + // ... then bitcoin.conf: + if (!boost::filesystem::is_directory(GetDataDir(false))) + { + // This message can not be translated, as translation is not initialized yet + // (which not yet possible because lang=XX can be overridden in bitcoin.conf in the data directory) + QMessageBox::critical(0, "Arepacoin", + QString("Error: Specified data directory \"%1\" does not exist.").arg(QString::fromStdString(mapArgs["-datadir"]))); + return 1; + } + ReadConfigFile(mapArgs, mapMultiArgs); + + // Application identification (must be set before OptionsModel is initialized, + // as it is used to locate QSettings) + app.setOrganizationName("Arepacoin"); + //XXX app.setOrganizationDomain(""); + if(GetBoolArg("-testnet")) // Separate UI settings for testnet + app.setApplicationName("Arepacoin-Qt-testnet"); + else + app.setApplicationName("Arepacoin-Qt"); + + // ... then GUI settings: + OptionsModel optionsModel; + + // Get desired locale (e.g. "de_DE") from command line or use system locale + QString lang_territory = QString::fromStdString(GetArg("-lang", QLocale::system().name().toStdString())); + QString lang = lang_territory; + // Convert to "de" only by truncating "_DE" + lang.truncate(lang_territory.lastIndexOf('_')); + + QTranslator qtTranslatorBase, qtTranslator, translatorBase, translator; + // Load language files for configured locale: + // - First load the translator for the base language, without territory + // - Then load the more specific locale translator + + // Load e.g. qt_de.qm + if (qtTranslatorBase.load("qt_" + lang, QLibraryInfo::location(QLibraryInfo::TranslationsPath))) + app.installTranslator(&qtTranslatorBase); + + // Load e.g. qt_de_DE.qm + if (qtTranslator.load("qt_" + lang_territory, QLibraryInfo::location(QLibraryInfo::TranslationsPath))) + app.installTranslator(&qtTranslator); + + // Load e.g. bitcoin_de.qm (shortcut "de" needs to be defined in bitcoin.qrc) + if (translatorBase.load(lang, ":/translations/")) + app.installTranslator(&translatorBase); + + // Load e.g. bitcoin_de_DE.qm (shortcut "de_DE" needs to be defined in bitcoin.qrc) + if (translator.load(lang_territory, ":/translations/")) + app.installTranslator(&translator); + + // Subscribe to global signals from core + uiInterface.ThreadSafeMessageBox.connect(ThreadSafeMessageBox); + uiInterface.ThreadSafeAskFee.connect(ThreadSafeAskFee); + uiInterface.ThreadSafeHandleURI.connect(ThreadSafeHandleURI); + uiInterface.InitMessage.connect(InitMessage); + uiInterface.QueueShutdown.connect(QueueShutdown); + uiInterface.Translate.connect(Translate); + + // Show help message immediately after parsing command-line options (for "-lang") and setting locale, + // but before showing splash screen. + if (mapArgs.count("-?") || mapArgs.count("--help")) + { + GUIUtil::HelpMessageBox help; + help.showOrPrint(); + return 1; + } + + QSplashScreen splash(QPixmap(":/images/splash"), 0); + if (GetBoolArg("-splash", true) && !GetBoolArg("-min")) + { + splash.show(); + splashref = &splash; + } + + app.processEvents(); + + app.setQuitOnLastWindowClosed(false); + + try + { + if (fUseBlackTheme) + GUIUtil::SetBlackThemeQSS(app); + + // Regenerate startup link, to fix links to old versions + if (GUIUtil::GetStartOnSystemStartup()) + GUIUtil::SetStartOnSystemStartup(true); + + BitcoinGUI window; + guiref = &window; + if(AppInit2()) + { + { + // Put this in a block, so that the Model objects are cleaned up before + // calling Shutdown(). + + if (splashref) + splash.finish(&window); + + ClientModel clientModel(&optionsModel); + WalletModel walletModel(pwalletMain, &optionsModel); + + window.setClientModel(&clientModel); + window.setWalletModel(&walletModel); + + // If -min option passed, start window minimized. + if(GetBoolArg("-min")) + { + window.showMinimized(); + } + else + { + window.show(); + } + + // Place this here as guiref has to be defined if we don't want to lose URIs + ipcInit(argc, argv); + + app.exec(); + + window.hide(); + window.setClientModel(0); + window.setWalletModel(0); + guiref = 0; + } + // Shutdown the core and its threads, but don't exit Bitcoin-Qt here + Shutdown(NULL); + } + else + { + return 1; + } + } catch (std::exception& e) { + handleRunawayException(&e); + } catch (...) { + handleRunawayException(NULL); + } + return 0; +} +#endif // BITCOIN_QT_TEST diff --git a/src/qt/bitcoin.qrc b/src/qt/bitcoin.qrc new file mode 100755 index 0000000..5caf4a6 --- /dev/null +++ b/src/qt/bitcoin.qrc @@ -0,0 +1,134 @@ + + + res/icons/arepacoin-80.png + res/icons/address-book.png + res/icons/quit.png + res/icons/send.png + res/icons/arepacoin-16.png + res/icons/connect0_16.png + res/icons/connect1_16.png + res/icons/connect2_16.png + res/icons/connect3_16.png + res/icons/connect4_16.png + res/icons/transaction0.png + res/icons/transaction2.png + res/icons/transaction_conflicted.png + res/icons/clock1.png + res/icons/clock2.png + res/icons/clock3.png + res/icons/clock4.png + res/icons/clock5.png + res/icons/configure.png + res/icons/receive.png + res/icons/editpaste.png + res/icons/editcopy.png + res/icons/add.png + res/icons/arepacoin-80.png + res/icons/arepacoin-16.png + res/icons/edit.png + res/icons/history.png + res/icons/overview.png + res/icons/export.png + res/icons/synced.png + res/icons/remove.png + res/icons/tx_mined.png + res/icons/tx_input.png + res/icons/tx_output.png + res/icons/tx_inout.png + res/icons/lock_closed.png + res/icons/lock_open.png + res/icons/key.png + res/icons/filesave.png + res/icons/qrcode.png + res/icons/about_qt.png + res/icons/debugwindow.png + res/icons/staking_off.png + res/icons/staking_on.png + res/icons/telegram.png + res/icons/twitter.png + + + res/images/about.png + res/images/splash.png + res/images/header.png + + + res/movies/spinner-000.png + res/movies/spinner-001.png + res/movies/spinner-002.png + res/movies/spinner-003.png + res/movies/spinner-004.png + res/movies/spinner-005.png + res/movies/spinner-006.png + res/movies/spinner-007.png + res/movies/spinner-008.png + res/movies/spinner-009.png + res/movies/spinner-010.png + res/movies/spinner-011.png + res/movies/spinner-012.png + res/movies/spinner-013.png + res/movies/spinner-014.png + res/movies/spinner-015.png + res/movies/spinner-016.png + res/movies/spinner-017.png + res/movies/spinner-018.png + res/movies/spinner-019.png + res/movies/spinner-020.png + res/movies/spinner-021.png + res/movies/spinner-022.png + res/movies/spinner-023.png + res/movies/spinner-024.png + res/movies/spinner-025.png + res/movies/spinner-026.png + res/movies/spinner-027.png + res/movies/spinner-028.png + res/movies/spinner-029.png + res/movies/spinner-030.png + res/movies/spinner-031.png + res/movies/spinner-032.png + res/movies/spinner-033.png + res/movies/spinner-034.png + res/movies/spinner-035.png + + + locale/bitcoin_ar.qm + locale/bitcoin_ca_ES.qm + locale/bitcoin_cs.qm + locale/bitcoin_da.qm + locale/bitcoin_de.qm + locale/bitcoin_el_GR.qm + locale/bitcoin_en.qm + locale/bitcoin_eo.qm + locale/bitcoin_es_CL.qm + locale/bitcoin_es_DO.qm + locale/bitcoin_es.qm + locale/bitcoin_fa.qm + locale/bitcoin_fi.qm + locale/bitcoin_fr_CA.qm + locale/bitcoin_fr.qm + locale/bitcoin_gl.qm + locale/bitcoin_he.qm + locale/bitcoin_hr.qm + locale/bitcoin_hu.qm + locale/bitcoin_it.qm + locale/bitcoin_ja.qm + locale/bitcoin_ka.qm + locale/bitcoin_ko_KR.qm + locale/bitcoin_lt.qm + locale/bitcoin_nb.qm + locale/bitcoin_nl.qm + locale/bitcoin_pam.qm + locale/bitcoin_pl.qm + locale/bitcoin_pt_BR.qm + locale/bitcoin_pt_PT.qm + locale/bitcoin_ro_RO.qm + locale/bitcoin_ru.qm + locale/bitcoin_sk.qm + locale/bitcoin_sl_SI.qm + locale/bitcoin_sv.qm + locale/bitcoin_tr.qm + locale/bitcoin_uk.qm + locale/bitcoin_zh_CN.qm + locale/bitcoin_zh_TW.qm + + diff --git a/src/qt/bitcoinaddressvalidator.cpp b/src/qt/bitcoinaddressvalidator.cpp new file mode 100755 index 0000000..5136ea0 --- /dev/null +++ b/src/qt/bitcoinaddressvalidator.cpp @@ -0,0 +1,77 @@ +#include "bitcoinaddressvalidator.h" + +/* Base58 characters are: + "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz" + + This is: + - All numbers except for '0' + - All upper-case letters except for 'I' and 'O' + - All lower-case letters except for 'l' + + User friendly Base58 input can map + - 'l' and 'I' to '1' + - '0' and 'O' to 'o' +*/ + +BitcoinAddressValidator::BitcoinAddressValidator(QObject *parent) : + QValidator(parent) +{ +} + +QValidator::State BitcoinAddressValidator::validate(QString &input, int &pos) const +{ + // Correction + for(int idx=0; idx= '0' && ch<='9') || + (ch >= 'a' && ch<='z') || + (ch >= 'A' && ch<='Z')) && + ch != 'l' && ch != 'I' && ch != '0' && ch != 'O') + { + // Alphanumeric and not a 'forbidden' character + } + else + { + state = QValidator::Invalid; + } + } + + // Empty address is "intermediate" input + if(input.isEmpty()) + { + state = QValidator::Intermediate; + } + + return state; +} diff --git a/src/qt/bitcoinaddressvalidator.h b/src/qt/bitcoinaddressvalidator.h new file mode 100755 index 0000000..9710d12 --- /dev/null +++ b/src/qt/bitcoinaddressvalidator.h @@ -0,0 +1,24 @@ +#ifndef BITCOINADDRESSVALIDATOR_H +#define BITCOINADDRESSVALIDATOR_H + +#include + +/** Base48 entry widget validator. + Corrects near-miss characters and refuses characters that are no part of base48. + */ +class BitcoinAddressValidator : public QValidator +{ + Q_OBJECT +public: + explicit BitcoinAddressValidator(QObject *parent = 0); + + State validate(QString &input, int &pos) const; + + static const int MaxAddressLength = 35; +signals: + +public slots: + +}; + +#endif // BITCOINADDRESSVALIDATOR_H diff --git a/src/qt/bitcoinamountfield.cpp b/src/qt/bitcoinamountfield.cpp new file mode 100755 index 0000000..9514ec8 --- /dev/null +++ b/src/qt/bitcoinamountfield.cpp @@ -0,0 +1,168 @@ +#include "bitcoinamountfield.h" +#include "qvaluecombobox.h" +#include "bitcoinunits.h" + +#include "guiconstants.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +BitcoinAmountField::BitcoinAmountField(QWidget *parent): + QWidget(parent), amount(0), currentUnit(-1) +{ + amount = new QDoubleSpinBox(this); + amount->setLocale(QLocale::c()); + amount->setDecimals(8); + amount->installEventFilter(this); + amount->setMaximumWidth(170); + amount->setSingleStep(0.001); + + QHBoxLayout *layout = new QHBoxLayout(this); + layout->addWidget(amount); + unit = new QValueComboBox(this); + unit->setModel(new BitcoinUnits(this)); + layout->addWidget(unit); + layout->addStretch(1); + layout->setContentsMargins(0,0,0,0); + + setLayout(layout); + + setFocusPolicy(Qt::TabFocus); + setFocusProxy(amount); + + // If one if the widgets changes, the combined content changes as well + connect(amount, SIGNAL(valueChanged(QString)), this, SIGNAL(textChanged())); + connect(unit, SIGNAL(currentIndexChanged(int)), this, SLOT(unitChanged(int))); + + // Set default based on configuration + unitChanged(unit->currentIndex()); +} + +void BitcoinAmountField::setText(const QString &text) +{ + if (text.isEmpty()) + amount->clear(); + else + amount->setValue(text.toDouble()); +} + +void BitcoinAmountField::clear() +{ + amount->clear(); + unit->setCurrentIndex(0); +} + +bool BitcoinAmountField::validate() +{ + bool valid = true; + if (amount->value() == 0.0) + valid = false; + if (valid && !BitcoinUnits::parse(currentUnit, text(), 0)) + valid = false; + + setValid(valid); + + return valid; +} + +void BitcoinAmountField::setValid(bool valid) +{ + if (valid) + amount->setStyleSheet(""); + else + amount->setStyleSheet(STYLE_INVALID); +} + +QString BitcoinAmountField::text() const +{ + if (amount->text().isEmpty()) + return QString(); + else + return amount->text(); +} + +bool BitcoinAmountField::eventFilter(QObject *object, QEvent *event) +{ + if (event->type() == QEvent::FocusIn) + { + // Clear invalid flag on focus + setValid(true); + } + else if (event->type() == QEvent::KeyPress || event->type() == QEvent::KeyRelease) + { + QKeyEvent *keyEvent = static_cast(event); + if (keyEvent->key() == Qt::Key_Comma) + { + // Translate a comma into a period + QKeyEvent periodKeyEvent(event->type(), Qt::Key_Period, keyEvent->modifiers(), ".", keyEvent->isAutoRepeat(), keyEvent->count()); + qApp->sendEvent(object, &periodKeyEvent); + return true; + } + } + return QWidget::eventFilter(object, event); +} + +QWidget *BitcoinAmountField::setupTabChain(QWidget *prev) +{ + QWidget::setTabOrder(prev, amount); + return amount; +} + +qint64 BitcoinAmountField::value(bool *valid_out) const +{ + qint64 val_out = 0; + bool valid = BitcoinUnits::parse(currentUnit, text(), &val_out); + if(valid_out) + { + *valid_out = valid; + } + return val_out; +} + +void BitcoinAmountField::setValue(qint64 value) +{ + setText(BitcoinUnits::format(currentUnit, value)); +} + +void BitcoinAmountField::unitChanged(int idx) +{ + // Use description tooltip for current unit for the combobox + unit->setToolTip(unit->itemData(idx, Qt::ToolTipRole).toString()); + + // Determine new unit ID + int newUnit = unit->itemData(idx, BitcoinUnits::UnitRole).toInt(); + + // Parse current value and convert to new unit + bool valid = false; + qint64 currentValue = value(&valid); + + currentUnit = newUnit; + + // Set max length after retrieving the value, to prevent truncation + amount->setDecimals(BitcoinUnits::decimals(currentUnit)); + amount->setMaximum(qPow(10, BitcoinUnits::amountDigits(currentUnit)) - qPow(10, -amount->decimals())); + + if(valid) + { + // If value was valid, re-place it in the widget with the new unit + setValue(currentValue); + } + else + { + // If current value is invalid, just clear field + setText(""); + } + setValid(true); +} + +void BitcoinAmountField::setDisplayUnit(int newUnit) +{ + unit->setValue(newUnit); +} diff --git a/src/qt/bitcoinamountfield.h b/src/qt/bitcoinamountfield.h new file mode 100755 index 0000000..66792e0 --- /dev/null +++ b/src/qt/bitcoinamountfield.h @@ -0,0 +1,60 @@ +#ifndef BITCOINFIELD_H +#define BITCOINFIELD_H + +#include + +QT_BEGIN_NAMESPACE +class QDoubleSpinBox; +class QValueComboBox; +QT_END_NAMESPACE + +/** Widget for entering bitcoin amounts. + */ +class BitcoinAmountField: public QWidget +{ + Q_OBJECT + Q_PROPERTY(qint64 value READ value WRITE setValue NOTIFY textChanged USER true) +public: + explicit BitcoinAmountField(QWidget *parent = 0); + + qint64 value(bool *valid=0) const; + void setValue(qint64 value); + + /** Mark current value as invalid in UI. */ + void setValid(bool valid); + /** Perform input validation, mark field as invalid if entered value is not valid. */ + bool validate(); + + /** Change unit used to display amount. */ + void setDisplayUnit(int unit); + + /** Make field empty and ready for new input. */ + void clear(); + + /** Qt messes up the tab chain by default in some cases (issue https://bugreports.qt-project.org/browse/QTBUG-10907), + in these cases we have to set it up manually. + */ + QWidget *setupTabChain(QWidget *prev); + +signals: + void textChanged(); + +protected: + /** Intercept focus-in event and ',' key presses */ + bool eventFilter(QObject *object, QEvent *event); + +private: + QDoubleSpinBox *amount; + QValueComboBox *unit; + int currentUnit; + + void setText(const QString &text); + QString text() const; + +private slots: + void unitChanged(int idx); + +}; + + +#endif // BITCOINFIELD_H diff --git a/src/qt/bitcoingui.cpp b/src/qt/bitcoingui.cpp new file mode 100755 index 0000000..72642e7 --- /dev/null +++ b/src/qt/bitcoingui.cpp @@ -0,0 +1,1032 @@ +/* + * Qt4 bitcoin GUI. + * + * W.J. van der Laan 2011-2012 + * The Bitcoin Developers 2011-2012 + */ +#include "bitcoingui.h" +#include "transactiontablemodel.h" +#include "addressbookpage.h" +#include "sendcoinsdialog.h" +#include "signverifymessagedialog.h" +#include "optionsdialog.h" +#include "aboutdialog.h" +#include "clientmodel.h" +#include "walletmodel.h" +#include "editaddressdialog.h" +#include "optionsmodel.h" +#include "transactiondescdialog.h" +#include "addresstablemodel.h" +#include "transactionview.h" +#include "overviewpage.h" +#include "bitcoinunits.h" +#include "guiconstants.h" +#include "askpassphrasedialog.h" +#include "notificator.h" +#include "guiutil.h" +#include "rpcconsole.h" +#include "wallet.h" + +#ifdef Q_OS_MAC +#include "macdockiconhandler.h" +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +extern CWallet* pwalletMain; +extern int64_t nLastCoinStakeSearchInterval; +double GetPoSKernelPS(); + +BitcoinGUI::BitcoinGUI(QWidget *parent): + QMainWindow(parent), + clientModel(0), + walletModel(0), + encryptWalletAction(0), + changePassphraseAction(0), + unlockWalletAction(0), + lockWalletAction(0), + aboutQtAction(0), + trayIcon(0), + notificator(0), + rpcConsole(0), + spinnerFrame(0), + prevBlocks(0), + nWeight(0) +{ + resize(850, 550); + setWindowTitle(tr("Arepacoin") + " - " + tr("Wallet")); +#ifndef Q_OS_MAC + qApp->setWindowIcon(QIcon(":icons/bitcoin")); + setWindowIcon(QIcon(":icons/bitcoin")); +#else + setUnifiedTitleAndToolBarOnMac(true); + QApplication::setAttribute(Qt::AA_DontShowIconsInMenus); +#endif + // Accept D&D of URIs + setAcceptDrops(true); + + // Create actions for the toolbar, menu bar and tray/dock icon + createActions(); + + // Create application menu bar + createMenuBar(); + + // Create the toolbars + createToolBars(); + + // Create the tray icon (or setup the dock icon) + createTrayIcon(); + + // Create tabs + overviewPage = new OverviewPage(); + + transactionsPage = new QWidget(this); + QVBoxLayout *vbox = new QVBoxLayout(); + transactionView = new TransactionView(this); + vbox->addWidget(transactionView); + transactionsPage->setLayout(vbox); + + addressBookPage = new AddressBookPage(AddressBookPage::ForEditing, AddressBookPage::SendingTab); + + receiveCoinsPage = new AddressBookPage(AddressBookPage::ForEditing, AddressBookPage::ReceivingTab); + + sendCoinsPage = new SendCoinsDialog(this); + + signVerifyMessageDialog = new SignVerifyMessageDialog(this); + + centralWidget = new QStackedWidget(this); + centralWidget->addWidget(overviewPage); + centralWidget->addWidget(transactionsPage); + centralWidget->addWidget(addressBookPage); + centralWidget->addWidget(receiveCoinsPage); + centralWidget->addWidget(sendCoinsPage); + setCentralWidget(centralWidget); + + // Create status bar + statusBar(); + + // Status bar notification icons + QFrame *frameBlocks = new QFrame(); + frameBlocks->setContentsMargins(0,0,0,0); + frameBlocks->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Preferred); + QHBoxLayout *frameBlocksLayout = new QHBoxLayout(frameBlocks); + frameBlocksLayout->setContentsMargins(3,0,3,0); + frameBlocksLayout->setSpacing(3); + labelEncryptionIcon = new QLabel(); + labelStakingIcon = new QLabel(); + labelConnectionsIcon = new QLabel(); + labelBlocksIcon = new QLabel(); + frameBlocksLayout->addStretch(); + frameBlocksLayout->addWidget(labelEncryptionIcon); + frameBlocksLayout->addStretch(); + frameBlocksLayout->addWidget(labelStakingIcon); + frameBlocksLayout->addStretch(); + frameBlocksLayout->addWidget(labelConnectionsIcon); + frameBlocksLayout->addStretch(); + frameBlocksLayout->addWidget(labelBlocksIcon); + frameBlocksLayout->addStretch(); + + if (GetBoolArg("-staking", true)) + { + QTimer *timerStakingIcon = new QTimer(labelStakingIcon); + connect(timerStakingIcon, SIGNAL(timeout()), this, SLOT(updateStakingIcon())); + timerStakingIcon->start(30 * 1000); + updateStakingIcon(); + } + + // Progress bar and label for blocks download + progressBarLabel = new QLabel(); + progressBarLabel->setVisible(false); + progressBar = new QProgressBar(); + progressBar->setAlignment(Qt::AlignCenter); + progressBar->setVisible(false); + + if (!fUseBlackTheme) + { + // Override style sheet for progress bar for styles that have a segmented progress bar, + // as they make the text unreadable (workaround for issue #1071) + // See https://qt-project.org/doc/qt-4.8/gallery.html + QString curStyle = qApp->style()->metaObject()->className(); + if(curStyle == "QWindowsStyle" || curStyle == "QWindowsXPStyle") + { + progressBar->setStyleSheet("QProgressBar { background-color: #e8e8e8; border: 1px solid grey; border-radius: 7px; padding: 1px; text-align: center; } QProgressBar::chunk { background: QLinearGradient(x1: 0, y1: 0, x2: 1, y2: 0, stop: 0 #FF8000, stop: 1 orange); border-radius: 7px; margin: 0px; }"); + } + } + + statusBar()->addWidget(progressBarLabel); + statusBar()->addWidget(progressBar); + statusBar()->addPermanentWidget(frameBlocks); + + // Clicking on a transaction on the overview page simply sends you to transaction history page + connect(overviewPage, SIGNAL(transactionClicked(QModelIndex)), this, SLOT(gotoHistoryPage())); + connect(overviewPage, SIGNAL(transactionClicked(QModelIndex)), transactionView, SLOT(focusTransaction(QModelIndex))); + + // Double-clicking on a transaction on the transaction history page shows details + connect(transactionView, SIGNAL(doubleClicked(QModelIndex)), transactionView, SLOT(showDetails())); + + rpcConsole = new RPCConsole(this); + connect(openRPCConsoleAction, SIGNAL(triggered()), rpcConsole, SLOT(show())); + + // Clicking on "Verify Message" in the address book sends you to the verify message tab + connect(addressBookPage, SIGNAL(verifyMessage(QString)), this, SLOT(gotoVerifyMessageTab(QString))); + // Clicking on "Sign Message" in the receive coins page sends you to the sign message tab + connect(receiveCoinsPage, SIGNAL(signMessage(QString)), this, SLOT(gotoSignMessageTab(QString))); + + gotoOverviewPage(); +} + +BitcoinGUI::~BitcoinGUI() +{ + if(trayIcon) // Hide tray icon, as deleting will let it linger until quit (on Ubuntu) + trayIcon->hide(); +#ifdef Q_OS_MAC + delete appMenuBar; +#endif +} + +void BitcoinGUI::createActions() +{ + QActionGroup *tabGroup = new QActionGroup(this); + + overviewAction = new QAction(QIcon(":/icons/overview"), tr("&Overview"), this); + overviewAction->setToolTip(tr("Show general overview of wallet")); + overviewAction->setCheckable(true); + overviewAction->setShortcut(QKeySequence(Qt::ALT + Qt::Key_1)); + tabGroup->addAction(overviewAction); + + sendCoinsAction = new QAction(QIcon(":/icons/send"), tr("&Send coins"), this); + sendCoinsAction->setToolTip(tr("Send coins to a Arepacoin address")); + sendCoinsAction->setCheckable(true); + sendCoinsAction->setShortcut(QKeySequence(Qt::ALT + Qt::Key_2)); + tabGroup->addAction(sendCoinsAction); + + receiveCoinsAction = new QAction(QIcon(":/icons/receiving_addresses"), tr("&Receive coins"), this); + receiveCoinsAction->setToolTip(tr("Show the list of addresses for receiving payments")); + receiveCoinsAction->setCheckable(true); + receiveCoinsAction->setShortcut(QKeySequence(Qt::ALT + Qt::Key_3)); + tabGroup->addAction(receiveCoinsAction); + + historyAction = new QAction(QIcon(":/icons/history"), tr("&Transactions"), this); + historyAction->setToolTip(tr("Browse transaction history")); + historyAction->setCheckable(true); + historyAction->setShortcut(QKeySequence(Qt::ALT + Qt::Key_4)); + tabGroup->addAction(historyAction); + + addressBookAction = new QAction(QIcon(":/icons/address-book"), tr("&Address Book"), this); + addressBookAction->setToolTip(tr("Edit the list of stored addresses and labels")); + addressBookAction->setCheckable(true); + addressBookAction->setShortcut(QKeySequence(Qt::ALT + Qt::Key_5)); + tabGroup->addAction(addressBookAction); + + telegramAction = new QAction(QIcon(":/icons/telegram"), tr("&Group Telegram"), this); + telegramAction->setToolTip(tr("Visit us on Telegram")); + + twitterAction = new QAction(QIcon(":/icons/twitter"), tr("&Arepa Twitter"), this); + twitterAction->setToolTip(tr("Follow us on Facebook")); + + connect(overviewAction, SIGNAL(triggered()), this, SLOT(showNormalIfMinimized())); + connect(overviewAction, SIGNAL(triggered()), this, SLOT(gotoOverviewPage())); + connect(sendCoinsAction, SIGNAL(triggered()), this, SLOT(showNormalIfMinimized())); + connect(sendCoinsAction, SIGNAL(triggered()), this, SLOT(gotoSendCoinsPage())); + connect(receiveCoinsAction, SIGNAL(triggered()), this, SLOT(showNormalIfMinimized())); + connect(receiveCoinsAction, SIGNAL(triggered()), this, SLOT(gotoReceiveCoinsPage())); + connect(historyAction, SIGNAL(triggered()), this, SLOT(showNormalIfMinimized())); + connect(historyAction, SIGNAL(triggered()), this, SLOT(gotoHistoryPage())); + connect(addressBookAction, SIGNAL(triggered()), this, SLOT(showNormalIfMinimized())); + connect(addressBookAction, SIGNAL(triggered()), this, SLOT(gotoAddressBookPage())); + connect(telegramAction, SIGNAL(triggered()), this, SLOT(openTelegram())); + connect(twitterAction, SIGNAL(triggered()), this, SLOT(openTwitter())); + + quitAction = new QAction(QIcon(":/icons/quit"), tr("E&xit"), this); + quitAction->setToolTip(tr("Quit application")); + quitAction->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_Q)); + quitAction->setMenuRole(QAction::QuitRole); + aboutAction = new QAction(QIcon(":/icons/bitcoin"), tr("&About Arepacoin"), this); + aboutAction->setToolTip(tr("Show information about Arepacoin")); + aboutAction->setMenuRole(QAction::AboutRole); + aboutQtAction = new QAction(QIcon(":/icons/about_qt"), tr("About &Qt"), this); + aboutQtAction->setToolTip(tr("Show information about Qt")); + aboutQtAction->setMenuRole(QAction::AboutQtRole); + optionsAction = new QAction(QIcon(":/icons/options"), tr("&Options..."), this); + optionsAction->setToolTip(tr("Modify configuration options for Arepacoin")); + optionsAction->setMenuRole(QAction::PreferencesRole); + toggleHideAction = new QAction(QIcon(":/icons/bitcoin"), tr("&Show / Hide"), this); + encryptWalletAction = new QAction(QIcon(":/icons/lock_closed"), tr("&Encrypt Wallet..."), this); + encryptWalletAction->setToolTip(tr("Encrypt or decrypt wallet")); + encryptWalletAction->setCheckable(true); + backupWalletAction = new QAction(QIcon(":/icons/filesave"), tr("&Backup Wallet..."), this); + backupWalletAction->setToolTip(tr("Backup wallet to another location")); + changePassphraseAction = new QAction(QIcon(":/icons/key"), tr("&Change Passphrase..."), this); + changePassphraseAction->setToolTip(tr("Change the passphrase used for wallet encryption")); + unlockWalletAction = new QAction(QIcon(":/icons/lock_open"), tr("&Unlock Wallet..."), this); + unlockWalletAction->setToolTip(tr("Unlock wallet")); + lockWalletAction = new QAction(QIcon(":/icons/lock_closed"), tr("&Lock Wallet"), this); + lockWalletAction->setToolTip(tr("Lock wallet")); + signMessageAction = new QAction(QIcon(":/icons/edit"), tr("Sign &message..."), this); + verifyMessageAction = new QAction(QIcon(":/icons/transaction_0"), tr("&Verify message..."), this); + + exportAction = new QAction(QIcon(":/icons/export"), tr("&Export..."), this); + exportAction->setToolTip(tr("Export the data in the current tab to a file")); + openRPCConsoleAction = new QAction(QIcon(":/icons/debugwindow"), tr("&Debug window"), this); + openRPCConsoleAction->setToolTip(tr("Open debugging and diagnostic console")); + + connect(quitAction, SIGNAL(triggered()), qApp, SLOT(quit())); + connect(aboutAction, SIGNAL(triggered()), this, SLOT(aboutClicked())); + connect(aboutQtAction, SIGNAL(triggered()), qApp, SLOT(aboutQt())); + connect(optionsAction, SIGNAL(triggered()), this, SLOT(optionsClicked())); + connect(toggleHideAction, SIGNAL(triggered()), this, SLOT(toggleHidden())); + connect(encryptWalletAction, SIGNAL(triggered(bool)), this, SLOT(encryptWallet(bool))); + connect(backupWalletAction, SIGNAL(triggered()), this, SLOT(backupWallet())); + connect(changePassphraseAction, SIGNAL(triggered()), this, SLOT(changePassphrase())); + connect(unlockWalletAction, SIGNAL(triggered()), this, SLOT(unlockWallet())); + connect(lockWalletAction, SIGNAL(triggered()), this, SLOT(lockWallet())); + connect(signMessageAction, SIGNAL(triggered()), this, SLOT(gotoSignMessageTab())); + connect(verifyMessageAction, SIGNAL(triggered()), this, SLOT(gotoVerifyMessageTab())); +} + +void BitcoinGUI::createMenuBar() +{ +#ifdef Q_OS_MAC + // Create a decoupled menu bar on Mac which stays even if the window is closed + appMenuBar = new QMenuBar(); +#else + // Get the main window's menu bar on other platforms + appMenuBar = menuBar(); +#endif + + // Configure the menus + QMenu *file = appMenuBar->addMenu(tr("&File")); + file->addAction(backupWalletAction); + file->addAction(exportAction); + file->addAction(signMessageAction); + file->addAction(verifyMessageAction); + file->addSeparator(); + file->addAction(quitAction); + + QMenu *settings = appMenuBar->addMenu(tr("&Settings")); + settings->addAction(encryptWalletAction); + settings->addAction(changePassphraseAction); + settings->addAction(unlockWalletAction); + settings->addAction(lockWalletAction); + settings->addSeparator(); + settings->addAction(optionsAction); + + QMenu *help = appMenuBar->addMenu(tr("&Help")); + help->addAction(openRPCConsoleAction); + help->addSeparator(); + help->addAction(aboutAction); + help->addAction(aboutQtAction); +} + +static QWidget* makeToolBarSpacer() +{ + QWidget* spacer = new QWidget(); + spacer->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Expanding); + spacer->setStyleSheet("QWidget { background: rgb(255,255,255); }"); + return spacer; +} + +void BitcoinGUI::createToolBars() +{ + QToolBar *toolbar = addToolBar(tr("Tabs toolbar")); + toolbar->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); + toolbar->setContextMenuPolicy(Qt::PreventContextMenu); + QWidget* header = new QWidget(); + header->setMinimumSize(144, 144); + header->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); + header->setStyleSheet("QWidget { background-color: rgb(255,255,255); background-repeat: no-repeat; background-image: url(:/images/header); background-position: center center; }"); + toolbar->addWidget(header); + toolbar->addWidget(makeToolBarSpacer()); + + //QMenu *toolbarMenu = new QMenu(); + toolbar->addAction(overviewAction); + toolbar->addAction(sendCoinsAction); + toolbar->addAction(receiveCoinsAction); + toolbar->addAction(historyAction); + toolbar->addAction(addressBookAction); + toolbar->addAction(exportAction); + // toolbar->addAction(telegramAction); + toolbar->addAction(twitterAction); + + toolbar->addWidget(makeToolBarSpacer()); + + toolbar->setOrientation(Qt::Vertical); + toolbar->setMovable(false); + + addToolBar(Qt::LeftToolBarArea, toolbar); + foreach(QAction *action, toolbar->actions()) { + toolbar->widgetForAction(action)->setFixedWidth(144); + } +} + +void BitcoinGUI::setClientModel(ClientModel *clientModel) +{ + this->clientModel = clientModel; + if(clientModel) + { + // Replace some strings and icons, when using the testnet + if(clientModel->isTestNet()) + { + setWindowTitle(windowTitle() + QString(" ") + tr("[testnet]")); +#ifndef Q_OS_MAC + qApp->setWindowIcon(QIcon(":icons/bitcoin_testnet")); + setWindowIcon(QIcon(":icons/bitcoin_testnet")); +#else + MacDockIconHandler::instance()->setIcon(QIcon(":icons/bitcoin_testnet")); +#endif + if(trayIcon) + { + trayIcon->setToolTip(tr("Arepacoin client") + QString(" ") + tr("[testnet]")); + trayIcon->setIcon(QIcon(":/icons/toolbar_testnet")); + toggleHideAction->setIcon(QIcon(":/icons/toolbar_testnet")); + } + + aboutAction->setIcon(QIcon(":/icons/toolbar_testnet")); + } + + // Keep up to date with client + setNumConnections(clientModel->getNumConnections()); + connect(clientModel, SIGNAL(numConnectionsChanged(int)), this, SLOT(setNumConnections(int))); + + setNumBlocks(clientModel->getNumBlocks(), clientModel->getNumBlocksOfPeers()); + connect(clientModel, SIGNAL(numBlocksChanged(int,int)), this, SLOT(setNumBlocks(int,int))); + + // Report errors from network/worker thread + connect(clientModel, SIGNAL(error(QString,QString,bool)), this, SLOT(error(QString,QString,bool))); + + rpcConsole->setClientModel(clientModel); + addressBookPage->setOptionsModel(clientModel->getOptionsModel()); + receiveCoinsPage->setOptionsModel(clientModel->getOptionsModel()); + } +} + +void BitcoinGUI::setWalletModel(WalletModel *walletModel) +{ + this->walletModel = walletModel; + if(walletModel) + { + // Report errors from wallet thread + connect(walletModel, SIGNAL(error(QString,QString,bool)), this, SLOT(error(QString,QString,bool))); + + // Put transaction list in tabs + transactionView->setModel(walletModel); + + overviewPage->setModel(walletModel); + addressBookPage->setModel(walletModel->getAddressTableModel()); + receiveCoinsPage->setModel(walletModel->getAddressTableModel()); + sendCoinsPage->setModel(walletModel); + signVerifyMessageDialog->setModel(walletModel); + + setEncryptionStatus(walletModel->getEncryptionStatus()); + connect(walletModel, SIGNAL(encryptionStatusChanged(int)), this, SLOT(setEncryptionStatus(int))); + + // Balloon pop-up for new transaction + connect(walletModel->getTransactionTableModel(), SIGNAL(rowsInserted(QModelIndex,int,int)), + this, SLOT(incomingTransaction(QModelIndex,int,int))); + + // Ask for passphrase if needed + connect(walletModel, SIGNAL(requireUnlock()), this, SLOT(unlockWallet())); + } +} + +void BitcoinGUI::createTrayIcon() +{ + QMenu *trayIconMenu; +#ifndef Q_OS_MAC + trayIcon = new QSystemTrayIcon(this); + trayIconMenu = new QMenu(this); + trayIcon->setContextMenu(trayIconMenu); + trayIcon->setToolTip(tr("Arepacoin client")); + trayIcon->setIcon(QIcon(":/icons/toolbar")); + connect(trayIcon, SIGNAL(activated(QSystemTrayIcon::ActivationReason)), + this, SLOT(trayIconActivated(QSystemTrayIcon::ActivationReason))); + trayIcon->show(); +#else + // Note: On Mac, the dock icon is used to provide the tray's functionality. + MacDockIconHandler *dockIconHandler = MacDockIconHandler::instance(); + dockIconHandler->setMainWindow((QMainWindow *)this); + trayIconMenu = dockIconHandler->dockMenu(); +#endif + + // Configuration of the tray icon (or dock icon) icon menu + trayIconMenu->addAction(toggleHideAction); + trayIconMenu->addSeparator(); + trayIconMenu->addAction(sendCoinsAction); + trayIconMenu->addAction(receiveCoinsAction); + trayIconMenu->addSeparator(); + trayIconMenu->addAction(signMessageAction); + trayIconMenu->addAction(verifyMessageAction); + trayIconMenu->addSeparator(); + trayIconMenu->addAction(optionsAction); + trayIconMenu->addAction(openRPCConsoleAction); +#ifndef Q_OS_MAC // This is built-in on Mac + trayIconMenu->addSeparator(); + trayIconMenu->addAction(quitAction); +#endif + + notificator = new Notificator(qApp->applicationName(), trayIcon); +} + +#ifndef Q_OS_MAC +void BitcoinGUI::trayIconActivated(QSystemTrayIcon::ActivationReason reason) +{ + if(reason == QSystemTrayIcon::Trigger) + { + // Click on system tray icon triggers show/hide of the main window + toggleHideAction->trigger(); + } +} +#endif + +void BitcoinGUI::optionsClicked() +{ + if(!clientModel || !clientModel->getOptionsModel()) + return; + OptionsDialog dlg; + dlg.setModel(clientModel->getOptionsModel()); + dlg.exec(); +} + +void BitcoinGUI::aboutClicked() +{ + AboutDialog dlg; + dlg.setModel(clientModel); + dlg.exec(); +} + +void BitcoinGUI::setNumConnections(int count) +{ + QString icon; + switch(count) + { + case 0: icon = ":/icons/connect_0"; break; + case 1: case 2: case 3: icon = ":/icons/connect_1"; break; + case 4: case 5: case 6: icon = ":/icons/connect_2"; break; + case 7: case 8: case 9: icon = ":/icons/connect_3"; break; + default: icon = ":/icons/connect_4"; break; + } + labelConnectionsIcon->setPixmap(QIcon(icon).pixmap(STATUSBAR_ICONSIZE,STATUSBAR_ICONSIZE)); + labelConnectionsIcon->setToolTip(tr("%n active connection(s) to Arepacoin network", "", count)); +} + +void BitcoinGUI::setNumBlocks(int count, int nTotalBlocks) +{ + // don't show / hide progress bar and its label if we have no connection to the network + if (!clientModel || clientModel->getNumConnections() == 0) + { + progressBarLabel->setVisible(false); + progressBar->setVisible(false); + + return; + } + + bool fShowStatusBar = true; + QString strStatusBarWarnings = clientModel->getStatusBarWarnings(); + QString tooltip; + + // Override progressBarLabel text and hide progress bar, when we have warnings to display + if (!strStatusBarWarnings.isEmpty()) + { + progressBarLabel->setText(strStatusBarWarnings); + progressBarLabel->setVisible(true); + progressBar->setVisible(false); + } + + QDateTime lastBlockDate = clientModel->getLastBlockDate(); + QDateTime currentDate = QDateTime::currentDateTime(); + int totalSecs = GetTime() - 1393221600; + int secs = lastBlockDate.secsTo(currentDate); + + if(count < nTotalBlocks) + { + tooltip = tr("Processed %1 of %2 (estimated) blocks of transaction history.").arg(count).arg(nTotalBlocks); + } + else + { + tooltip = tr("Processed %1 blocks of transaction history.").arg(count); + } + + // Set icon state: spinning if catching up, tick otherwise + if(secs < 90*60 && count >= nTotalBlocks) + { + tooltip = tr("Up to date") + QString(".
") + tooltip; + labelBlocksIcon->setPixmap(QIcon(":/icons/synced").pixmap(STATUSBAR_ICONSIZE, STATUSBAR_ICONSIZE)); + + overviewPage->showOutOfSyncWarning(false); + + progressBarLabel->setVisible(false); + progressBar->setVisible(false); + } + else + { + // Represent time from last generated block in human readable text + QString timeBehindText; + const int HOUR_IN_SECONDS = 60*60; + const int DAY_IN_SECONDS = 24*60*60; + const int WEEK_IN_SECONDS = 7*24*60*60; + const int YEAR_IN_SECONDS = 31556952; // Average length of year in Gregorian calendar + if(secs < 2*DAY_IN_SECONDS) + { + timeBehindText = tr("%n hour(s)","",secs/HOUR_IN_SECONDS); + } + else if(secs < 2*WEEK_IN_SECONDS) + { + timeBehindText = tr("%n day(s)","",secs/DAY_IN_SECONDS); + } + else if(secs < YEAR_IN_SECONDS) + { + timeBehindText = tr("%n week(s)","",secs/WEEK_IN_SECONDS); + } + else + { + int years = secs / YEAR_IN_SECONDS; + int remainder = secs % YEAR_IN_SECONDS; + timeBehindText = tr("%1 and %2").arg(tr("%n year(s)", "", years)).arg(tr("%n week(s)","", remainder/WEEK_IN_SECONDS)); + } + + progressBarLabel->setText(tr("Synchronizing with network...")); + progressBarLabel->setVisible(true); + progressBar->setFormat(tr("%1 behind").arg(timeBehindText)); + progressBar->setMaximum(totalSecs); + progressBar->setValue(totalSecs - secs); + progressBar->setVisible(true); + fShowStatusBar = true; + + tooltip = tr("Catching up...") + QString("
") + tooltip; + //labelBlocksIcon->setMovie(syncIconMovie); + //syncIconMovie->start(); + QString qstr_ = QString(":/movies/spinner-%1").arg(spinnerFrame, 3, 10, QChar('0')); + labelBlocksIcon->setPixmap(QIcon(qstr_).pixmap(STATUSBAR_ICONSIZE, STATUSBAR_ICONSIZE)); + spinnerFrame = (spinnerFrame + 1) % SPINNER_FRAMES; + + overviewPage->showOutOfSyncWarning(true); + + tooltip += QString("
"); + tooltip += tr("Last received block was generated %1 ago.").arg(timeBehindText); + tooltip += QString("
"); + tooltip += tr("Transactions after this will not yet be visible."); + } + + // Don't word-wrap this (fixed-width) tooltip + tooltip = QString("") + tooltip + QString(""); + + labelBlocksIcon->setToolTip(tooltip); + progressBarLabel->setToolTip(tooltip); + progressBar->setToolTip(tooltip); + + statusBar()->setVisible(fShowStatusBar); +} + +void BitcoinGUI::error(const QString &title, const QString &message, bool modal) +{ + // Report errors from network/worker thread + if(modal) + { + QMessageBox::critical(this, title, message, QMessageBox::Ok, QMessageBox::Ok); + } else { + notificator->notify(Notificator::Critical, title, message); + } +} + +void BitcoinGUI::changeEvent(QEvent *e) +{ + QMainWindow::changeEvent(e); +#ifndef Q_OS_MAC // Ignored on Mac + if(e->type() == QEvent::WindowStateChange) + { + if(clientModel && clientModel->getOptionsModel()->getMinimizeToTray()) + { + QWindowStateChangeEvent *wsevt = static_cast(e); + if(!(wsevt->oldState() & Qt::WindowMinimized) && isMinimized()) + { + QTimer::singleShot(0, this, SLOT(hide())); + e->ignore(); + } + } + } +#endif +} + +void BitcoinGUI::closeEvent(QCloseEvent *event) +{ + if(clientModel) + { +#ifndef Q_OS_MAC // Ignored on Mac + if(!clientModel->getOptionsModel()->getMinimizeToTray() && + !clientModel->getOptionsModel()->getMinimizeOnClose()) + { + qApp->quit(); + } +#endif + } + QMainWindow::closeEvent(event); +} + +void BitcoinGUI::askFee(qint64 nFeeRequired, bool *payFee) +{ + QString strMessage = + tr("This transaction is over the size limit. You can still send it for a fee of %1, " + "which goes to the nodes that process your transaction and helps to support the network. " + "Do you want to pay the fee?").arg( + BitcoinUnits::formatWithUnit(BitcoinUnits::BTC, nFeeRequired)); + QMessageBox::StandardButton retval = QMessageBox::question( + this, tr("Confirm transaction fee"), strMessage, + QMessageBox::Yes|QMessageBox::Cancel, QMessageBox::Yes); + *payFee = (retval == QMessageBox::Yes); +} + +void BitcoinGUI::incomingTransaction(const QModelIndex & parent, int start, int end) +{ + if(!walletModel || !clientModel) + return; + TransactionTableModel *ttm = walletModel->getTransactionTableModel(); + qint64 amount = ttm->index(start, TransactionTableModel::Amount, parent) + .data(Qt::EditRole).toULongLong(); + if(!clientModel->inInitialBlockDownload()) + { + // On new transaction, make an info balloon + // Unless the initial block download is in progress, to prevent balloon-spam + QString date = ttm->index(start, TransactionTableModel::Date, parent) + .data().toString(); + QString type = ttm->index(start, TransactionTableModel::Type, parent) + .data().toString(); + QString address = ttm->index(start, TransactionTableModel::ToAddress, parent) + .data().toString(); + QIcon icon = qvariant_cast(ttm->index(start, + TransactionTableModel::ToAddress, parent) + .data(Qt::DecorationRole)); + + notificator->notify(Notificator::Information, + (amount)<0 ? tr("Sent transaction") : + tr("Incoming transaction"), + tr("Date: %1\n" + "Amount: %2\n" + "Type: %3\n" + "Address: %4\n") + .arg(date) + .arg(BitcoinUnits::formatWithUnit(walletModel->getOptionsModel()->getDisplayUnit(), amount, true)) + .arg(type) + .arg(address), icon); + } +} + +void BitcoinGUI::gotoOverviewPage() +{ + overviewAction->setChecked(true); + centralWidget->setCurrentWidget(overviewPage); + + exportAction->setEnabled(false); + disconnect(exportAction, SIGNAL(triggered()), 0, 0); +} + +void BitcoinGUI::gotoHistoryPage() +{ + historyAction->setChecked(true); + centralWidget->setCurrentWidget(transactionsPage); + + exportAction->setEnabled(true); + disconnect(exportAction, SIGNAL(triggered()), 0, 0); + connect(exportAction, SIGNAL(triggered()), transactionView, SLOT(exportClicked())); +} + +void BitcoinGUI::gotoAddressBookPage() +{ + addressBookAction->setChecked(true); + centralWidget->setCurrentWidget(addressBookPage); + + exportAction->setEnabled(true); + disconnect(exportAction, SIGNAL(triggered()), 0, 0); + connect(exportAction, SIGNAL(triggered()), addressBookPage, SLOT(exportClicked())); +} + +void BitcoinGUI::gotoReceiveCoinsPage() +{ + receiveCoinsAction->setChecked(true); + centralWidget->setCurrentWidget(receiveCoinsPage); + + exportAction->setEnabled(true); + disconnect(exportAction, SIGNAL(triggered()), 0, 0); + connect(exportAction, SIGNAL(triggered()), receiveCoinsPage, SLOT(exportClicked())); +} + +void BitcoinGUI::gotoSendCoinsPage() +{ + sendCoinsAction->setChecked(true); + centralWidget->setCurrentWidget(sendCoinsPage); + + exportAction->setEnabled(false); + disconnect(exportAction, SIGNAL(triggered()), 0, 0); +} + +void BitcoinGUI::gotoSignMessageTab(QString addr) +{ + // call show() in showTab_SM() + signVerifyMessageDialog->showTab_SM(true); + + if(!addr.isEmpty()) + signVerifyMessageDialog->setAddress_SM(addr); +} + +void BitcoinGUI::openTelegram() +{ + QDesktopServices::openUrl(QUrl("https://t.me/ArepacoinVE_ES")); +} + +void BitcoinGUI::openTwitter() +{ + QDesktopServices::openUrl(QUrl("https://twitter.com/ArepaCoinVe")); +} + +void BitcoinGUI::gotoVerifyMessageTab(QString addr) +{ + // call show() in showTab_VM() + signVerifyMessageDialog->showTab_VM(true); + + if(!addr.isEmpty()) + signVerifyMessageDialog->setAddress_VM(addr); +} + +void BitcoinGUI::dragEnterEvent(QDragEnterEvent *event) +{ + // Accept only URIs + if(event->mimeData()->hasUrls()) + event->acceptProposedAction(); +} + +void BitcoinGUI::dropEvent(QDropEvent *event) +{ + if(event->mimeData()->hasUrls()) + { + int nValidUrisFound = 0; + QList uris = event->mimeData()->urls(); + foreach(const QUrl &uri, uris) + { + if (sendCoinsPage->handleURI(uri.toString())) + nValidUrisFound++; + } + + // if valid URIs were found + if (nValidUrisFound) + gotoSendCoinsPage(); + else + notificator->notify(Notificator::Warning, tr("URI handling"), tr("URI can not be parsed! This can be caused by an invalid Arepacoin address or malformed URI parameters.")); + } + + event->acceptProposedAction(); +} + +void BitcoinGUI::handleURI(QString strURI) +{ + // URI has to be valid + if (sendCoinsPage->handleURI(strURI)) + { + showNormalIfMinimized(); + gotoSendCoinsPage(); + } + else + notificator->notify(Notificator::Warning, tr("URI handling"), tr("URI can not be parsed! This can be caused by an invalid Arepacoin address or malformed URI parameters.")); +} + +void BitcoinGUI::setEncryptionStatus(int status) +{ + switch(status) + { + case WalletModel::Unencrypted: + labelEncryptionIcon->hide(); + encryptWalletAction->setChecked(false); + changePassphraseAction->setEnabled(false); + unlockWalletAction->setVisible(false); + lockWalletAction->setVisible(false); + encryptWalletAction->setEnabled(true); + break; + case WalletModel::Unlocked: + labelEncryptionIcon->show(); + labelEncryptionIcon->setPixmap(QIcon(":/icons/lock_open").pixmap(STATUSBAR_ICONSIZE,STATUSBAR_ICONSIZE)); + labelEncryptionIcon->setToolTip(tr("Wallet is encrypted and currently unlocked")); + encryptWalletAction->setChecked(true); + changePassphraseAction->setEnabled(true); + unlockWalletAction->setVisible(false); + lockWalletAction->setVisible(true); + encryptWalletAction->setEnabled(false); // TODO: decrypt currently not supported + break; + case WalletModel::Locked: + labelEncryptionIcon->show(); + labelEncryptionIcon->setPixmap(QIcon(":/icons/lock_closed").pixmap(STATUSBAR_ICONSIZE,STATUSBAR_ICONSIZE)); + labelEncryptionIcon->setToolTip(tr("Wallet is encrypted and currently locked")); + encryptWalletAction->setChecked(true); + changePassphraseAction->setEnabled(true); + unlockWalletAction->setVisible(true); + lockWalletAction->setVisible(false); + encryptWalletAction->setEnabled(false); // TODO: decrypt currently not supported + break; + } +} + +void BitcoinGUI::encryptWallet(bool status) +{ + if(!walletModel) + return; + AskPassphraseDialog dlg(status ? AskPassphraseDialog::Encrypt: + AskPassphraseDialog::Decrypt, this); + dlg.setModel(walletModel); + dlg.exec(); + + setEncryptionStatus(walletModel->getEncryptionStatus()); +} + +void BitcoinGUI::backupWallet() +{ + QString saveDir = QDesktopServices::storageLocation(QDesktopServices::DocumentsLocation); + QString filename = QFileDialog::getSaveFileName(this, tr("Backup Wallet"), saveDir, tr("Wallet Data (*.dat)")); + if(!filename.isEmpty()) { + if(!walletModel->backupWallet(filename)) { + QMessageBox::warning(this, tr("Backup Failed"), tr("There was an error trying to save the wallet data to the new location.")); + } + } +} + +void BitcoinGUI::changePassphrase() +{ + AskPassphraseDialog dlg(AskPassphraseDialog::ChangePass, this); + dlg.setModel(walletModel); + dlg.exec(); +} + +void BitcoinGUI::unlockWallet() +{ + if(!walletModel) + return; + // Unlock wallet when requested by wallet model + if(walletModel->getEncryptionStatus() == WalletModel::Locked) + { + AskPassphraseDialog::Mode mode = sender() == unlockWalletAction ? + AskPassphraseDialog::UnlockStaking : AskPassphraseDialog::Unlock; + AskPassphraseDialog dlg(mode, this); + dlg.setModel(walletModel); + dlg.exec(); + } +} + +void BitcoinGUI::lockWallet() +{ + if(!walletModel) + return; + + walletModel->setWalletLocked(true); +} + +void BitcoinGUI::showNormalIfMinimized(bool fToggleHidden) +{ + // activateWindow() (sometimes) helps with keyboard focus on Windows + if (isHidden()) + { + show(); + activateWindow(); + } + else if (isMinimized()) + { + showNormal(); + activateWindow(); + } + else if (GUIUtil::isObscured(this)) + { + raise(); + activateWindow(); + } + else if(fToggleHidden) + hide(); +} + +void BitcoinGUI::toggleHidden() +{ + showNormalIfMinimized(true); +} + +void BitcoinGUI::updateWeight() +{ + if (!pwalletMain) + return; + + TRY_LOCK(cs_main, lockMain); + if (!lockMain) + return; + + TRY_LOCK(pwalletMain->cs_wallet, lockWallet); + if (!lockWallet) + return; + + uint64_t nMinWeight = 0, nMaxWeight = 0; + pwalletMain->GetStakeWeight(*pwalletMain, nMinWeight, nMaxWeight, nWeight); +} + +void BitcoinGUI::updateStakingIcon() +{ + updateWeight(); + + if (nLastCoinStakeSearchInterval && nWeight) + { + uint64_t nNetworkWeight = GetPoSKernelPS(); + unsigned nEstimateTime = nTargetSpacing * nNetworkWeight / nWeight; + + QString text; + if (nEstimateTime < 60) + { + text = tr("%n second(s)", "", nEstimateTime); + } + else if (nEstimateTime < 60*60) + { + text = tr("%n minute(s)", "", nEstimateTime/60); + } + else if (nEstimateTime < 24*60*60) + { + text = tr("%n hour(s)", "", nEstimateTime/(60*60)); + } + else + { + text = tr("%n day(s)", "", nEstimateTime/(60*60*24)); + } + + labelStakingIcon->setPixmap(QIcon(":/icons/staking_on").pixmap(STATUSBAR_ICONSIZE,STATUSBAR_ICONSIZE)); + labelStakingIcon->setToolTip(tr("Staking.
Your weight is %1
Network weight is %2
Expected time to earn reward is %3").arg(nWeight).arg(nNetworkWeight).arg(text)); + } + else + { + labelStakingIcon->setPixmap(QIcon(":/icons/staking_off").pixmap(STATUSBAR_ICONSIZE,STATUSBAR_ICONSIZE)); + if (pwalletMain && pwalletMain->IsLocked()) + labelStakingIcon->setToolTip(tr("Not staking because wallet is locked")); + else if (vNodes.empty()) + labelStakingIcon->setToolTip(tr("Not staking because wallet is offline")); + else if (IsInitialBlockDownload()) + labelStakingIcon->setToolTip(tr("Not staking because wallet is syncing")); + else if (!nWeight) + labelStakingIcon->setToolTip(tr("Not staking because you don't have mature coins")); + else + labelStakingIcon->setToolTip(tr("Not staking")); + } +} diff --git a/src/qt/bitcoingui.h b/src/qt/bitcoingui.h new file mode 100755 index 0000000..8b715ed --- /dev/null +++ b/src/qt/bitcoingui.h @@ -0,0 +1,201 @@ +#ifndef BITCOINGUI_H +#define BITCOINGUI_H + +#include +#include + +#include + +class TransactionTableModel; +class ClientModel; +class WalletModel; +class TransactionView; +class OverviewPage; +class AddressBookPage; +class SendCoinsDialog; +class SignVerifyMessageDialog; +class Notificator; +class RPCConsole; + +QT_BEGIN_NAMESPACE +class QLabel; +class QLineEdit; +class QTableView; +class QAbstractItemModel; +class QModelIndex; +class QProgressBar; +class QStackedWidget; +class QUrl; +QT_END_NAMESPACE + +/** + Bitcoin GUI main class. This class represents the main window of the Bitcoin UI. It communicates with both the client and + wallet models to give the user an up-to-date view of the current core state. +*/ +class BitcoinGUI : public QMainWindow +{ + Q_OBJECT +public: + explicit BitcoinGUI(QWidget *parent = 0); + ~BitcoinGUI(); + + /** Set the client model. + The client model represents the part of the core that communicates with the P2P network, and is wallet-agnostic. + */ + void setClientModel(ClientModel *clientModel); + /** Set the wallet model. + The wallet model represents a bitcoin wallet, and offers access to the list of transactions, address book and sending + functionality. + */ + void setWalletModel(WalletModel *walletModel); + +protected: + void changeEvent(QEvent *e); + void closeEvent(QCloseEvent *event); + void dragEnterEvent(QDragEnterEvent *event); + void dropEvent(QDropEvent *event); + +private: + ClientModel *clientModel; + WalletModel *walletModel; + + QStackedWidget *centralWidget; + + OverviewPage *overviewPage; + QWidget *transactionsPage; + AddressBookPage *addressBookPage; + AddressBookPage *receiveCoinsPage; + SendCoinsDialog *sendCoinsPage; + SignVerifyMessageDialog *signVerifyMessageDialog; + + QLabel *labelEncryptionIcon; + QLabel *labelStakingIcon; + QLabel *labelConnectionsIcon; + QLabel *labelBlocksIcon; + QLabel *progressBarLabel; + QProgressBar *progressBar; + + QMenuBar *appMenuBar; + QAction *overviewAction; + QAction *historyAction; + QAction *quitAction; + QAction *sendCoinsAction; + QAction *addressBookAction; + QAction *signMessageAction; + QAction *verifyMessageAction; + QAction *aboutAction; + QAction *receiveCoinsAction; + QAction *optionsAction; + QAction *toggleHideAction; + QAction *exportAction; + QAction *encryptWalletAction; + QAction *backupWalletAction; + QAction *changePassphraseAction; + QAction *unlockWalletAction; + QAction *lockWalletAction; + QAction *aboutQtAction; + QAction *openRPCConsoleAction; + QAction *telegramAction; + QAction *twitterAction; + + QSystemTrayIcon *trayIcon; + Notificator *notificator; + TransactionView *transactionView; + RPCConsole *rpcConsole; + + QMovie *syncIconMovie; + /** Keep track of previous number of blocks, to detect progress */ + int prevBlocks; + + uint64_t nWeight; + + int spinnerFrame; + + /** Create the main UI actions. */ + void createActions(); + /** Create the menu bar and sub-menus. */ + void createMenuBar(); + /** Create the toolbars */ + void createToolBars(); + /** Create system tray (notification) icon */ + void createTrayIcon(); + +public slots: + /** Set number of connections shown in the UI */ + void setNumConnections(int count); + /** Set number of blocks shown in the UI */ + void setNumBlocks(int count, int nTotalBlocks); + /** Set the encryption status as shown in the UI. + @param[in] status current encryption status + @see WalletModel::EncryptionStatus + */ + void setEncryptionStatus(int status); + + /** Notify the user of an error in the network or transaction handling code. */ + void error(const QString &title, const QString &message, bool modal); + /** Asks the user whether to pay the transaction fee or to cancel the transaction. + It is currently not possible to pass a return value to another thread through + BlockingQueuedConnection, so an indirected pointer is used. + https://bugreports.qt-project.org/browse/QTBUG-10440 + + @param[in] nFeeRequired the required fee + @param[out] payFee true to pay the fee, false to not pay the fee + */ + void askFee(qint64 nFeeRequired, bool *payFee); + void handleURI(QString strURI); + +private slots: + /** Switch to overview (home) page */ + void gotoOverviewPage(); + /** Switch to history (transactions) page */ + void gotoHistoryPage(); + /** Switch to address book page */ + void gotoAddressBookPage(); + /** Switch to receive coins page */ + void gotoReceiveCoinsPage(); + /** Switch to send coins page */ + void gotoSendCoinsPage(); + /** Switch to Arepacoin Telegram Group */ + void openTelegram(); + /** Switch to Arepacoin Twitter */ + void openTwitter(); + + /** Show Sign/Verify Message dialog and switch to sign message tab */ + void gotoSignMessageTab(QString addr = ""); + /** Show Sign/Verify Message dialog and switch to verify message tab */ + void gotoVerifyMessageTab(QString addr = ""); + + /** Show configuration dialog */ + void optionsClicked(); + /** Show about dialog */ + void aboutClicked(); +#ifndef Q_OS_MAC + /** Handle tray icon clicked */ + void trayIconActivated(QSystemTrayIcon::ActivationReason reason); +#endif + /** Show incoming transaction notification for new transactions. + + The new items are those between start and end inclusive, under the given parent item. + */ + void incomingTransaction(const QModelIndex & parent, int start, int end); + /** Encrypt the wallet */ + void encryptWallet(bool status); + /** Backup the wallet */ + void backupWallet(); + /** Change encrypted wallet passphrase */ + void changePassphrase(); + /** Ask for passphrase to unlock wallet temporarily */ + void unlockWallet(); + + void lockWallet(); + + /** Show window if hidden, unminimize when minimized, rise when obscured or show if hidden and fToggleHidden is true */ + void showNormalIfMinimized(bool fToggleHidden = false); + /** simply calls showNormalIfMinimized(true) for use in SLOT() macro */ + void toggleHidden(); + + void updateWeight(); + void updateStakingIcon(); +}; + +#endif diff --git a/src/qt/bitcoinstrings.cpp b/src/qt/bitcoinstrings.cpp new file mode 100755 index 0000000..5805959 --- /dev/null +++ b/src/qt/bitcoinstrings.cpp @@ -0,0 +1,201 @@ +#include +// Automatically generated by extract_strings.py +#ifdef __GNUC__ +#define UNUSED __attribute__((unused)) +#else +#define UNUSED +#endif +static const char UNUSED *bitcoin_strings[] = {QT_TRANSLATE_NOOP("bitcoin-core", "To use the %s option"), +QT_TRANSLATE_NOOP("bitcoin-core", "" +"%s, you must set a rpcpassword in the configuration file:\n" +" %s\n" +"It is recommended you use the following random password:\n" +"rpcuser=arepacoinrpc\n" +"rpcpassword=%s\n" +"(you do not need to remember this password)\n" +"The username and password MUST NOT be the same.\n" +"If the file does not exist, create it with owner-readable-only file " +"permissions.\n" +"It is also recommended to set alertnotify so you are notified of problems;\n" +"for example: alertnotify=echo %%s | mail -s \"Arepacoin Alert\" admin@foo." +"com\n"), +QT_TRANSLATE_NOOP("bitcoin-core", "Error"), +QT_TRANSLATE_NOOP("bitcoin-core", "" +"An error occurred while setting up the RPC port %u for listening on IPv6, " +"falling back to IPv4: %s"), +QT_TRANSLATE_NOOP("bitcoin-core", "" +"An error occurred while setting up the RPC port %u for listening on IPv4: %s"), +QT_TRANSLATE_NOOP("bitcoin-core", "" +"You must set rpcpassword= in the configuration file:\n" +"%s\n" +"If the file does not exist, create it with owner-readable-only file " +"permissions."), +QT_TRANSLATE_NOOP("bitcoin-core", "Arepacoin version"), +QT_TRANSLATE_NOOP("bitcoin-core", "Usage:"), +QT_TRANSLATE_NOOP("bitcoin-core", "Send command to -server or arepacoind"), +QT_TRANSLATE_NOOP("bitcoin-core", "List commands"), +QT_TRANSLATE_NOOP("bitcoin-core", "Get help for a command"), +QT_TRANSLATE_NOOP("bitcoin-core", "Arepacoin"), +QT_TRANSLATE_NOOP("bitcoin-core", "Options:"), +QT_TRANSLATE_NOOP("bitcoin-core", "This help message"), +QT_TRANSLATE_NOOP("bitcoin-core", "Specify configuration file (default: arepacoin.conf)"), +QT_TRANSLATE_NOOP("bitcoin-core", "Specify pid file (default: arepacoind.pid)"), +QT_TRANSLATE_NOOP("bitcoin-core", "Specify data directory"), +QT_TRANSLATE_NOOP("bitcoin-core", "Specify wallet file (within data directory)"), +QT_TRANSLATE_NOOP("bitcoin-core", "Set database cache size in megabytes (default: 25)"), +QT_TRANSLATE_NOOP("bitcoin-core", "Set database disk log size in megabytes (default: 100)"), +QT_TRANSLATE_NOOP("bitcoin-core", "Specify connection timeout in milliseconds (default: 5000)"), +QT_TRANSLATE_NOOP("bitcoin-core", "Connect through socks proxy"), +QT_TRANSLATE_NOOP("bitcoin-core", "Select the version of socks proxy to use (4-5, default: 5)"), +QT_TRANSLATE_NOOP("bitcoin-core", "Use proxy to reach tor hidden services (default: same as -proxy)"), +QT_TRANSLATE_NOOP("bitcoin-core", "Allow DNS lookups for -addnode, -seednode and -connect"), +QT_TRANSLATE_NOOP("bitcoin-core", "Listen for connections on (default: 9853 or testnet: 19853)"), +QT_TRANSLATE_NOOP("bitcoin-core", "Maintain at most connections to peers (default: 125)"), +QT_TRANSLATE_NOOP("bitcoin-core", "Add a node to connect to and attempt to keep the connection open"), +QT_TRANSLATE_NOOP("bitcoin-core", "Connect only to the specified node(s)"), +QT_TRANSLATE_NOOP("bitcoin-core", "Connect to a node to retrieve peer addresses, and disconnect"), +QT_TRANSLATE_NOOP("bitcoin-core", "Specify your own public address"), +QT_TRANSLATE_NOOP("bitcoin-core", "Only connect to nodes in network (IPv4, IPv6 or Tor)"), +QT_TRANSLATE_NOOP("bitcoin-core", "Discover own IP address (default: 1 when listening and no -externalip)"), +QT_TRANSLATE_NOOP("bitcoin-core", "Find peers using internet relay chat (default: 0)"), +QT_TRANSLATE_NOOP("bitcoin-core", "Accept connections from outside (default: 1 if no -proxy or -connect)"), +QT_TRANSLATE_NOOP("bitcoin-core", "Bind to given address. Use [host]:port notation for IPv6"), +QT_TRANSLATE_NOOP("bitcoin-core", "Find peers using DNS lookup (default: 1)"), +QT_TRANSLATE_NOOP("bitcoin-core", "Stake your coins to support network and gain reward (default: 1)"), +QT_TRANSLATE_NOOP("bitcoin-core", "" +"Sync time with other nodes. Disable if time on your system is precise e.g. " +"syncing with NTP (default: 1)"), +QT_TRANSLATE_NOOP("bitcoin-core", "Sync checkpoints policy (default: strict)"), +QT_TRANSLATE_NOOP("bitcoin-core", "Threshold for disconnecting misbehaving peers (default: 100)"), +QT_TRANSLATE_NOOP("bitcoin-core", "" +"Number of seconds to keep misbehaving peers from reconnecting (default: " +"86400)"), +QT_TRANSLATE_NOOP("bitcoin-core", "Maximum per-connection receive buffer, *1000 bytes (default: 5000)"), +QT_TRANSLATE_NOOP("bitcoin-core", "Maximum per-connection send buffer, *1000 bytes (default: 1000)"), +QT_TRANSLATE_NOOP("bitcoin-core", "Use UPnP to map the listening port (default: 1 when listening)"), +QT_TRANSLATE_NOOP("bitcoin-core", "Use UPnP to map the listening port (default: 0)"), +QT_TRANSLATE_NOOP("bitcoin-core", "" +"Detach block and address databases. Increases shutdown time (default: 0)"), +QT_TRANSLATE_NOOP("bitcoin-core", "Fee per KB to add to transactions you send"), +QT_TRANSLATE_NOOP("bitcoin-core", "" +"When creating transactions, ignore inputs with value less than this " +"(default: 0.01)"), +QT_TRANSLATE_NOOP("bitcoin-core", "Accept command line and JSON-RPC commands"), +QT_TRANSLATE_NOOP("bitcoin-core", "Run in the background as a daemon and accept commands"), +QT_TRANSLATE_NOOP("bitcoin-core", "Use the test network"), +QT_TRANSLATE_NOOP("bitcoin-core", "Output extra debugging information. Implies all other -debug* options"), +QT_TRANSLATE_NOOP("bitcoin-core", "Output extra network debugging information"), +QT_TRANSLATE_NOOP("bitcoin-core", "Prepend debug output with timestamp"), +QT_TRANSLATE_NOOP("bitcoin-core", "Shrink debug.log file on client startup (default: 1 when no -debug)"), +QT_TRANSLATE_NOOP("bitcoin-core", "Send trace/debug info to console instead of debug.log file"), +QT_TRANSLATE_NOOP("bitcoin-core", "Send trace/debug info to debugger"), +QT_TRANSLATE_NOOP("bitcoin-core", "Username for JSON-RPC connections"), +QT_TRANSLATE_NOOP("bitcoin-core", "Password for JSON-RPC connections"), +QT_TRANSLATE_NOOP("bitcoin-core", "" +"Listen for JSON-RPC connections on (default: 9852 or testnet: 19852)"), +QT_TRANSLATE_NOOP("bitcoin-core", "Allow JSON-RPC connections from specified IP address"), +QT_TRANSLATE_NOOP("bitcoin-core", "Send commands to node running on (default: 127.0.0.1)"), +QT_TRANSLATE_NOOP("bitcoin-core", "" +"Execute command when the best block changes (%s in cmd is replaced by block " +"hash)"), +QT_TRANSLATE_NOOP("bitcoin-core", "" +"Execute command when a wallet transaction changes (%s in cmd is replaced by " +"TxID)"), +QT_TRANSLATE_NOOP("bitcoin-core", "Require a confirmations for change (default: 0)"), +QT_TRANSLATE_NOOP("bitcoin-core", "" +"Enforce transaction scripts to use canonical PUSH operators (default: 1)"), +QT_TRANSLATE_NOOP("bitcoin-core", "" +"Execute command when a relevant alert is received (%s in cmd is replaced by " +"message)"), +QT_TRANSLATE_NOOP("bitcoin-core", "Upgrade wallet to latest format"), +QT_TRANSLATE_NOOP("bitcoin-core", "Set key pool size to (default: 100)"), +QT_TRANSLATE_NOOP("bitcoin-core", "Rescan the block chain for missing wallet transactions"), +QT_TRANSLATE_NOOP("bitcoin-core", "Attempt to recover private keys from a corrupt wallet.dat"), +QT_TRANSLATE_NOOP("bitcoin-core", "How many blocks to check at startup (default: 2500, 0 = all)"), +QT_TRANSLATE_NOOP("bitcoin-core", "How thorough the block verification is (0-6, default: 1)"), +QT_TRANSLATE_NOOP("bitcoin-core", "Imports blocks from external blk000?.dat file"), +QT_TRANSLATE_NOOP("bitcoin-core", "Block creation options:"), +QT_TRANSLATE_NOOP("bitcoin-core", "Set minimum block size in bytes (default: 0)"), +QT_TRANSLATE_NOOP("bitcoin-core", "Set maximum block size in bytes (default: 250000)"), +QT_TRANSLATE_NOOP("bitcoin-core", "" +"Set maximum size of high-priority/low-fee transactions in bytes (default: " +"27000)"), +QT_TRANSLATE_NOOP("bitcoin-core", "SSL options: (see the Bitcoin Wiki for SSL setup instructions)"), +QT_TRANSLATE_NOOP("bitcoin-core", "Use OpenSSL (https) for JSON-RPC connections"), +QT_TRANSLATE_NOOP("bitcoin-core", "Server certificate file (default: server.cert)"), +QT_TRANSLATE_NOOP("bitcoin-core", "Server private key (default: server.pem)"), +QT_TRANSLATE_NOOP("bitcoin-core", "" +"Acceptable ciphers (default: TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:" +"@STRENGTH)"), +QT_TRANSLATE_NOOP("bitcoin-core", "Invalid amount for -paytxfee=: '%s'"), +QT_TRANSLATE_NOOP("bitcoin-core", "" +"Warning: -paytxfee is set very high! This is the transaction fee you will " +"pay if you send a transaction."), +QT_TRANSLATE_NOOP("bitcoin-core", "Invalid amount for -mininput=: '%s'"), +QT_TRANSLATE_NOOP("bitcoin-core", "Wallet %s resides outside data directory %s."), +QT_TRANSLATE_NOOP("bitcoin-core", "" +"Cannot obtain a lock on data directory %s. Arepacoin is probably already " +"running."), +QT_TRANSLATE_NOOP("bitcoin-core", "Verifying database integrity..."), +QT_TRANSLATE_NOOP("bitcoin-core", "" +"Error initializing database environment %s! To recover, BACKUP THAT " +"DIRECTORY, then remove everything from it except for wallet.dat."), +QT_TRANSLATE_NOOP("bitcoin-core", "" +"Warning: wallet.dat corrupt, data salvaged! Original wallet.dat saved as " +"wallet.{timestamp}.bak in %s; if your balance or transactions are incorrect " +"you should restore from a backup."), +QT_TRANSLATE_NOOP("bitcoin-core", "wallet.dat corrupt, salvage failed"), +QT_TRANSLATE_NOOP("bitcoin-core", "Unknown -socks proxy version requested: %i"), +QT_TRANSLATE_NOOP("bitcoin-core", "Unknown network specified in -onlynet: '%s'"), +QT_TRANSLATE_NOOP("bitcoin-core", "Invalid -proxy address: '%s'"), +QT_TRANSLATE_NOOP("bitcoin-core", "Invalid -tor address: '%s'"), +QT_TRANSLATE_NOOP("bitcoin-core", "Cannot resolve -bind address: '%s'"), +QT_TRANSLATE_NOOP("bitcoin-core", "Failed to listen on any port. Use -listen=0 if you want this."), +QT_TRANSLATE_NOOP("bitcoin-core", "Cannot resolve -externalip address: '%s'"), +QT_TRANSLATE_NOOP("bitcoin-core", "Invalid amount for -reservebalance="), +QT_TRANSLATE_NOOP("bitcoin-core", "Unable to sign checkpoint, wrong checkpointkey?\n"), +QT_TRANSLATE_NOOP("bitcoin-core", "Loading block index..."), +QT_TRANSLATE_NOOP("bitcoin-core", "Error loading blkindex.dat"), +QT_TRANSLATE_NOOP("bitcoin-core", "Loading wallet..."), +QT_TRANSLATE_NOOP("bitcoin-core", "Error loading wallet.dat: Wallet corrupted"), +QT_TRANSLATE_NOOP("bitcoin-core", "" +"Warning: error reading wallet.dat! All keys read correctly, but transaction " +"data or address book entries might be missing or incorrect."), +QT_TRANSLATE_NOOP("bitcoin-core", "Error loading wallet.dat: Wallet requires newer version of Arepacoin"), +QT_TRANSLATE_NOOP("bitcoin-core", "Wallet needed to be rewritten: restart Arepacoin to complete"), +QT_TRANSLATE_NOOP("bitcoin-core", "Error loading wallet.dat"), +QT_TRANSLATE_NOOP("bitcoin-core", "Cannot downgrade wallet"), +QT_TRANSLATE_NOOP("bitcoin-core", "Cannot initialize keypool"), +QT_TRANSLATE_NOOP("bitcoin-core", "Cannot write default address"), +QT_TRANSLATE_NOOP("bitcoin-core", "Rescanning..."), +QT_TRANSLATE_NOOP("bitcoin-core", "Importing blockchain data file."), +QT_TRANSLATE_NOOP("bitcoin-core", "Importing bootstrap blockchain data file."), +QT_TRANSLATE_NOOP("bitcoin-core", "Loading addresses..."), +QT_TRANSLATE_NOOP("bitcoin-core", "Error: could not start node"), +QT_TRANSLATE_NOOP("bitcoin-core", "Done loading"), +QT_TRANSLATE_NOOP("bitcoin-core", "" +"Unable to bind to %s on this computer. Arepacoin is probably already running."), +QT_TRANSLATE_NOOP("bitcoin-core", "Unable to bind to %s on this computer (bind returned error %d, %s)"), +QT_TRANSLATE_NOOP("bitcoin-core", "Error: Wallet locked, unable to create transaction "), +QT_TRANSLATE_NOOP("bitcoin-core", "Error: Wallet unlocked for staking only, unable to create transaction."), +QT_TRANSLATE_NOOP("bitcoin-core", "" +"Error: This transaction requires a transaction fee of at least %s because of " +"its amount, complexity, or use of recently received funds "), +QT_TRANSLATE_NOOP("bitcoin-core", "Error: Transaction creation failed "), +QT_TRANSLATE_NOOP("bitcoin-core", "Sending..."), +QT_TRANSLATE_NOOP("bitcoin-core", "" +"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."), +QT_TRANSLATE_NOOP("bitcoin-core", "Invalid amount"), +QT_TRANSLATE_NOOP("bitcoin-core", "Insufficient funds"), +QT_TRANSLATE_NOOP("bitcoin-core", "" +"Warning: Please check that your computer's date and time are correct! If " +"your clock is wrong Arepacoin will not work properly."), +QT_TRANSLATE_NOOP("bitcoin-core", "Warning: This version is obsolete, upgrade required!"), +QT_TRANSLATE_NOOP("bitcoin-core", "WARNING: syncronized checkpoint violation detected, but skipped!"), +QT_TRANSLATE_NOOP("bitcoin-core", "Warning: Disk space is low!"), +QT_TRANSLATE_NOOP("bitcoin-core", "" +"WARNING: Invalid checkpoint found! Displayed transactions may not be " +"correct! You may need to upgrade, or notify developers."), +}; \ No newline at end of file diff --git a/src/qt/bitcoinunits.cpp b/src/qt/bitcoinunits.cpp new file mode 100755 index 0000000..35a6313 --- /dev/null +++ b/src/qt/bitcoinunits.cpp @@ -0,0 +1,181 @@ +#include "bitcoinunits.h" + +#include + +BitcoinUnits::BitcoinUnits(QObject *parent): + QAbstractListModel(parent), + unitlist(availableUnits()) +{ +} + +QList BitcoinUnits::availableUnits() +{ + QList unitlist; + unitlist.append(BTC); + unitlist.append(mBTC); + unitlist.append(uBTC); + return unitlist; +} + +bool BitcoinUnits::valid(int unit) +{ + switch(unit) + { + case BTC: + case mBTC: + case uBTC: + return true; + default: + return false; + } +} + +QString BitcoinUnits::name(int unit) +{ + switch(unit) + { + case BTC: return QString("AREPA"); + case mBTC: return QString("mAREPA"); + case uBTC: return QString::fromUtf8("μAREPA"); + default: return QString("???"); + } +} + +QString BitcoinUnits::description(int unit) +{ + switch(unit) + { + case BTC: return QString("Arepacoins"); + case mBTC: return QString("Milli-Arepacoins (1 / 1,000)"); + case uBTC: return QString("Micro-Arepacoins (1 / 1,000,000)"); + default: return QString("???"); + } +} + +qint64 BitcoinUnits::factor(int unit) +{ + switch(unit) + { + case BTC: return 100000000; + case mBTC: return 100000; + case uBTC: return 100; + default: return 100000000; + } +} + +int BitcoinUnits::amountDigits(int unit) +{ + switch(unit) + { + case BTC: return 8; // 21,000,000 (# digits, without commas) + case mBTC: return 11; // 21,000,000,000 + case uBTC: return 14; // 21,000,000,000,000 + default: return 0; + } +} + +int BitcoinUnits::decimals(int unit) +{ + switch(unit) + { + case BTC: return 8; + case mBTC: return 5; + case uBTC: return 2; + default: return 0; + } +} + +QString BitcoinUnits::format(int unit, qint64 n, bool fPlus) +{ + // Note: not using straight sprintf here because we do NOT want + // localized number formatting. + if(!valid(unit)) + return QString(); // Refuse to format invalid unit + qint64 coin = factor(unit); + int num_decimals = decimals(unit); + qint64 n_abs = (n > 0 ? n : -n); + qint64 quotient = n_abs / coin; + qint64 remainder = n_abs % coin; + QString quotient_str = QString::number(quotient); + QString remainder_str = QString::number(remainder).rightJustified(num_decimals, '0'); + + // Right-trim excess zeros after the decimal point + int nTrim = 0; + for (int i = remainder_str.size()-1; i>=2 && (remainder_str.at(i) == '0'); --i) + ++nTrim; + remainder_str.chop(nTrim); + + if (n < 0) + quotient_str.insert(0, '-'); + else if (fPlus && n > 0) + quotient_str.insert(0, '+'); + return quotient_str + QString(".") + remainder_str; +} + +QString BitcoinUnits::formatWithUnit(int unit, qint64 amount, bool plussign) +{ + return format(unit, amount, plussign) + QString(" ") + name(unit); +} + +bool BitcoinUnits::parse(int unit, const QString &value, qint64 *val_out) +{ + if(!valid(unit) || value.isEmpty()) + return false; // Refuse to parse invalid unit or empty string + int num_decimals = decimals(unit); + QStringList parts = value.split("."); + + if(parts.size() > 2) + { + return false; // More than one dot + } + QString whole = parts[0]; + QString decimals; + + if(parts.size() > 1) + { + decimals = parts[1]; + } + if(decimals.size() > num_decimals) + { + return false; // Exceeds max precision + } + bool ok = false; + QString str = whole + decimals.leftJustified(num_decimals, '0'); + + if(str.size() > 18) + { + return false; // Longer numbers will exceed 63 bits + } + qint64 retvalue = str.toLongLong(&ok); + if(val_out) + { + *val_out = retvalue; + } + return ok; +} + +int BitcoinUnits::rowCount(const QModelIndex &parent) const +{ + Q_UNUSED(parent); + return unitlist.size(); +} + +QVariant BitcoinUnits::data(const QModelIndex &index, int role) const +{ + int row = index.row(); + if(row >= 0 && row < unitlist.size()) + { + Unit unit = unitlist.at(row); + switch(role) + { + case Qt::EditRole: + case Qt::DisplayRole: + return QVariant(name(unit)); + case Qt::ToolTipRole: + return QVariant(description(unit)); + case UnitRole: + return QVariant(static_cast(unit)); + } + } + return QVariant(); +} diff --git a/src/qt/bitcoinunits.h b/src/qt/bitcoinunits.h new file mode 100755 index 0000000..9b7c9e1 --- /dev/null +++ b/src/qt/bitcoinunits.h @@ -0,0 +1,66 @@ +#ifndef BITCOINUNITS_H +#define BITCOINUNITS_H + +#include +#include + +/** Bitcoin unit definitions. Encapsulates parsing and formatting + and serves as list model for drop-down selection boxes. +*/ +class BitcoinUnits: public QAbstractListModel +{ +public: + explicit BitcoinUnits(QObject *parent); + + /** Bitcoin units. + @note Source: https://en.bitcoin.it/wiki/Units . Please add only sensible ones + */ + enum Unit + { + BTC, + mBTC, + uBTC + }; + + //! @name Static API + //! Unit conversion and formatting + ///@{ + + //! Get list of units, for drop-down box + static QList availableUnits(); + //! Is unit ID valid? + static bool valid(int unit); + //! Short name + static QString name(int unit); + //! Longer description + static QString description(int unit); + //! Number of Satoshis (1e-8) per unit + static qint64 factor(int unit); + //! Number of amount digits (to represent max number of coins) + static int amountDigits(int unit); + //! Number of decimals left + static int decimals(int unit); + //! Format as string + static QString format(int unit, qint64 amount, bool plussign=false); + //! Format as string (with unit) + static QString formatWithUnit(int unit, qint64 amount, bool plussign=false); + //! Parse string to coin amount + static bool parse(int unit, const QString &value, qint64 *val_out); + ///@} + + //! @name AbstractListModel implementation + //! List model for unit drop-down selection box. + ///@{ + enum RoleIndex { + /** Unit identifier */ + UnitRole = Qt::UserRole + }; + int rowCount(const QModelIndex &parent) const; + QVariant data(const QModelIndex &index, int role) const; + ///@} +private: + QList unitlist; +}; +typedef BitcoinUnits::Unit BitcoinUnit; + +#endif // BITCOINUNITS_H diff --git a/src/qt/clientmodel.cpp b/src/qt/clientmodel.cpp new file mode 100755 index 0000000..7f9befb --- /dev/null +++ b/src/qt/clientmodel.cpp @@ -0,0 +1,200 @@ +#include "clientmodel.h" +#include "guiconstants.h" +#include "optionsmodel.h" +#include "addresstablemodel.h" +#include "transactiontablemodel.h" + +#include "alert.h" +#include "main.h" +#include "ui_interface.h" + +#include +#include + +static const int64_t nClientStartupTime = GetTime(); + +ClientModel::ClientModel(OptionsModel *optionsModel, QObject *parent) : + QObject(parent), optionsModel(optionsModel), + cachedNumBlocks(0), cachedNumBlocksOfPeers(0), pollTimer(0) +{ + numBlocksAtStartup = -1; + + pollTimer = new QTimer(this); + pollTimer->setInterval(MODEL_UPDATE_DELAY); + pollTimer->start(); + connect(pollTimer, SIGNAL(timeout()), this, SLOT(updateTimer())); + + subscribeToCoreSignals(); +} + +ClientModel::~ClientModel() +{ + unsubscribeFromCoreSignals(); +} + +int ClientModel::getNumConnections() const +{ + return vNodes.size(); +} + +int ClientModel::getNumBlocks() const +{ + LOCK(cs_main); + return nBestHeight; +} + +int ClientModel::getNumBlocksAtStartup() +{ + if (numBlocksAtStartup == -1) numBlocksAtStartup = getNumBlocks(); + return numBlocksAtStartup; +} + +quint64 ClientModel::getTotalBytesRecv() const +{ + return CNode::GetTotalBytesRecv(); +} + +quint64 ClientModel::getTotalBytesSent() const +{ + return CNode::GetTotalBytesSent(); +} + +QDateTime ClientModel::getLastBlockDate() const +{ + LOCK(cs_main); + if (pindexBest) + return QDateTime::fromTime_t(pindexBest->GetBlockTime()); + else + return QDateTime::fromTime_t(1474758308); // Genesis block's time +} + +void ClientModel::updateTimer() +{ + // Get required lock upfront. This avoids the GUI from getting stuck on + // periodical polls if the core is holding the locks for a longer time - + // for example, during a wallet rescan. + TRY_LOCK(cs_main, lockMain); + if(!lockMain) + return; + // Some quantities (such as number of blocks) change so fast that we don't want to be notified for each change. + // Periodically check and update with a timer. + int newNumBlocks = getNumBlocks(); + int newNumBlocksOfPeers = getNumBlocksOfPeers(); + + if(cachedNumBlocks != newNumBlocks || cachedNumBlocksOfPeers != newNumBlocksOfPeers) + { + cachedNumBlocks = newNumBlocks; + cachedNumBlocksOfPeers = newNumBlocksOfPeers; + + emit numBlocksChanged(newNumBlocks, newNumBlocksOfPeers); + } + + emit bytesChanged(getTotalBytesRecv(), getTotalBytesSent()); +} + +void ClientModel::updateNumConnections(int numConnections) +{ + emit numConnectionsChanged(numConnections); +} + +void ClientModel::updateAlert(const QString &hash, int status) +{ + // Show error message notification for new alert + if(status == CT_NEW) + { + uint256 hash_256; + hash_256.SetHex(hash.toStdString()); + CAlert alert = CAlert::getAlertByHash(hash_256); + if(!alert.IsNull()) + { + emit error(tr("Network Alert"), QString::fromStdString(alert.strStatusBar), false); + } + } + + // Emit a numBlocksChanged when the status message changes, + // so that the view recomputes and updates the status bar. + emit numBlocksChanged(getNumBlocks(), getNumBlocksOfPeers()); +} + +bool ClientModel::isTestNet() const +{ + return fTestNet; +} + +bool ClientModel::inInitialBlockDownload() const +{ + return IsInitialBlockDownload(); +} + +int ClientModel::getNumBlocksOfPeers() const +{ + return GetNumBlocksOfPeers(); +} + +QString ClientModel::getStatusBarWarnings() const +{ + return QString::fromStdString(GetWarnings("statusbar")); +} + +OptionsModel *ClientModel::getOptionsModel() +{ + return optionsModel; +} + +QString ClientModel::formatFullVersion() const +{ + return QString::fromStdString(FormatFullVersion()); +} + +QString ClientModel::formatBuildDate() const +{ + return QString::fromStdString(CLIENT_DATE); +} + +QString ClientModel::clientName() const +{ + return QString::fromStdString(CLIENT_NAME); +} + +QString ClientModel::formatClientStartupTime() const +{ + return QDateTime::fromTime_t(nClientStartupTime).toString(); +} + +// Handlers for core signals +static void NotifyBlocksChanged(ClientModel *clientmodel) +{ + // This notification is too frequent. Don't trigger a signal. + // Don't remove it, though, as it might be useful later. +} + +static void NotifyNumConnectionsChanged(ClientModel *clientmodel, int newNumConnections) +{ + // Too noisy: OutputDebugStringF("NotifyNumConnectionsChanged %i\n", newNumConnections); + QMetaObject::invokeMethod(clientmodel, "updateNumConnections", Qt::QueuedConnection, + Q_ARG(int, newNumConnections)); +} + +static void NotifyAlertChanged(ClientModel *clientmodel, const uint256 &hash, ChangeType status) +{ + OutputDebugStringF("NotifyAlertChanged %s status=%i\n", hash.GetHex().c_str(), status); + QMetaObject::invokeMethod(clientmodel, "updateAlert", Qt::QueuedConnection, + Q_ARG(QString, QString::fromStdString(hash.GetHex())), + Q_ARG(int, status)); +} + +void ClientModel::subscribeToCoreSignals() +{ + // Connect signals to client + uiInterface.NotifyBlocksChanged.connect(boost::bind(NotifyBlocksChanged, this)); + uiInterface.NotifyNumConnectionsChanged.connect(boost::bind(NotifyNumConnectionsChanged, this, _1)); + uiInterface.NotifyAlertChanged.connect(boost::bind(NotifyAlertChanged, this, _1, _2)); +} + +void ClientModel::unsubscribeFromCoreSignals() +{ + // Disconnect signals from client + uiInterface.NotifyBlocksChanged.disconnect(boost::bind(NotifyBlocksChanged, this)); + uiInterface.NotifyNumConnectionsChanged.disconnect(boost::bind(NotifyNumConnectionsChanged, this, _1)); + uiInterface.NotifyAlertChanged.disconnect(boost::bind(NotifyAlertChanged, this, _1, _2)); +} diff --git a/src/qt/clientmodel.h b/src/qt/clientmodel.h new file mode 100755 index 0000000..1be40f2 --- /dev/null +++ b/src/qt/clientmodel.h @@ -0,0 +1,75 @@ +#ifndef CLIENTMODEL_H +#define CLIENTMODEL_H + +#include + +class OptionsModel; +class AddressTableModel; +class TransactionTableModel; +class CWallet; + +QT_BEGIN_NAMESPACE +class QDateTime; +class QTimer; +QT_END_NAMESPACE + +/** Model for Bitcoin network client. */ +class ClientModel : public QObject +{ + Q_OBJECT +public: + explicit ClientModel(OptionsModel *optionsModel, QObject *parent = 0); + ~ClientModel(); + + OptionsModel *getOptionsModel(); + + int getNumConnections() const; + int getNumBlocks() const; + int getNumBlocksAtStartup(); + + quint64 getTotalBytesRecv() const; + quint64 getTotalBytesSent() const; + + QDateTime getLastBlockDate() const; + + //! Return true if client connected to testnet + bool isTestNet() const; + //! Return true if core is doing initial block download + bool inInitialBlockDownload() const; + //! Return conservative estimate of total number of blocks, or 0 if unknown + int getNumBlocksOfPeers() const; + //! Return warnings to be displayed in status bar + QString getStatusBarWarnings() const; + + QString formatFullVersion() const; + QString formatBuildDate() const; + QString clientName() const; + QString formatClientStartupTime() const; + +private: + OptionsModel *optionsModel; + + int cachedNumBlocks; + int cachedNumBlocksOfPeers; + + int numBlocksAtStartup; + + QTimer *pollTimer; + + void subscribeToCoreSignals(); + void unsubscribeFromCoreSignals(); +signals: + void numConnectionsChanged(int count); + void numBlocksChanged(int count, int countOfPeers); + void bytesChanged(quint64 totalBytesIn, quint64 totalBytesOut); + + //! Asynchronous error notification + void error(const QString &title, const QString &message, bool modal); + +public slots: + void updateTimer(); + void updateNumConnections(int numConnections); + void updateAlert(const QString &hash, int status); +}; + +#endif // CLIENTMODEL_H diff --git a/src/qt/coincontroldialog.cpp b/src/qt/coincontroldialog.cpp new file mode 100755 index 0000000..f1008d4 --- /dev/null +++ b/src/qt/coincontroldialog.cpp @@ -0,0 +1,738 @@ +#include "coincontroldialog.h" +#include "ui_coincontroldialog.h" + +#include "init.h" +#include "bitcoinunits.h" +#include "walletmodel.h" +#include "addresstablemodel.h" +#include "optionsmodel.h" +#include "coincontrol.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace std; +QList CoinControlDialog::payAmounts; +CCoinControl* CoinControlDialog::coinControl = new CCoinControl(); + +CoinControlDialog::CoinControlDialog(QWidget *parent) : + QDialog(parent), + ui(new Ui::CoinControlDialog), + model(0) +{ + ui->setupUi(this); + + // context menu actions + QAction *copyAddressAction = new QAction(tr("Copy address"), this); + QAction *copyLabelAction = new QAction(tr("Copy label"), this); + QAction *copyAmountAction = new QAction(tr("Copy amount"), this); + copyTransactionHashAction = new QAction(tr("Copy transaction ID"), this); // we need to enable/disable this + //lockAction = new QAction(tr("Lock unspent"), this); // we need to enable/disable this + //unlockAction = new QAction(tr("Unlock unspent"), this); // we need to enable/disable this + + // context menu + contextMenu = new QMenu(); + contextMenu->addAction(copyAddressAction); + contextMenu->addAction(copyLabelAction); + contextMenu->addAction(copyAmountAction); + contextMenu->addAction(copyTransactionHashAction); + //contextMenu->addSeparator(); + //contextMenu->addAction(lockAction); + //contextMenu->addAction(unlockAction); + + // context menu signals + connect(ui->treeWidget, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(showMenu(QPoint))); + connect(copyAddressAction, SIGNAL(triggered()), this, SLOT(copyAddress())); + connect(copyLabelAction, SIGNAL(triggered()), this, SLOT(copyLabel())); + connect(copyAmountAction, SIGNAL(triggered()), this, SLOT(copyAmount())); + connect(copyTransactionHashAction, SIGNAL(triggered()), this, SLOT(copyTransactionHash())); + //connect(lockAction, SIGNAL(triggered()), this, SLOT(lockCoin())); + //connect(unlockAction, SIGNAL(triggered()), this, SLOT(unlockCoin())); + + // clipboard actions + QAction *clipboardQuantityAction = new QAction(tr("Copy quantity"), this); + QAction *clipboardAmountAction = new QAction(tr("Copy amount"), this); + QAction *clipboardFeeAction = new QAction(tr("Copy fee"), this); + QAction *clipboardAfterFeeAction = new QAction(tr("Copy after fee"), this); + QAction *clipboardBytesAction = new QAction(tr("Copy bytes"), this); + QAction *clipboardPriorityAction = new QAction(tr("Copy priority"), this); + QAction *clipboardLowOutputAction = new QAction(tr("Copy low output"), this); + QAction *clipboardChangeAction = new QAction(tr("Copy change"), this); + + connect(clipboardQuantityAction, SIGNAL(triggered()), this, SLOT(clipboardQuantity())); + connect(clipboardAmountAction, SIGNAL(triggered()), this, SLOT(clipboardAmount())); + connect(clipboardFeeAction, SIGNAL(triggered()), this, SLOT(clipboardFee())); + connect(clipboardAfterFeeAction, SIGNAL(triggered()), this, SLOT(clipboardAfterFee())); + connect(clipboardBytesAction, SIGNAL(triggered()), this, SLOT(clipboardBytes())); + connect(clipboardPriorityAction, SIGNAL(triggered()), this, SLOT(clipboardPriority())); + connect(clipboardLowOutputAction, SIGNAL(triggered()), this, SLOT(clipboardLowOutput())); + connect(clipboardChangeAction, SIGNAL(triggered()), this, SLOT(clipboardChange())); + + ui->labelCoinControlQuantity->addAction(clipboardQuantityAction); + ui->labelCoinControlAmount->addAction(clipboardAmountAction); + ui->labelCoinControlFee->addAction(clipboardFeeAction); + ui->labelCoinControlAfterFee->addAction(clipboardAfterFeeAction); + ui->labelCoinControlBytes->addAction(clipboardBytesAction); + ui->labelCoinControlPriority->addAction(clipboardPriorityAction); + ui->labelCoinControlLowOutput->addAction(clipboardLowOutputAction); + ui->labelCoinControlChange->addAction(clipboardChangeAction); + + // toggle tree/list mode + connect(ui->radioTreeMode, SIGNAL(toggled(bool)), this, SLOT(radioTreeMode(bool))); + connect(ui->radioListMode, SIGNAL(toggled(bool)), this, SLOT(radioListMode(bool))); + + // click on checkbox + connect(ui->treeWidget, SIGNAL(itemChanged( QTreeWidgetItem*, int)), this, SLOT(viewItemChanged( QTreeWidgetItem*, int))); + + // click on header + ui->treeWidget->header()->setClickable(true); + connect(ui->treeWidget->header(), SIGNAL(sectionClicked(int)), this, SLOT(headerSectionClicked(int))); + + // ok button + connect(ui->buttonBox, SIGNAL(clicked( QAbstractButton*)), this, SLOT(buttonBoxClicked(QAbstractButton*))); + + // (un)select all + connect(ui->pushButtonSelectAll, SIGNAL(clicked()), this, SLOT(buttonSelectAllClicked())); + + ui->treeWidget->setColumnWidth(COLUMN_CHECKBOX, 84); + ui->treeWidget->setColumnWidth(COLUMN_AMOUNT, 100); + ui->treeWidget->setColumnWidth(COLUMN_LABEL, 170); + ui->treeWidget->setColumnWidth(COLUMN_ADDRESS, 290); + ui->treeWidget->setColumnWidth(COLUMN_DATE, 110); + ui->treeWidget->setColumnWidth(COLUMN_CONFIRMATIONS, 100); + ui->treeWidget->setColumnWidth(COLUMN_PRIORITY, 100); + ui->treeWidget->setColumnHidden(COLUMN_TXHASH, true); // store transacton hash in this column, but dont show it + ui->treeWidget->setColumnHidden(COLUMN_VOUT_INDEX, true); // store vout index in this column, but dont show it + ui->treeWidget->setColumnHidden(COLUMN_AMOUNT_INT64, true); // store amount int64_t in this column, but dont show it + ui->treeWidget->setColumnHidden(COLUMN_PRIORITY_INT64, true); // store priority int64_t in this column, but dont show it + + // default view is sorted by amount desc + sortView(COLUMN_AMOUNT_INT64, Qt::DescendingOrder); +} + +CoinControlDialog::~CoinControlDialog() +{ + delete ui; +} + +void CoinControlDialog::setModel(WalletModel *model) +{ + this->model = model; + + if(model && model->getOptionsModel() && model->getAddressTableModel()) + { + updateView(); + //updateLabelLocked(); + CoinControlDialog::updateLabels(model, this); + } +} + +// helper function str_pad +QString CoinControlDialog::strPad(QString s, int nPadLength, QString sPadding) +{ + while (s.length() < nPadLength) + s = sPadding + s; + + return s; +} + +// ok button +void CoinControlDialog::buttonBoxClicked(QAbstractButton* button) +{ + if (ui->buttonBox->buttonRole(button) == QDialogButtonBox::AcceptRole) + done(QDialog::Accepted); // closes the dialog +} + +// (un)select all +void CoinControlDialog::buttonSelectAllClicked() +{ + Qt::CheckState state = Qt::Checked; + for (int i = 0; i < ui->treeWidget->topLevelItemCount(); i++) + { + if (ui->treeWidget->topLevelItem(i)->checkState(COLUMN_CHECKBOX) != Qt::Unchecked) + { + state = Qt::Unchecked; + break; + } + } + ui->treeWidget->setEnabled(false); + for (int i = 0; i < ui->treeWidget->topLevelItemCount(); i++) + if (ui->treeWidget->topLevelItem(i)->checkState(COLUMN_CHECKBOX) != state) + ui->treeWidget->topLevelItem(i)->setCheckState(COLUMN_CHECKBOX, state); + ui->treeWidget->setEnabled(true); + CoinControlDialog::updateLabels(model, this); +} + +// context menu +void CoinControlDialog::showMenu(const QPoint &point) +{ + QTreeWidgetItem *item = ui->treeWidget->itemAt(point); + if(item) + { + contextMenuItem = item; + + // disable some items (like Copy Transaction ID, lock, unlock) for tree roots in context menu + if (item->text(COLUMN_TXHASH).length() == 64) // transaction hash is 64 characters (this means its a child node, so its not a parent node in tree mode) + { + copyTransactionHashAction->setEnabled(true); + //if (model->isLockedCoin(uint256(item->text(COLUMN_TXHASH).toStdString()), item->text(COLUMN_VOUT_INDEX).toUInt())) + //{ + // lockAction->setEnabled(false); + // unlockAction->setEnabled(true); + //} + //else + //{ + // lockAction->setEnabled(true); + // unlockAction->setEnabled(false); + //} + } + else // this means click on parent node in tree mode -> disable all + { + copyTransactionHashAction->setEnabled(false); + //lockAction->setEnabled(false); + //unlockAction->setEnabled(false); + } + + // show context menu + contextMenu->exec(QCursor::pos()); + } +} + +// context menu action: copy amount +void CoinControlDialog::copyAmount() +{ + QApplication::clipboard()->setText(contextMenuItem->text(COLUMN_AMOUNT)); +} + +// context menu action: copy label +void CoinControlDialog::copyLabel() +{ + if (ui->radioTreeMode->isChecked() && contextMenuItem->text(COLUMN_LABEL).length() == 0 && contextMenuItem->parent()) + QApplication::clipboard()->setText(contextMenuItem->parent()->text(COLUMN_LABEL)); + else + QApplication::clipboard()->setText(contextMenuItem->text(COLUMN_LABEL)); +} + +// context menu action: copy address +void CoinControlDialog::copyAddress() +{ + if (ui->radioTreeMode->isChecked() && contextMenuItem->text(COLUMN_ADDRESS).length() == 0 && contextMenuItem->parent()) + QApplication::clipboard()->setText(contextMenuItem->parent()->text(COLUMN_ADDRESS)); + else + QApplication::clipboard()->setText(contextMenuItem->text(COLUMN_ADDRESS)); +} + +// context menu action: copy transaction id +void CoinControlDialog::copyTransactionHash() +{ + QApplication::clipboard()->setText(contextMenuItem->text(COLUMN_TXHASH)); +} + +// context menu action: lock coin +/*void CoinControlDialog::lockCoin() +{ + if (contextMenuItem->checkState(COLUMN_CHECKBOX) == Qt::Checked) + contextMenuItem->setCheckState(COLUMN_CHECKBOX, Qt::Unchecked); + + COutPoint outpt(uint256(contextMenuItem->text(COLUMN_TXHASH).toStdString()), contextMenuItem->text(COLUMN_VOUT_INDEX).toUInt()); + model->lockCoin(outpt); + contextMenuItem->setDisabled(true); + contextMenuItem->setIcon(COLUMN_CHECKBOX, QIcon(":/icons/lock_closed")); + updateLabelLocked(); +}*/ + +// context menu action: unlock coin +/*void CoinControlDialog::unlockCoin() +{ + COutPoint outpt(uint256(contextMenuItem->text(COLUMN_TXHASH).toStdString()), contextMenuItem->text(COLUMN_VOUT_INDEX).toUInt()); + model->unlockCoin(outpt); + contextMenuItem->setDisabled(false); + contextMenuItem->setIcon(COLUMN_CHECKBOX, QIcon()); + updateLabelLocked(); +}*/ + +// copy label "Quantity" to clipboard +void CoinControlDialog::clipboardQuantity() +{ + QApplication::clipboard()->setText(ui->labelCoinControlQuantity->text()); +} + +// copy label "Amount" to clipboard +void CoinControlDialog::clipboardAmount() +{ + QApplication::clipboard()->setText(ui->labelCoinControlAmount->text().left(ui->labelCoinControlAmount->text().indexOf(" "))); +} + +// copy label "Fee" to clipboard +void CoinControlDialog::clipboardFee() +{ + QApplication::clipboard()->setText(ui->labelCoinControlFee->text().left(ui->labelCoinControlFee->text().indexOf(" "))); +} + +// copy label "After fee" to clipboard +void CoinControlDialog::clipboardAfterFee() +{ + QApplication::clipboard()->setText(ui->labelCoinControlAfterFee->text().left(ui->labelCoinControlAfterFee->text().indexOf(" "))); +} + +// copy label "Bytes" to clipboard +void CoinControlDialog::clipboardBytes() +{ + QApplication::clipboard()->setText(ui->labelCoinControlBytes->text()); +} + +// copy label "Priority" to clipboard +void CoinControlDialog::clipboardPriority() +{ + QApplication::clipboard()->setText(ui->labelCoinControlPriority->text()); +} + +// copy label "Low output" to clipboard +void CoinControlDialog::clipboardLowOutput() +{ + QApplication::clipboard()->setText(ui->labelCoinControlLowOutput->text()); +} + +// copy label "Change" to clipboard +void CoinControlDialog::clipboardChange() +{ + QApplication::clipboard()->setText(ui->labelCoinControlChange->text().left(ui->labelCoinControlChange->text().indexOf(" "))); +} + +// treeview: sort +void CoinControlDialog::sortView(int column, Qt::SortOrder order) +{ + sortColumn = column; + sortOrder = order; + ui->treeWidget->sortItems(column, order); + ui->treeWidget->header()->setSortIndicator((sortColumn == COLUMN_AMOUNT_INT64 ? COLUMN_AMOUNT : (sortColumn == COLUMN_PRIORITY_INT64 ? COLUMN_PRIORITY : sortColumn)), sortOrder); +} + +// treeview: clicked on header +void CoinControlDialog::headerSectionClicked(int logicalIndex) +{ + if (logicalIndex == COLUMN_CHECKBOX) // click on most left column -> do nothing + { + ui->treeWidget->header()->setSortIndicator((sortColumn == COLUMN_AMOUNT_INT64 ? COLUMN_AMOUNT : (sortColumn == COLUMN_PRIORITY_INT64 ? COLUMN_PRIORITY : sortColumn)), sortOrder); + } + else + { + if (logicalIndex == COLUMN_AMOUNT) // sort by amount + logicalIndex = COLUMN_AMOUNT_INT64; + + if (logicalIndex == COLUMN_PRIORITY) // sort by priority + logicalIndex = COLUMN_PRIORITY_INT64; + + if (sortColumn == logicalIndex) + sortOrder = ((sortOrder == Qt::AscendingOrder) ? Qt::DescendingOrder : Qt::AscendingOrder); + else + { + sortColumn = logicalIndex; + sortOrder = ((sortColumn == COLUMN_AMOUNT_INT64 || sortColumn == COLUMN_PRIORITY_INT64 || sortColumn == COLUMN_DATE || sortColumn == COLUMN_CONFIRMATIONS) ? Qt::DescendingOrder : Qt::AscendingOrder); // if amount,date,conf,priority then default => desc, else default => asc + } + + sortView(sortColumn, sortOrder); + } +} + +// toggle tree mode +void CoinControlDialog::radioTreeMode(bool checked) +{ + if (checked && model) + updateView(); +} + +// toggle list mode +void CoinControlDialog::radioListMode(bool checked) +{ + if (checked && model) + updateView(); +} + +// checkbox clicked by user +void CoinControlDialog::viewItemChanged(QTreeWidgetItem* item, int column) +{ + if (column == COLUMN_CHECKBOX && item->text(COLUMN_TXHASH).length() == 64) // transaction hash is 64 characters (this means its a child node, so its not a parent node in tree mode) + { + COutPoint outpt(uint256(item->text(COLUMN_TXHASH).toStdString()), item->text(COLUMN_VOUT_INDEX).toUInt()); + + if (item->checkState(COLUMN_CHECKBOX) == Qt::Unchecked) + coinControl->UnSelect(outpt); + else if (item->isDisabled()) // locked (this happens if "check all" through parent node) + item->setCheckState(COLUMN_CHECKBOX, Qt::Unchecked); + else + coinControl->Select(outpt); + + // selection changed -> update labels + if (ui->treeWidget->isEnabled()) // do not update on every click for (un)select all + CoinControlDialog::updateLabels(model, this); + } +} + +// helper function, return human readable label for priority number +QString CoinControlDialog::getPriorityLabel(double dPriority) +{ + if (dPriority > 576000ULL) // at least medium, this number is from AllowFree(), the other thresholds are kinda random + { + if (dPriority > 5760000000ULL) return tr("highest"); + else if (dPriority > 576000000ULL) return tr("high"); + else if (dPriority > 57600000ULL) return tr("medium-high"); + else return tr("medium"); + } + else + { + if (dPriority > 5760ULL) return tr("low-medium"); + else if (dPriority > 58ULL) return tr("low"); + else return tr("lowest"); + } +} + +// shows count of locked unspent outputs +/*void CoinControlDialog::updateLabelLocked() +{ + vector vOutpts; + model->listLockedCoins(vOutpts); + if (vOutpts.size() > 0) + { + ui->labelLocked->setText(tr("(%1 locked)").arg(vOutpts.size())); + ui->labelLocked->setVisible(true); + } + else ui->labelLocked->setVisible(false); +}*/ + +void CoinControlDialog::updateLabels(WalletModel *model, QDialog* dialog) +{ + if (!model) return; + + // nPayAmount + qint64 nPayAmount = 0; + bool fLowOutput = false; + bool fDust = false; + CTransaction txDummy; + foreach(const qint64 &amount, CoinControlDialog::payAmounts) + { + nPayAmount += amount; + + if (amount > 0) + { + if (amount < CENT) + fLowOutput = true; + + CTxOut txout(amount, (CScript)vector(24, 0)); + txDummy.vout.push_back(txout); + } + } + + QString sPriorityLabel = ""; + int64_t nAmount = 0; + int64_t nPayFee = 0; + int64_t nAfterFee = 0; + int64_t nChange = 0; + unsigned int nBytes = 0; + unsigned int nBytesInputs = 0; + double dPriority = 0; + double dPriorityInputs = 0; + unsigned int nQuantity = 0; + + vector vCoinControl; + vector vOutputs; + coinControl->ListSelected(vCoinControl); + model->getOutputs(vCoinControl, vOutputs); + + BOOST_FOREACH(const COutput& out, vOutputs) + { + // Quantity + nQuantity++; + + // Amount + nAmount += out.tx->vout[out.i].nValue; + + // Priority + dPriorityInputs += (double)out.tx->vout[out.i].nValue * (out.nDepth+1); + + // Bytes + CTxDestination address; + if(ExtractDestination(out.tx->vout[out.i].scriptPubKey, address)) + { + CPubKey pubkey; + CKeyID *keyid = boost::get< CKeyID >(&address); + if (keyid && model->getPubKey(*keyid, pubkey)) + nBytesInputs += (pubkey.IsCompressed() ? 148 : 180); + else + nBytesInputs += 148; // in all error cases, simply assume 148 here + } + else nBytesInputs += 148; + } + + // calculation + if (nQuantity > 0) + { + // Bytes + nBytes = nBytesInputs + ((CoinControlDialog::payAmounts.size() > 0 ? CoinControlDialog::payAmounts.size() + 1 : 2) * 34) + 10; // always assume +1 output for change here + + // Priority + dPriority = dPriorityInputs / nBytes; + sPriorityLabel = CoinControlDialog::getPriorityLabel(dPriority); + + // Fee + int64_t nFee = nTransactionFee * (1 + (int64_t)nBytes / 1000); + + // Min Fee + int64_t nMinFee = txDummy.GetMinFee(1, GMF_SEND, nBytes); + + nPayFee = max(nFee, nMinFee); + + if (nPayAmount > 0) + { + nChange = nAmount - nPayFee - nPayAmount; + + // if sub-cent change is required, the fee must be raised to at least CTransaction::nMinTxFee + if (nPayFee < CENT && nChange > 0 && nChange < CENT) + { + if (nChange < CENT) // change < 0.01 => simply move all change to fees + { + nPayFee = nChange; + nChange = 0; + } + else + { + nChange = nChange + nPayFee - CENT; + nPayFee = CENT; + } + } + + if (nChange == 0) + nBytes -= 34; + } + + // after fee + nAfterFee = nAmount - nPayFee; + if (nAfterFee < 0) + nAfterFee = 0; + } + + // actually update labels + int nDisplayUnit = BitcoinUnits::BTC; + if (model && model->getOptionsModel()) + nDisplayUnit = model->getOptionsModel()->getDisplayUnit(); + + QLabel *l1 = dialog->findChild("labelCoinControlQuantity"); + QLabel *l2 = dialog->findChild("labelCoinControlAmount"); + QLabel *l3 = dialog->findChild("labelCoinControlFee"); + QLabel *l4 = dialog->findChild("labelCoinControlAfterFee"); + QLabel *l5 = dialog->findChild("labelCoinControlBytes"); + QLabel *l6 = dialog->findChild("labelCoinControlPriority"); + QLabel *l7 = dialog->findChild("labelCoinControlLowOutput"); + QLabel *l8 = dialog->findChild("labelCoinControlChange"); + + // enable/disable "low output" and "change" + dialog->findChild("labelCoinControlLowOutputText")->setEnabled(nPayAmount > 0); + dialog->findChild("labelCoinControlLowOutput") ->setEnabled(nPayAmount > 0); + dialog->findChild("labelCoinControlChangeText") ->setEnabled(nPayAmount > 0); + dialog->findChild("labelCoinControlChange") ->setEnabled(nPayAmount > 0); + + // stats + l1->setText(QString::number(nQuantity)); // Quantity + l2->setText(BitcoinUnits::formatWithUnit(nDisplayUnit, nAmount)); // Amount + l3->setText(BitcoinUnits::formatWithUnit(nDisplayUnit, nPayFee)); // Fee + l4->setText(BitcoinUnits::formatWithUnit(nDisplayUnit, nAfterFee)); // After Fee + l5->setText(((nBytes > 0) ? "~" : "") + QString::number(nBytes)); // Bytes + l6->setText(sPriorityLabel); // Priority + l7->setText((fLowOutput ? (fDust ? tr("DUST") : tr("yes")) : tr("no"))); // Low Output / Dust + l8->setText(BitcoinUnits::formatWithUnit(nDisplayUnit, nChange)); // Change + + // turn labels "red" + l5->setStyleSheet((nBytes >= 10000) ? "color:red;" : ""); // Bytes >= 10000 + l6->setStyleSheet((dPriority <= 576000) ? "color:red;" : ""); // Priority < "medium" + l7->setStyleSheet((fLowOutput) ? "color:red;" : ""); // Low Output = "yes" + l8->setStyleSheet((nChange > 0 && nChange < CENT) ? "color:red;" : ""); // Change < 0.01BTC + + // tool tips + l5->setToolTip(tr("This label turns red, if the transaction size is bigger than 10000 bytes.\n\n This means a fee of at least %1 per kb is required.\n\n Can vary +/- 1 Byte per input.").arg(BitcoinUnits::formatWithUnit(nDisplayUnit, CENT))); + l6->setToolTip(tr("Transactions with higher priority get more likely into a block.\n\nThis label turns red, if the priority is smaller than \"medium\".\n\n This means a fee of at least %1 per kb is required.").arg(BitcoinUnits::formatWithUnit(nDisplayUnit, CENT))); + l7->setToolTip(tr("This label turns red, if any recipient receives an amount smaller than %1.\n\n This means a fee of at least %2 is required. \n\n Amounts below 0.546 times the minimum relay fee are shown as DUST.").arg(BitcoinUnits::formatWithUnit(nDisplayUnit, CENT)).arg(BitcoinUnits::formatWithUnit(nDisplayUnit, CENT))); + l8->setToolTip(tr("This label turns red, if the change is smaller than %1.\n\n This means a fee of at least %2 is required.").arg(BitcoinUnits::formatWithUnit(nDisplayUnit, CENT)).arg(BitcoinUnits::formatWithUnit(nDisplayUnit, CENT))); + dialog->findChild("labelCoinControlBytesText") ->setToolTip(l5->toolTip()); + dialog->findChild("labelCoinControlPriorityText") ->setToolTip(l6->toolTip()); + dialog->findChild("labelCoinControlLowOutputText")->setToolTip(l7->toolTip()); + dialog->findChild("labelCoinControlChangeText") ->setToolTip(l8->toolTip()); + + // Insufficient funds + QLabel *label = dialog->findChild("labelCoinControlInsuffFunds"); + if (label) + label->setVisible(nChange < 0); +} + +void CoinControlDialog::updateView() +{ + bool treeMode = ui->radioTreeMode->isChecked(); + + ui->treeWidget->clear(); + ui->treeWidget->setEnabled(false); // performance, otherwise updateLabels would be called for every checked checkbox + ui->treeWidget->setAlternatingRowColors(!treeMode); + QFlags flgCheckbox=Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsUserCheckable; + QFlags flgTristate=Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsUserCheckable | Qt::ItemIsTristate; + + int nDisplayUnit = BitcoinUnits::BTC; + if (model && model->getOptionsModel()) + nDisplayUnit = model->getOptionsModel()->getDisplayUnit(); + + map > mapCoins; + model->listCoins(mapCoins); + + BOOST_FOREACH(PAIRTYPE(QString, vector) coins, mapCoins) + { + QTreeWidgetItem *itemWalletAddress = new QTreeWidgetItem(); + QString sWalletAddress = coins.first; + QString sWalletLabel = ""; + if (model->getAddressTableModel()) + sWalletLabel = model->getAddressTableModel()->labelForAddress(sWalletAddress); + if (sWalletLabel.length() == 0) + sWalletLabel = tr("(no label)"); + + if (treeMode) + { + // wallet address + ui->treeWidget->addTopLevelItem(itemWalletAddress); + + itemWalletAddress->setFlags(flgTristate); + itemWalletAddress->setCheckState(COLUMN_CHECKBOX,Qt::Unchecked); + + for (int i = 0; i < ui->treeWidget->columnCount(); i++) + itemWalletAddress->setBackground(i, QColor(248, 247, 246)); + + // label + itemWalletAddress->setText(COLUMN_LABEL, sWalletLabel); + + // address + itemWalletAddress->setText(COLUMN_ADDRESS, sWalletAddress); + } + + int64_t nSum = 0; + double dPrioritySum = 0; + int nChildren = 0; + int nInputSum = 0; + BOOST_FOREACH(const COutput& out, coins.second) + { + int nInputSize = 148; // 180 if uncompressed public key + nSum += out.tx->vout[out.i].nValue; + nChildren++; + + QTreeWidgetItem *itemOutput; + if (treeMode) itemOutput = new QTreeWidgetItem(itemWalletAddress); + else itemOutput = new QTreeWidgetItem(ui->treeWidget); + itemOutput->setFlags(flgCheckbox); + itemOutput->setCheckState(COLUMN_CHECKBOX,Qt::Unchecked); + + // address + CTxDestination outputAddress; + QString sAddress = ""; + if(ExtractDestination(out.tx->vout[out.i].scriptPubKey, outputAddress)) + { + sAddress = CBitcoinAddress(outputAddress).ToString().c_str(); + + // if listMode or change => show bitcoin address. In tree mode, address is not shown again for direct wallet address outputs + if (!treeMode || (!(sAddress == sWalletAddress))) + itemOutput->setText(COLUMN_ADDRESS, sAddress); + + CPubKey pubkey; + CKeyID *keyid = boost::get< CKeyID >(&outputAddress); + if (keyid && model->getPubKey(*keyid, pubkey) && !pubkey.IsCompressed()) + nInputSize = 180; + } + + // label + if (!(sAddress == sWalletAddress)) // change + { + // tooltip from where the change comes from + itemOutput->setToolTip(COLUMN_LABEL, tr("change from %1 (%2)").arg(sWalletLabel).arg(sWalletAddress)); + itemOutput->setText(COLUMN_LABEL, tr("(change)")); + } + else if (!treeMode) + { + QString sLabel = ""; + if (model->getAddressTableModel()) + sLabel = model->getAddressTableModel()->labelForAddress(sAddress); + if (sLabel.length() == 0) + sLabel = tr("(no label)"); + itemOutput->setText(COLUMN_LABEL, sLabel); + } + + // amount + itemOutput->setText(COLUMN_AMOUNT, BitcoinUnits::format(nDisplayUnit, out.tx->vout[out.i].nValue)); + itemOutput->setText(COLUMN_AMOUNT_INT64, strPad(QString::number(out.tx->vout[out.i].nValue), 15, " ")); // padding so that sorting works correctly + + // date + itemOutput->setText(COLUMN_DATE, QDateTime::fromTime_t(out.tx->GetTxTime()).toUTC().toString("yy-MM-dd hh:mm")); + + // immature PoS reward + if (out.tx->IsCoinStake() && out.tx->GetBlocksToMaturity() > 0 && out.tx->GetDepthInMainChain() > 0) { + itemOutput->setBackground(COLUMN_CONFIRMATIONS, Qt::red); + itemOutput->setDisabled(true); + } + + // confirmations + itemOutput->setText(COLUMN_CONFIRMATIONS, strPad(QString::number(out.nDepth), 8, " ")); + + // priority + double dPriority = ((double)out.tx->vout[out.i].nValue / (nInputSize + 78)) * (out.nDepth+1); // 78 = 2 * 34 + 10 + itemOutput->setText(COLUMN_PRIORITY, CoinControlDialog::getPriorityLabel(dPriority)); + itemOutput->setText(COLUMN_PRIORITY_INT64, strPad(QString::number((int64_t)dPriority), 20, " ")); + dPrioritySum += (double)out.tx->vout[out.i].nValue * (out.nDepth+1); + nInputSum += nInputSize; + + // transaction hash + uint256 txhash = out.tx->GetHash(); + itemOutput->setText(COLUMN_TXHASH, txhash.GetHex().c_str()); + + // vout index + itemOutput->setText(COLUMN_VOUT_INDEX, QString::number(out.i)); + + // disable locked coins + /*if (model->isLockedCoin(txhash, out.i)) + { + COutPoint outpt(txhash, out.i); + coinControl->UnSelect(outpt); // just to be sure + itemOutput->setDisabled(true); + itemOutput->setIcon(COLUMN_CHECKBOX, QIcon(":/icons/lock_closed")); + }*/ + + // set checkbox + if (coinControl->IsSelected(txhash, out.i)) + itemOutput->setCheckState(COLUMN_CHECKBOX,Qt::Checked); + } + + // amount + if (treeMode) + { + dPrioritySum = dPrioritySum / (nInputSum + 78); + itemWalletAddress->setText(COLUMN_CHECKBOX, "(" + QString::number(nChildren) + ")"); + itemWalletAddress->setText(COLUMN_AMOUNT, BitcoinUnits::format(nDisplayUnit, nSum)); + itemWalletAddress->setText(COLUMN_AMOUNT_INT64, strPad(QString::number(nSum), 15, " ")); + itemWalletAddress->setText(COLUMN_PRIORITY, CoinControlDialog::getPriorityLabel(dPrioritySum)); + itemWalletAddress->setText(COLUMN_PRIORITY_INT64, strPad(QString::number((int64_t)dPrioritySum), 20, " ")); + } + } + + // expand all partially selected + if (treeMode) + { + for (int i = 0; i < ui->treeWidget->topLevelItemCount(); i++) + if (ui->treeWidget->topLevelItem(i)->checkState(COLUMN_CHECKBOX) == Qt::PartiallyChecked) + ui->treeWidget->topLevelItem(i)->setExpanded(true); + } + + // sort view + sortView(sortColumn, sortOrder); + ui->treeWidget->setEnabled(true); +} diff --git a/src/qt/coincontroldialog.h b/src/qt/coincontroldialog.h new file mode 100755 index 0000000..5d0a90b --- /dev/null +++ b/src/qt/coincontroldialog.h @@ -0,0 +1,92 @@ +#ifndef COINCONTROLDIALOG_H +#define COINCONTROLDIALOG_H + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace Ui { + class CoinControlDialog; +} +class WalletModel; +class CCoinControl; + +class CoinControlDialog : public QDialog +{ + Q_OBJECT + +public: + explicit CoinControlDialog(QWidget *parent = 0); + ~CoinControlDialog(); + + void setModel(WalletModel *model); + + // static because also called from sendcoinsdialog + static void updateLabels(WalletModel*, QDialog*); + static QString getPriorityLabel(double); + + static QList payAmounts; + static CCoinControl *coinControl; + +private: + Ui::CoinControlDialog *ui; + WalletModel *model; + int sortColumn; + Qt::SortOrder sortOrder; + + QMenu *contextMenu; + QTreeWidgetItem *contextMenuItem; + QAction *copyTransactionHashAction; + //QAction *lockAction; + //QAction *unlockAction; + + QString strPad(QString, int, QString); + void sortView(int, Qt::SortOrder); + void updateView(); + + enum + { + COLUMN_CHECKBOX, + COLUMN_AMOUNT, + COLUMN_LABEL, + COLUMN_ADDRESS, + COLUMN_DATE, + COLUMN_CONFIRMATIONS, + COLUMN_PRIORITY, + COLUMN_TXHASH, + COLUMN_VOUT_INDEX, + COLUMN_AMOUNT_INT64, + COLUMN_PRIORITY_INT64 + }; + +private slots: + void showMenu(const QPoint &); + void copyAmount(); + void copyLabel(); + void copyAddress(); + void copyTransactionHash(); + //void lockCoin(); + //void unlockCoin(); + void clipboardQuantity(); + void clipboardAmount(); + void clipboardFee(); + void clipboardAfterFee(); + void clipboardBytes(); + void clipboardPriority(); + void clipboardLowOutput(); + void clipboardChange(); + void radioTreeMode(bool); + void radioListMode(bool); + void viewItemChanged(QTreeWidgetItem*, int); + void headerSectionClicked(int); + void buttonBoxClicked(QAbstractButton*); + void buttonSelectAllClicked(); + //void updateLabelLocked(); +}; + +#endif // COINCONTROLDIALOG_H diff --git a/src/qt/coincontroltreewidget.cpp b/src/qt/coincontroltreewidget.cpp new file mode 100755 index 0000000..aa75a49 --- /dev/null +++ b/src/qt/coincontroltreewidget.cpp @@ -0,0 +1,28 @@ +#include "coincontroltreewidget.h" +#include "coincontroldialog.h" + +CoinControlTreeWidget::CoinControlTreeWidget(QWidget *parent) : + QTreeWidget(parent) +{ + +} + +void CoinControlTreeWidget::keyPressEvent(QKeyEvent *event) +{ + if (event->key() == Qt::Key_Space) // press spacebar -> select checkbox + { + event->ignore(); + int COLUMN_CHECKBOX = 0; + this->currentItem()->setCheckState(COLUMN_CHECKBOX, ((this->currentItem()->checkState(COLUMN_CHECKBOX) == Qt::Checked) ? Qt::Unchecked : Qt::Checked)); + } + else if (event->key() == Qt::Key_Escape) // press esc -> close dialog + { + event->ignore(); + CoinControlDialog *coinControlDialog = (CoinControlDialog*)this->parentWidget(); + coinControlDialog->done(QDialog::Accepted); + } + else + { + this->QTreeWidget::keyPressEvent(event); + } +} \ No newline at end of file diff --git a/src/qt/coincontroltreewidget.h b/src/qt/coincontroltreewidget.h new file mode 100755 index 0000000..d981f72 --- /dev/null +++ b/src/qt/coincontroltreewidget.h @@ -0,0 +1,17 @@ +#ifndef COINCONTROLTREEWIDGET_H +#define COINCONTROLTREEWIDGET_H + +#include +#include + +class CoinControlTreeWidget : public QTreeWidget { +Q_OBJECT + +public: + explicit CoinControlTreeWidget(QWidget *parent = 0); + +protected: + virtual void keyPressEvent(QKeyEvent *event); +}; + +#endif // COINCONTROLTREEWIDGET_H \ No newline at end of file diff --git a/src/qt/csvmodelwriter.cpp b/src/qt/csvmodelwriter.cpp new file mode 100755 index 0000000..8a50bba --- /dev/null +++ b/src/qt/csvmodelwriter.cpp @@ -0,0 +1,88 @@ +#include "csvmodelwriter.h" + +#include +#include +#include + +CSVModelWriter::CSVModelWriter(const QString &filename, QObject *parent) : + QObject(parent), + filename(filename), model(0) +{ +} + +void CSVModelWriter::setModel(const QAbstractItemModel *model) +{ + this->model = model; +} + +void CSVModelWriter::addColumn(const QString &title, int column, int role) +{ + Column col; + col.title = title; + col.column = column; + col.role = role; + + columns.append(col); +} + +static void writeValue(QTextStream &f, const QString &value) +{ + QString escaped = value; + escaped.replace('"', "\"\""); + f << "\"" << escaped << "\""; +} + +static void writeSep(QTextStream &f) +{ + f << ","; +} + +static void writeNewline(QTextStream &f) +{ + f << "\n"; +} + +bool CSVModelWriter::write() +{ + QFile file(filename); + if(!file.open(QIODevice::WriteOnly | QIODevice::Text)) + return false; + QTextStream out(&file); + + int numRows = 0; + if(model) + { + numRows = model->rowCount(); + } + + // Header row + for(int i=0; iindex(j, columns[i].column).data(columns[i].role); + writeValue(out, data.toString()); + } + writeNewline(out); + } + + file.close(); + + return file.error() == QFile::NoError; +} + diff --git a/src/qt/csvmodelwriter.h b/src/qt/csvmodelwriter.h new file mode 100755 index 0000000..6c9dcba --- /dev/null +++ b/src/qt/csvmodelwriter.h @@ -0,0 +1,46 @@ +#ifndef CSVMODELWRITER_H +#define CSVMODELWRITER_H + +#include +#include + +QT_BEGIN_NAMESPACE +class QAbstractItemModel; +QT_END_NAMESPACE + +/** Export a Qt table model to a CSV file. This is useful for analyzing or post-processing the data in + a spreadsheet. + */ +class CSVModelWriter : public QObject +{ + Q_OBJECT +public: + explicit CSVModelWriter(const QString &filename, QObject *parent = 0); + + void setModel(const QAbstractItemModel *model); + void addColumn(const QString &title, int column, int role=Qt::EditRole); + + /** Perform export of the model to CSV. + @returns true on success, false otherwise + */ + bool write(); + +private: + QString filename; + const QAbstractItemModel *model; + + struct Column + { + QString title; + int column; + int role; + }; + QList columns; + +signals: + +public slots: + +}; + +#endif // CSVMODELWRITER_H diff --git a/src/qt/editaddressdialog.cpp b/src/qt/editaddressdialog.cpp new file mode 100755 index 0000000..905d07c --- /dev/null +++ b/src/qt/editaddressdialog.cpp @@ -0,0 +1,136 @@ +#include "editaddressdialog.h" +#include "ui_editaddressdialog.h" +#include "addresstablemodel.h" +#include "guiutil.h" + +#include +#include + +EditAddressDialog::EditAddressDialog(Mode mode, QWidget *parent) : + QDialog(parent), + ui(new Ui::EditAddressDialog), mapper(0), mode(mode), model(0) +{ + ui->setupUi(this); + + GUIUtil::setupAddressWidget(ui->addressEdit, this); + + switch(mode) + { + case NewReceivingAddress: + setWindowTitle(tr("New receiving address")); + ui->addressEdit->setEnabled(false); + break; + case NewSendingAddress: + setWindowTitle(tr("New sending address")); + break; + case EditReceivingAddress: + setWindowTitle(tr("Edit receiving address")); + ui->addressEdit->setEnabled(false); + break; + case EditSendingAddress: + setWindowTitle(tr("Edit sending address")); + break; + } + + mapper = new QDataWidgetMapper(this); + mapper->setSubmitPolicy(QDataWidgetMapper::ManualSubmit); +} + +EditAddressDialog::~EditAddressDialog() +{ + delete ui; +} + +void EditAddressDialog::setModel(AddressTableModel *model) +{ + this->model = model; + if(!model) + return; + + mapper->setModel(model); + mapper->addMapping(ui->labelEdit, AddressTableModel::Label); + mapper->addMapping(ui->addressEdit, AddressTableModel::Address); +} + +void EditAddressDialog::loadRow(int row) +{ + mapper->setCurrentIndex(row); +} + +bool EditAddressDialog::saveCurrentRow() +{ + if(!model) + return false; + + switch(mode) + { + case NewReceivingAddress: + case NewSendingAddress: + address = model->addRow( + mode == NewSendingAddress ? AddressTableModel::Send : AddressTableModel::Receive, + ui->labelEdit->text(), + ui->addressEdit->text()); + break; + case EditReceivingAddress: + case EditSendingAddress: + if(mapper->submit()) + { + address = ui->addressEdit->text(); + } + break; + } + return !address.isEmpty(); +} + +void EditAddressDialog::accept() +{ + if(!model) + return; + + if(!saveCurrentRow()) + { + switch(model->getEditStatus()) + { + case AddressTableModel::OK: + // Failed with unknown reason. Just reject. + break; + case AddressTableModel::NO_CHANGES: + // No changes were made during edit operation. Just reject. + break; + case AddressTableModel::INVALID_ADDRESS: + QMessageBox::warning(this, windowTitle(), + tr("The entered address \"%1\" is not a valid Arepacoin address.").arg(ui->addressEdit->text()), + QMessageBox::Ok, QMessageBox::Ok); + break; + case AddressTableModel::DUPLICATE_ADDRESS: + QMessageBox::warning(this, windowTitle(), + tr("The entered address \"%1\" is already in the address book.").arg(ui->addressEdit->text()), + QMessageBox::Ok, QMessageBox::Ok); + break; + case AddressTableModel::WALLET_UNLOCK_FAILURE: + QMessageBox::critical(this, windowTitle(), + tr("Could not unlock wallet."), + QMessageBox::Ok, QMessageBox::Ok); + break; + case AddressTableModel::KEY_GENERATION_FAILURE: + QMessageBox::critical(this, windowTitle(), + tr("New key generation failed."), + QMessageBox::Ok, QMessageBox::Ok); + break; + + } + return; + } + QDialog::accept(); +} + +QString EditAddressDialog::getAddress() const +{ + return address; +} + +void EditAddressDialog::setAddress(const QString &address) +{ + this->address = address; + ui->addressEdit->setText(address); +} diff --git a/src/qt/editaddressdialog.h b/src/qt/editaddressdialog.h new file mode 100755 index 0000000..0e4183b --- /dev/null +++ b/src/qt/editaddressdialog.h @@ -0,0 +1,52 @@ +#ifndef EDITADDRESSDIALOG_H +#define EDITADDRESSDIALOG_H + +#include + +QT_BEGIN_NAMESPACE +class QDataWidgetMapper; +QT_END_NAMESPACE + +namespace Ui { + class EditAddressDialog; +} +class AddressTableModel; + +/** Dialog for editing an address and associated information. + */ +class EditAddressDialog : public QDialog +{ + Q_OBJECT + +public: + enum Mode { + NewReceivingAddress, + NewSendingAddress, + EditReceivingAddress, + EditSendingAddress + }; + + explicit EditAddressDialog(Mode mode, QWidget *parent = 0); + ~EditAddressDialog(); + + void setModel(AddressTableModel *model); + void loadRow(int row); + + QString getAddress() const; + void setAddress(const QString &address); + +public slots: + void accept(); + +private: + bool saveCurrentRow(); + + Ui::EditAddressDialog *ui; + QDataWidgetMapper *mapper; + Mode mode; + AddressTableModel *model; + + QString address; +}; + +#endif // EDITADDRESSDIALOG_H diff --git a/src/qt/forms/aboutdialog.ui b/src/qt/forms/aboutdialog.ui new file mode 100755 index 0000000..0fb7211 --- /dev/null +++ b/src/qt/forms/aboutdialog.ui @@ -0,0 +1,191 @@ + + + AboutDialog + + + + 0 + 0 + 593 + 319 + + + + About Arepacoin + + + + + + + 0 + 0 + + + + :/images/about + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + IBeamCursor + + + <b>Arepacoin</b> version + + + Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse + + + + + + + IBeamCursor + + + 0.3.666-beta + + + Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + IBeamCursor + + + Copyright © 2009-2014 The Bitcoin developers +Copyright © 2012-2014 The NovaCoin developers +Copyright © 2018 The Arepacoin Developers + + + Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse + + + + + + + IBeamCursor + + + +This is experimental software. + +Distributed under the MIT/X11 software license, see the accompanying file COPYING or <a href="http://www.opensource.org/licenses/mit-license.php">http://www.opensource.org/licenses/mit-license.php</a>. + +This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit (<a href="https://www.openssl.org/">https://www.openssl.org/</a>) and cryptographic software written by Eric Young (<a href="mailto:eay@cryptsoft.com">eay@cryptsoft.com</a>) and UPnP software written by Thomas Bernard. + + + Qt::RichText + + + true + + + Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Ok + + + + + + + + + + + + + buttonBox + accepted() + AboutDialog + accept() + + + 360 + 308 + + + 157 + 274 + + + + + buttonBox + rejected() + AboutDialog + reject() + + + 428 + 308 + + + 286 + 274 + + + + + diff --git a/src/qt/forms/addressbookpage.ui b/src/qt/forms/addressbookpage.ui new file mode 100755 index 0000000..1038b9c --- /dev/null +++ b/src/qt/forms/addressbookpage.ui @@ -0,0 +1,175 @@ + + + AddressBookPage + + + + 0 + 0 + 760 + 380 + + + + Address Book + + + + + + These are your Arepacoin addresses for receiving payments. You may want to give a different one to each sender so you can keep track of who is paying you. + + + Qt::PlainText + + + true + + + + + + + Qt::CustomContextMenu + + + Double-click to edit address or label + + + false + + + true + + + QAbstractItemView::SingleSelection + + + QAbstractItemView::SelectRows + + + true + + + false + + + + + + + + + Create a new address + + + &New Address + + + + :/icons/add:/icons/add + + + + + + + Copy the currently selected address to the system clipboard + + + &Copy Address + + + + :/icons/editcopy:/icons/editcopy + + + + + + + Show &QR Code + + + + :/icons/qrcode:/icons/qrcode + + + + + + + Sign a message to prove you own a Arepacoin address + + + Sign &Message + + + + :/icons/edit:/icons/edit + + + + + + + Verify a message to ensure it was signed with a specified Arepacoin address + + + &Verify Message + + + + :/icons/transaction_0:/icons/transaction_0 + + + + + + + Delete the currently selected address from the list + + + &Delete + + + + :/icons/remove:/icons/remove + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 0 + 0 + + + + QDialogButtonBox::Ok + + + + + + + + + + + + diff --git a/src/qt/forms/askpassphrasedialog.ui b/src/qt/forms/askpassphrasedialog.ui new file mode 100755 index 0000000..02ea8ff --- /dev/null +++ b/src/qt/forms/askpassphrasedialog.ui @@ -0,0 +1,167 @@ + + + AskPassphraseDialog + + + + 0 + 0 + 598 + 198 + + + + + 0 + 0 + + + + + 550 + 0 + + + + Passphrase Dialog + + + + + + Qt::RichText + + + true + + + + + + + QFormLayout::AllNonFixedFieldsGrow + + + + + Enter passphrase + + + + + + + QLineEdit::Password + + + + + + + New passphrase + + + + + + + QLineEdit::Password + + + + + + + Repeat new passphrase + + + + + + + QLineEdit::Password + + + + + + + + 75 + true + + + + + + + Qt::AlignCenter + + + + + + + true + + + Serves to disable the trivial sendmoney when OS account compromised. Provides no real security. + + + For staking only + + + false + + + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + + + buttonBox + accepted() + AskPassphraseDialog + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + AskPassphraseDialog + reject() + + + 316 + 260 + + + 286 + 274 + + + + + diff --git a/src/qt/forms/coincontroldialog.ui b/src/qt/forms/coincontroldialog.ui new file mode 100755 index 0000000..6510da7 --- /dev/null +++ b/src/qt/forms/coincontroldialog.ui @@ -0,0 +1,549 @@ + + + CoinControlDialog + + + + 0 + 0 + 1000 + 500 + + + + Coin Control + + + + + + 0 + + + 10 + + + + + 10 + + + 10 + + + 6 + + + 6 + + + + + font-weight:bold; + + + Quantity: + + + + + + + + Monospace + 10 + + + + IBeamCursor + + + Qt::ActionsContextMenu + + + 0 + + + Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse + + + + + + + font-weight:bold; + + + Bytes: + + + + + + + + Monospace + 10 + + + + IBeamCursor + + + Qt::ActionsContextMenu + + + 0 + + + Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse + + + + + + + + + 10 + + + 10 + + + 6 + + + 6 + + + + + font-weight:bold; + + + Amount: + + + + + + + + Monospace + 10 + + + + IBeamCursor + + + Qt::ActionsContextMenu + + + 0.00 AREPA + + + Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse + + + + + + + font-weight:bold; + + + Priority: + + + + + + + + Monospace + 10 + + + + IBeamCursor + + + Qt::ActionsContextMenu + + + + + + Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse + + + + + + + + + 10 + + + 10 + + + 6 + + + 6 + + + + + font-weight:bold; + + + Fee: + + + + + + + + Monospace + 10 + + + + IBeamCursor + + + Qt::ActionsContextMenu + + + 0.00 AREPA + + + Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse + + + + + + + false + + + font-weight:bold; + + + Low Output: + + + + + + + false + + + + Monospace + 10 + + + + IBeamCursor + + + Qt::ActionsContextMenu + + + no + + + Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse + + + + + + + + + 10 + + + 10 + + + 6 + + + 6 + + + + + font-weight:bold; + + + After Fee: + + + + + + + + Monospace + 10 + + + + IBeamCursor + + + Qt::ActionsContextMenu + + + 0.00 AREPA + + + Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse + + + + + + + false + + + font-weight:bold; + + + Change: + + + + + + + false + + + + Monospace + 10 + + + + IBeamCursor + + + Qt::ActionsContextMenu + + + 0.00 AREPA + + + Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse + + + + + + + + + + + + 0 + 40 + + + + QFrame::StyledPanel + + + QFrame::Sunken + + + + + 10 + 0 + 781 + 41 + + + + + 14 + + + + + + 0 + 0 + + + + (un)select all + + + + + + + + 0 + 0 + + + + Tree mode + + + true + + + + + + + + 0 + 0 + + + + List mode + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + Qt::CustomContextMenu + + + false + + + 11 + + + true + + + false + + + + + + + + + Amount + + + + + Label + + + + + Address + + + + + Date + + + + + Confirmations + + + Confirmed + + + + + Priority + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + 0 + + + + Qt::Horizontal + + + QDialogButtonBox::Ok + + + + + + + + CoinControlTreeWidget + QTreeWidget +
coincontroltreewidget.h
+
+
+ + +
diff --git a/src/qt/forms/editaddressdialog.ui b/src/qt/forms/editaddressdialog.ui new file mode 100755 index 0000000..b4a4c1b --- /dev/null +++ b/src/qt/forms/editaddressdialog.ui @@ -0,0 +1,105 @@ + + + EditAddressDialog + + + + 0 + 0 + 457 + 126 + + + + Edit Address + + + + + + QFormLayout::AllNonFixedFieldsGrow + + + + + &Label + + + labelEdit + + + + + + + The label associated with this address book entry + + + + + + + &Address + + + addressEdit + + + + + + + The address associated with this address book entry. This can only be modified for sending addresses. + + + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + + + buttonBox + accepted() + EditAddressDialog + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + EditAddressDialog + reject() + + + 316 + 260 + + + 286 + 274 + + + + + diff --git a/src/qt/forms/optionsdialog.ui b/src/qt/forms/optionsdialog.ui new file mode 100755 index 0000000..97585cb --- /dev/null +++ b/src/qt/forms/optionsdialog.ui @@ -0,0 +1,513 @@ + + + OptionsDialog + + + + 0 + 0 + 540 + 380 + + + + Options + + + true + + + + + + QTabWidget::North + + + 0 + + + + &Main + + + + + + Optional transaction fee per kB that helps make sure your transactions are processed quickly. Most transactions are 1 kB. Fee 0.01 recommended. + + + Qt::PlainText + + + true + + + + + + + + + Pay transaction &fee + + + Qt::PlainText + + + transactionFee + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + Reserved amount does not participate in staking and is therefore spendable at any time. + + + Qt::PlainText + + + true + + + + + + + + + Reserve + + + Qt::PlainText + + + reserveBalance + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + Automatically start Arepacoin after logging in to the system. + + + &Start Arepacoin on system login + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + &Network + + + + + + Automatically open the Arepacoin client port on the router. This only works when your router supports UPnP and it is enabled. + + + Map port using &UPnP + + + + + + + Connect to the Arepacoin network through a SOCKS proxy (e.g. when connecting through Tor). + + + &Connect through SOCKS proxy: + + + + + + + + + Proxy &IP: + + + Qt::PlainText + + + proxyIp + + + + + + + + 140 + 16777215 + + + + IP address of the proxy (e.g. 127.0.0.1) + + + + + + + &Port: + + + Qt::PlainText + + + proxyPort + + + + + + + + 55 + 16777215 + + + + Port of the proxy (e.g. 9050) + + + + + + + SOCKS &Version: + + + Qt::PlainText + + + socksVersion + + + + + + + SOCKS version of the proxy (e.g. 5) + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + &Window + + + + + + Show only a tray icon after minimizing the window. + + + &Minimize to the tray instead of the taskbar + + + + + + + Minimize instead of exit the application when the window is closed. When this option is enabled, the application will be closed only after selecting Quit in the menu. + + + M&inimize on close + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + &Display + + + + + + + + User Interface &language: + + + Qt::PlainText + + + lang + + + + + + + The user interface language can be set here. This setting will take effect after restarting Arepacoin. + + + + + + + + + + + &Unit to show amounts in: + + + Qt::PlainText + + + unit + + + + + + + Choose the default subdivision unit to show in the interface and when sending coins. + + + + + + + + + Whether to show Arepacoin addresses in the transaction list or not. + + + &Display addresses in transaction list + + + + + + + Whether to show coin control features or not. + + + Display coin &control features (experts only!) + + + + + + + Use black visual theme (requires restart) + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + + + + Qt::Horizontal + + + + 40 + 48 + + + + + + + + + 75 + true + + + + + + + Qt::PlainText + + + true + + + + + + + Qt::Horizontal + + + + 40 + 48 + + + + + + + + &OK + + + + + + + &Cancel + + + false + + + + + + + &Apply + + + false + + + + + + + + + + BitcoinAmountField + QSpinBox +
bitcoinamountfield.h
+
+ + QValueComboBox + QComboBox +
qvaluecombobox.h
+
+ + QValidatedLineEdit + QLineEdit +
qvalidatedlineedit.h
+
+
+ + +
diff --git a/src/qt/forms/overviewpage.ui b/src/qt/forms/overviewpage.ui new file mode 100755 index 0000000..168da0e --- /dev/null +++ b/src/qt/forms/overviewpage.ui @@ -0,0 +1,349 @@ + + + OverviewPage + + + + 0 + 0 + 573 + 342 + + + + Form + + + + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + + + + 11 + 75 + true + + + + Wallet + + + + + + + The displayed information may be out of date. Your wallet automatically synchronizes with the Arepacoin network after a connection is established, but this process has not completed yet. + + + QLabel { color: red; } + + + (out of sync) + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + QFormLayout::AllNonFixedFieldsGrow + + + 12 + + + 12 + + + + + Spendable: + + + + + + + + 75 + true + + + + IBeamCursor + + + Your current spendable balance + + + 0 AREPA + + + Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse + + + + + + + Stake: + + + + + + + + 75 + true + + + + IBeamCursor + + + Total of coins that was staked, and do not yet count toward the current balance + + + 0 AREPA + + + Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse + + + + + + + Unconfirmed: + + + + + + + + 75 + true + + + + IBeamCursor + + + Total of transactions that have yet to be confirmed, and do not yet count toward the current balance + + + 0 AREPA + + + Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse + + + + + + + Immature: + + + + + + + + 75 + true + + + + Mined balance that has not yet matured + + + 0 AREPA + + + Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse + + + + + + + Qt::Horizontal + + + + + + + Total: + + + + + + + + 75 + true + + + + IBeamCursor + + + Your current total balance + + + 0 BTC + + + Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse + + + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + + + <b>Recent transactions</b> + + + + + + + The displayed information may be out of date. Your wallet automatically synchronizes with the Arepacoin network after a connection is established, but this process has not completed yet. + + + QLabel { color: red; } + + + (out of sync) + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + QListView { background: transparent; } + + + QFrame::NoFrame + + + Qt::ScrollBarAlwaysOff + + + Qt::ScrollBarAlwaysOff + + + QAbstractItemView::NoSelection + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + + + diff --git a/src/qt/forms/qrcodedialog.ui b/src/qt/forms/qrcodedialog.ui new file mode 100755 index 0000000..52e9db3 --- /dev/null +++ b/src/qt/forms/qrcodedialog.ui @@ -0,0 +1,212 @@ + + + QRCodeDialog + + + + 0 + 0 + 340 + 530 + + + + QR Code Dialog + + + + + + + 0 + 0 + + + + + 300 + 300 + + + + Qt::PlainText + + + Qt::AlignCenter + + + true + + + + + + + + 0 + 0 + + + + + 0 + 50 + + + + true + + + Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse + + + + + + + + + + true + + + Request Payment + + + + + + + QFormLayout::AllNonFixedFieldsGrow + + + + + Label: + + + Qt::PlainText + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + lnLabel + + + + + + + + + + Message: + + + Qt::PlainText + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + lnMessage + + + + + + + + + + + 0 + 0 + + + + Amount: + + + Qt::PlainText + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + lnReqAmount + + + + + + + false + + + + 80 + 0 + + + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + &Save As... + + + + + + + + + + + + + BitcoinAmountField + QSpinBox +
bitcoinamountfield.h
+
+
+ + + + chkReqPayment + clicked(bool) + lnReqAmount + setEnabled(bool) + + + 92 + 285 + + + 98 + 311 + + + + +
diff --git a/src/qt/forms/rpcconsole.ui b/src/qt/forms/rpcconsole.ui new file mode 100755 index 0000000..ef337f7 --- /dev/null +++ b/src/qt/forms/rpcconsole.ui @@ -0,0 +1,717 @@ + + + RPCConsole + + + + 0 + 0 + 740 + 450 + + + + Arepacoin - Debug window + + + + + + 0 + + + + &Information + + + + 12 + + + + + + 75 + true + + + + Arepacoin Core + + + + + + + Client name + + + + + + + IBeamCursor + + + N/A + + + Qt::PlainText + + + Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse + + + + + + + Client version + + + + + + + IBeamCursor + + + N/A + + + Qt::PlainText + + + Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse + + + + + + + Using OpenSSL version + + + 10 + + + + + + + IBeamCursor + + + N/A + + + Qt::PlainText + + + Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse + + + + + + + Build date + + + + + + + IBeamCursor + + + N/A + + + Qt::PlainText + + + Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse + + + + + + + Startup time + + + + + + + IBeamCursor + + + N/A + + + Qt::PlainText + + + Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse + + + + + + + + 75 + true + + + + Network + + + + + + + Number of connections + + + + + + + IBeamCursor + + + N/A + + + Qt::PlainText + + + Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse + + + + + + + On testnet + + + + + + + false + + + + + + + + + + + 75 + true + + + + Block chain + + + + + + + Current number of blocks + + + + + + + IBeamCursor + + + N/A + + + Qt::PlainText + + + Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse + + + + + + + Estimated total blocks + + + + + + + IBeamCursor + + + N/A + + + Qt::PlainText + + + Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse + + + + + + + Last block time + + + + + + + IBeamCursor + + + N/A + + + Qt::PlainText + + + Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse + + + + + + + Qt::Vertical + + + + 20 + 20 + + + + + + + + + 75 + true + + + + Debug log file + + + + + + + Open the Arepacoin debug log file from the current data directory. This can take a few seconds for large log files. + + + &Open + + + false + + + + + + + + 75 + true + + + + Command-line options + + + + + + + Show the Arepacoin-Qt help message to get a list with possible Arepacoin command-line options. + + + &Show + + + false + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + &Console + + + + 3 + + + + + + 0 + 100 + + + + true + + + false + + + 2 + + + + + + + 3 + + + + + > + + + + + + + + + + + 24 + 24 + + + + Clear console + + + + + + + :/icons/remove:/icons/remove + + + Ctrl+L + + + false + + + + + + + + + + &Network Traffic + + + + + + + + + 0 + 0 + + + + + + + + + + 1 + + + 288 + + + 12 + + + 6 + + + Qt::Horizontal + + + + + + + + 100 + 0 + + + + Qt::AlignCenter + + + + + + + &Clear + + + + + + + + + + + + + Totals + + + + + + + + + 0 + 0 + + + + + 10 + 0 + + + + + + + + + 0 + 255 + 0 + + + + + + + + + 0 + 255 + 0 + + + + + + + + + 0 + 255 + 0 + + + + + + + + Qt::Horizontal + + + + + + + In: + + + + + + + + 50 + 0 + + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + + + + + 0 + 0 + + + + + 10 + 0 + + + + + + + + + 255 + 0 + 0 + + + + + + + + + 255 + 0 + 0 + + + + + + + + + 255 + 0 + 0 + + + + + + + + Qt::Horizontal + + + + + + + Out: + + + + + + + + 50 + 0 + + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + + Qt::Vertical + + + + 20 + 407 + + + + + + + + + + + + + + + + + + TrafficGraphWidget + QWidget +
trafficgraphwidget.h
+ 1 + + clear() + +
+
+ + + + +
diff --git a/src/qt/forms/sendcoinsdialog.ui b/src/qt/forms/sendcoinsdialog.ui new file mode 100755 index 0000000..26f8fd7 --- /dev/null +++ b/src/qt/forms/sendcoinsdialog.ui @@ -0,0 +1,788 @@ + + + SendCoinsDialog + + + + 0 + 0 + 850 + 400 + + + + Send Coins + + + + 8 + + + + + + 0 + 0 + + + + + 16777215 + 16777215 + + + + QFrame::StyledPanel + + + QFrame::Sunken + + + + -1 + + + 0 + + + 0 + + + 0 + + + 6 + + + + + 0 + + + 10 + + + 10 + + + + + 15 + + + + + + 0 + 0 + + + + + 75 + true + + + + font-weight:bold; + + + Coin Control Features + + + + + + + + + 8 + + + 10 + + + + + + + + Inputs... + + + + + + + automatically selected + + + 5 + + + + + + + + 75 + true + + + + color:red;font-weight:bold; + + + Insufficient funds! + + + 5 + + + + + + + Qt::Horizontal + + + + 40 + 1 + + + + + + + + + + + 0 + 0 + + + + + 0 + 0 + + + + + + + + 0 + + + + + 20 + + + 0 + + + 10 + + + + + 10 + + + 14 + + + 10 + + + 4 + + + 6 + + + + + font-weight:bold; + + + Quantity: + + + 0 + + + + + + + + Monospace + 10 + + + + IBeamCursor + + + Qt::ActionsContextMenu + + + 0 + + + 0 + + + Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse + + + + + + + font-weight:bold; + + + Bytes: + + + + + + + + Monospace + 10 + + + + IBeamCursor + + + Qt::ActionsContextMenu + + + 0 + + + Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse + + + + + + + + + 10 + + + 14 + + + 6 + + + 4 + + + 6 + + + + + font-weight:bold; + + + Amount: + + + 0 + + + + + + + + Monospace + 10 + + + + IBeamCursor + + + Qt::ActionsContextMenu + + + 0.00 AREPA + + + Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse + + + + + + + font-weight:bold; + + + Priority: + + + + + + + + Monospace + 10 + + + + IBeamCursor + + + Qt::ActionsContextMenu + + + medium + + + Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse + + + + + + + + + 10 + + + 14 + + + 6 + + + 4 + + + 6 + + + + + font-weight:bold; + + + Fee: + + + 0 + + + + + + + + Monospace + 10 + + + + IBeamCursor + + + Qt::ActionsContextMenu + + + 0.00 AREPA + + + Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse + + + + + + + font-weight:bold; + + + Low Output: + + + + + + + + Monospace + 10 + + + + IBeamCursor + + + Qt::ActionsContextMenu + + + no + + + Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse + + + + + + + + + 10 + + + 14 + + + 6 + + + 4 + + + 6 + + + + + font-weight:bold; + + + After Fee: + + + 0 + + + + + + + + Monospace + 10 + + + + IBeamCursor + + + Qt::ActionsContextMenu + + + 0.00 AREPA + + + Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse + + + + + + + font-weight:bold; + + + Change + + + + + + + + Monospace + 10 + + + + IBeamCursor + + + Qt::ActionsContextMenu + + + 0.00 AREPA + + + Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse + + + + + + + + + + + + + + 12 + + + QLayout::SetDefaultConstraint + + + 5 + + + 5 + + + + + custom change address + + + + + + + false + + + + 0 + 0 + + + + + + + + + 0 + 0 + + + + + 0 + 0 + + + + + + + 3 + + + + + + + + + Qt::Vertical + + + + 800 + 1 + + + + + + + + + + + + + true + + + + + 0 + 0 + 830 + 165 + + + + + 0 + + + + + 6 + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + + + + Send to multiple recipients at once + + + Add &Recipient + + + + :/icons/add:/icons/add + + + false + + + + + + + + 0 + 0 + + + + Remove all transaction fields + + + Clear &All + + + + :/icons/remove:/icons/remove + + + 300 + + + false + + + + + + + 3 + + + + + + 0 + 0 + + + + Balance: + + + + + + + + 0 + 0 + + + + IBeamCursor + + + 123.456 AREPA + + + Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 150 + 0 + + + + Confirm the send action + + + S&end + + + + :/icons/send:/icons/send + + + true + + + + + + + + + + + + diff --git a/src/qt/forms/sendcoinsentry.ui b/src/qt/forms/sendcoinsentry.ui new file mode 100755 index 0000000..24408ae --- /dev/null +++ b/src/qt/forms/sendcoinsentry.ui @@ -0,0 +1,169 @@ + + + SendCoinsEntry + + + + 0 + 0 + 729 + 136 + + + + Form + + + QFrame::StyledPanel + + + QFrame::Sunken + + + + 12 + + + + + A&mount: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + payAmount + + + + + + + Pay &To: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + payTo + + + + + + + + + + 0 + + + + + true + + + Enter a label for this address to add it to your address book + + + + + + + + + &Label: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + addAsLabel + + + + + + + 0 + + + + + The address to send the payment to (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + 34 + + + + + + + Choose address from address book + + + + + + + :/icons/address-book:/icons/address-book + + + Alt+A + + + + + + + Paste address from clipboard + + + + + + + :/icons/editpaste:/icons/editpaste + + + Alt+P + + + + + + + Remove this recipient + + + + + + + :/icons/remove:/icons/remove + + + + + + + + + + QValidatedLineEdit + QLineEdit +
qvalidatedlineedit.h
+
+ + BitcoinAmountField + QLineEdit +
bitcoinamountfield.h
+ 1 +
+
+ + + + +
diff --git a/src/qt/forms/signverifymessagedialog.ui b/src/qt/forms/signverifymessagedialog.ui new file mode 100755 index 0000000..a122a12 --- /dev/null +++ b/src/qt/forms/signverifymessagedialog.ui @@ -0,0 +1,386 @@ + + + SignVerifyMessageDialog + + + + 0 + 0 + 700 + 380 + + + + Signatures - Sign / Verify a Message + + + true + + + + + + 1 + + + + &Sign Message + + + + + + You can sign messages with your addresses to prove you own them. Be careful not to sign anything vague, as phishing attacks may try to trick you into signing your identity over to them. Only sign fully-detailed statements you agree to. + + + Qt::PlainText + + + true + + + + + + + 0 + + + + + The address to sign the message with (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + 34 + + + + + + + Choose an address from the address book + + + + + + + :/icons/address-book:/icons/address-book + + + Alt+A + + + false + + + + + + + Paste address from clipboard + + + + + + + :/icons/editpaste:/icons/editpaste + + + Alt+P + + + false + + + + + + + + + Enter the message you want to sign here + + + + + + + 0 + + + + + + true + + + + true + + + + + + + Copy the current signature to the system clipboard + + + + + + + :/icons/editcopy:/icons/editcopy + + + false + + + + + + + + + + + Sign the message to prove you own this Arepacoin address + + + &Sign Message + + + + :/icons/edit:/icons/edit + + + false + + + + + + + Reset all sign message fields + + + Clear &All + + + + :/icons/remove:/icons/remove + + + false + + + + + + + Qt::Horizontal + + + + 40 + 48 + + + + + + + + + 75 + true + + + + + + + true + + + + + + + Qt::Horizontal + + + + 40 + 48 + + + + + + + + + + + &Verify Message + + + + + + Enter the signing address, message (ensure you copy line breaks, spaces, tabs, etc. exactly) and signature below to verify the message. Be careful not to read more into the signature than what is in the signed message itself, to avoid being tricked by a man-in-the-middle attack. + + + Qt::PlainText + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop + + + true + + + + + + + 0 + + + + + The address the message was signed with (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + 34 + + + + + + + Choose an address from the address book + + + + + + + :/icons/address-book:/icons/address-book + + + Alt+A + + + false + + + + + + + + + + + + + + + + + Verify the message to ensure it was signed with the specified Arepacoin address + + + &Verify Message + + + + :/icons/transaction_0:/icons/transaction_0 + + + false + + + + + + + Reset all verify message fields + + + Clear &All + + + + :/icons/remove:/icons/remove + + + false + + + + + + + Qt::Horizontal + + + + 40 + 48 + + + + + + + + + 75 + true + + + + + + + true + + + + + + + Qt::Horizontal + + + + 40 + 48 + + + + + + + + + + + + + + + QValidatedLineEdit + QLineEdit +
qvalidatedlineedit.h
+
+
+ + + + +
diff --git a/src/qt/forms/transactiondescdialog.ui b/src/qt/forms/transactiondescdialog.ui new file mode 100755 index 0000000..b38dffc --- /dev/null +++ b/src/qt/forms/transactiondescdialog.ui @@ -0,0 +1,74 @@ + + + TransactionDescDialog + + + + 0 + 0 + 620 + 250 + + + + Transaction details + + + + + + This pane shows a detailed description of the transaction + + + true + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Close + + + + + + + + + buttonBox + accepted() + TransactionDescDialog + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + TransactionDescDialog + reject() + + + 316 + 260 + + + 286 + 274 + + + + + diff --git a/src/qt/guiconstants.h b/src/qt/guiconstants.h new file mode 100755 index 0000000..11e3c32 --- /dev/null +++ b/src/qt/guiconstants.h @@ -0,0 +1,37 @@ +#ifndef GUICONSTANTS_H +#define GUICONSTANTS_H + +/* Milliseconds between model updates */ +static const int MODEL_UPDATE_DELAY = 250; + +/* AskPassphraseDialog -- Maximum passphrase length */ +static const int MAX_PASSPHRASE_SIZE = 1024; + +/* BitcoinGUI -- Size of icons in status bar */ +static const int STATUSBAR_ICONSIZE = 16; + +/* Invalid field background style */ +#define STYLE_INVALID "background:#FF8080" + +/* Transaction list -- unconfirmed transaction */ +#define COLOR_UNCONFIRMED QColor(128, 128, 128) +/* Transaction list -- negative amount */ +#define COLOR_NEGATIVE QColor(255, 0, 0) +/* Transaction list -- bare address (without label) */ +#define COLOR_BAREADDRESS QColor(140, 140, 140) + +/* Tooltips longer than this (in characters) are converted into rich text, + so that they can be word-wrapped. + */ +static const int TOOLTIP_WRAP_THRESHOLD = 80; + +/* Maximum allowed URI length */ +static const int MAX_URI_LENGTH = 255; + +/* QRCodeDialog -- size of exported QR Code image */ +#define EXPORT_IMAGE_SIZE 256 + +/* Number of frames in spinner animation */ +#define SPINNER_FRAMES 35 + +#endif // GUICONSTANTS_H diff --git a/src/qt/guiutil.cpp b/src/qt/guiutil.cpp new file mode 100755 index 0000000..61f4476 --- /dev/null +++ b/src/qt/guiutil.cpp @@ -0,0 +1,497 @@ +#include "guiutil.h" +#include "bitcoinaddressvalidator.h" +#include "walletmodel.h" +#include "bitcoinunits.h" +#include "util.h" +#include "init.h" + +#include +#include +#include +#include +#include +#include +#include // For Qt::escape +#include +#include +#include +#include +#include +#include + +#include +#include + +#ifdef WIN32 +#ifdef _WIN32_WINNT +#undef _WIN32_WINNT +#endif +#define _WIN32_WINNT 0x0501 +#ifdef _WIN32_IE +#undef _WIN32_IE +#endif +#define _WIN32_IE 0x0501 +#define WIN32_LEAN_AND_MEAN 1 +#ifndef NOMINMAX +#define NOMINMAX +#endif +#include "shlwapi.h" +#include "shlobj.h" +#include "shellapi.h" +#endif + +namespace GUIUtil { + +QString dateTimeStr(const QDateTime &date) +{ + return date.date().toString(Qt::SystemLocaleShortDate) + QString(" ") + date.toString("hh:mm"); +} + +QString dateTimeStr(qint64 nTime) +{ + return dateTimeStr(QDateTime::fromTime_t((qint32)nTime)); +} + +QFont bitcoinAddressFont() +{ + QFont font("Monospace"); +#if QT_VERSION >= 0x040800 + font.setStyleHint(QFont::Monospace); +#else + font.setStyleHint(QFont::TypeWriter); +#endif + return font; +} + +void setupAddressWidget(QLineEdit *widget, QWidget *parent) +{ + widget->setMaxLength(BitcoinAddressValidator::MaxAddressLength); + widget->setValidator(new BitcoinAddressValidator(parent)); + widget->setFont(bitcoinAddressFont()); +} + +void setupAmountWidget(QLineEdit *widget, QWidget *parent) +{ + QDoubleValidator *amountValidator = new QDoubleValidator(parent); + amountValidator->setDecimals(8); + amountValidator->setBottom(0.0); + widget->setValidator(amountValidator); + widget->setAlignment(Qt::AlignRight|Qt::AlignVCenter); +} + +bool parseBitcoinURI(const QUrl &uri, SendCoinsRecipient *out) +{ + // NovaCoin: check prefix + if(uri.scheme() != QString("arepacoin")) + return false; + + SendCoinsRecipient rv; + rv.address = uri.path(); + rv.amount = 0; + QList > items = uri.queryItems(); + for (QList >::iterator i = items.begin(); i != items.end(); i++) + { + bool fShouldReturnFalse = false; + if (i->first.startsWith("req-")) + { + i->first.remove(0, 4); + fShouldReturnFalse = true; + } + + if (i->first == "label") + { + rv.label = i->second; + fShouldReturnFalse = false; + } + else if (i->first == "amount") + { + if(!i->second.isEmpty()) + { + if(!BitcoinUnits::parse(BitcoinUnits::BTC, i->second, &rv.amount)) + { + return false; + } + } + fShouldReturnFalse = false; + } + + if (fShouldReturnFalse) + return false; + } + if(out) + { + *out = rv; + } + return true; +} + +bool parseBitcoinURI(QString uri, SendCoinsRecipient *out) +{ + // Convert arepacoin:// to arepacoin: + // + // Cannot handle this later, because bitcoin:// will cause Qt to see the part after // as host, + // which will lower-case it (and thus invalidate the address). + if(uri.startsWith("arepacoin://")) + { + uri.replace(0, 12, "arepacoin:"); + } + QUrl uriInstance(uri); + return parseBitcoinURI(uriInstance, out); +} + +QString HtmlEscape(const QString& str, bool fMultiLine) +{ + QString escaped = Qt::escape(str); + if(fMultiLine) + { + escaped = escaped.replace("\n", "
\n"); + } + return escaped; +} + +QString HtmlEscape(const std::string& str, bool fMultiLine) +{ + return HtmlEscape(QString::fromStdString(str), fMultiLine); +} + +void copyEntryData(QAbstractItemView *view, int column, int role) +{ + if(!view || !view->selectionModel()) + return; + QModelIndexList selection = view->selectionModel()->selectedRows(column); + + if(!selection.isEmpty()) + { + // Copy first item + QApplication::clipboard()->setText(selection.at(0).data(role).toString()); + } +} + +QString getSaveFileName(QWidget *parent, const QString &caption, + const QString &dir, + const QString &filter, + QString *selectedSuffixOut) +{ + QString selectedFilter; + QString myDir; + if(dir.isEmpty()) // Default to user documents location + { + myDir = QDesktopServices::storageLocation(QDesktopServices::DocumentsLocation); + } + else + { + myDir = dir; + } + QString result = QFileDialog::getSaveFileName(parent, caption, myDir, filter, &selectedFilter); + + /* Extract first suffix from filter pattern "Description (*.foo)" or "Description (*.foo *.bar ...) */ + QRegExp filter_re(".* \\(\\*\\.(.*)[ \\)]"); + QString selectedSuffix; + if(filter_re.exactMatch(selectedFilter)) + { + selectedSuffix = filter_re.cap(1); + } + + /* Add suffix if needed */ + QFileInfo info(result); + if(!result.isEmpty()) + { + if(info.suffix().isEmpty() && !selectedSuffix.isEmpty()) + { + /* No suffix specified, add selected suffix */ + if(!result.endsWith(".")) + result.append("."); + result.append(selectedSuffix); + } + } + + /* Return selected suffix if asked to */ + if(selectedSuffixOut) + { + *selectedSuffixOut = selectedSuffix; + } + return result; +} + +Qt::ConnectionType blockingGUIThreadConnection() +{ + if(QThread::currentThread() != QCoreApplication::instance()->thread()) + { + return Qt::BlockingQueuedConnection; + } + else + { + return Qt::DirectConnection; + } +} + +bool checkPoint(const QPoint &p, const QWidget *w) +{ + QWidget *atW = qApp->widgetAt(w->mapToGlobal(p)); + if (!atW) return false; + return atW->topLevelWidget() == w; +} + +bool isObscured(QWidget *w) +{ + return !(checkPoint(QPoint(0, 0), w) + && checkPoint(QPoint(w->width() - 1, 0), w) + && checkPoint(QPoint(0, w->height() - 1), w) + && checkPoint(QPoint(w->width() - 1, w->height() - 1), w) + && checkPoint(QPoint(w->width() / 2, w->height() / 2), w)); +} + +void openDebugLogfile() +{ + boost::filesystem::path pathDebug = GetDataDir() / "debug.log"; + + /* Open debug.log with the associated application */ + if (boost::filesystem::exists(pathDebug)) + QDesktopServices::openUrl(QUrl::fromLocalFile(QString::fromStdString(pathDebug.string()))); +} + +ToolTipToRichTextFilter::ToolTipToRichTextFilter(int size_threshold, QObject *parent) : + QObject(parent), size_threshold(size_threshold) +{ + +} + +bool ToolTipToRichTextFilter::eventFilter(QObject *obj, QEvent *evt) +{ + if(evt->type() == QEvent::ToolTipChange) + { + QWidget *widget = static_cast(obj); + QString tooltip = widget->toolTip(); + if(tooltip.size() > size_threshold && !tooltip.startsWith("") && !Qt::mightBeRichText(tooltip)) + { + // Prefix to make sure Qt detects this as rich text + // Escape the current message as HTML and replace \n by
+ tooltip = "" + HtmlEscape(tooltip, true) + ""; + widget->setToolTip(tooltip); + return true; + } + } + return QObject::eventFilter(obj, evt); +} + +#ifdef WIN32 +boost::filesystem::path static StartupShortcutPath() +{ + return GetSpecialFolderPath(CSIDL_STARTUP) / "Arepacoin.lnk"; +} + +bool GetStartOnSystemStartup() +{ + // check for Bitcoin.lnk + return boost::filesystem::exists(StartupShortcutPath()); +} + +bool SetStartOnSystemStartup(bool fAutoStart) +{ + // If the shortcut exists already, remove it for updating + boost::filesystem::remove(StartupShortcutPath()); + + if (fAutoStart) + { + CoInitialize(NULL); + + // Get a pointer to the IShellLink interface. + IShellLink* psl = NULL; + HRESULT hres = CoCreateInstance(CLSID_ShellLink, NULL, + CLSCTX_INPROC_SERVER, IID_IShellLink, + reinterpret_cast(&psl)); + + if (SUCCEEDED(hres)) + { + // Get the current executable path + TCHAR pszExePath[MAX_PATH]; + GetModuleFileName(NULL, pszExePath, sizeof(pszExePath)); + + TCHAR pszArgs[5] = TEXT("-min"); + + // Set the path to the shortcut target + psl->SetPath(pszExePath); + PathRemoveFileSpec(pszExePath); + psl->SetWorkingDirectory(pszExePath); + psl->SetShowCmd(SW_SHOWMINNOACTIVE); + psl->SetArguments(pszArgs); + + // Query IShellLink for the IPersistFile interface for + // saving the shortcut in persistent storage. + IPersistFile* ppf = NULL; + hres = psl->QueryInterface(IID_IPersistFile, + reinterpret_cast(&ppf)); + if (SUCCEEDED(hres)) + { + WCHAR pwsz[MAX_PATH]; + // Ensure that the string is ANSI. + MultiByteToWideChar(CP_ACP, 0, StartupShortcutPath().string().c_str(), -1, pwsz, MAX_PATH); + // Save the link by calling IPersistFile::Save. + hres = ppf->Save(pwsz, TRUE); + ppf->Release(); + psl->Release(); + CoUninitialize(); + return true; + } + psl->Release(); + } + CoUninitialize(); + return false; + } + return true; +} + +#elif defined(Q_OS_LINUX) + +// Follow the Desktop Application Autostart Spec: +// http://standards.freedesktop.org/autostart-spec/autostart-spec-latest.html + +boost::filesystem::path static GetAutostartDir() +{ + namespace fs = boost::filesystem; + + char* pszConfigHome = getenv("XDG_CONFIG_HOME"); + if (pszConfigHome) return fs::path(pszConfigHome) / "autostart"; + char* pszHome = getenv("HOME"); + if (pszHome) return fs::path(pszHome) / ".config" / "autostart"; + return fs::path(); +} + +boost::filesystem::path static GetAutostartFilePath() +{ + return GetAutostartDir() / "arepacoin.desktop"; +} + +bool GetStartOnSystemStartup() +{ + boost::filesystem::ifstream optionFile(GetAutostartFilePath()); + if (!optionFile.good()) + return false; + // Scan through file for "Hidden=true": + std::string line; + while (!optionFile.eof()) + { + getline(optionFile, line); + if (line.find("Hidden") != std::string::npos && + line.find("true") != std::string::npos) + return false; + } + optionFile.close(); + + return true; +} + +bool SetStartOnSystemStartup(bool fAutoStart) +{ + if (!fAutoStart) + boost::filesystem::remove(GetAutostartFilePath()); + else + { + char pszExePath[MAX_PATH+1]; + memset(pszExePath, 0, sizeof(pszExePath)); + if (readlink("/proc/self/exe", pszExePath, sizeof(pszExePath)-1) == -1) + return false; + + boost::filesystem::create_directories(GetAutostartDir()); + + boost::filesystem::ofstream optionFile(GetAutostartFilePath(), std::ios_base::out|std::ios_base::trunc); + if (!optionFile.good()) + return false; + // Write a bitcoin.desktop file to the autostart directory: + optionFile << "[Desktop Entry]\n"; + optionFile << "Type=Application\n"; + optionFile << "Name=Arepacoin\n"; + optionFile << "Exec=" << pszExePath << " -min\n"; + optionFile << "Terminal=false\n"; + optionFile << "Hidden=false\n"; + optionFile.close(); + } + return true; +} +#else + +// TODO: OSX startup stuff; see: +// https://developer.apple.com/library/mac/#documentation/MacOSX/Conceptual/BPSystemStartup/Articles/CustomLogin.html + +bool GetStartOnSystemStartup() { return false; } +bool SetStartOnSystemStartup(bool fAutoStart) { return false; } + +#endif + +HelpMessageBox::HelpMessageBox(QWidget *parent) : + QMessageBox(parent) +{ + header = tr("Arepacoin-Qt") + " " + tr("version") + " " + + QString::fromStdString(FormatFullVersion()) + "\n\n" + + tr("Usage:") + "\n" + + " arepacoin-qt [" + tr("command-line options") + "] " + "\n"; + + coreOptions = QString::fromStdString(HelpMessage()); + + uiOptions = tr("UI options") + ":\n" + + " -lang= " + tr("Set language, for example \"de_DE\" (default: system locale)") + "\n" + + " -min " + tr("Start minimized") + "\n" + + " -splash " + tr("Show splash screen on startup (default: 1)") + "\n"; + + setWindowTitle(tr("Arepacoin-Qt")); + setTextFormat(Qt::PlainText); + // setMinimumWidth is ignored for QMessageBox so put in non-breaking spaces to make it wider. + setText(header + QString(QChar(0x2003)).repeated(50)); + setDetailedText(coreOptions + "\n" + uiOptions); +} + +void HelpMessageBox::printToConsole() +{ + // On other operating systems, the expected action is to print the message to the console. + QString strUsage = header + "\n" + coreOptions + "\n" + uiOptions; + fprintf(stdout, "%s", strUsage.toStdString().c_str()); +} + +void HelpMessageBox::showOrPrint() +{ +#if defined(WIN32) + // On Windows, show a message box, as there is no stderr/stdout in windowed applications + exec(); +#else + // On other operating systems, print help text to console + printToConsole(); +#endif +} + +void SetBlackThemeQSS(QApplication& app) +{ + app.setStyleSheet("QWidget { background: rgb(255,255,255); }" + "QFrame { border: none; }" + "QComboBox { color: rgb(28,28,28); }" + "QComboBox QAbstractItemView::item { color: rgb(28,28,28); }" + "QPushButton { background: rgb(255,253,231); color: rgb(28,28,28); }" + "QDoubleSpinBox { background: rgb(255,255,255); color: rgb(28,28,28); border-color: rgb(251,192,45); }" + "QLineEdit { background: rgb(255,255,255); color: rgb(28,28,28); border-color: rgb(251,192,45); }" + "QTextEdit { background: rgb(255,255,255); color: rgb(28,28,28); }" + "QPlainTextEdit { background: rgb(255,255,255); color: rgb(28,28,28); }" + "QMenuBar { background: rgb(41,44,48); color: rgb(28,28,28); }" + "QMenu { background: rgb(255,255,255); color: rgb(28,28,28); }" + "QMenuBar::item { background-color: rgb(41,44,48); color: rgb(255,245,157);}" + "QMenu::item:selected { background-color: rgb(251,192,45); }" + "QMenuBar::item:selected { background-color: rgb(41,44,48); }" + "QLabel { color: rgb(28,28,28); }" + "QScrollBar { color: rgb(255,245,157); }" + "QCheckBox { color: rgb(28,28,28); }" + "QRadioButton { color: rgb(28,28,28); }" + "QTabBar::tab { color: rgb(28,28,28); border: 1px solid rgb(78,79,83); border-bottom: none; padding: 5px; }" + "QTabBar::tab:selected { background: rgb(255,255,255); }" + "QTabBar::tab:!selected { background: rgb(255,255,255); margin-top: 2px; }" + "QTabWidget::pane { border: 1px solid rgb(78,79,83); }" + "QToolButton { background: rgb(255,255,255); color: rgb(28,28,28); border: none; border-left-color: rgb(255,245,157); border-left-style: solid; border-left-width: 6px; margin-top: 8px; margin-bottom: 8px; }" + "QToolButton:checked { color: rgb(28,28,28); border: none; border-left-color: rgb(255,235,59); border-left-style: solid; border-left-width: 6px; }" + "QProgressBar { color: rgb(28,28,28); border-color: rgb(255,245,157); border-width: 1px; border-style: solid; }" + "QProgressBar::chunk { background: rgb(255,245,157); }" + "QTreeView::item { background: rgb(255,255,255); color: rgb(28,28,28); }" + "QTreeView::item:selected { background-color: rgb(59,124,220); }" + "QTableView { background: rgb(255,253,231); color: rgb(28,28,28); gridline-color: rgb(157,160,165); }" + "QHeaderView::section { background: rgb(255,235,59); color: rgb(28,28,28); }" + "QToolBar { background: rgb(255,255,255); border: rgb(255,245,157); }"); +} + +} // namespace GUIUtil + diff --git a/src/qt/guiutil.h b/src/qt/guiutil.h new file mode 100755 index 0000000..74b6609 --- /dev/null +++ b/src/qt/guiutil.h @@ -0,0 +1,122 @@ +#ifndef GUIUTIL_H +#define GUIUTIL_H + +#include +#include +#include + +QT_BEGIN_NAMESPACE +class QFont; +class QLineEdit; +class QWidget; +class QDateTime; +class QUrl; +class QAbstractItemView; +QT_END_NAMESPACE +class SendCoinsRecipient; + +/** Utility functions used by the Bitcoin Qt UI. + */ +namespace GUIUtil +{ + // Create human-readable string from date + QString dateTimeStr(const QDateTime &datetime); + QString dateTimeStr(qint64 nTime); + + // Render Bitcoin addresses in monospace font + QFont bitcoinAddressFont(); + + // Set up widgets for address and amounts + void setupAddressWidget(QLineEdit *widget, QWidget *parent); + void setupAmountWidget(QLineEdit *widget, QWidget *parent); + + // Parse "arepacoin:" URI into recipient object, return true on successful parsing + // See Bitcoin URI definition discussion here: https://bitcointalk.org/index.php?topic=33490.0 + bool parseBitcoinURI(const QUrl &uri, SendCoinsRecipient *out); + bool parseBitcoinURI(QString uri, SendCoinsRecipient *out); + + // HTML escaping for rich text controls + QString HtmlEscape(const QString& str, bool fMultiLine=false); + QString HtmlEscape(const std::string& str, bool fMultiLine=false); + + /** Copy a field of the currently selected entry of a view to the clipboard. Does nothing if nothing + is selected. + @param[in] column Data column to extract from the model + @param[in] role Data role to extract from the model + @see TransactionView::copyLabel, TransactionView::copyAmount, TransactionView::copyAddress + */ + void copyEntryData(QAbstractItemView *view, int column, int role=Qt::EditRole); + + /** Get save filename, mimics QFileDialog::getSaveFileName, except that it appends a default suffix + when no suffix is provided by the user. + + @param[in] parent Parent window (or 0) + @param[in] caption Window caption (or empty, for default) + @param[in] dir Starting directory (or empty, to default to documents directory) + @param[in] filter Filter specification such as "Comma Separated Files (*.csv)" + @param[out] selectedSuffixOut Pointer to return the suffix (file type) that was selected (or 0). + Can be useful when choosing the save file format based on suffix. + */ + QString getSaveFileName(QWidget *parent=0, const QString &caption=QString(), + const QString &dir=QString(), const QString &filter=QString(), + QString *selectedSuffixOut=0); + + /** Get connection type to call object slot in GUI thread with invokeMethod. The call will be blocking. + + @returns If called from the GUI thread, return a Qt::DirectConnection. + If called from another thread, return a Qt::BlockingQueuedConnection. + */ + Qt::ConnectionType blockingGUIThreadConnection(); + + // Determine whether a widget is hidden behind other windows + bool isObscured(QWidget *w); + + // Open debug.log + void openDebugLogfile(); + + /** Qt event filter that intercepts ToolTipChange events, and replaces the tooltip with a rich text + representation if needed. This assures that Qt can word-wrap long tooltip messages. + Tooltips longer than the provided size threshold (in characters) are wrapped. + */ + class ToolTipToRichTextFilter : public QObject + { + Q_OBJECT + + public: + explicit ToolTipToRichTextFilter(int size_threshold, QObject *parent = 0); + + protected: + bool eventFilter(QObject *obj, QEvent *evt); + + private: + int size_threshold; + }; + + bool GetStartOnSystemStartup(); + bool SetStartOnSystemStartup(bool fAutoStart); + + /** Help message for Bitcoin-Qt, shown with --help. */ + class HelpMessageBox : public QMessageBox + { + Q_OBJECT + + public: + HelpMessageBox(QWidget *parent = 0); + + /** Show message box or print help message to standard output, based on operating system. */ + void showOrPrint(); + + /** Print help message to console */ + void printToConsole(); + + private: + QString header; + QString coreOptions; + QString uiOptions; + }; + + void SetBlackThemeQSS(QApplication& app); + +} // namespace GUIUtil + +#endif // GUIUTIL_H diff --git a/src/qt/locale/bitcoin_af_ZA.ts b/src/qt/locale/bitcoin_af_ZA.ts new file mode 100755 index 0000000..dac3db1 --- /dev/null +++ b/src/qt/locale/bitcoin_af_ZA.ts @@ -0,0 +1,3275 @@ + + + AboutDialog + + + About Arepacoin + + + + + <b>Arepacoin</b> version + + + + + Copyright © 2009-2014 The Bitcoin developers +Copyright © 2012-2014 The NovaCoin developers +Copyright © 2014 The Arepacoin developers + + + + + +This is experimental software. + +Distributed under the MIT/X11 software license, see the accompanying file COPYING or http://www.opensource.org/licenses/mit-license.php. + +This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit (http://www.openssl.org/) and cryptographic software written by Eric Young (eay@cryptsoft.com) and UPnP software written by Thomas Bernard. + + + + + AddressBookPage + + + Address Book + + + + + Double-click to edit address or label + Dubbel-klik om die adres of etiket te wysig + + + + Create a new address + Skep 'n nuwe adres + + + + Copy the currently selected address to the system clipboard + Maak 'n kopie van die huidige adres na die stelsel klipbord + + + + &New Address + + + + + These are your Arepacoin addresses for receiving payments. You may want to give a different one to each sender so you can keep track of who is paying you. + + + + + &Copy Address + + + + + Show &QR Code + + + + + Sign a message to prove you own a Arepacoin address + + + + + Sign &Message + + + + + Delete the currently selected address from the list + + + + + Verify a message to ensure it was signed with a specified Arepacoin address + + + + + &Verify Message + + + + + &Delete + &Verwyder + + + + Copy &Label + + + + + &Edit + + + + + Export Address Book Data + + + + + Comma separated file (*.csv) + + + + + Error exporting + + + + + Could not write to file %1. + + + + + AddressTableModel + + + Label + Etiket + + + + Address + Adres + + + + (no label) + (geen etiket) + + + + AskPassphraseDialog + + + Passphrase Dialog + + + + + Enter passphrase + Tik Wagwoord in + + + + New passphrase + Nuwe wagwoord + + + + Repeat new passphrase + Herhaal nuwe wagwoord + + + + Serves to disable the trivial sendmoney when OS account compromised. Provides no real security. + + + + + For staking only + + + + + Enter the new passphrase to the wallet.<br/>Please use a passphrase of <b>10 or more random characters</b>, or <b>eight or more words</b>. + Tik die nuwe wagwoord vir die beursie in.<br/>Gebruik asseblief 'n wagwoord van <b>ten minste 10 ewekansige karakters</b>, of <b>agt (8) of meer woorde.</b> + + + + Encrypt wallet + Enkripteer beursie + + + + This operation needs your wallet passphrase to unlock the wallet. + Hierdie operasie benodig 'n wagwoord om die beursie oop te sluit. + + + + Unlock wallet + Sluit beursie oop + + + + This operation needs your wallet passphrase to decrypt the wallet. + Hierdie operasie benodig 'n wagwoord om die beursie oop te sluit. + + + + Decrypt wallet + Sluit beursie oop + + + + Change passphrase + Verander wagwoord + + + + Enter the old and new passphrase to the wallet. + Tik asseblief die ou en nuwe wagwoord vir die beursie in. + + + + Confirm wallet encryption + Bevestig beursie enkripsie. + + + + Warning: If you encrypt your wallet and lose your passphrase, you will <b>LOSE ALL OF YOUR COINS</b>! + + + + + Are you sure you wish to encrypt your wallet? + + + + + IMPORTANT: Any previous backups you have made of your wallet file should be replaced with the newly generated, encrypted wallet file. For security reasons, previous backups of the unencrypted wallet file will become useless as soon as you start using the new, encrypted wallet. + + + + + + Warning: The Caps Lock key is on! + + + + + + Wallet encrypted + Die beursie is nou bewaak + + + + Arepacoin will close now to finish the encryption process. Remember that encrypting your wallet cannot fully protect your coins from being stolen by malware infecting your computer. + + + + + + + + Wallet encryption failed + Die beursie kon nie bewaak word nie + + + + Wallet encryption failed due to an internal error. Your wallet was not encrypted. + Beursie bewaaking het misluk as gevolg van 'n interne fout. Die beursie is nie bewaak nie! + + + + + The supplied passphrases do not match. + Die wagwoord stem nie ooreen nie + + + + Wallet unlock failed + Beursie oopsluiting het misluk + + + + + + The passphrase entered for the wallet decryption was incorrect. + Die wagwoord wat ingetik was om die beursie oop te sluit, was verkeerd. + + + + Wallet decryption failed + Beursie dekripsie het misluk + + + + Wallet passphrase was successfully changed. + + + + + BitcoinGUI + + + Sign &message... + + + + + Synchronizing with network... + Sinchroniseer met die netwerk ... + + + + &Overview + &Oorsig + + + + Show general overview of wallet + Wys algemene oorsig van die beursie + + + + &Transactions + &Transaksies + + + + Browse transaction history + Besoek transaksie geskiedenis + + + + &Address Book + + + + + Edit the list of stored addresses and labels + + + + + &Receive coins + + + + + Show the list of addresses for receiving payments + + + + + &Send coins + + + + + E&xit + S&luit af + + + + Quit application + Sluit af + + + + Show information about Arepacoin + + + + + About &Qt + + + + + Show information about Qt + Wys inligting oor Qt + + + + &Options... + &Opsies + + + + &Encrypt Wallet... + + + + + &Backup Wallet... + + + + + &Change Passphrase... + + + + + ~%n block(s) remaining + + + + + Downloaded %1 of %2 blocks of transaction history (%3% done). + + + + + &Export... + + + + + Send coins to a Arepacoin address + + + + + Modify configuration options for Arepacoin + + + + + Export the data in the current tab to a file + + + + + Encrypt or decrypt wallet + + + + + Backup wallet to another location + + + + + Change the passphrase used for wallet encryption + + + + + &Debug window + + + + + Open debugging and diagnostic console + + + + + &Verify message... + + + + + Arepacoin + + + + + Wallet + Beursie + + + + &About Arepacoin + + + + + &Show / Hide + + + + + Unlock wallet + + + + + &Lock Wallet + + + + + Lock wallet + + + + + &File + &Lêer + + + + &Settings + &Instellings + + + + &Help + &Hulp + + + + Tabs toolbar + Blad nutsbalk + + + + Actions toolbar + + + + + + [testnet] + + + + + + Arepacoin client + + + + + %n active connection(s) to Arepacoin network + + + + + Downloaded %1 blocks of transaction history. + + + + + Staking.<br>Your weight is %1<br>Network weight is %2<br>Expected time to earn reward is %3 + + + + + Not staking because wallet is locked + + + + + Not staking because wallet is offline + + + + + Not staking because wallet is syncing + + + + + Not staking because you don't have mature coins + + + + + %n second(s) ago + + + + + &Unlock Wallet... + + + + + %n minute(s) ago + + + + + %n hour(s) ago + + + + + %n day(s) ago + + + + + Up to date + + + + + Catching up... + + + + + Last received block was generated %1. + + + + + This transaction is over the size limit. You can still send it for a fee of %1, which goes to the nodes that process your transaction and helps to support the network. Do you want to pay the fee? + + + + + Confirm transaction fee + + + + + Sent transaction + + + + + Incoming transaction + + + + + Date: %1 +Amount: %2 +Type: %3 +Address: %4 + + + + + + + URI handling + + + + + + URI can not be parsed! This can be caused by an invalid Arepacoin address or malformed URI parameters. + + + + + Wallet is <b>encrypted</b> and currently <b>unlocked</b> + + + + + Wallet is <b>encrypted</b> and currently <b>locked</b> + + + + + Backup Wallet + + + + + Wallet Data (*.dat) + + + + + Backup Failed + + + + + There was an error trying to save the wallet data to the new location. + + + + + %n second(s) + + + + + %n minute(s) + + + + + %n hour(s) + + + + + %n day(s) + + + + + Not staking + + + + + A fatal error occurred. Arepacoin can no longer continue safely and will quit. + + + + + ClientModel + + + Network Alert + + + + + CoinControlDialog + + + Coin Control + + + + + Quantity: + + + + + Bytes: + + + + + Amount: + Bedrag: + + + + Priority: + + + + + Fee: + + + + + Low Output: + + + + + no + + + + + After Fee: + + + + + Change: + + + + + (un)select all + + + + + Tree mode + + + + + List mode + + + + + Amount + Bedrag + + + + Label + + + + + Address + Adres + + + + Date + Datum + + + + Confirmations + + + + + Confirmed + + + + + Priority + + + + + Copy address + Maak kopie van adres + + + + Copy label + + + + + + Copy amount + Kopieer bedrag + + + + Copy transaction ID + + + + + Copy quantity + + + + + Copy fee + + + + + Copy after fee + + + + + Copy bytes + + + + + Copy priority + + + + + Copy low output + + + + + Copy change + + + + + highest + + + + + high + + + + + medium-high + + + + + medium + + + + + low-medium + + + + + low + + + + + lowest + + + + + DUST + + + + + yes + + + + + This label turns red, if the transaction size is bigger than 10000 bytes. + + This means a fee of at least %1 per kb is required. + + Can vary +/- 1 Byte per input. + + + + + Transactions with higher priority get more likely into a block. + +This label turns red, if the priority is smaller than "medium". + + This means a fee of at least %1 per kb is required. + + + + + This label turns red, if any recipient receives an amount smaller than %1. + + This means a fee of at least %2 is required. + + Amounts below 0.546 times the minimum relay fee are shown as DUST. + + + + + This label turns red, if the change is smaller than %1. + + This means a fee of at least %2 is required. + + + + + + (no label) + (geen etiket) + + + + change from %1 (%2) + + + + + (change) + + + + + EditAddressDialog + + + Edit Address + + + + + &Label + + + + + The label associated with this address book entry + + + + + &Address + + + + + The address associated with this address book entry. This can only be modified for sending addresses. + + + + + New receiving address + Nuwe ontvangende adres + + + + New sending address + Nuwe stuurende adres + + + + Edit receiving address + Wysig ontvangende adres + + + + Edit sending address + Wysig stuurende adres + + + + The entered address "%1" is already in the address book. + + + + + The entered address "%1" is not a valid Arepacoin address. + + + + + Could not unlock wallet. + Kon nie die beursie oopsluit nie. + + + + New key generation failed. + + + + + GUIUtil::HelpMessageBox + + + + Arepacoin-Qt + + + + + version + + + + + Usage: + + + + + command-line options + + + + + UI options + + + + + Set language, for example "de_DE" (default: system locale) + + + + + Start minimized + + + + + Show splash screen on startup (default: 1) + + + + + OptionsDialog + + + Options + Opsies + + + + &Main + + + + + Optional transaction fee per kB that helps make sure your transactions are processed quickly. Most transactions are 1 kB. Fee 0.01 recommended. + + + + + Pay transaction &fee + + + + + Reserved amount does not participate in staking and is therefore spendable at any time. + + + + + Reserve + + + + + Automatically start Arepacoin after logging in to the system. + + + + + &Start Arepacoin on system login + + + + + Detach block and address databases at shutdown. This means they can be moved to another data directory, but it slows down shutdown. The wallet is always detached. + + + + + &Detach databases at shutdown + + + + + &Network + + + + + Automatically open the Arepacoin client port on the router. This only works when your router supports UPnP and it is enabled. + + + + + Map port using &UPnP + + + + + Connect to the Arepacoin network through a SOCKS proxy (e.g. when connecting through Tor). + + + + + &Connect through SOCKS proxy: + + + + + Proxy &IP: + + + + + IP address of the proxy (e.g. 127.0.0.1) + + + + + &Port: + + + + + Port of the proxy (e.g. 9050) + + + + + SOCKS &Version: + + + + + SOCKS version of the proxy (e.g. 5) + + + + + &Window + + + + + Show only a tray icon after minimizing the window. + + + + + &Minimize to the tray instead of the taskbar + + + + + Minimize instead of exit the application when the window is closed. When this option is enabled, the application will be closed only after selecting Quit in the menu. + + + + + M&inimize on close + + + + + &Display + + + + + User Interface &language: + + + + + The user interface language can be set here. This setting will take effect after restarting Arepacoin. + + + + + &Unit to show amounts in: + + + + + Choose the default subdivision unit to show in the interface and when sending coins. + + + + + Whether to show Arepacoin addresses in the transaction list or not. + + + + + &Display addresses in transaction list + + + + + Whether to show coin control features or not. + + + + + Display coin &control features (experts only!) + + + + + &OK + + + + + &Cancel + + + + + &Apply + + + + + default + + + + + + Warning + + + + + + This setting will take effect after restarting Arepacoin. + + + + + The supplied proxy address is invalid. + + + + + OverviewPage + + + Form + Vorm + + + + + The displayed information may be out of date. Your wallet automatically synchronizes with the Arepacoin network after a connection is established, but this process has not completed yet. + + + + + Stake: + + + + + Unconfirmed: + + + + + Wallet + Beursie + + + + Spendable: + + + + + Your current spendable balance + + + + + Immature: + + + + + Mined balance that has not yet matured + + + + + Total: + + + + + Your current total balance + + + + + <b>Recent transactions</b> + <b>Onlangse transaksies</b> + + + + Total of transactions that have yet to be confirmed, and do not yet count toward the current balance + + + + + Total of coins that was staked, and do not yet count toward the current balance + + + + + + out of sync + + + + + QRCodeDialog + + + QR Code Dialog + + + + + Request Payment + + + + + Amount: + + + + + Label: + + + + + Message: + + + + + &Save As... + + + + + Error encoding URI into QR Code. + + + + + The entered amount is invalid, please check. + + + + + Resulting URI too long, try to reduce the text for label / message. + + + + + Save QR Code + + + + + PNG Images (*.png) + + + + + RPCConsole + + + Client name + + + + + + + + + + + + + + N/A + + + + + Client version + + + + + &Information + + + + + Using OpenSSL version + + + + + Startup time + + + + + Network + + + + + Number of connections + + + + + On testnet + + + + + Block chain + + + + + Current number of blocks + + + + + Estimated total blocks + + + + + Last block time + + + + + &Open + + + + + Command-line options + + + + + Show the Arepacoin-Qt help message to get a list with possible Arepacoin command-line options. + + + + + &Show + + + + + &Console + + + + + Build date + + + + + Arepacoin - Debug window + + + + + Arepacoin Core + + + + + Debug log file + + + + + Open the Arepacoin debug log file from the current data directory. This can take a few seconds for large log files. + + + + + Clear console + + + + + Welcome to the Arepacoin RPC console. + + + + + Use up and down arrows to navigate history, and <b>Ctrl-L</b> to clear screen. + + + + + Type <b>help</b> for an overview of available commands. + + + + + SendCoinsDialog + + + + + + + + + + Send Coins + Stuur Munstukke + + + + Coin Control Features + + + + + Inputs... + + + + + automatically selected + + + + + Insufficient funds! + + + + + Quantity: + + + + + + 0 + + + + + Bytes: + + + + + Amount: + Bedrag: + + + + + + + 0.00 BC + + + + + Priority: + + + + + medium + + + + + Fee: + + + + + Low Output: + + + + + no + + + + + After Fee: + + + + + Change + + + + + custom change address + + + + + Send to multiple recipients at once + Stuur aan vele ontvangers op eens + + + + Add &Recipient + + + + + Remove all transaction fields + + + + + Clear &All + + + + + Balance: + Balans: + + + + 123.456 BC + + + + + Confirm the send action + + + + + S&end + S&tuur + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Copy quantity + + + + + Copy amount + Kopieer bedrag + + + + Copy fee + + + + + Copy after fee + + + + + Copy bytes + + + + + Copy priority + + + + + Copy low output + + + + + Copy change + + + + + <b>%1</b> to %2 (%3) + + + + + Confirm send coins + + + + + Are you sure you want to send %1? + + + + + and + + + + + The recipient address is not valid, please recheck. + + + + + The amount to pay must be larger than 0. + + + + + The amount exceeds your balance. + + + + + The total exceeds your balance when the %1 transaction fee is included. + + + + + Duplicate address found, can only send to each address once per send operation. + + + + + Error: Transaction creation failed. + + + + + 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. + + + + + WARNING: Invalid Arepacoin address + + + + + (no label) + (geen etiket) + + + + WARNING: unknown change address + + + + + SendCoinsEntry + + + Form + + + + + A&mount: + + + + + Pay &To: + + + + + + Enter a label for this address to add it to your address book + + + + + &Label: + + + + + The address to send the payment to (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Choose address from address book + + + + + Alt+A + + + + + Paste address from clipboard + + + + + Alt+P + + + + + Remove this recipient + + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + SignVerifyMessageDialog + + + Signatures - Sign / Verify a Message + + + + + + &Sign Message + &Teken boodskap + + + + You can sign messages with your addresses to prove you own them. Be careful not to sign anything vague, as phishing attacks may try to trick you into signing your identity over to them. Only sign fully-detailed statements you agree to. + + + + + The address to sign the message with (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + + Choose an address from the address book + + + + + + Alt+A + + + + + Paste address from clipboard + + + + + Alt+P + + + + + Enter the message you want to sign here + + + + + Copy the current signature to the system clipboard + + + + + Sign the message to prove you own this Arepacoin address + + + + + Reset all sign message fields + + + + + + Clear &All + + + + + + &Verify Message + + + + + Enter the signing address, message (ensure you copy line breaks, spaces, tabs, etc. exactly) and signature below to verify the message. Be careful not to read more into the signature than what is in the signed message itself, to avoid being tricked by a man-in-the-middle attack. + + + + + The address the message was signed with (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Verify the message to ensure it was signed with the specified Arepacoin address + + + + + Reset all verify message fields + + + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Click "Sign Message" to generate signature + + + + + Enter Arepacoin signature + + + + + + The entered address is invalid. + + + + + + + + Please check the address and try again. + + + + + + The entered address does not refer to a key. + + + + + Wallet unlock was cancelled. + + + + + Private key for the entered address is not available. + + + + + Message signing failed. + + + + + Message signed. + + + + + The signature could not be decoded. + + + + + + Please check the signature and try again. + + + + + The signature did not match the message digest. + + + + + Message verification failed. + + + + + Message verified. + + + + + TransactionDesc + + + Open until %1 + + + + + Open for %n block(s) + + + + + conflicted + + + + + %1/offline + + + + + %1/unconfirmed + + + + + %1 confirmations + + + + + Status + + + + + , broadcast through %n node(s) + + + + + Date + Datum + + + + Source + + + + + Generated + + + + + + From + Van + + + + + + To + Na + + + + + own address + eie adres + + + + label + etiket + + + + + + + + Credit + Krediet + + + + matures in %n more block(s) + + + + + not accepted + nie aanvaar nie + + + + + + + Debit + Debiet + + + + Transaction fee + Transaksie fooi + + + + Net amount + Netto bedrag + + + + Message + Boodskap + + + + Comment + + + + + Transaction ID + Transaksie ID + + + + Generated coins must mature 6 blocks before they can be spent. When you generated this block, it was broadcast to the network to be added to the block chain. If it fails to get into the chain, its state will change to "not accepted" and it won't be spendable. This may occasionally happen if another node generates a block within a few seconds of yours. + + + + + Debug information + + + + + Transaction + + + + + Inputs + + + + + Amount + Bedrag + + + + true + waar + + + + false + onwaar + + + + , has not been successfully broadcast yet + + + + + unknown + onbekend + + + + TransactionDescDialog + + + Transaction details + + + + + This pane shows a detailed description of the transaction + + + + + TransactionTableModel + + + Date + Datum + + + + Type + Tipe + + + + Address + Adres + + + + Amount + Bedrag + + + + Open until %1 + + + + + Confirmed (%1 confirmations) + + + + + Open for %n more block(s) + + + + + Offline + + + + + Unconfirmed + + + + + Confirming (%1 of %2 recommended confirmations) + + + + + Conflicted + + + + + Immature (%1 confirmations, will be available after %2) + + + + + This block was not received by any other nodes and will probably not be accepted! + + + + + Generated but not accepted + + + + + Received with + Ontvang met + + + + Received from + Ontvang van + + + + Sent to + Gestuur na + + + + Payment to yourself + Betalings Aan/na jouself + + + + Mined + Gemyn + + + + (n/a) + (n.v.t) + + + + Transaction status. Hover over this field to show number of confirmations. + + + + + Date and time that the transaction was received. + Datum en tyd wat die transaksie ontvang was. + + + + Type of transaction. + Tipe transaksie. + + + + Destination address of transaction. + + + + + Amount removed from or added to balance. + + + + + TransactionView + + + + All + Alles + + + + Today + Vandag + + + + This week + Hierdie week + + + + This month + Hierdie maand + + + + Last month + Verlede maand + + + + This year + Hierdie jaar + + + + Range... + Reeks... + + + + Received with + Ontvang met + + + + Sent to + Gestuur na + + + + To yourself + Aan/na jouself + + + + Mined + Gemyn + + + + Other + Ander + + + + Enter address or label to search + + + + + Min amount + Min bedrag + + + + Copy address + Maak kopie van adres + + + + Copy label + + + + + Copy amount + Kopieer bedrag + + + + Copy transaction ID + + + + + Edit label + + + + + Show transaction details + + + + + Export Transaction Data + + + + + Comma separated file (*.csv) + + + + + Confirmed + + + + + Date + Datum + + + + Type + Tipe + + + + Label + Etiket + + + + Address + Adres + + + + Amount + Bedrag + + + + ID + ID + + + + Error exporting + + + + + Could not write to file %1. + + + + + Range: + Reeks: + + + + to + aan + + + + WalletModel + + + Sending... + + + + + bitcoin-core + + + Arepacoin version + + + + + Usage: + Gebruik: + + + + Send command to -server or arepacoind + + + + + List commands + + + + + Get help for a command + + + + + Options: + Opsies: + + + + Specify configuration file (default: arepacoin.conf) + + + + + Specify pid file (default: arepacoind.pid) + + + + + Specify wallet file (within data directory) + + + + + Specify data directory + + + + + Set database cache size in megabytes (default: 25) + + + + + Set database disk log size in megabytes (default: 100) + + + + + Listen for connections on <port> (default: 9853 or testnet: 19853) + + + + + Maintain at most <n> connections to peers (default: 125) + Onderhou op die meeste <n> konneksies na eweknieë (standaard: 125) + + + + Connect to a node to retrieve peer addresses, and disconnect + + + + + Specify your own public address + + + + + Bind to given address. Use [host]:port notation for IPv6 + + + + + Stake your coins to support network and gain reward (default: 1) + + + + + Threshold for disconnecting misbehaving peers (default: 100) + + + + + Number of seconds to keep misbehaving peers from reconnecting (default: 86400) + + + + + An error occurred while setting up the RPC port %u for listening on IPv4: %s + + + + + Detach block and address databases. Increases shutdown time (default: 0) + + + + + 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. + + + + + Error: This transaction requires a transaction fee of at least %s because of its amount, complexity, or use of recently received funds + + + + + Listen for JSON-RPC connections on <port> (default: 9852 or testnet: 19852) + + + + + Accept command line and JSON-RPC commands + + + + + Error: Transaction creation failed + + + + + Error: Wallet locked, unable to create transaction + + + + + Importing blockchain data file. + + + + + Importing bootstrap blockchain data file. + + + + + Run in the background as a daemon and accept commands + + + + + Use the test network + Gebruik die toets netwerk + + + + Accept connections from outside (default: 1 if no -proxy or -connect) + + + + + An error occurred while setting up the RPC port %u for listening on IPv6, falling back to IPv4: %s + + + + + Error initializing database environment %s! To recover, BACKUP THAT DIRECTORY, then remove everything from it except for wallet.dat. + + + + + Set maximum size of high-priority/low-fee transactions in bytes (default: 27000) + + + + + Warning: -paytxfee is set very high! This is the transaction fee you will pay if you send a transaction. + + + + + Warning: Please check that your computer's date and time are correct! If your clock is wrong Arepacoin will not work properly. + + + + + Warning: error reading wallet.dat! All keys read correctly, but transaction data or address book entries might be missing or incorrect. + + + + + Warning: wallet.dat corrupt, data salvaged! Original wallet.dat saved as wallet.{timestamp}.bak in %s; if your balance or transactions are incorrect you should restore from a backup. + + + + + Attempt to recover private keys from a corrupt wallet.dat + + + + + Block creation options: + + + + + Connect only to the specified node(s) + + + + + Discover own IP address (default: 1 when listening and no -externalip) + + + + + Failed to listen on any port. Use -listen=0 if you want this. + + + + + Find peers using DNS lookup (default: 1) + + + + + Sync checkpoints policy (default: strict) + + + + + Invalid -tor address: '%s' + + + + + Invalid amount for -reservebalance=<amount> + + + + + Maximum per-connection receive buffer, <n>*1000 bytes (default: 5000) + + + + + Maximum per-connection send buffer, <n>*1000 bytes (default: 1000) + + + + + Only connect to nodes in network <net> (IPv4, IPv6 or Tor) + + + + + Output extra debugging information. Implies all other -debug* options + + + + + Output extra network debugging information + + + + + Prepend debug output with timestamp + + + + + SSL options: (see the Bitcoin Wiki for SSL setup instructions) + + + + + Select the version of socks proxy to use (4-5, default: 5) + + + + + Send trace/debug info to console instead of debug.log file + + + + + Send trace/debug info to debugger + + + + + Set maximum block size in bytes (default: 250000) + + + + + Set minimum block size in bytes (default: 0) + + + + + Shrink debug.log file on client startup (default: 1 when no -debug) + + + + + Specify connection timeout in milliseconds (default: 5000) + + + + + Unable to sign checkpoint, wrong checkpointkey? + + + + + + Use UPnP to map the listening port (default: 0) + + + + + Use UPnP to map the listening port (default: 1 when listening) + + + + + Use proxy to reach tor hidden services (default: same as -proxy) + + + + + Username for JSON-RPC connections + + + + + Verifying database integrity... + + + + + WARNING: syncronized checkpoint violation detected, but skipped! + + + + + Warning: Disk space is low! + + + + + Warning: This version is obsolete, upgrade required! + + + + + wallet.dat corrupt, salvage failed + + + + + Password for JSON-RPC connections + + + + + %s, you must set a rpcpassword in the configuration file: + %s +It is recommended you use the following random password: +rpcuser=arepacoinrpc +rpcpassword=%s +(you do not need to remember this password) +The username and password MUST NOT be the same. +If the file does not exist, create it with owner-readable-only file permissions. +It is also recommended to set alertnotify so you are notified of problems; +for example: alertnotify=echo %%s | mail -s "Arepacoin Alert" admin@foo.com + + + + + + Find peers using internet relay chat (default: 0) + + + + + Sync time with other nodes. Disable if time on your system is precise e.g. syncing with NTP (default: 1) + + + + + When creating transactions, ignore inputs with value less than this (default: 0.01) + + + + + Allow JSON-RPC connections from specified IP address + + + + + Send commands to node running on <ip> (default: 127.0.0.1) + + + + + Execute command when the best block changes (%s in cmd is replaced by block hash) + + + + + Execute command when a wallet transaction changes (%s in cmd is replaced by TxID) + + + + + Require a confirmations for change (default: 0) + + + + + Enforce transaction scripts to use canonical PUSH operators (default: 1) + + + + + Execute command when a relevant alert is received (%s in cmd is replaced by message) + + + + + Upgrade wallet to latest format + + + + + Set key pool size to <n> (default: 100) + + + + + Rescan the block chain for missing wallet transactions + + + + + How many blocks to check at startup (default: 2500, 0 = all) + + + + + How thorough the block verification is (0-6, default: 1) + + + + + Imports blocks from external blk000?.dat file + + + + + Use OpenSSL (https) for JSON-RPC connections + + + + + Server certificate file (default: server.cert) + + + + + Server private key (default: server.pem) + + + + + Acceptable ciphers (default: TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH) + + + + + Error: Wallet unlocked for staking only, unable to create transaction. + + + + + WARNING: Invalid checkpoint found! Displayed transactions may not be correct! You may need to upgrade, or notify developers. + + + + + This help message + Hierdie help boodskap + + + + Wallet %s resides outside data directory %s. + + + + + Cannot obtain a lock on data directory %s. Arepacoin is probably already running. + + + + + Arepacoin + + + + + Unable to bind to %s on this computer (bind returned error %d, %s) + + + + + Connect through socks proxy + + + + + Allow DNS lookups for -addnode, -seednode and -connect + + + + + Loading addresses... + Laai adresse... + + + + Error loading blkindex.dat + + + + + Error loading wallet.dat: Wallet corrupted + + + + + Error loading wallet.dat: Wallet requires newer version of Arepacoin + + + + + Wallet needed to be rewritten: restart Arepacoin to complete + + + + + Error loading wallet.dat + + + + + Invalid -proxy address: '%s' + + + + + Unknown network specified in -onlynet: '%s' + + + + + Unknown -socks proxy version requested: %i + + + + + Cannot resolve -bind address: '%s' + + + + + Cannot resolve -externalip address: '%s' + + + + + Invalid amount for -paytxfee=<amount>: '%s' + + + + + Error: could not start node + + + + + Sending... + + + + + Invalid amount + Ongeldige bedrag + + + + Insufficient funds + Onvoldoende fondse + + + + Loading block index... + Laai blok indeks... + + + + Add a node to connect to and attempt to keep the connection open + + + + + Unable to bind to %s on this computer. Arepacoin is probably already running. + + + + + Fee per KB to add to transactions you send + + + + + Invalid amount for -mininput=<amount>: '%s' + + + + + Loading wallet... + Laai beursie... + + + + Cannot downgrade wallet + + + + + Cannot initialize keypool + + + + + Cannot write default address + + + + + Rescanning... + + + + + Done loading + Klaar gelaai + + + + To use the %s option + + + + + Error + Fout + + + + You must set rpcpassword=<password> in the configuration file: +%s +If the file does not exist, create it with owner-readable-only file permissions. + + + + \ No newline at end of file diff --git a/src/qt/locale/bitcoin_ar.ts b/src/qt/locale/bitcoin_ar.ts new file mode 100755 index 0000000..5c59921 --- /dev/null +++ b/src/qt/locale/bitcoin_ar.ts @@ -0,0 +1,3278 @@ + + + AboutDialog + + + About Arepacoin + عن البلاك كوين + + + + <b>Arepacoin</b> version + جزء البلاك كوين + + + + Copyright © 2009-2014 The Bitcoin developers +Copyright © 2012-2014 The NovaCoin developers +Copyright © 2014 The Arepacoin developers + + + + + +This is experimental software. + +Distributed under the MIT/X11 software license, see the accompanying file COPYING or http://www.opensource.org/licenses/mit-license.php. + +This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit (http://www.openssl.org/) and cryptographic software written by Eric Young (eay@cryptsoft.com) and UPnP software written by Thomas Bernard. + + + + + AddressBookPage + + + Address Book + كتاب العنوان + + + + Double-click to edit address or label + أنقر على الماوس مرتين لتعديل العنوان + + + + Create a new address + انشأ عنوان جديد + + + + Copy the currently selected address to the system clipboard + قم بنسخ العنوان المختار لحافظة النظام + + + + &New Address + &عنوان جديد + + + + These are your Arepacoin addresses for receiving payments. You may want to give a different one to each sender so you can keep track of who is paying you. + هذه هي عناوين البلاك كوين لاستقبال الدفعات. يمكن أن تعطي عنوان مختلف لكل مرسل من اجل أن تتابع من يرسل لك. + + + + &Copy Address + انسخ العنوان + + + + Show &QR Code + اظهار &رمز الاستجابة السريعة + + + + Sign a message to prove you own a Arepacoin address + التوقيع علي رسالة لاثبات بانك تملك عنوان البلاك كوين + + + + Sign &Message + وقع &الرسالة + + + + Delete the currently selected address from the list + خذف العنوان الحالي التي تم اختياره من القائمة + + + + Verify a message to ensure it was signed with a specified Arepacoin address + تحقق من الرسالة لتثبت بانه تم توقيعه بعنوان بلاك كوين محدد + + + + &Verify Message + &تحقق الرسالة + + + + &Delete + &أمسح + + + + Copy &Label + نسخ &التسمية + + + + &Edit + تعديل + + + + Export Address Book Data + تصدير بيانات كتاب العناوين + + + + Comma separated file (*.csv) + + + + + Error exporting + خطا في التصدير + + + + Could not write to file %1. + لا يمكن الكتابة الي الملف %1. + + + + AddressTableModel + + + Label + وصف + + + + Address + عنوان + + + + (no label) + (لا وصف) + + + + AskPassphraseDialog + + + Passphrase Dialog + حوار كلمة المرور + + + + Enter passphrase + ادخل كلمة المرور + + + + New passphrase + عبارة مرور جديدة + + + + Repeat new passphrase + ادخل الجملة السرية مرة أخرى + + + + Serves to disable the trivial sendmoney when OS account compromised. Provides no real security. + + + + + For staking only + + + + + Enter the new passphrase to the wallet.<br/>Please use a passphrase of <b>10 or more random characters</b>, or <b>eight or more words</b>. + أدخل عبارة مرور جديدة إلى المحفظة. الرجاء استخدام عبارة مرور تتكون من10 حروف عشوائية على الاقل, أو أكثر من 7 كلمات + + + + Encrypt wallet + تشفير المحفظة + + + + This operation needs your wallet passphrase to unlock the wallet. + هذه العملية تحتاج عبارة المرور محفظتك لفتحها + + + + Unlock wallet + إفتح المحفظة + + + + This operation needs your wallet passphrase to decrypt the wallet. + هذه العملية تحتاج عبارة المرور محفظتك فك تشفيرها + + + + Decrypt wallet + فك تشفير المحفظة + + + + Change passphrase + تغيير عبارة المرور + + + + Enter the old and new passphrase to the wallet. + أدخل عبارة المرور القديمة والجديدة إلى المحفظة. + + + + Confirm wallet encryption + تأكيد التشفير المحفظة + + + + Warning: If you encrypt your wallet and lose your passphrase, you will <b>LOSE ALL OF YOUR COINS</b>! + تخذير : اذا تم تشفير المحفظة وضيعت كلمة المرور, لن تستطيع الحصول علي البلاك كوين + + + + Are you sure you wish to encrypt your wallet? + هل انت متأكد من رغبتك في تشفير المحفظة؟ + + + + IMPORTANT: Any previous backups you have made of your wallet file should be replaced with the newly generated, encrypted wallet file. For security reasons, previous backups of the unencrypted wallet file will become useless as soon as you start using the new, encrypted wallet. + + + + + + Warning: The Caps Lock key is on! + + + + + + Wallet encrypted + محفظة مشفرة + + + + Arepacoin will close now to finish the encryption process. Remember that encrypting your wallet cannot fully protect your coins from being stolen by malware infecting your computer. + بلاك كوين + + + + + + + Wallet encryption failed + فشل تشفير المحفظة + + + + Wallet encryption failed due to an internal error. Your wallet was not encrypted. + شل تشفير المحفظة بسبب خطأ داخلي. لم يتم تشفير محفظتك. + + + + + The supplied passphrases do not match. + عبارتي المرور ليستا متطابقتان + + + + + Wallet unlock failed + فشل فتح المحفظة + + + + + + The passphrase entered for the wallet decryption was incorrect. + عبارة المرور التي تم إدخالها لفك شفرة المحفظة غير صحيحة. + + + + + Wallet decryption failed + فشل فك التشفير المحفظة + + + + Wallet passphrase was successfully changed. + كلمة مرور المحفظة تم تغييره بشكل ناجح + + + + BitcoinGUI + + + Sign &message... + التوقيع و الرسائل + + + + Synchronizing with network... + مزامنة مع شبكة ... + + + + &Overview + نظرة عامة + + + + Show general overview of wallet + إظهار نظرة عامة على المحفظة + + + + &Transactions + المعاملات + + + + Browse transaction history + تصفح التاريخ المعاملات + + + + &Address Book + &كتاب العنوان + + + + Edit the list of stored addresses and labels + تعديل قائمة العنوان المحفوظة + + + + &Receive coins + &استقبال البلاك كوين + + + + Show the list of addresses for receiving payments + اظهار قائمة العناوين التي تستقبل التعاملات + + + + &Send coins + &ارسال البلاك كوين + + + + E&xit + خروج + + + + Quit application + الخروج من التطبيق + + + + Show information about Arepacoin + اظهار المعلومات عن البلاك كوين + + + + About &Qt + عن + + + + Show information about Qt + اظهر المعلومات + + + + &Options... + خيارات ... + + + + &Encrypt Wallet... + تشفير المحفظة + + + + &Backup Wallet... + حفظ ودعم المحفظة + + + + &Change Passphrase... + تغيير كلمة المرور + + + + ~%n block(s) remaining + + + + + Downloaded %1 of %2 blocks of transaction history (%3% done). + + + + + &Export... + &تصدير... + + + + Send coins to a Arepacoin address + ارسال البلاك كوين الي عنوان اخر + + + + Modify configuration options for Arepacoin + تعديل خيارات التكوين للبلاك كوين + + + + Export the data in the current tab to a file + ارسال البيانات الحالية الي ملف + + + + Encrypt or decrypt wallet + تشفير او فك التشفير للمحفظة + + + + Backup wallet to another location + احفظ نسخة احتياطية للمحفظة في مكان آخر + + + + Change the passphrase used for wallet encryption + تغيير عبارة المرور المستخدمة لتشفير المحفظة + + + + &Debug window + + + + + Open debugging and diagnostic console + + + + + &Verify message... + تأكيد الرسالة + + + + Arepacoin + البلاك كوين + + + + Wallet + محفظة + + + + &About Arepacoin + عن البلاك كوين + + + + &Show / Hide + اظهار/ اخفاء + + + + Unlock wallet + فتح المحفظة + + + + &Lock Wallet + قفل المحفظة + + + + Lock wallet + قفل المحفظة + + + + &File + ملف + + + + &Settings + الاعدادات + + + + &Help + مساعدة + + + + Tabs toolbar + شريط أدوات علامات التبويب + + + + Actions toolbar + + + + + + [testnet] + [testnet] + + + + + Arepacoin client + برنامج البلاك كوين + + + + %n active connection(s) to Arepacoin network + + + + + Downloaded %1 blocks of transaction history. + + + + + Staking.<br>Your weight is %1<br>Network weight is %2<br>Expected time to earn reward is %3 + + + + + Not staking because wallet is locked + + + + + Not staking because wallet is offline + + + + + Not staking because wallet is syncing + + + + + Not staking because you don't have mature coins + + + + + %n second(s) ago + + + + + &Unlock Wallet... + + + + + %n minute(s) ago + + + + + %n hour(s) ago + + + + + %n day(s) ago + + + + + Up to date + محين + + + + Catching up... + اللحاق بالركب ... + + + + Last received block was generated %1. + + + + + This transaction is over the size limit. You can still send it for a fee of %1, which goes to the nodes that process your transaction and helps to support the network. Do you want to pay the fee? + + + + + Confirm transaction fee + تأكيد رسوم المعاملة + + + + Sent transaction + المعاملات المرسلة + + + + Incoming transaction + المعاملات واردة + + + + Date: %1 +Amount: %2 +Type: %3 +Address: %4 + + + + + + + URI handling + + + + + + URI can not be parsed! This can be caused by an invalid Arepacoin address or malformed URI parameters. + + + + + Wallet is <b>encrypted</b> and currently <b>unlocked</b> + المحفظة مشفرة و مفتوحة حاليا + + + + Wallet is <b>encrypted</b> and currently <b>locked</b> + المحفظة مشفرة و مقفلة حاليا + + + + Backup Wallet + النسخ الاحتياطي للمحفظة + + + + Wallet Data (*.dat) + بيانات المحفظة (*.dat) + + + + Backup Failed + فشل الدعم + + + + There was an error trying to save the wallet data to the new location. + خطا في محاولة حفظ بيانات الحفظة في مكان جديد + + + + %n second(s) + + + + + %n minute(s) + + + + + %n hour(s) + + + + + %n day(s) + + + + + Not staking + + + + + A fatal error occurred. Arepacoin can no longer continue safely and will quit. + خطا فادح! بلاك كوين لا يمكن أن يستمر جاري الاغلاق + + + + ClientModel + + + Network Alert + تحذير الشبكة + + + + CoinControlDialog + + + Coin Control + سيطرة الكوين + + + + Quantity: + الكمية: + + + + Bytes: + + + + + Amount: + المبلغ: + + + + Priority: + اهمية: + + + + Fee: + رسوم: + + + + Low Output: + + + + + no + لا + + + + After Fee: + بعد الرسوم: + + + + Change: + تغيير: + + + + (un)select all + + + + + Tree mode + + + + + List mode + + + + + Amount + المبلغ + + + + Label + + + + + Address + عنوان + + + + Date + التاريخ + + + + Confirmations + + + + + Confirmed + تأكيد + + + + Priority + + + + + Copy address + انسخ عنوان + + + + Copy label + انسخ التسمية + + + + + Copy amount + نسخ الكمية + + + + Copy transaction ID + + + + + Copy quantity + + + + + Copy fee + + + + + Copy after fee + + + + + Copy bytes + + + + + Copy priority + + + + + Copy low output + + + + + Copy change + + + + + highest + + + + + high + + + + + medium-high + + + + + medium + + + + + low-medium + + + + + low + + + + + lowest + + + + + DUST + + + + + yes + نعم + + + + This label turns red, if the transaction size is bigger than 10000 bytes. + + This means a fee of at least %1 per kb is required. + + Can vary +/- 1 Byte per input. + + + + + Transactions with higher priority get more likely into a block. + +This label turns red, if the priority is smaller than "medium". + + This means a fee of at least %1 per kb is required. + + + + + This label turns red, if any recipient receives an amount smaller than %1. + + This means a fee of at least %2 is required. + + Amounts below 0.546 times the minimum relay fee are shown as DUST. + + + + + This label turns red, if the change is smaller than %1. + + This means a fee of at least %2 is required. + + + + + + (no label) + (لا وصف) + + + + change from %1 (%2) + + + + + (change) + + + + + EditAddressDialog + + + Edit Address + عدل العنوان + + + + &Label + + + + + The label associated with this address book entry + + + + + &Address + العنوان + + + + The address associated with this address book entry. This can only be modified for sending addresses. + + + + + New receiving address + عنوان تلقي جديد + + + + New sending address + عنوان إرسال جديد + + + + Edit receiving address + تعديل عنوان التلقي + + + + + Edit sending address + تعديل عنوان الارسال + + + + The entered address "%1" is already in the address book. + هدا العنوان "%1" موجود مسبقا في دفتر العناوين + + + + The entered address "%1" is not a valid Arepacoin address. + + + + + Could not unlock wallet. + يمكن فتح المحفظة. + + + + New key generation failed. + فشل توليد مفتاح جديد. + + + + GUIUtil::HelpMessageBox + + + + Arepacoin-Qt + + + + + version + + + + + Usage: + + + + + command-line options + + + + + UI options + + + + + Set language, for example "de_DE" (default: system locale) + + + + + Start minimized + + + + + Show splash screen on startup (default: 1) + + + + + OptionsDialog + + + Options + خيارات ... + + + + &Main + الرئيسي + + + + Optional transaction fee per kB that helps make sure your transactions are processed quickly. Most transactions are 1 kB. Fee 0.01 recommended. + + + + + Pay transaction &fee + ادفع &رسوم المعاملة + + + + Reserved amount does not participate in staking and is therefore spendable at any time. + + + + + Reserve + حجز + + + + Automatically start Arepacoin after logging in to the system. + بد البلاك كوين تلقائي عند الدخول الي الجهاز + + + + &Start Arepacoin on system login + + + + + Detach block and address databases at shutdown. This means they can be moved to another data directory, but it slows down shutdown. The wallet is always detached. + + + + + &Detach databases at shutdown + + + + + &Network + &الشبكة + + + + Automatically open the Arepacoin client port on the router. This only works when your router supports UPnP and it is enabled. + + + + + Map port using &UPnP + + + + + Connect to the Arepacoin network through a SOCKS proxy (e.g. when connecting through Tor). + + + + + &Connect through SOCKS proxy: + + + + + Proxy &IP: + + + + + IP address of the proxy (e.g. 127.0.0.1) + + + + + &Port: + + + + + Port of the proxy (e.g. 9050) + + + + + SOCKS &Version: + + + + + SOCKS version of the proxy (e.g. 5) + + + + + &Window + نافذه + + + + Show only a tray icon after minimizing the window. + + + + + &Minimize to the tray instead of the taskbar + + + + + Minimize instead of exit the application when the window is closed. When this option is enabled, the application will be closed only after selecting Quit in the menu. + + + + + M&inimize on close + + + + + &Display + + + + + User Interface &language: + + + + + The user interface language can be set here. This setting will take effect after restarting Arepacoin. + + + + + &Unit to show amounts in: + + + + + Choose the default subdivision unit to show in the interface and when sending coins. + + + + + Whether to show Arepacoin addresses in the transaction list or not. + + + + + &Display addresses in transaction list + عرض العناوين في قائمة الصفقة + + + + Whether to show coin control features or not. + + + + + Display coin &control features (experts only!) + + + + + &OK + تم + + + + &Cancel + الغاء + + + + &Apply + + + + + default + الافتراضي + + + + + Warning + + + + + + This setting will take effect after restarting Arepacoin. + + + + + The supplied proxy address is invalid. + عنوان الوكيل توفيره غير صالح. + + + + OverviewPage + + + Form + نمودج + + + + + The displayed information may be out of date. Your wallet automatically synchronizes with the Arepacoin network after a connection is established, but this process has not completed yet. + + + + + Stake: + + + + + Unconfirmed: + + + + + Wallet + محفظة + + + + Spendable: + + + + + Your current spendable balance + + + + + Immature: + غير ناضجة + + + + Mined balance that has not yet matured + + + + + Total: + الكامل: + + + + Your current total balance + + + + + <b>Recent transactions</b> + اخر المعملات + + + + Total of transactions that have yet to be confirmed, and do not yet count toward the current balance + + + + + Total of coins that was staked, and do not yet count toward the current balance + + + + + + out of sync + خارج المزامنه + + + + QRCodeDialog + + + QR Code Dialog + + + + + Request Payment + + + + + Amount: + + + + + Label: + + + + + Message: + + + + + &Save As... + + + + + Error encoding URI into QR Code. + + + + + The entered amount is invalid, please check. + + + + + Resulting URI too long, try to reduce the text for label / message. + + + + + Save QR Code + + + + + PNG Images (*.png) + + + + + RPCConsole + + + Client name + اسم العميل + + + + + + + + + + + + + N/A + غير معروف + + + + Client version + نسخه العميل + + + + &Information + المعلومات + + + + Using OpenSSL version + + + + + Startup time + + + + + Network + الشبكه + + + + Number of connections + عدد الاتصالات + + + + On testnet + + + + + Block chain + + + + + Current number of blocks + + + + + Estimated total blocks + + + + + Last block time + + + + + &Open + الفتح + + + + Command-line options + + + + + Show the Arepacoin-Qt help message to get a list with possible Arepacoin command-line options. + + + + + &Show + + + + + &Console + + + + + Build date + وقت البناء + + + + Arepacoin - Debug window + + + + + Arepacoin Core + + + + + Debug log file + + + + + Open the Arepacoin debug log file from the current data directory. This can take a few seconds for large log files. + + + + + Clear console + + + + + Welcome to the Arepacoin RPC console. + + + + + Use up and down arrows to navigate history, and <b>Ctrl-L</b> to clear screen. + + + + + Type <b>help</b> for an overview of available commands. + + + + + SendCoinsDialog + + + + + + + + + + Send Coins + إرسال Coins + + + + Coin Control Features + + + + + Inputs... + + + + + automatically selected + + + + + Insufficient funds! + + + + + Quantity: + + + + + + 0 + + + + + Bytes: + + + + + Amount: + + + + + + + + 0.00 BC + + + + + Priority: + + + + + medium + + + + + Fee: + + + + + Low Output: + + + + + no + + + + + After Fee: + + + + + Change + + + + + custom change address + + + + + Send to multiple recipients at once + إرسال إلى عدة مستلمين في وقت واحد + + + + Add &Recipient + + + + + Remove all transaction fields + + + + + Clear &All + مسح الكل + + + + Balance: + الرصيد: + + + + 123.456 BC + + + + + Confirm the send action + تأكيد الإرسال + + + + S&end + + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Copy quantity + + + + + Copy amount + نسخ الكمية + + + + Copy fee + + + + + Copy after fee + + + + + Copy bytes + + + + + Copy priority + + + + + Copy low output + + + + + Copy change + + + + + <b>%1</b> to %2 (%3) + + + + + Confirm send coins + تأكيد الإرسال Coins + + + + Are you sure you want to send %1? + + + + + and + + + + + The recipient address is not valid, please recheck. + + + + + The amount to pay must be larger than 0. + المبلغ المدفوع يجب ان يكون اكبر من 0 + + + + The amount exceeds your balance. + + + + + The total exceeds your balance when the %1 transaction fee is included. + + + + + Duplicate address found, can only send to each address once per send operation. + + + + + Error: Transaction creation failed. + + + + + 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. + + + + + WARNING: Invalid Arepacoin address + + + + + (no label) + (لا وصف) + + + + WARNING: unknown change address + + + + + SendCoinsEntry + + + Form + + + + + A&mount: + + + + + Pay &To: + ادفع الى + + + + + Enter a label for this address to add it to your address book + إدخال تسمية لهذا العنوان لإضافته إلى دفتر العناوين الخاص بك + + + + &Label: + + + + + The address to send the payment to (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + العنوان لارسال المعاملة الي (مثلا AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + Choose address from address book + اختيار عنوان من كتاب العناوين + + + + Alt+A + Alt+A + + + + Paste address from clipboard + انسخ العنوان من لوحة المفاتيح + + + + Alt+P + Alt+P + + + + Remove this recipient + خذف هذا المستخدم + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + ادخال عنوان البلاك كوين (مثلا AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + SignVerifyMessageDialog + + + Signatures - Sign / Verify a Message + التواقيع - التوقيع /تأكيد الرسالة + + + + + &Sign Message + &وقع الرسالة + + + + You can sign messages with your addresses to prove you own them. Be careful not to sign anything vague, as phishing attacks may try to trick you into signing your identity over to them. Only sign fully-detailed statements you agree to. + + + + + The address to sign the message with (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + + Choose an address from the address book + اختيار عنوان من كتاب العناوين + + + + + Alt+A + Alt+A + + + + Paste address from clipboard + انسخ العنوان من لوحة المفاتيح + + + + Alt+P + Alt+P + + + + Enter the message you want to sign here + + + + + Copy the current signature to the system clipboard + + + + + Sign the message to prove you own this Arepacoin address + + + + + Reset all sign message fields + + + + + + Clear &All + مسح الكل + + + + + &Verify Message + + + + + Enter the signing address, message (ensure you copy line breaks, spaces, tabs, etc. exactly) and signature below to verify the message. Be careful not to read more into the signature than what is in the signed message itself, to avoid being tricked by a man-in-the-middle attack. + + + + + The address the message was signed with (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Verify the message to ensure it was signed with the specified Arepacoin address + + + + + Reset all verify message fields + + + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Click "Sign Message" to generate signature + + + + + Enter Arepacoin signature + + + + + + The entered address is invalid. + العنوان المدخل غير صالح + + + + + + + Please check the address and try again. + الرجاء التأكد من العنوان والمحاولة مرة اخرى + + + + + The entered address does not refer to a key. + العنوان المدخل لا يشير الى مفتاح + + + + Wallet unlock was cancelled. + + + + + Private key for the entered address is not available. + المفتاح الخاص للعنوان المدخل غير موجود. + + + + Message signing failed. + فشل توقيع الرسالة. + + + + Message signed. + الرسالة موقعة. + + + + The signature could not be decoded. + + + + + + Please check the signature and try again. + + + + + The signature did not match the message digest. + + + + + Message verification failed. + فشلت عملية التأكد من الرسالة. + + + + Message verified. + تم تأكيد الرسالة. + + + + TransactionDesc + + + Open until %1 + مفتوح حتى 1٪ + + + + Open for %n block(s) + + + + + conflicted + + + + + %1/offline + 1% غير متواجد + + + + %1/unconfirmed + غير مؤكدة/1% + + + + %1 confirmations + تأكيد %1 + + + + Status + الحالة. + + + + , broadcast through %n node(s) + + + + + Date + التاريخ + + + + Source + المصدر + + + + Generated + تم اصداره. + + + + + From + من + + + + + + To + الى + + + + + own address + عنوانه + + + + label + + + + + + + + + Credit + + + + + matures in %n more block(s) + + + + + not accepted + غير مقبولة + + + + + + + Debit + دين + + + + Transaction fee + رسوم التحويل + + + + Net amount + + + + + Message + + + + + Comment + تعليق + + + + Transaction ID + رقم المعاملة + + + + Generated coins must mature 6 blocks before they can be spent. When you generated this block, it was broadcast to the network to be added to the block chain. If it fails to get into the chain, its state will change to "not accepted" and it won't be spendable. This may occasionally happen if another node generates a block within a few seconds of yours. + + + + + Debug information + + + + + Transaction + معاملة + + + + Inputs + + + + + Amount + المبلغ + + + + true + صحيح + + + + false + خاطئ + + + + , has not been successfully broadcast yet + لم يتم حتى الآن البث بنجاح + + + + unknown + غير معروف + + + + TransactionDescDialog + + + Transaction details + تفاصيل المعاملة + + + + This pane shows a detailed description of the transaction + يبين هذا الجزء وصفا مفصلا لهده المعاملة + + + + TransactionTableModel + + + Date + التاريخ + + + + Type + النوع + + + + Address + عنوان + + + + Amount + المبلغ + + + + Open until %1 + مفتوح حتى 1٪ + + + + Confirmed (%1 confirmations) + تأكيد الإرسال Coins + + + + Open for %n more block(s) + + + + + Offline + غير متصل + + + + Unconfirmed + + + + + Confirming (%1 of %2 recommended confirmations) + + + + + Conflicted + + + + + Immature (%1 confirmations, will be available after %2) + + + + + This block was not received by any other nodes and will probably not be accepted! + لم يتم تلقى هذه الكتلة (Block) من قبل أي العقد الأخرى وربما لن تكون مقبولة! + + + + Generated but not accepted + ولدت ولكن لم تقبل + + + + Received with + استقبل مع + + + + Received from + استقبل من + + + + Sent to + أرسل إلى + + + + Payment to yourself + دفع لنفسك + + + + Mined + Mined + + + + (n/a) + غير متوفر + + + + Transaction status. Hover over this field to show number of confirmations. + حالة المعاملة. تحوم حول هذا الحقل لعرض عدد التأكيدات. + + + + Date and time that the transaction was received. + التاريخ والوقت الذي تم فيه تلقي المعاملة. + + + + Type of transaction. + نوع المعاملات + + + + Destination address of transaction. + عنوان وجهة المعاملة + + + + Amount removed from or added to balance. + المبلغ الذي أزيل أو أضيف الى الرصيد + + + + TransactionView + + + + All + الكل + + + + Today + اليوم + + + + This week + هدا الاسبوع + + + + This month + هدا الشهر + + + + Last month + الشهر الماضي + + + + This year + هدا العام + + + + Range... + نطاق + + + + Received with + استقبل مع + + + + Sent to + أرسل إلى + + + + To yourself + إليك + + + + Mined + Mined + + + + Other + اخرى + + + + Enter address or label to search + ادخل عنوان أووصف للبحث + + + + Min amount + الكمية الادني + + + + Copy address + انسخ عنوان + + + + Copy label + انسخ التسمية + + + + Copy amount + نسخ الكمية + + + + Copy transaction ID + نسخ رقم المعاملة + + + + Edit label + عدل الوصف + + + + Show transaction details + اظهار تفاصيل المعاملة + + + + Export Transaction Data + تصدير بيانات المعاملة + + + + Comma separated file (*.csv) + + + + + Confirmed + تأكيد + + + + Date + التاريخ + + + + Type + النوع + + + + Label + وصف + + + + Address + عنوان + + + + Amount + المبلغ + + + + ID + العنوان + + + + Error exporting + خطا في التصدير + + + + Could not write to file %1. + لا يمكن الكتابة الي الملف %1. + + + + Range: + نطاق: + + + + to + الى + + + + WalletModel + + + Sending... + ارسال.... + + + + bitcoin-core + + + Arepacoin version + جزع البلاك كوين + + + + Usage: + المستخدم + + + + Send command to -server or arepacoind + + + + + List commands + اعرض الأوامر + + + + Get help for a command + مساعدة في كتابة الاوامر + + + + Options: + خيارات: + + + + Specify configuration file (default: arepacoin.conf) + + + + + Specify pid file (default: arepacoind.pid) + + + + + Specify wallet file (within data directory) + + + + + Specify data directory + حدد موقع مجلد المعلومات او data directory + + + + Set database cache size in megabytes (default: 25) + ضع حجم كاش قاعدة البيانات بالميجابايت (الافتراضي: 25) + + + + Set database disk log size in megabytes (default: 100) + + + + + Listen for connections on <port> (default: 9853 or testnet: 19853) + + + + + Maintain at most <n> connections to peers (default: 125) + + + + + Connect to a node to retrieve peer addresses, and disconnect + + + + + Specify your own public address + حدد عنوانك العام هنا + + + + Bind to given address. Use [host]:port notation for IPv6 + + + + + Stake your coins to support network and gain reward (default: 1) + + + + + Threshold for disconnecting misbehaving peers (default: 100) + + + + + Number of seconds to keep misbehaving peers from reconnecting (default: 86400) + + + + + An error occurred while setting up the RPC port %u for listening on IPv4: %s + + + + + Detach block and address databases. Increases shutdown time (default: 0) + + + + + 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. + + + + + Error: This transaction requires a transaction fee of at least %s because of its amount, complexity, or use of recently received funds + + + + + Listen for JSON-RPC connections on <port> (default: 9852 or testnet: 19852) + + + + + Accept command line and JSON-RPC commands + + + + + Error: Transaction creation failed + تحذير صناعة المعاملة فشلت + + + + Error: Wallet locked, unable to create transaction + خطا : المحفظة مقفلة, لا يمكن عمل المعاملة + + + + Importing blockchain data file. + استيراد بيانات ملف سلسلة الكتل + + + + Importing bootstrap blockchain data file. + + + + + Run in the background as a daemon and accept commands + + + + + Use the test network + استخدم التحقق من الشبكه + + + + Accept connections from outside (default: 1 if no -proxy or -connect) + قبول الاتصالات من خارج + + + + An error occurred while setting up the RPC port %u for listening on IPv6, falling back to IPv4: %s + + + + + Error initializing database environment %s! To recover, BACKUP THAT DIRECTORY, then remove everything from it except for wallet.dat. + + + + + Set maximum size of high-priority/low-fee transactions in bytes (default: 27000) + + + + + Warning: -paytxfee is set very high! This is the transaction fee you will pay if you send a transaction. + + + + + Warning: Please check that your computer's date and time are correct! If your clock is wrong Arepacoin will not work properly. + تحذير : تأكد من ساعة وتاريخ الكمبيوتر! اذا ساعة غير صحيحة بلاك كوين لن يعمل بشكل صحيح + + + + Warning: error reading wallet.dat! All keys read correctly, but transaction data or address book entries might be missing or incorrect. + تحذير : خطا في قراءة wallet.dat! كل المفاتيح تم قرائتة بشكل صحيح لكن بيانات الصفقة او إدخالات كتاب العنوان غير صحيحة او غير موجودة + + + + Warning: wallet.dat corrupt, data salvaged! Original wallet.dat saved as wallet.{timestamp}.bak in %s; if your balance or transactions are incorrect you should restore from a backup. + تخذير :wallet.dat غير صالح تم حفظ البيانات. المحفظة الاصلية تم حفظه ك wallet.{timestamp}.bak %s في ; اذا حسابك او صفقاتك غير صحيح يجب عليك استعادة النسخ الاحتياطي + + + + Attempt to recover private keys from a corrupt wallet.dat + محاولة استرجاع المفاتيح الخاصة من wallet.dat الغير صالح + + + + Block creation options: + خيارات صناعة الكتل + + + + Connect only to the specified node(s) + + + + + Discover own IP address (default: 1 when listening and no -externalip) + + + + + Failed to listen on any port. Use -listen=0 if you want this. + فشل في الاستماع على أي منفذ. استخدام الاستماع = 0 إذا كنت تريد هذا. + + + + Find peers using DNS lookup (default: 1) + + + + + Sync checkpoints policy (default: strict) + + + + + Invalid -tor address: '%s' + + + + + Invalid amount for -reservebalance=<amount> + + + + + Maximum per-connection receive buffer, <n>*1000 bytes (default: 5000) + + + + + Maximum per-connection send buffer, <n>*1000 bytes (default: 1000) + + + + + Only connect to nodes in network <net> (IPv4, IPv6 or Tor) + + + + + Output extra debugging information. Implies all other -debug* options + + + + + Output extra network debugging information + + + + + Prepend debug output with timestamp + + + + + SSL options: (see the Bitcoin Wiki for SSL setup instructions) + + + + + Select the version of socks proxy to use (4-5, default: 5) + + + + + Send trace/debug info to console instead of debug.log file + + + + + Send trace/debug info to debugger + + + + + Set maximum block size in bytes (default: 250000) + + + + + Set minimum block size in bytes (default: 0) + + + + + Shrink debug.log file on client startup (default: 1 when no -debug) + + + + + Specify connection timeout in milliseconds (default: 5000) + + + + + Unable to sign checkpoint, wrong checkpointkey? + + + + + + Use UPnP to map the listening port (default: 0) + + + + + Use UPnP to map the listening port (default: 1 when listening) + + + + + Use proxy to reach tor hidden services (default: same as -proxy) + + + + + Username for JSON-RPC connections + + + + + Verifying database integrity... + + + + + WARNING: syncronized checkpoint violation detected, but skipped! + + + + + Warning: Disk space is low! + تحذير : مساحة القرص منخفض + + + + Warning: This version is obsolete, upgrade required! + تحذير هذا الجزء قديم, التجديد مطلوب + + + + wallet.dat corrupt, salvage failed + wallet.dat غير صالح لا يمكن الاسترجاع + + + + Password for JSON-RPC connections + + + + + %s, you must set a rpcpassword in the configuration file: + %s +It is recommended you use the following random password: +rpcuser=arepacoinrpc +rpcpassword=%s +(you do not need to remember this password) +The username and password MUST NOT be the same. +If the file does not exist, create it with owner-readable-only file permissions. +It is also recommended to set alertnotify so you are notified of problems; +for example: alertnotify=echo %%s | mail -s "Arepacoin Alert" admin@foo.com + + + + + + Find peers using internet relay chat (default: 0) + + + + + Sync time with other nodes. Disable if time on your system is precise e.g. syncing with NTP (default: 1) + + + + + When creating transactions, ignore inputs with value less than this (default: 0.01) + عند + + + + Allow JSON-RPC connections from specified IP address + + + + + Send commands to node running on <ip> (default: 127.0.0.1) + + + + + Execute command when the best block changes (%s in cmd is replaced by block hash) + + + + + Execute command when a wallet transaction changes (%s in cmd is replaced by TxID) + + + + + Require a confirmations for change (default: 0) + + + + + Enforce transaction scripts to use canonical PUSH operators (default: 1) + + + + + Execute command when a relevant alert is received (%s in cmd is replaced by message) + + + + + Upgrade wallet to latest format + ارقاء المحفظة الي اخر نسخة + + + + Set key pool size to <n> (default: 100) + + + + + Rescan the block chain for missing wallet transactions + اعادة بحث سلسلة الكتلة لايجاد معالمات المحفظة + + + + How many blocks to check at startup (default: 2500, 0 = all) + كمية الكتل التي تريد ان تبحث عنه عند بداية البرنامج (التلقائي 2500, 0 = الكل) + + + + How thorough the block verification is (0-6, default: 1) + كمية تأكيد الكتل (0-6 التلقائي 1) + + + + Imports blocks from external blk000?.dat file + نقل كتل من ملف blk000.dat خارجي + + + + Use OpenSSL (https) for JSON-RPC connections + + + + + Server certificate file (default: server.cert) + + + + + Server private key (default: server.pem) + + + + + Acceptable ciphers (default: TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH) + + + + + Error: Wallet unlocked for staking only, unable to create transaction. + + + + + WARNING: Invalid checkpoint found! Displayed transactions may not be correct! You may need to upgrade, or notify developers. + + + + + This help message + رسالة المساعدة هذه + + + + Wallet %s resides outside data directory %s. + + + + + Cannot obtain a lock on data directory %s. Arepacoin is probably already running. + + + + + Arepacoin + البلاك كوين + + + + Unable to bind to %s on this computer (bind returned error %d, %s) + + + + + Connect through socks proxy + + + + + Allow DNS lookups for -addnode, -seednode and -connect + + + + + Loading addresses... + تحميل العنوان + + + + Error loading blkindex.dat + خظا في تحميل blkindex.dat + + + + Error loading wallet.dat: Wallet corrupted + خطأ عند تنزيل wallet.dat: المحفظة تالفة + + + + Error loading wallet.dat: Wallet requires newer version of Arepacoin + + + + + Wallet needed to be rewritten: restart Arepacoin to complete + المحفظة يجب أن يعاد كتابته : أعد البلاك كوين لتكتمل + + + + Error loading wallet.dat + خطأ عند تنزيل wallet.dat + + + + Invalid -proxy address: '%s' + + + + + Unknown network specified in -onlynet: '%s' + + + + + Unknown -socks proxy version requested: %i + + + + + Cannot resolve -bind address: '%s' + + + + + Cannot resolve -externalip address: '%s' + + + + + Invalid amount for -paytxfee=<amount>: '%s' + + + + + Error: could not start node + + + + + Sending... + ارسال.... + + + + Invalid amount + مبلغ خاطئ + + + + Insufficient funds + حسابك لا يكفي + + + + Loading block index... + + + + + Add a node to connect to and attempt to keep the connection open + + + + + Unable to bind to %s on this computer. Arepacoin is probably already running. + + + + + Fee per KB to add to transactions you send + + + + + Invalid amount for -mininput=<amount>: '%s' + + + + + Loading wallet... + تحميل المحفظه + + + + Cannot downgrade wallet + لا يمكن خفض المحفظة + + + + Cannot initialize keypool + + + + + Cannot write default address + لا يمكن كتابة العنوان الافتراضي + + + + Rescanning... + إعادة مسح + + + + Done loading + انتهاء التحميل + + + + To use the %s option + + + + + Error + خطأ + + + + You must set rpcpassword=<password> in the configuration file: +%s +If the file does not exist, create it with owner-readable-only file permissions. + + + + \ No newline at end of file diff --git a/src/qt/locale/bitcoin_be_BY.ts b/src/qt/locale/bitcoin_be_BY.ts new file mode 100755 index 0000000..5613808 --- /dev/null +++ b/src/qt/locale/bitcoin_be_BY.ts @@ -0,0 +1,3279 @@ + + + AboutDialog + + + About Arepacoin + + + + + <b>Arepacoin</b> version + + + + + Copyright © 2009-2014 The Bitcoin developers +Copyright © 2012-2014 The NovaCoin developers +Copyright © 2014 The Arepacoin developers + + + + + +This is experimental software. + +Distributed under the MIT/X11 software license, see the accompanying file COPYING or http://www.opensource.org/licenses/mit-license.php. + +This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit (http://www.openssl.org/) and cryptographic software written by Eric Young (eay@cryptsoft.com) and UPnP software written by Thomas Bernard. + + + + + AddressBookPage + + + Address Book + + + + + Double-click to edit address or label + Двайны клік для рэдагавання адрасу ці пазнакі + + + + Create a new address + Стварыць новы адрас + + + + Copy the currently selected address to the system clipboard + Капіяваць пазначаны адрас у сістэмны буфер абмену + + + + &New Address + + + + + These are your Arepacoin addresses for receiving payments. You may want to give a different one to each sender so you can keep track of who is paying you. + + + + + &Copy Address + + + + + Show &QR Code + + + + + Sign a message to prove you own a Arepacoin address + + + + + Sign &Message + + + + + Delete the currently selected address from the list + + + + + Verify a message to ensure it was signed with a specified Arepacoin address + + + + + &Verify Message + + + + + &Delete + Выдаліць + + + + Copy &Label + + + + + &Edit + + + + + Export Address Book Data + + + + + Comma separated file (*.csv) + Коскамі падзелены файл (*.csv) + + + + Error exporting + + + + + Could not write to file %1. + + + + + AddressTableModel + + + Label + Пазнака + + + + Address + Адрас + + + + (no label) + непазначаны + + + + AskPassphraseDialog + + + Passphrase Dialog + + + + + Enter passphrase + Увядзіце кодавую фразу + + + + New passphrase + Новая кодавая фраза + + + + Repeat new passphrase + Паўтарыце новую кодавую фразу + + + + Serves to disable the trivial sendmoney when OS account compromised. Provides no real security. + + + + + For staking only + + + + + Enter the new passphrase to the wallet.<br/>Please use a passphrase of <b>10 or more random characters</b>, or <b>eight or more words</b>. + Увядзіце новую кодавую фразу для гаманца. <br/>Калі ласка, ўжывайце пароль <b>не меньша за 10 адвольных сімвалаў</b>, ці <b>болей васьмі слоў</b>. + + + + Encrypt wallet + Зашыфраваць гаманец. + + + + This operation needs your wallet passphrase to unlock the wallet. + Гэтая аперацыя патрабуе кодавую фразу, каб рзблакаваць гаманец. + + + + Unlock wallet + Разблакаваць гаманец + + + + This operation needs your wallet passphrase to decrypt the wallet. + Гэтая аперацыя патрабуе пароль каб расшыфраваць гаманец. + + + + Decrypt wallet + Рачшыфраваць гаманец + + + + Change passphrase + Змяніць пароль + + + + Enter the old and new passphrase to the wallet. + Увядзіце стары і новы пароль да гаманца. + + + + Confirm wallet encryption + Пацвердзіце шыфраванне гаманца + + + + Warning: If you encrypt your wallet and lose your passphrase, you will <b>LOSE ALL OF YOUR COINS</b>! + + + + + Are you sure you wish to encrypt your wallet? + + + + + IMPORTANT: Any previous backups you have made of your wallet file should be replaced with the newly generated, encrypted wallet file. For security reasons, previous backups of the unencrypted wallet file will become useless as soon as you start using the new, encrypted wallet. + + + + + + Warning: The Caps Lock key is on! + + + + + + Wallet encrypted + Гаманец зашыфраваны + + + + Arepacoin will close now to finish the encryption process. Remember that encrypting your wallet cannot fully protect your coins from being stolen by malware infecting your computer. + + + + + + + + Wallet encryption failed + Шыфраванне гаманца няўдалае + + + + Wallet encryption failed due to an internal error. Your wallet was not encrypted. + Шыфраванне гаманца не адбылося з-за ўнутранай памылкі. Гаманец незашыфраваны. + + + + + The supplied passphrases do not match. + Уведдзеныя паролі не супадаюць + + + + Wallet unlock failed + Разблакаванне гаманца няўдалае + + + + + + The passphrase entered for the wallet decryption was incorrect. + Уведзена пароль дзеля расшыфравання гаманца памылковы + + + + Wallet decryption failed + Расшыфраванне гаманца няўдалае + + + + Wallet passphrase was successfully changed. + + + + + BitcoinGUI + + + Sign &message... + + + + + Synchronizing with network... + Сінхранізацыя з сецівам... + + + + &Overview + Агляд + + + + Show general overview of wallet + Паказвае агульныя звесткі аб гаманцы + + + + &Transactions + Транзакцыі + + + + Browse transaction history + Праглядзець гісторыю транзакцый + + + + &Address Book + + + + + Edit the list of stored addresses and labels + + + + + &Receive coins + + + + + Show the list of addresses for receiving payments + + + + + &Send coins + + + + + E&xit + Выйсці + + + + Quit application + Выйсці з праграмы + + + + Show information about Arepacoin + + + + + About &Qt + Аб Qt + + + + Show information about Qt + Паказаць інфармацыю аб Qt + + + + &Options... + Опцыі... + + + + &Encrypt Wallet... + + + + + &Backup Wallet... + + + + + &Change Passphrase... + + + + + ~%n block(s) remaining + + + + + Downloaded %1 of %2 blocks of transaction history (%3% done). + + + + + &Export... + + + + + Send coins to a Arepacoin address + + + + + Modify configuration options for Arepacoin + + + + + Export the data in the current tab to a file + + + + + Encrypt or decrypt wallet + + + + + Backup wallet to another location + Зрабіце копію гаманца ў іншае месца + + + + Change the passphrase used for wallet encryption + Змяніць пароль шыфравання гаманца + + + + &Debug window + + + + + Open debugging and diagnostic console + + + + + &Verify message... + + + + + Arepacoin + + + + + Wallet + + + + + &About Arepacoin + + + + + &Show / Hide + + + + + Unlock wallet + + + + + &Lock Wallet + + + + + Lock wallet + + + + + &File + Ф&айл + + + + &Settings + Наладкі + + + + &Help + Дапамога + + + + Tabs toolbar + + + + + Actions toolbar + + + + + + [testnet] + [testnet] + + + + + Arepacoin client + + + + + %n active connection(s) to Arepacoin network + + + + + Downloaded %1 blocks of transaction history. + + + + + Staking.<br>Your weight is %1<br>Network weight is %2<br>Expected time to earn reward is %3 + + + + + Not staking because wallet is locked + + + + + Not staking because wallet is offline + + + + + Not staking because wallet is syncing + + + + + Not staking because you don't have mature coins + + + + + %n second(s) ago + + + + + &Unlock Wallet... + + + + + %n minute(s) ago + + + + + %n hour(s) ago + + + + + %n day(s) ago + + + + + Up to date + Сінхранізавана + + + + Catching up... + Наганяем... + + + + Last received block was generated %1. + + + + + This transaction is over the size limit. You can still send it for a fee of %1, which goes to the nodes that process your transaction and helps to support the network. Do you want to pay the fee? + + + + + Confirm transaction fee + + + + + Sent transaction + Дасланыя транзакцыі + + + + Incoming transaction + Прынятыя транзакцыі + + + + Date: %1 +Amount: %2 +Type: %3 +Address: %4 + + Дата: %1 +Колькасць: %2 +Тып: %3 +Адрас: %4 + + + + + + URI handling + + + + + + URI can not be parsed! This can be caused by an invalid Arepacoin address or malformed URI parameters. + + + + + Wallet is <b>encrypted</b> and currently <b>unlocked</b> + Гаманец <b>зашыфраваны</b> і зараз <b>разблакаваны</b> + + + + Wallet is <b>encrypted</b> and currently <b>locked</b> + Гаманец <b>зашыфраваны</b> і зараз <b>заблакаваны</b> + + + + Backup Wallet + + + + + Wallet Data (*.dat) + + + + + Backup Failed + + + + + There was an error trying to save the wallet data to the new location. + + + + + %n second(s) + + + + + %n minute(s) + + + + + %n hour(s) + + + + + %n day(s) + + + + + Not staking + + + + + A fatal error occurred. Arepacoin can no longer continue safely and will quit. + + + + + ClientModel + + + Network Alert + + + + + CoinControlDialog + + + Coin Control + + + + + Quantity: + + + + + Bytes: + + + + + Amount: + + + + + Priority: + + + + + Fee: + + + + + Low Output: + + + + + no + + + + + After Fee: + + + + + Change: + + + + + (un)select all + + + + + Tree mode + + + + + List mode + + + + + Amount + Колькасць + + + + Label + + + + + Address + Адрас + + + + Date + Дата + + + + Confirmations + + + + + Confirmed + Пацверджана + + + + Priority + + + + + Copy address + Капіяваць адрас + + + + Copy label + Капіяваць пазнаку + + + + + Copy amount + Капіяваць колькасць + + + + Copy transaction ID + Капіяваць ID транзакцыі + + + + Copy quantity + + + + + Copy fee + + + + + Copy after fee + + + + + Copy bytes + + + + + Copy priority + + + + + Copy low output + + + + + Copy change + + + + + highest + + + + + high + + + + + medium-high + + + + + medium + + + + + low-medium + + + + + low + + + + + lowest + + + + + DUST + + + + + yes + + + + + This label turns red, if the transaction size is bigger than 10000 bytes. + + This means a fee of at least %1 per kb is required. + + Can vary +/- 1 Byte per input. + + + + + Transactions with higher priority get more likely into a block. + +This label turns red, if the priority is smaller than "medium". + + This means a fee of at least %1 per kb is required. + + + + + This label turns red, if any recipient receives an amount smaller than %1. + + This means a fee of at least %2 is required. + + Amounts below 0.546 times the minimum relay fee are shown as DUST. + + + + + This label turns red, if the change is smaller than %1. + + This means a fee of at least %2 is required. + + + + + + (no label) + непазначаны + + + + change from %1 (%2) + + + + + (change) + + + + + EditAddressDialog + + + Edit Address + Рэдагаваць Адрас + + + + &Label + Пазнака + + + + The label associated with this address book entry + + + + + &Address + Адрас + + + + The address associated with this address book entry. This can only be modified for sending addresses. + + + + + New receiving address + Новы адрас для атрымання + + + + New sending address + Новы адрас для дасылання + + + + Edit receiving address + Рэдагаваць адрас прымання + + + + Edit sending address + Рэдагаваць адрас дасылання + + + + The entered address "%1" is already in the address book. + Уведзены адрас "%1" ужо ў кніге адрасоў + + + + The entered address "%1" is not a valid Arepacoin address. + + + + + Could not unlock wallet. + Немагчыма разблакаваць гаманец + + + + New key generation failed. + Генерацыя новага ключа няўдалая + + + + GUIUtil::HelpMessageBox + + + + Arepacoin-Qt + + + + + version + + + + + Usage: + + + + + command-line options + + + + + UI options + + + + + Set language, for example "de_DE" (default: system locale) + + + + + Start minimized + + + + + Show splash screen on startup (default: 1) + + + + + OptionsDialog + + + Options + Опцыі + + + + &Main + + + + + Optional transaction fee per kB that helps make sure your transactions are processed quickly. Most transactions are 1 kB. Fee 0.01 recommended. + + + + + Pay transaction &fee + + + + + Reserved amount does not participate in staking and is therefore spendable at any time. + + + + + Reserve + + + + + Automatically start Arepacoin after logging in to the system. + + + + + &Start Arepacoin on system login + + + + + Detach block and address databases at shutdown. This means they can be moved to another data directory, but it slows down shutdown. The wallet is always detached. + + + + + &Detach databases at shutdown + + + + + &Network + + + + + Automatically open the Arepacoin client port on the router. This only works when your router supports UPnP and it is enabled. + + + + + Map port using &UPnP + + + + + Connect to the Arepacoin network through a SOCKS proxy (e.g. when connecting through Tor). + + + + + &Connect through SOCKS proxy: + + + + + Proxy &IP: + + + + + IP address of the proxy (e.g. 127.0.0.1) + + + + + &Port: + + + + + Port of the proxy (e.g. 9050) + + + + + SOCKS &Version: + + + + + SOCKS version of the proxy (e.g. 5) + + + + + &Window + + + + + Show only a tray icon after minimizing the window. + + + + + &Minimize to the tray instead of the taskbar + + + + + Minimize instead of exit the application when the window is closed. When this option is enabled, the application will be closed only after selecting Quit in the menu. + + + + + M&inimize on close + + + + + &Display + + + + + User Interface &language: + + + + + The user interface language can be set here. This setting will take effect after restarting Arepacoin. + + + + + &Unit to show amounts in: + + + + + Choose the default subdivision unit to show in the interface and when sending coins. + + + + + Whether to show Arepacoin addresses in the transaction list or not. + + + + + &Display addresses in transaction list + + + + + Whether to show coin control features or not. + + + + + Display coin &control features (experts only!) + + + + + &OK + + + + + &Cancel + + + + + &Apply + + + + + default + + + + + + Warning + + + + + + This setting will take effect after restarting Arepacoin. + + + + + The supplied proxy address is invalid. + + + + + OverviewPage + + + Form + Форма + + + + + The displayed information may be out of date. Your wallet automatically synchronizes with the Arepacoin network after a connection is established, but this process has not completed yet. + + + + + Stake: + + + + + Unconfirmed: + + + + + Wallet + + + + + Spendable: + + + + + Your current spendable balance + + + + + Immature: + + + + + Mined balance that has not yet matured + + + + + Total: + + + + + Your current total balance + + + + + <b>Recent transactions</b> + <b>Нядаўнія транзаццыі</b> + + + + Total of transactions that have yet to be confirmed, and do not yet count toward the current balance + + + + + Total of coins that was staked, and do not yet count toward the current balance + + + + + + out of sync + + + + + QRCodeDialog + + + QR Code Dialog + + + + + Request Payment + + + + + Amount: + + + + + Label: + + + + + Message: + + + + + &Save As... + + + + + Error encoding URI into QR Code. + + + + + The entered amount is invalid, please check. + + + + + Resulting URI too long, try to reduce the text for label / message. + + + + + Save QR Code + + + + + PNG Images (*.png) + + + + + RPCConsole + + + Client name + + + + + + + + + + + + + + N/A + + + + + Client version + + + + + &Information + + + + + Using OpenSSL version + + + + + Startup time + + + + + Network + + + + + Number of connections + + + + + On testnet + + + + + Block chain + + + + + Current number of blocks + + + + + Estimated total blocks + + + + + Last block time + + + + + &Open + + + + + Command-line options + + + + + Show the Arepacoin-Qt help message to get a list with possible Arepacoin command-line options. + + + + + &Show + + + + + &Console + + + + + Build date + + + + + Arepacoin - Debug window + + + + + Arepacoin Core + + + + + Debug log file + + + + + Open the Arepacoin debug log file from the current data directory. This can take a few seconds for large log files. + + + + + Clear console + + + + + Welcome to the Arepacoin RPC console. + + + + + Use up and down arrows to navigate history, and <b>Ctrl-L</b> to clear screen. + + + + + Type <b>help</b> for an overview of available commands. + + + + + SendCoinsDialog + + + + + + + + + + Send Coins + Даслаць Манеты + + + + Coin Control Features + + + + + Inputs... + + + + + automatically selected + + + + + Insufficient funds! + + + + + Quantity: + + + + + + 0 + + + + + Bytes: + + + + + Amount: + + + + + + + + 0.00 BC + + + + + Priority: + + + + + medium + + + + + Fee: + + + + + Low Output: + + + + + no + + + + + After Fee: + + + + + Change + + + + + custom change address + + + + + Send to multiple recipients at once + Даслаць адразу некалькім атрымальнікам + + + + Add &Recipient + + + + + Remove all transaction fields + + + + + Clear &All + + + + + Balance: + Баланс: + + + + 123.456 BC + + + + + Confirm the send action + Пацвердзіць дасыланне + + + + S&end + + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Copy quantity + + + + + Copy amount + Капіяваць колькасць + + + + Copy fee + + + + + Copy after fee + + + + + Copy bytes + + + + + Copy priority + + + + + Copy low output + + + + + Copy change + + + + + <b>%1</b> to %2 (%3) + + + + + Confirm send coins + Пацвердзіць дасыланне манет + + + + Are you sure you want to send %1? + + + + + and + + + + + The recipient address is not valid, please recheck. + + + + + The amount to pay must be larger than 0. + Велічыня плацяжу мае быць больш за 0. + + + + The amount exceeds your balance. + + + + + The total exceeds your balance when the %1 transaction fee is included. + + + + + Duplicate address found, can only send to each address once per send operation. + + + + + Error: Transaction creation failed. + + + + + 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. + + + + + WARNING: Invalid Arepacoin address + + + + + (no label) + непазначаны + + + + WARNING: unknown change address + + + + + SendCoinsEntry + + + Form + + + + + A&mount: + Колькасць: + + + + Pay &To: + Заплаціць да: + + + + + Enter a label for this address to add it to your address book + Увядзіце пазнаку гэтаму адрасу, каб дадаць яго ў адрасную кнігу + + + + &Label: + Пазнака: + + + + The address to send the payment to (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Choose address from address book + + + + + Alt+A + Alt+A + + + + Paste address from clipboard + Уставіць адрас з буферу абмена + + + + Alt+P + Alt+P + + + + Remove this recipient + + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + SignVerifyMessageDialog + + + Signatures - Sign / Verify a Message + + + + + + &Sign Message + + + + + You can sign messages with your addresses to prove you own them. Be careful not to sign anything vague, as phishing attacks may try to trick you into signing your identity over to them. Only sign fully-detailed statements you agree to. + + + + + The address to sign the message with (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + + Choose an address from the address book + + + + + + Alt+A + Alt+A + + + + Paste address from clipboard + Уставіць адрас з буферу абмена + + + + Alt+P + Alt+P + + + + Enter the message you want to sign here + + + + + Copy the current signature to the system clipboard + + + + + Sign the message to prove you own this Arepacoin address + + + + + Reset all sign message fields + + + + + + Clear &All + + + + + + &Verify Message + + + + + Enter the signing address, message (ensure you copy line breaks, spaces, tabs, etc. exactly) and signature below to verify the message. Be careful not to read more into the signature than what is in the signed message itself, to avoid being tricked by a man-in-the-middle attack. + + + + + The address the message was signed with (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Verify the message to ensure it was signed with the specified Arepacoin address + + + + + Reset all verify message fields + + + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Click "Sign Message" to generate signature + + + + + Enter Arepacoin signature + + + + + + The entered address is invalid. + + + + + + + + Please check the address and try again. + + + + + + The entered address does not refer to a key. + + + + + Wallet unlock was cancelled. + + + + + Private key for the entered address is not available. + + + + + Message signing failed. + + + + + Message signed. + + + + + The signature could not be decoded. + + + + + + Please check the signature and try again. + + + + + The signature did not match the message digest. + + + + + Message verification failed. + + + + + Message verified. + + + + + TransactionDesc + + + Open until %1 + + + + + Open for %n block(s) + + + + + conflicted + + + + + %1/offline + + + + + %1/unconfirmed + %1/непацверджана + + + + %1 confirmations + %1 пацверджанняў + + + + Status + + + + + , broadcast through %n node(s) + + + + + Date + Дата + + + + Source + + + + + Generated + + + + + + From + + + + + + + To + + + + + + own address + + + + + label + + + + + + + + + Credit + + + + + matures in %n more block(s) + + + + + not accepted + + + + + + + + Debit + + + + + Transaction fee + + + + + Net amount + + + + + Message + + + + + Comment + + + + + Transaction ID + + + + + Generated coins must mature 6 blocks before they can be spent. When you generated this block, it was broadcast to the network to be added to the block chain. If it fails to get into the chain, its state will change to "not accepted" and it won't be spendable. This may occasionally happen if another node generates a block within a few seconds of yours. + + + + + Debug information + + + + + Transaction + + + + + Inputs + + + + + Amount + Колькасць + + + + true + + + + + false + + + + + , has not been successfully broadcast yet + , пакуль не было паспяхова транслявана + + + + unknown + невядома + + + + TransactionDescDialog + + + Transaction details + Дэталі транзакцыі + + + + This pane shows a detailed description of the transaction + Гэтая панэль паказвае дэтальнае апісанне транзакцыі + + + + TransactionTableModel + + + Date + Дата + + + + Type + Тып + + + + Address + Адрас + + + + Amount + Колькасць + + + + Open until %1 + + + + + Confirmed (%1 confirmations) + Пацверджана (%1 пацверджанняў) + + + + Open for %n more block(s) + + + + + Offline + + + + + Unconfirmed + + + + + Confirming (%1 of %2 recommended confirmations) + + + + + Conflicted + + + + + Immature (%1 confirmations, will be available after %2) + + + + + This block was not received by any other nodes and will probably not be accepted! + Гэты блок не быў прыняты іншымі вузламі і магчыма не будзе ўхвалены! + + + + Generated but not accepted + Згенеравана, але не прынята + + + + Received with + Прынята з + + + + Received from + Прынята ад + + + + Sent to + Даслана да + + + + Payment to yourself + Плацёж самому сабе + + + + Mined + Здабыта + + + + (n/a) + (n/a) + + + + Transaction status. Hover over this field to show number of confirmations. + Статус транзакцыі. Навядзіце курсар на гэтае поле, каб паказаць колькасць пацверджанняў. + + + + Date and time that the transaction was received. + Дата і час, калі транзакцыя была прынята. + + + + Type of transaction. + Тып транзакцыі + + + + Destination address of transaction. + Адрас прызначэння транзакцыі. + + + + Amount removed from or added to balance. + Колькасць аднятая ці даданая да балансу. + + + + TransactionView + + + + All + Усё + + + + Today + Сёння + + + + This week + Гэты тыдзень + + + + This month + Гэты месяц + + + + Last month + Мінулы месяц + + + + This year + Гэты год + + + + Range... + Прамежак... + + + + Received with + Прынята з + + + + Sent to + Даслана да + + + + To yourself + Да сябе + + + + Mined + Здабыта + + + + Other + Іншыя + + + + Enter address or label to search + Увядзіце адрас ці пазнаку для пошуку + + + + Min amount + Мін. колькасць + + + + Copy address + Капіяваць адрас + + + + Copy label + Капіяваць пазнаку + + + + Copy amount + Капіяваць колькасць + + + + Copy transaction ID + Капіяваць ID транзакцыі + + + + Edit label + Рэдагаваць пазнаку + + + + Show transaction details + + + + + Export Transaction Data + + + + + Comma separated file (*.csv) + Коскамі падзелены файл (*.csv) + + + + Confirmed + Пацверджана + + + + Date + Дата + + + + Type + Тып + + + + Label + Пазнака + + + + Address + Адрас + + + + Amount + Колькасць + + + + ID + ID + + + + Error exporting + + + + + Could not write to file %1. + + + + + Range: + Прамежак: + + + + to + да + + + + WalletModel + + + Sending... + + + + + bitcoin-core + + + Arepacoin version + + + + + Usage: + Ужыванне: + + + + Send command to -server or arepacoind + + + + + List commands + Спіс каманд + + + + Get help for a command + Атрымаць дапамогу для каманды + + + + Options: + Опцыі: + + + + Specify configuration file (default: arepacoin.conf) + + + + + Specify pid file (default: arepacoind.pid) + + + + + Specify wallet file (within data directory) + + + + + Specify data directory + Вызначыць каталог даных + + + + Set database cache size in megabytes (default: 25) + Пазначыць памер кэшу базы звестак у мегабайтах (тыпова: 25) + + + + Set database disk log size in megabytes (default: 100) + + + + + Listen for connections on <port> (default: 9853 or testnet: 19853) + + + + + Maintain at most <n> connections to peers (default: 125) + Трымаць не больш за <n> злучэнняў на асобу (зыходна: 125) + + + + Connect to a node to retrieve peer addresses, and disconnect + + + + + Specify your own public address + + + + + Bind to given address. Use [host]:port notation for IPv6 + + + + + Stake your coins to support network and gain reward (default: 1) + + + + + Threshold for disconnecting misbehaving peers (default: 100) + Парог для адлучэння злаўмысных карыстальнікаў (тыпова: 100) + + + + Number of seconds to keep misbehaving peers from reconnecting (default: 86400) + Колькасць секунд для ўстрымання асобаў да перадалучэння (заходна: 86400) + + + + An error occurred while setting up the RPC port %u for listening on IPv4: %s + + + + + Detach block and address databases. Increases shutdown time (default: 0) + + + + + 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. + + + + + Error: This transaction requires a transaction fee of at least %s because of its amount, complexity, or use of recently received funds + + + + + Listen for JSON-RPC connections on <port> (default: 9852 or testnet: 19852) + + + + + Accept command line and JSON-RPC commands + Прымаць камандны радок і JSON-RPC каманды + + + + Error: Transaction creation failed + + + + + Error: Wallet locked, unable to create transaction + + + + + Importing blockchain data file. + + + + + Importing bootstrap blockchain data file. + + + + + Run in the background as a daemon and accept commands + Запусціць у фоне як дэман і прымаць каманды + + + + Use the test network + Ужываць тэставае сеціва + + + + Accept connections from outside (default: 1 if no -proxy or -connect) + + + + + An error occurred while setting up the RPC port %u for listening on IPv6, falling back to IPv4: %s + + + + + Error initializing database environment %s! To recover, BACKUP THAT DIRECTORY, then remove everything from it except for wallet.dat. + + + + + Set maximum size of high-priority/low-fee transactions in bytes (default: 27000) + + + + + Warning: -paytxfee is set very high! This is the transaction fee you will pay if you send a transaction. + + + + + Warning: Please check that your computer's date and time are correct! If your clock is wrong Arepacoin will not work properly. + + + + + Warning: error reading wallet.dat! All keys read correctly, but transaction data or address book entries might be missing or incorrect. + + + + + Warning: wallet.dat corrupt, data salvaged! Original wallet.dat saved as wallet.{timestamp}.bak in %s; if your balance or transactions are incorrect you should restore from a backup. + + + + + Attempt to recover private keys from a corrupt wallet.dat + + + + + Block creation options: + + + + + Connect only to the specified node(s) + + + + + Discover own IP address (default: 1 when listening and no -externalip) + + + + + Failed to listen on any port. Use -listen=0 if you want this. + + + + + Find peers using DNS lookup (default: 1) + + + + + Sync checkpoints policy (default: strict) + + + + + Invalid -tor address: '%s' + + + + + Invalid amount for -reservebalance=<amount> + + + + + Maximum per-connection receive buffer, <n>*1000 bytes (default: 5000) + + + + + Maximum per-connection send buffer, <n>*1000 bytes (default: 1000) + + + + + Only connect to nodes in network <net> (IPv4, IPv6 or Tor) + + + + + Output extra debugging information. Implies all other -debug* options + + + + + Output extra network debugging information + + + + + Prepend debug output with timestamp + + + + + SSL options: (see the Bitcoin Wiki for SSL setup instructions) + + + + + Select the version of socks proxy to use (4-5, default: 5) + + + + + Send trace/debug info to console instead of debug.log file + Слаць trace/debug звесткі ў кансоль замест файла debug.log + + + + Send trace/debug info to debugger + + + + + Set maximum block size in bytes (default: 250000) + + + + + Set minimum block size in bytes (default: 0) + + + + + Shrink debug.log file on client startup (default: 1 when no -debug) + + + + + Specify connection timeout in milliseconds (default: 5000) + + + + + Unable to sign checkpoint, wrong checkpointkey? + + + + + + Use UPnP to map the listening port (default: 0) + + + + + Use UPnP to map the listening port (default: 1 when listening) + + + + + Use proxy to reach tor hidden services (default: same as -proxy) + + + + + Username for JSON-RPC connections + Імя карыстальника для JSON-RPC злучэнняў + + + + Verifying database integrity... + + + + + WARNING: syncronized checkpoint violation detected, but skipped! + + + + + Warning: Disk space is low! + + + + + Warning: This version is obsolete, upgrade required! + + + + + wallet.dat corrupt, salvage failed + + + + + Password for JSON-RPC connections + Пароль для JSON-RPC злучэнняў + + + + %s, you must set a rpcpassword in the configuration file: + %s +It is recommended you use the following random password: +rpcuser=arepacoinrpc +rpcpassword=%s +(you do not need to remember this password) +The username and password MUST NOT be the same. +If the file does not exist, create it with owner-readable-only file permissions. +It is also recommended to set alertnotify so you are notified of problems; +for example: alertnotify=echo %%s | mail -s "Arepacoin Alert" admin@foo.com + + + + + + Find peers using internet relay chat (default: 0) + + + + + Sync time with other nodes. Disable if time on your system is precise e.g. syncing with NTP (default: 1) + + + + + When creating transactions, ignore inputs with value less than this (default: 0.01) + + + + + Allow JSON-RPC connections from specified IP address + Дазволіць JSON-RPC злучэнні з пэўнага IP адрасу + + + + Send commands to node running on <ip> (default: 127.0.0.1) + Адпраўляць каманды вузлу на <ip> (зыходна: 127.0.0.1) + + + + Execute command when the best block changes (%s in cmd is replaced by block hash) + Выканаць каманду калі лепшы блок зменіцца (%s замяняецца на хэш блока) + + + + Execute command when a wallet transaction changes (%s in cmd is replaced by TxID) + + + + + Require a confirmations for change (default: 0) + + + + + Enforce transaction scripts to use canonical PUSH operators (default: 1) + + + + + Execute command when a relevant alert is received (%s in cmd is replaced by message) + + + + + Upgrade wallet to latest format + Абнавіць гаманец на новы фармат + + + + Set key pool size to <n> (default: 100) + Устанавіць памер фонда ключоў у <n> (тыпова: 100) + + + + Rescan the block chain for missing wallet transactions + Перасканаваць ланцуг блокаў дзеля пошуку адсутных транзакцый + + + + How many blocks to check at startup (default: 2500, 0 = all) + + + + + How thorough the block verification is (0-6, default: 1) + + + + + Imports blocks from external blk000?.dat file + + + + + Use OpenSSL (https) for JSON-RPC connections + Ужываць OpenSSL (https) для JSON-RPC злучэнняў + + + + Server certificate file (default: server.cert) + Файл-сертыфікат сервера (зыходна: server.cert) + + + + Server private key (default: server.pem) + Прыватны ключ сервера (зыходна: server.pem) + + + + Acceptable ciphers (default: TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH) + + + + + Error: Wallet unlocked for staking only, unable to create transaction. + + + + + WARNING: Invalid checkpoint found! Displayed transactions may not be correct! You may need to upgrade, or notify developers. + + + + + This help message + + + + + Wallet %s resides outside data directory %s. + + + + + Cannot obtain a lock on data directory %s. Arepacoin is probably already running. + + + + + Arepacoin + + + + + Unable to bind to %s on this computer (bind returned error %d, %s) + + + + + Connect through socks proxy + + + + + Allow DNS lookups for -addnode, -seednode and -connect + + + + + Loading addresses... + Загружаем адрасы... + + + + Error loading blkindex.dat + + + + + Error loading wallet.dat: Wallet corrupted + Памылка загрузкі wallet.dat: гаманец пашкоджаны + + + + Error loading wallet.dat: Wallet requires newer version of Arepacoin + + + + + Wallet needed to be rewritten: restart Arepacoin to complete + + + + + Error loading wallet.dat + Памылка загрузкі wallet.dat + + + + Invalid -proxy address: '%s' + + + + + Unknown network specified in -onlynet: '%s' + + + + + Unknown -socks proxy version requested: %i + + + + + Cannot resolve -bind address: '%s' + + + + + Cannot resolve -externalip address: '%s' + + + + + Invalid amount for -paytxfee=<amount>: '%s' + + + + + Error: could not start node + + + + + Sending... + + + + + Invalid amount + Памылковая колькасць + + + + Insufficient funds + Недастаткова сродкаў + + + + Loading block index... + Загружаем індэкс блокаў... + + + + Add a node to connect to and attempt to keep the connection open + + + + + Unable to bind to %s on this computer. Arepacoin is probably already running. + + + + + Fee per KB to add to transactions you send + + + + + Invalid amount for -mininput=<amount>: '%s' + + + + + Loading wallet... + Загружаем гаманец... + + + + Cannot downgrade wallet + + + + + Cannot initialize keypool + + + + + Cannot write default address + + + + + Rescanning... + Перасканаванне... + + + + Done loading + Загрузка выканана + + + + To use the %s option + + + + + Error + Памылка + + + + You must set rpcpassword=<password> in the configuration file: +%s +If the file does not exist, create it with owner-readable-only file permissions. + + + + \ No newline at end of file diff --git a/src/qt/locale/bitcoin_bg.ts b/src/qt/locale/bitcoin_bg.ts new file mode 100755 index 0000000..b46dfe8 --- /dev/null +++ b/src/qt/locale/bitcoin_bg.ts @@ -0,0 +1,3280 @@ + + + AboutDialog + + + About Arepacoin + + + + + <b>Arepacoin</b> version + + + + + Copyright © 2009-2014 The Bitcoin developers +Copyright © 2012-2014 The NovaCoin developers +Copyright © 2014 The Arepacoin developers + + + + + +This is experimental software. + +Distributed under the MIT/X11 software license, see the accompanying file COPYING or http://www.opensource.org/licenses/mit-license.php. + +This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit (http://www.openssl.org/) and cryptographic software written by Eric Young (eay@cryptsoft.com) and UPnP software written by Thomas Bernard. + +Това е експериментален софтуер. + +Разпространява се под MIT/X11 софтуерен лиценз, виж COPYING или http://www.opensource.org/licenses/mit-license.php. + +Използван е софтуер, разработен от OpenSSL Project за употреба в OpenSSL Toolkit (http://www.openssl.org/), криптографски софтуер разработен от Eric Young (eay@cryptsoft.com) и UPnP софтуер разработен от Thomas Bernard. + + + + AddressBookPage + + + Address Book + + + + + Double-click to edit address or label + Двоен клик за редакция на адрес или име + + + + Create a new address + Създаване на нов адрес + + + + Copy the currently selected address to the system clipboard + Копирай избрания адрес + + + + &New Address + + + + + These are your Arepacoin addresses for receiving payments. You may want to give a different one to each sender so you can keep track of who is paying you. + + + + + &Copy Address + &Копирай + + + + Show &QR Code + + + + + Sign a message to prove you own a Arepacoin address + + + + + Sign &Message + + + + + Delete the currently selected address from the list + Изтрий избрания адрес от списъка + + + + Verify a message to ensure it was signed with a specified Arepacoin address + + + + + &Verify Message + + + + + &Delete + &Изтрий + + + + Copy &Label + Копирай &име + + + + &Edit + &Редактирай + + + + Export Address Book Data + + + + + Comma separated file (*.csv) + CSV файл (*.csv) + + + + Error exporting + + + + + Could not write to file %1. + + + + + AddressTableModel + + + Label + Име + + + + Address + Адрес + + + + (no label) + (без име) + + + + AskPassphraseDialog + + + Passphrase Dialog + + + + + Enter passphrase + Въведи парола + + + + New passphrase + Нова парола + + + + Repeat new passphrase + Още веднъж + + + + Serves to disable the trivial sendmoney when OS account compromised. Provides no real security. + + + + + For staking only + + + + + Enter the new passphrase to the wallet.<br/>Please use a passphrase of <b>10 or more random characters</b>, or <b>eight or more words</b>. + Въведете нова парола за портфейла.<br/>Моля използвайте <b>поне 10 случайни символа</b> или <b>8 или повече думи</b>. + + + + Encrypt wallet + Криптиране на портфейла + + + + This operation needs your wallet passphrase to unlock the wallet. + Тази операция изисква Вашата парола за отключване на портфейла. + + + + Unlock wallet + Отключване на портфейла + + + + This operation needs your wallet passphrase to decrypt the wallet. + Тази операция изисква Вашата парола за декриптиране на портфейла. + + + + Decrypt wallet + Декриптиране на портфейла + + + + Change passphrase + Смяна на паролата + + + + Enter the old and new passphrase to the wallet. + Въведете текущата и новата парола за портфейла. + + + + Confirm wallet encryption + Потвърждаване на криптирането + + + + Warning: If you encrypt your wallet and lose your passphrase, you will <b>LOSE ALL OF YOUR COINS</b>! + + + + + Are you sure you wish to encrypt your wallet? + + + + + IMPORTANT: Any previous backups you have made of your wallet file should be replaced with the newly generated, encrypted wallet file. For security reasons, previous backups of the unencrypted wallet file will become useless as soon as you start using the new, encrypted wallet. + + + + + + Warning: The Caps Lock key is on! + + + + + + Wallet encrypted + Портфейлът е криптиран + + + + Arepacoin will close now to finish the encryption process. Remember that encrypting your wallet cannot fully protect your coins from being stolen by malware infecting your computer. + + + + + + + + Wallet encryption failed + Криптирането беше неуспешно + + + + Wallet encryption failed due to an internal error. Your wallet was not encrypted. + Криптирането на портфейла беше неуспешно поради неизвестен проблем. Портфейлът не е криптиран. + + + + + The supplied passphrases do not match. + Паролите не съвпадат + + + + Wallet unlock failed + Отключването беше неуспешно + + + + + + The passphrase entered for the wallet decryption was incorrect. + Паролата въведена за декриптиране на портфейла е грешна. + + + + Wallet decryption failed + Декриптирането беше неуспешно + + + + Wallet passphrase was successfully changed. + Паролата на портфейла беше променена успешно. + + + + BitcoinGUI + + + Sign &message... + Подписване на &съобщение... + + + + Synchronizing with network... + Синхронизиране с мрежата... + + + + &Overview + &Баланс + + + + Show general overview of wallet + Обобщена информация за портфейла + + + + &Transactions + &Транзакции + + + + Browse transaction history + История на транзакциите + + + + &Address Book + + + + + Edit the list of stored addresses and labels + + + + + &Receive coins + + + + + Show the list of addresses for receiving payments + + + + + &Send coins + + + + + E&xit + Из&ход + + + + Quit application + Изход от приложението + + + + Show information about Arepacoin + + + + + About &Qt + За &Qt + + + + Show information about Qt + Покажи информация за Qt + + + + &Options... + &Опции... + + + + &Encrypt Wallet... + &Криптиране на портфейла... + + + + &Backup Wallet... + &Запазване на портфейла... + + + + &Change Passphrase... + &Смяна на паролата... + + + + ~%n block(s) remaining + + + + + Downloaded %1 of %2 blocks of transaction history (%3% done). + + + + + &Export... + + + + + Send coins to a Arepacoin address + + + + + Modify configuration options for Arepacoin + + + + + Export the data in the current tab to a file + + + + + Encrypt or decrypt wallet + + + + + Backup wallet to another location + + + + + Change the passphrase used for wallet encryption + Променя паролата за портфейла + + + + &Debug window + + + + + Open debugging and diagnostic console + + + + + &Verify message... + &Проверка на съобщение... + + + + Arepacoin + + + + + Wallet + Портфейл + + + + &About Arepacoin + + + + + &Show / Hide + + + + + Unlock wallet + + + + + &Lock Wallet + + + + + Lock wallet + + + + + &File + &Файл + + + + &Settings + &Настройки + + + + &Help + &Помощ + + + + Tabs toolbar + Раздели + + + + Actions toolbar + + + + + + [testnet] + [testnet] + + + + + Arepacoin client + + + + + %n active connection(s) to Arepacoin network + + + + + Downloaded %1 blocks of transaction history. + + + + + Staking.<br>Your weight is %1<br>Network weight is %2<br>Expected time to earn reward is %3 + + + + + Not staking because wallet is locked + + + + + Not staking because wallet is offline + + + + + Not staking because wallet is syncing + + + + + Not staking because you don't have mature coins + + + + + %n second(s) ago + + + + + &Unlock Wallet... + + + + + %n minute(s) ago + + + + + %n hour(s) ago + + + + + %n day(s) ago + + + + + Up to date + Синхронизиран + + + + Catching up... + Зарежда блокове... + + + + Last received block was generated %1. + + + + + This transaction is over the size limit. You can still send it for a fee of %1, which goes to the nodes that process your transaction and helps to support the network. Do you want to pay the fee? + + + + + Confirm transaction fee + + + + + Sent transaction + Изходяща транзакция + + + + Incoming transaction + Входяща транзакция + + + + Date: %1 +Amount: %2 +Type: %3 +Address: %4 + + + + + + + URI handling + + + + + + URI can not be parsed! This can be caused by an invalid Arepacoin address or malformed URI parameters. + + + + + Wallet is <b>encrypted</b> and currently <b>unlocked</b> + Портфейлът е <b>криптиран</b> и <b>отключен</b> + + + + Wallet is <b>encrypted</b> and currently <b>locked</b> + Портфейлът е <b>криптиран</b> и <b>заключен</b> + + + + Backup Wallet + + + + + Wallet Data (*.dat) + + + + + Backup Failed + + + + + There was an error trying to save the wallet data to the new location. + + + + + %n second(s) + + + + + %n minute(s) + + + + + %n hour(s) + + + + + %n day(s) + + + + + Not staking + + + + + A fatal error occurred. Arepacoin can no longer continue safely and will quit. + + + + + ClientModel + + + Network Alert + + + + + CoinControlDialog + + + Coin Control + + + + + Quantity: + + + + + Bytes: + + + + + Amount: + Сума: + + + + Priority: + + + + + Fee: + + + + + Low Output: + + + + + no + + + + + After Fee: + + + + + Change: + + + + + (un)select all + + + + + Tree mode + + + + + List mode + + + + + Amount + Сума + + + + Label + + + + + Address + Адрес + + + + Date + Дата + + + + Confirmations + + + + + Confirmed + Потвърдени + + + + Priority + + + + + Copy address + Копирай адрес + + + + Copy label + Копирай име + + + + + Copy amount + Копирай сума + + + + Copy transaction ID + + + + + Copy quantity + + + + + Copy fee + + + + + Copy after fee + + + + + Copy bytes + + + + + Copy priority + + + + + Copy low output + + + + + Copy change + + + + + highest + + + + + high + + + + + medium-high + + + + + medium + + + + + low-medium + + + + + low + + + + + lowest + + + + + DUST + + + + + yes + + + + + This label turns red, if the transaction size is bigger than 10000 bytes. + + This means a fee of at least %1 per kb is required. + + Can vary +/- 1 Byte per input. + + + + + Transactions with higher priority get more likely into a block. + +This label turns red, if the priority is smaller than "medium". + + This means a fee of at least %1 per kb is required. + + + + + This label turns red, if any recipient receives an amount smaller than %1. + + This means a fee of at least %2 is required. + + Amounts below 0.546 times the minimum relay fee are shown as DUST. + + + + + This label turns red, if the change is smaller than %1. + + This means a fee of at least %2 is required. + + + + + + (no label) + (без име) + + + + change from %1 (%2) + + + + + (change) + + + + + EditAddressDialog + + + Edit Address + Редактиране на адрес + + + + &Label + &Име + + + + The label associated with this address book entry + + + + + &Address + &Адрес + + + + The address associated with this address book entry. This can only be modified for sending addresses. + + + + + New receiving address + Нов адрес за получаване + + + + New sending address + Нов адрес за изпращане + + + + Edit receiving address + Редактиране на входящ адрес + + + + Edit sending address + Редактиране на изходящ адрес + + + + The entered address "%1" is already in the address book. + Вече има адрес "%1" в списъка с адреси. + + + + The entered address "%1" is not a valid Arepacoin address. + + + + + Could not unlock wallet. + Отключването на портфейла беше неуспешно. + + + + New key generation failed. + Създаването на ключ беше неуспешно. + + + + GUIUtil::HelpMessageBox + + + + Arepacoin-Qt + + + + + version + + + + + Usage: + + + + + command-line options + + + + + UI options + + + + + Set language, for example "de_DE" (default: system locale) + + + + + Start minimized + + + + + Show splash screen on startup (default: 1) + + + + + OptionsDialog + + + Options + Опции + + + + &Main + &Основни + + + + Optional transaction fee per kB that helps make sure your transactions are processed quickly. Most transactions are 1 kB. Fee 0.01 recommended. + + + + + Pay transaction &fee + &Такса за изходяща транзакция + + + + Reserved amount does not participate in staking and is therefore spendable at any time. + + + + + Reserve + + + + + Automatically start Arepacoin after logging in to the system. + + + + + &Start Arepacoin on system login + + + + + Detach block and address databases at shutdown. This means they can be moved to another data directory, but it slows down shutdown. The wallet is always detached. + + + + + &Detach databases at shutdown + + + + + &Network + &Мрежа + + + + Automatically open the Arepacoin client port on the router. This only works when your router supports UPnP and it is enabled. + + + + + Map port using &UPnP + Отваряне на входящия порт чрез &UPnP + + + + Connect to the Arepacoin network through a SOCKS proxy (e.g. when connecting through Tor). + + + + + &Connect through SOCKS proxy: + + + + + Proxy &IP: + + + + + IP address of the proxy (e.g. 127.0.0.1) + + + + + &Port: + + + + + Port of the proxy (e.g. 9050) + + + + + SOCKS &Version: + + + + + SOCKS version of the proxy (e.g. 5) + + + + + &Window + &Прозорец + + + + Show only a tray icon after minimizing the window. + След минимизиране ще е видима само иконата в системния трей. + + + + &Minimize to the tray instead of the taskbar + &Минимизиране в системния трей + + + + Minimize instead of exit the application when the window is closed. When this option is enabled, the application will be closed only after selecting Quit in the menu. + При затваряне на прозореца приложението остава минимизирано. Ако изберете тази опция, приложението може да се затвори само чрез Изход в менюто. + + + + M&inimize on close + М&инимизиране при затваряне + + + + &Display + &Интерфейс + + + + User Interface &language: + Език: + + + + The user interface language can be set here. This setting will take effect after restarting Arepacoin. + + + + + &Unit to show amounts in: + Мерни единици: + + + + Choose the default subdivision unit to show in the interface and when sending coins. + Изберете единиците, показвани по подразбиране в интерфейса. + + + + Whether to show Arepacoin addresses in the transaction list or not. + + + + + &Display addresses in transaction list + Показвай и адресите в списъка с транзакции + + + + Whether to show coin control features or not. + + + + + Display coin &control features (experts only!) + + + + + &OK + + + + + &Cancel + + + + + &Apply + + + + + default + + + + + + Warning + + + + + + This setting will take effect after restarting Arepacoin. + + + + + The supplied proxy address is invalid. + Прокси адресът е невалиден. + + + + OverviewPage + + + Form + Форма + + + + + The displayed information may be out of date. Your wallet automatically synchronizes with the Arepacoin network after a connection is established, but this process has not completed yet. + + + + + Stake: + + + + + Unconfirmed: + + + + + Wallet + Портфейл + + + + Spendable: + + + + + Your current spendable balance + + + + + Immature: + + + + + Mined balance that has not yet matured + + + + + Total: + + + + + Your current total balance + + + + + <b>Recent transactions</b> + <b>Последни транзакции</b> + + + + Total of transactions that have yet to be confirmed, and do not yet count toward the current balance + + + + + Total of coins that was staked, and do not yet count toward the current balance + + + + + + out of sync + несинхронизиран + + + + QRCodeDialog + + + QR Code Dialog + + + + + Request Payment + + + + + Amount: + + + + + Label: + + + + + Message: + + + + + &Save As... + + + + + Error encoding URI into QR Code. + + + + + The entered amount is invalid, please check. + + + + + Resulting URI too long, try to reduce the text for label / message. + + + + + Save QR Code + + + + + PNG Images (*.png) + + + + + RPCConsole + + + Client name + + + + + + + + + + + + + + N/A + N/A + + + + Client version + + + + + &Information + + + + + Using OpenSSL version + + + + + Startup time + + + + + Network + Мрежа + + + + Number of connections + + + + + On testnet + + + + + Block chain + + + + + Current number of blocks + + + + + Estimated total blocks + + + + + Last block time + + + + + &Open + + + + + Command-line options + + + + + Show the Arepacoin-Qt help message to get a list with possible Arepacoin command-line options. + + + + + &Show + + + + + &Console + + + + + Build date + + + + + Arepacoin - Debug window + + + + + Arepacoin Core + + + + + Debug log file + + + + + Open the Arepacoin debug log file from the current data directory. This can take a few seconds for large log files. + + + + + Clear console + Изчисти конзолата + + + + Welcome to the Arepacoin RPC console. + + + + + Use up and down arrows to navigate history, and <b>Ctrl-L</b> to clear screen. + Използвайте стрелки надолу и нагореза разглеждане на историятаот команди и <b>Ctrl-L</b> за изчистване на конзолата. + + + + Type <b>help</b> for an overview of available commands. + + + + + SendCoinsDialog + + + + + + + + + + Send Coins + Изпращане + + + + Coin Control Features + + + + + Inputs... + + + + + automatically selected + + + + + Insufficient funds! + + + + + Quantity: + + + + + + 0 + + + + + Bytes: + + + + + Amount: + Сума: + + + + + + + 0.00 BC + + + + + Priority: + + + + + medium + + + + + Fee: + + + + + Low Output: + + + + + no + + + + + After Fee: + + + + + Change + + + + + custom change address + + + + + Send to multiple recipients at once + Изпращане към повече от един получател + + + + Add &Recipient + Добави &получател + + + + Remove all transaction fields + + + + + Clear &All + &Изчисти + + + + Balance: + Баланс: + + + + 123.456 BC + + + + + Confirm the send action + Потвърдете изпращането + + + + S&end + И&зпрати + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Copy quantity + + + + + Copy amount + Копирай сума + + + + Copy fee + + + + + Copy after fee + + + + + Copy bytes + + + + + Copy priority + + + + + Copy low output + + + + + Copy change + + + + + <b>%1</b> to %2 (%3) + + + + + Confirm send coins + Потвърждаване + + + + Are you sure you want to send %1? + + + + + and + + + + + The recipient address is not valid, please recheck. + Невалиден адрес на получателя. + + + + The amount to pay must be larger than 0. + Сумата трябва да е по-голяма от 0. + + + + The amount exceeds your balance. + + + + + The total exceeds your balance when the %1 transaction fee is included. + + + + + Duplicate address found, can only send to each address once per send operation. + + + + + Error: Transaction creation failed. + + + + + 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. + + + + + WARNING: Invalid Arepacoin address + + + + + (no label) + (без име) + + + + WARNING: unknown change address + + + + + SendCoinsEntry + + + Form + + + + + A&mount: + С&ума: + + + + Pay &To: + Плати &На: + + + + + Enter a label for this address to add it to your address book + Въведете име за този адрес, за да го добавите в списъка с адреси + + + + &Label: + &Име: + + + + The address to send the payment to (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Choose address from address book + + + + + Alt+A + Alt+A + + + + Paste address from clipboard + Вмъкни от клипборда + + + + Alt+P + Alt+P + + + + Remove this recipient + + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + SignVerifyMessageDialog + + + Signatures - Sign / Verify a Message + Подпиши / Провери съобщение + + + + + &Sign Message + &Подпиши + + + + You can sign messages with your addresses to prove you own them. Be careful not to sign anything vague, as phishing attacks may try to trick you into signing your identity over to them. Only sign fully-detailed statements you agree to. + Можете да подпишете съобщение като доказателство, че притежавате определен адрес. Бъдете внимателни и не подписвайте съобщения, които биха разкрили лична информация без вашето съгласие. + + + + The address to sign the message with (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + + Choose an address from the address book + + + + + + Alt+A + Alt+A + + + + Paste address from clipboard + Вмъкни от клипборда + + + + Alt+P + Alt+P + + + + Enter the message you want to sign here + Въведете съобщението тук + + + + Copy the current signature to the system clipboard + Копиране на текущия подпис + + + + Sign the message to prove you own this Arepacoin address + + + + + Reset all sign message fields + + + + + + Clear &All + &Изчисти + + + + + &Verify Message + &Провери + + + + Enter the signing address, message (ensure you copy line breaks, spaces, tabs, etc. exactly) and signature below to verify the message. Be careful not to read more into the signature than what is in the signed message itself, to avoid being tricked by a man-in-the-middle attack. + + + + + The address the message was signed with (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Verify the message to ensure it was signed with the specified Arepacoin address + + + + + Reset all verify message fields + + + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Click "Sign Message" to generate signature + Натиснете "Подписване на съобщение" за да създадете подпис + + + + Enter Arepacoin signature + + + + + + The entered address is invalid. + Въведеният адрес е невалиден. + + + + + + + Please check the address and try again. + Моля проверете адреса и опитайте отново. + + + + + The entered address does not refer to a key. + + + + + Wallet unlock was cancelled. + + + + + Private key for the entered address is not available. + Не е наличен частният ключ за въведеният адрес. + + + + Message signing failed. + Подписването на съобщение бе неуспешно. + + + + Message signed. + Съобщението е подписано. + + + + The signature could not be decoded. + Подписът не може да бъде декодиран. + + + + + Please check the signature and try again. + Проверете подписа и опитайте отново. + + + + The signature did not match the message digest. + Подписът не отговаря на комбинацията от съобщение и адрес. + + + + Message verification failed. + Проверката на съобщението беше неуспешна. + + + + Message verified. + Съобщението е потвърдено. + + + + TransactionDesc + + + Open until %1 + Подлежи на промяна до %1 + + + + Open for %n block(s) + + + + + conflicted + + + + + %1/offline + %1/офлайн + + + + %1/unconfirmed + %1/непотвърдени + + + + %1 confirmations + включена в %1 блока + + + + Status + Статус + + + + , broadcast through %n node(s) + + + + + Date + Дата + + + + Source + Източник + + + + Generated + Издадени + + + + + From + От + + + + + + To + За + + + + + own address + собствен адрес + + + + label + име + + + + + + + + Credit + Кредит + + + + matures in %n more block(s) + + + + + not accepted + + + + + + + + Debit + Дебит + + + + Transaction fee + Такса + + + + Net amount + Сума нето + + + + Message + Съобщение + + + + Comment + Коментар + + + + Transaction ID + ID + + + + Generated coins must mature 6 blocks before they can be spent. When you generated this block, it was broadcast to the network to be added to the block chain. If it fails to get into the chain, its state will change to "not accepted" and it won't be spendable. This may occasionally happen if another node generates a block within a few seconds of yours. + + + + + Debug information + + + + + Transaction + Транзакция + + + + Inputs + + + + + Amount + Сума + + + + true + true + + + + false + false + + + + , has not been successfully broadcast yet + , все още не е изпратено + + + + unknown + неизвестен + + + + TransactionDescDialog + + + Transaction details + Транзакция + + + + This pane shows a detailed description of the transaction + Описание на транзакцията + + + + TransactionTableModel + + + Date + Дата + + + + Type + Тип + + + + Address + Адрес + + + + Amount + Сума + + + + Open until %1 + Подлежи на промяна до %1 + + + + Confirmed (%1 confirmations) + Потвърдени (%1 потвърждения) + + + + Open for %n more block(s) + + + + + Offline + + + + + Unconfirmed + + + + + Confirming (%1 of %2 recommended confirmations) + + + + + Conflicted + + + + + Immature (%1 confirmations, will be available after %2) + + + + + This block was not received by any other nodes and will probably not be accepted! + Блокът не е получен от останалите участници и най-вероятно няма да бъде одобрен. + + + + Generated but not accepted + Генерирана, но отхвърлена от мрежата + + + + Received with + Получени с + + + + Received from + Получен от + + + + Sent to + Изпратени на + + + + Payment to yourself + + + + + Mined + Емитирани + + + + (n/a) + (n/a) + + + + Transaction status. Hover over this field to show number of confirmations. + Състояние на транзакцията. Задръжте върху това поле за брой потвърждения. + + + + Date and time that the transaction was received. + Дата и час на получаване. + + + + Type of transaction. + Тип на транзакцията. + + + + Destination address of transaction. + Получател на транзакцията. + + + + Amount removed from or added to balance. + Сума извадена или добавена към баланса. + + + + TransactionView + + + + All + Всички + + + + Today + Днес + + + + This week + Тази седмица + + + + This month + Този месец + + + + Last month + Предния месец + + + + This year + Тази година + + + + Range... + От - до... + + + + Received with + Получени + + + + Sent to + Изпратени на + + + + To yourself + Собствени + + + + Mined + Емитирани + + + + Other + Други + + + + Enter address or label to search + Търсене по адрес или име + + + + Min amount + Минимална сума + + + + Copy address + Копирай адрес + + + + Copy label + Копирай име + + + + Copy amount + Копирай сума + + + + Copy transaction ID + + + + + Edit label + Редактирай име + + + + Show transaction details + + + + + Export Transaction Data + + + + + Comma separated file (*.csv) + CSV файл (*.csv) + + + + Confirmed + Потвърдени + + + + Date + Дата + + + + Type + Тип + + + + Label + Име + + + + Address + Адрес + + + + Amount + Сума + + + + ID + ИД + + + + Error exporting + + + + + Could not write to file %1. + + + + + Range: + От: + + + + to + до + + + + WalletModel + + + Sending... + + + + + bitcoin-core + + + Arepacoin version + + + + + Usage: + Използване: + + + + Send command to -server or arepacoind + + + + + List commands + Вписване на команди + + + + Get help for a command + Получете помощ за команда + + + + Options: + Опции: + + + + Specify configuration file (default: arepacoin.conf) + + + + + Specify pid file (default: arepacoind.pid) + + + + + Specify wallet file (within data directory) + + + + + Specify data directory + Определете директория за данните + + + + Set database cache size in megabytes (default: 25) + + + + + Set database disk log size in megabytes (default: 100) + + + + + Listen for connections on <port> (default: 9853 or testnet: 19853) + + + + + Maintain at most <n> connections to peers (default: 125) + + + + + Connect to a node to retrieve peer addresses, and disconnect + + + + + Specify your own public address + + + + + Bind to given address. Use [host]:port notation for IPv6 + + + + + Stake your coins to support network and gain reward (default: 1) + + + + + Threshold for disconnecting misbehaving peers (default: 100) + Праг на прекъсване на връзката при непорядъчно държащи се пиъри (по подразбиране:100) + + + + Number of seconds to keep misbehaving peers from reconnecting (default: 86400) + Брой секунди до възтановяване на връзката за зле държащите се пиъри (по подразбиране:86400) + + + + An error occurred while setting up the RPC port %u for listening on IPv4: %s + + + + + Detach block and address databases. Increases shutdown time (default: 0) + + + + + 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. + + + + + Error: This transaction requires a transaction fee of at least %s because of its amount, complexity, or use of recently received funds + + + + + Listen for JSON-RPC connections on <port> (default: 9852 or testnet: 19852) + + + + + Accept command line and JSON-RPC commands + + + + + Error: Transaction creation failed + + + + + Error: Wallet locked, unable to create transaction + + + + + Importing blockchain data file. + + + + + Importing bootstrap blockchain data file. + + + + + Run in the background as a daemon and accept commands + + + + + Use the test network + Използвайте тестовата мрежа + + + + Accept connections from outside (default: 1 if no -proxy or -connect) + + + + + An error occurred while setting up the RPC port %u for listening on IPv6, falling back to IPv4: %s + + + + + Error initializing database environment %s! To recover, BACKUP THAT DIRECTORY, then remove everything from it except for wallet.dat. + + + + + Set maximum size of high-priority/low-fee transactions in bytes (default: 27000) + + + + + Warning: -paytxfee is set very high! This is the transaction fee you will pay if you send a transaction. + + + + + Warning: Please check that your computer's date and time are correct! If your clock is wrong Arepacoin will not work properly. + + + + + Warning: error reading wallet.dat! All keys read correctly, but transaction data or address book entries might be missing or incorrect. + + + + + Warning: wallet.dat corrupt, data salvaged! Original wallet.dat saved as wallet.{timestamp}.bak in %s; if your balance or transactions are incorrect you should restore from a backup. + + + + + Attempt to recover private keys from a corrupt wallet.dat + + + + + Block creation options: + + + + + Connect only to the specified node(s) + + + + + Discover own IP address (default: 1 when listening and no -externalip) + + + + + Failed to listen on any port. Use -listen=0 if you want this. + + + + + Find peers using DNS lookup (default: 1) + + + + + Sync checkpoints policy (default: strict) + + + + + Invalid -tor address: '%s' + + + + + Invalid amount for -reservebalance=<amount> + + + + + Maximum per-connection receive buffer, <n>*1000 bytes (default: 5000) + + + + + Maximum per-connection send buffer, <n>*1000 bytes (default: 1000) + + + + + Only connect to nodes in network <net> (IPv4, IPv6 or Tor) + + + + + Output extra debugging information. Implies all other -debug* options + + + + + Output extra network debugging information + + + + + Prepend debug output with timestamp + + + + + SSL options: (see the Bitcoin Wiki for SSL setup instructions) + + + + + Select the version of socks proxy to use (4-5, default: 5) + + + + + Send trace/debug info to console instead of debug.log file + Изпрати локализиращата или дебъг информацията към конзолата, вместо файлът debug.log + + + + Send trace/debug info to debugger + + + + + Set maximum block size in bytes (default: 250000) + + + + + Set minimum block size in bytes (default: 0) + + + + + Shrink debug.log file on client startup (default: 1 when no -debug) + + + + + Specify connection timeout in milliseconds (default: 5000) + + + + + Unable to sign checkpoint, wrong checkpointkey? + + + + + + Use UPnP to map the listening port (default: 0) + + + + + Use UPnP to map the listening port (default: 1 when listening) + + + + + Use proxy to reach tor hidden services (default: same as -proxy) + + + + + Username for JSON-RPC connections + Потребителско име за JSON-RPC връзките + + + + Verifying database integrity... + + + + + WARNING: syncronized checkpoint violation detected, but skipped! + + + + + Warning: Disk space is low! + + + + + Warning: This version is obsolete, upgrade required! + + + + + wallet.dat corrupt, salvage failed + + + + + Password for JSON-RPC connections + Парола за JSON-RPC връзките + + + + %s, you must set a rpcpassword in the configuration file: + %s +It is recommended you use the following random password: +rpcuser=arepacoinrpc +rpcpassword=%s +(you do not need to remember this password) +The username and password MUST NOT be the same. +If the file does not exist, create it with owner-readable-only file permissions. +It is also recommended to set alertnotify so you are notified of problems; +for example: alertnotify=echo %%s | mail -s "Arepacoin Alert" admin@foo.com + + + + + + Find peers using internet relay chat (default: 0) + + + + + Sync time with other nodes. Disable if time on your system is precise e.g. syncing with NTP (default: 1) + + + + + When creating transactions, ignore inputs with value less than this (default: 0.01) + + + + + Allow JSON-RPC connections from specified IP address + Разреши JSON-RPC връзките от отучнен IP адрес + + + + Send commands to node running on <ip> (default: 127.0.0.1) + Изпрати команди до възел функциониращ на <ip> (По подразбиране: 127.0.0.1) + + + + Execute command when the best block changes (%s in cmd is replaced by block hash) + + + + + Execute command when a wallet transaction changes (%s in cmd is replaced by TxID) + + + + + Require a confirmations for change (default: 0) + + + + + Enforce transaction scripts to use canonical PUSH operators (default: 1) + + + + + Execute command when a relevant alert is received (%s in cmd is replaced by message) + + + + + Upgrade wallet to latest format + + + + + Set key pool size to <n> (default: 100) + + + + + Rescan the block chain for missing wallet transactions + Повторно сканиране на блок-връзка за липсващи портефейлни транзакции + + + + How many blocks to check at startup (default: 2500, 0 = all) + + + + + How thorough the block verification is (0-6, default: 1) + + + + + Imports blocks from external blk000?.dat file + + + + + Use OpenSSL (https) for JSON-RPC connections + Използвайте OpenSSL (https) за JSON-RPC връзките + + + + Server certificate file (default: server.cert) + Сертификатен файл на сървъра (По подразбиране:server.cert) + + + + Server private key (default: server.pem) + Поверителен ключ за сървъра (default: server.pem) + + + + Acceptable ciphers (default: TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH) + + + + + Error: Wallet unlocked for staking only, unable to create transaction. + + + + + WARNING: Invalid checkpoint found! Displayed transactions may not be correct! You may need to upgrade, or notify developers. + + + + + This help message + Това помощно съобщение + + + + Wallet %s resides outside data directory %s. + + + + + Cannot obtain a lock on data directory %s. Arepacoin is probably already running. + + + + + Arepacoin + + + + + Unable to bind to %s on this computer (bind returned error %d, %s) + + + + + Connect through socks proxy + + + + + Allow DNS lookups for -addnode, -seednode and -connect + + + + + Loading addresses... + Зареждане на адресите... + + + + Error loading blkindex.dat + + + + + Error loading wallet.dat: Wallet corrupted + + + + + Error loading wallet.dat: Wallet requires newer version of Arepacoin + + + + + Wallet needed to be rewritten: restart Arepacoin to complete + + + + + Error loading wallet.dat + + + + + Invalid -proxy address: '%s' + Невалиден -proxy address: '%s' + + + + Unknown network specified in -onlynet: '%s' + + + + + Unknown -socks proxy version requested: %i + + + + + Cannot resolve -bind address: '%s' + + + + + Cannot resolve -externalip address: '%s' + + + + + Invalid amount for -paytxfee=<amount>: '%s' + + + + + Error: could not start node + + + + + Sending... + + + + + Invalid amount + + + + + Insufficient funds + + + + + Loading block index... + Зареждане на блок индекса... + + + + Add a node to connect to and attempt to keep the connection open + + + + + Unable to bind to %s on this computer. Arepacoin is probably already running. + + + + + Fee per KB to add to transactions you send + + + + + Invalid amount for -mininput=<amount>: '%s' + + + + + Loading wallet... + Зареждане на портфейла... + + + + Cannot downgrade wallet + + + + + Cannot initialize keypool + + + + + Cannot write default address + + + + + Rescanning... + Преразглеждане на последовтелността от блокове... + + + + Done loading + Зареждането е завършено + + + + To use the %s option + + + + + Error + Грешка + + + + You must set rpcpassword=<password> in the configuration file: +%s +If the file does not exist, create it with owner-readable-only file permissions. + + + + \ No newline at end of file diff --git a/src/qt/locale/bitcoin_bs.ts b/src/qt/locale/bitcoin_bs.ts new file mode 100755 index 0000000..9a2acb2 --- /dev/null +++ b/src/qt/locale/bitcoin_bs.ts @@ -0,0 +1,3275 @@ + + + AboutDialog + + + About Arepacoin + + + + + <b>Arepacoin</b> version + + + + + Copyright © 2009-2014 The Bitcoin developers +Copyright © 2012-2014 The NovaCoin developers +Copyright © 2014 The Arepacoin developers + + + + + +This is experimental software. + +Distributed under the MIT/X11 software license, see the accompanying file COPYING or http://www.opensource.org/licenses/mit-license.php. + +This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit (http://www.openssl.org/) and cryptographic software written by Eric Young (eay@cryptsoft.com) and UPnP software written by Thomas Bernard. + + + + + AddressBookPage + + + Address Book + + + + + Double-click to edit address or label + + + + + Create a new address + + + + + Copy the currently selected address to the system clipboard + + + + + &New Address + + + + + These are your Arepacoin addresses for receiving payments. You may want to give a different one to each sender so you can keep track of who is paying you. + + + + + &Copy Address + + + + + Show &QR Code + + + + + Sign a message to prove you own a Arepacoin address + + + + + Sign &Message + + + + + Delete the currently selected address from the list + + + + + Verify a message to ensure it was signed with a specified Arepacoin address + + + + + &Verify Message + + + + + &Delete + + + + + Copy &Label + + + + + &Edit + + + + + Export Address Book Data + + + + + Comma separated file (*.csv) + + + + + Error exporting + + + + + Could not write to file %1. + + + + + AddressTableModel + + + Label + + + + + Address + + + + + (no label) + + + + + AskPassphraseDialog + + + Passphrase Dialog + + + + + Enter passphrase + + + + + New passphrase + + + + + Repeat new passphrase + + + + + Serves to disable the trivial sendmoney when OS account compromised. Provides no real security. + + + + + For staking only + + + + + Enter the new passphrase to the wallet.<br/>Please use a passphrase of <b>10 or more random characters</b>, or <b>eight or more words</b>. + + + + + Encrypt wallet + + + + + This operation needs your wallet passphrase to unlock the wallet. + + + + + Unlock wallet + + + + + This operation needs your wallet passphrase to decrypt the wallet. + + + + + Decrypt wallet + + + + + Change passphrase + + + + + Enter the old and new passphrase to the wallet. + + + + + Confirm wallet encryption + + + + + Warning: If you encrypt your wallet and lose your passphrase, you will <b>LOSE ALL OF YOUR COINS</b>! + + + + + Are you sure you wish to encrypt your wallet? + + + + + IMPORTANT: Any previous backups you have made of your wallet file should be replaced with the newly generated, encrypted wallet file. For security reasons, previous backups of the unencrypted wallet file will become useless as soon as you start using the new, encrypted wallet. + + + + + + Warning: The Caps Lock key is on! + + + + + + Wallet encrypted + + + + + Arepacoin will close now to finish the encryption process. Remember that encrypting your wallet cannot fully protect your coins from being stolen by malware infecting your computer. + + + + + + + + Wallet encryption failed + + + + + Wallet encryption failed due to an internal error. Your wallet was not encrypted. + + + + + + The supplied passphrases do not match. + + + + + Wallet unlock failed + + + + + + + The passphrase entered for the wallet decryption was incorrect. + + + + + Wallet decryption failed + + + + + Wallet passphrase was successfully changed. + + + + + BitcoinGUI + + + Sign &message... + + + + + Synchronizing with network... + + + + + &Overview + + + + + Show general overview of wallet + + + + + &Transactions + + + + + Browse transaction history + + + + + &Address Book + + + + + Edit the list of stored addresses and labels + + + + + &Receive coins + + + + + Show the list of addresses for receiving payments + + + + + &Send coins + + + + + E&xit + + + + + Quit application + + + + + Show information about Arepacoin + + + + + About &Qt + + + + + Show information about Qt + + + + + &Options... + + + + + &Encrypt Wallet... + + + + + &Backup Wallet... + + + + + &Change Passphrase... + + + + + ~%n block(s) remaining + + + + + Downloaded %1 of %2 blocks of transaction history (%3% done). + + + + + &Export... + + + + + Send coins to a Arepacoin address + + + + + Modify configuration options for Arepacoin + + + + + Export the data in the current tab to a file + + + + + Encrypt or decrypt wallet + + + + + Backup wallet to another location + + + + + Change the passphrase used for wallet encryption + + + + + &Debug window + + + + + Open debugging and diagnostic console + + + + + &Verify message... + + + + + Arepacoin + + + + + Wallet + + + + + &About Arepacoin + + + + + &Show / Hide + + + + + Unlock wallet + + + + + &Lock Wallet + + + + + Lock wallet + + + + + &File + + + + + &Settings + + + + + &Help + + + + + Tabs toolbar + + + + + Actions toolbar + + + + + + [testnet] + + + + + + Arepacoin client + + + + + %n active connection(s) to Arepacoin network + + + + + Downloaded %1 blocks of transaction history. + + + + + Staking.<br>Your weight is %1<br>Network weight is %2<br>Expected time to earn reward is %3 + + + + + Not staking because wallet is locked + + + + + Not staking because wallet is offline + + + + + Not staking because wallet is syncing + + + + + Not staking because you don't have mature coins + + + + + %n second(s) ago + + + + + &Unlock Wallet... + + + + + %n minute(s) ago + + + + + %n hour(s) ago + + + + + %n day(s) ago + + + + + Up to date + + + + + Catching up... + + + + + Last received block was generated %1. + + + + + This transaction is over the size limit. You can still send it for a fee of %1, which goes to the nodes that process your transaction and helps to support the network. Do you want to pay the fee? + + + + + Confirm transaction fee + + + + + Sent transaction + + + + + Incoming transaction + + + + + Date: %1 +Amount: %2 +Type: %3 +Address: %4 + + + + + + + URI handling + + + + + + URI can not be parsed! This can be caused by an invalid Arepacoin address or malformed URI parameters. + + + + + Wallet is <b>encrypted</b> and currently <b>unlocked</b> + + + + + Wallet is <b>encrypted</b> and currently <b>locked</b> + + + + + Backup Wallet + + + + + Wallet Data (*.dat) + + + + + Backup Failed + + + + + There was an error trying to save the wallet data to the new location. + + + + + %n second(s) + + + + + %n minute(s) + + + + + %n hour(s) + + + + + %n day(s) + + + + + Not staking + + + + + A fatal error occurred. Arepacoin can no longer continue safely and will quit. + + + + + ClientModel + + + Network Alert + + + + + CoinControlDialog + + + Coin Control + + + + + Quantity: + + + + + Bytes: + + + + + Amount: + + + + + Priority: + + + + + Fee: + + + + + Low Output: + + + + + no + + + + + After Fee: + + + + + Change: + + + + + (un)select all + + + + + Tree mode + + + + + List mode + + + + + Amount + + + + + Label + + + + + Address + + + + + Date + + + + + Confirmations + + + + + Confirmed + + + + + Priority + + + + + Copy address + + + + + Copy label + + + + + + Copy amount + + + + + Copy transaction ID + + + + + Copy quantity + + + + + Copy fee + + + + + Copy after fee + + + + + Copy bytes + + + + + Copy priority + + + + + Copy low output + + + + + Copy change + + + + + highest + + + + + high + + + + + medium-high + + + + + medium + + + + + low-medium + + + + + low + + + + + lowest + + + + + DUST + + + + + yes + + + + + This label turns red, if the transaction size is bigger than 10000 bytes. + + This means a fee of at least %1 per kb is required. + + Can vary +/- 1 Byte per input. + + + + + Transactions with higher priority get more likely into a block. + +This label turns red, if the priority is smaller than "medium". + + This means a fee of at least %1 per kb is required. + + + + + This label turns red, if any recipient receives an amount smaller than %1. + + This means a fee of at least %2 is required. + + Amounts below 0.546 times the minimum relay fee are shown as DUST. + + + + + This label turns red, if the change is smaller than %1. + + This means a fee of at least %2 is required. + + + + + + (no label) + + + + + change from %1 (%2) + + + + + (change) + + + + + EditAddressDialog + + + Edit Address + + + + + &Label + + + + + The label associated with this address book entry + + + + + &Address + + + + + The address associated with this address book entry. This can only be modified for sending addresses. + + + + + New receiving address + + + + + New sending address + + + + + Edit receiving address + + + + + Edit sending address + + + + + The entered address "%1" is already in the address book. + + + + + The entered address "%1" is not a valid Arepacoin address. + + + + + Could not unlock wallet. + + + + + New key generation failed. + + + + + GUIUtil::HelpMessageBox + + + + Arepacoin-Qt + + + + + version + + + + + Usage: + + + + + command-line options + + + + + UI options + + + + + Set language, for example "de_DE" (default: system locale) + + + + + Start minimized + + + + + Show splash screen on startup (default: 1) + + + + + OptionsDialog + + + Options + + + + + &Main + + + + + Optional transaction fee per kB that helps make sure your transactions are processed quickly. Most transactions are 1 kB. Fee 0.01 recommended. + + + + + Pay transaction &fee + + + + + Reserved amount does not participate in staking and is therefore spendable at any time. + + + + + Reserve + + + + + Automatically start Arepacoin after logging in to the system. + + + + + &Start Arepacoin on system login + + + + + Detach block and address databases at shutdown. This means they can be moved to another data directory, but it slows down shutdown. The wallet is always detached. + + + + + &Detach databases at shutdown + + + + + &Network + + + + + Automatically open the Arepacoin client port on the router. This only works when your router supports UPnP and it is enabled. + + + + + Map port using &UPnP + + + + + Connect to the Arepacoin network through a SOCKS proxy (e.g. when connecting through Tor). + + + + + &Connect through SOCKS proxy: + + + + + Proxy &IP: + + + + + IP address of the proxy (e.g. 127.0.0.1) + + + + + &Port: + + + + + Port of the proxy (e.g. 9050) + + + + + SOCKS &Version: + + + + + SOCKS version of the proxy (e.g. 5) + + + + + &Window + + + + + Show only a tray icon after minimizing the window. + + + + + &Minimize to the tray instead of the taskbar + + + + + Minimize instead of exit the application when the window is closed. When this option is enabled, the application will be closed only after selecting Quit in the menu. + + + + + M&inimize on close + + + + + &Display + + + + + User Interface &language: + + + + + The user interface language can be set here. This setting will take effect after restarting Arepacoin. + + + + + &Unit to show amounts in: + + + + + Choose the default subdivision unit to show in the interface and when sending coins. + + + + + Whether to show Arepacoin addresses in the transaction list or not. + + + + + &Display addresses in transaction list + + + + + Whether to show coin control features or not. + + + + + Display coin &control features (experts only!) + + + + + &OK + + + + + &Cancel + + + + + &Apply + + + + + default + + + + + + Warning + + + + + + This setting will take effect after restarting Arepacoin. + + + + + The supplied proxy address is invalid. + + + + + OverviewPage + + + Form + + + + + + The displayed information may be out of date. Your wallet automatically synchronizes with the Arepacoin network after a connection is established, but this process has not completed yet. + + + + + Stake: + + + + + Unconfirmed: + + + + + Wallet + + + + + Spendable: + + + + + Your current spendable balance + + + + + Immature: + + + + + Mined balance that has not yet matured + + + + + Total: + + + + + Your current total balance + + + + + <b>Recent transactions</b> + + + + + Total of transactions that have yet to be confirmed, and do not yet count toward the current balance + + + + + Total of coins that was staked, and do not yet count toward the current balance + + + + + + out of sync + + + + + QRCodeDialog + + + QR Code Dialog + + + + + Request Payment + + + + + Amount: + + + + + Label: + + + + + Message: + + + + + &Save As... + + + + + Error encoding URI into QR Code. + + + + + The entered amount is invalid, please check. + + + + + Resulting URI too long, try to reduce the text for label / message. + + + + + Save QR Code + + + + + PNG Images (*.png) + + + + + RPCConsole + + + Client name + + + + + + + + + + + + + + N/A + + + + + Client version + + + + + &Information + + + + + Using OpenSSL version + + + + + Startup time + + + + + Network + + + + + Number of connections + + + + + On testnet + + + + + Block chain + + + + + Current number of blocks + + + + + Estimated total blocks + + + + + Last block time + + + + + &Open + + + + + Command-line options + + + + + Show the Arepacoin-Qt help message to get a list with possible Arepacoin command-line options. + + + + + &Show + + + + + &Console + + + + + Build date + + + + + Arepacoin - Debug window + + + + + Arepacoin Core + + + + + Debug log file + + + + + Open the Arepacoin debug log file from the current data directory. This can take a few seconds for large log files. + + + + + Clear console + + + + + Welcome to the Arepacoin RPC console. + + + + + Use up and down arrows to navigate history, and <b>Ctrl-L</b> to clear screen. + + + + + Type <b>help</b> for an overview of available commands. + + + + + SendCoinsDialog + + + + + + + + + + Send Coins + + + + + Coin Control Features + + + + + Inputs... + + + + + automatically selected + + + + + Insufficient funds! + + + + + Quantity: + + + + + + 0 + + + + + Bytes: + + + + + Amount: + + + + + + + + 0.00 BC + + + + + Priority: + + + + + medium + + + + + Fee: + + + + + Low Output: + + + + + no + + + + + After Fee: + + + + + Change + + + + + custom change address + + + + + Send to multiple recipients at once + + + + + Add &Recipient + + + + + Remove all transaction fields + + + + + Clear &All + + + + + Balance: + + + + + 123.456 BC + + + + + Confirm the send action + + + + + S&end + + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Copy quantity + + + + + Copy amount + + + + + Copy fee + + + + + Copy after fee + + + + + Copy bytes + + + + + Copy priority + + + + + Copy low output + + + + + Copy change + + + + + <b>%1</b> to %2 (%3) + + + + + Confirm send coins + + + + + Are you sure you want to send %1? + + + + + and + + + + + The recipient address is not valid, please recheck. + + + + + The amount to pay must be larger than 0. + + + + + The amount exceeds your balance. + + + + + The total exceeds your balance when the %1 transaction fee is included. + + + + + Duplicate address found, can only send to each address once per send operation. + + + + + Error: Transaction creation failed. + + + + + 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. + + + + + WARNING: Invalid Arepacoin address + + + + + (no label) + + + + + WARNING: unknown change address + + + + + SendCoinsEntry + + + Form + + + + + A&mount: + + + + + Pay &To: + + + + + + Enter a label for this address to add it to your address book + + + + + &Label: + + + + + The address to send the payment to (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Choose address from address book + + + + + Alt+A + Alt+A + + + + Paste address from clipboard + + + + + Alt+P + Alt+P + + + + Remove this recipient + + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + SignVerifyMessageDialog + + + Signatures - Sign / Verify a Message + + + + + + &Sign Message + + + + + You can sign messages with your addresses to prove you own them. Be careful not to sign anything vague, as phishing attacks may try to trick you into signing your identity over to them. Only sign fully-detailed statements you agree to. + + + + + The address to sign the message with (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + + Choose an address from the address book + + + + + + Alt+A + Alt+A + + + + Paste address from clipboard + + + + + Alt+P + Alt+P + + + + Enter the message you want to sign here + + + + + Copy the current signature to the system clipboard + + + + + Sign the message to prove you own this Arepacoin address + + + + + Reset all sign message fields + + + + + + Clear &All + + + + + + &Verify Message + + + + + Enter the signing address, message (ensure you copy line breaks, spaces, tabs, etc. exactly) and signature below to verify the message. Be careful not to read more into the signature than what is in the signed message itself, to avoid being tricked by a man-in-the-middle attack. + + + + + The address the message was signed with (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Verify the message to ensure it was signed with the specified Arepacoin address + + + + + Reset all verify message fields + + + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Click "Sign Message" to generate signature + + + + + Enter Arepacoin signature + + + + + + The entered address is invalid. + + + + + + + + Please check the address and try again. + + + + + + The entered address does not refer to a key. + + + + + Wallet unlock was cancelled. + + + + + Private key for the entered address is not available. + + + + + Message signing failed. + + + + + Message signed. + + + + + The signature could not be decoded. + + + + + + Please check the signature and try again. + + + + + The signature did not match the message digest. + + + + + Message verification failed. + + + + + Message verified. + + + + + TransactionDesc + + + Open until %1 + + + + + Open for %n block(s) + + + + + conflicted + + + + + %1/offline + + + + + %1/unconfirmed + + + + + %1 confirmations + + + + + Status + + + + + , broadcast through %n node(s) + + + + + Date + + + + + Source + + + + + Generated + + + + + + From + + + + + + + To + + + + + + own address + + + + + label + + + + + + + + + Credit + + + + + matures in %n more block(s) + + + + + not accepted + + + + + + + + Debit + + + + + Transaction fee + + + + + Net amount + + + + + Message + + + + + Comment + + + + + Transaction ID + + + + + Generated coins must mature 6 blocks before they can be spent. When you generated this block, it was broadcast to the network to be added to the block chain. If it fails to get into the chain, its state will change to "not accepted" and it won't be spendable. This may occasionally happen if another node generates a block within a few seconds of yours. + + + + + Debug information + + + + + Transaction + + + + + Inputs + + + + + Amount + + + + + true + + + + + false + + + + + , has not been successfully broadcast yet + + + + + unknown + + + + + TransactionDescDialog + + + Transaction details + + + + + This pane shows a detailed description of the transaction + + + + + TransactionTableModel + + + Date + + + + + Type + + + + + Address + + + + + Amount + + + + + Open until %1 + + + + + Confirmed (%1 confirmations) + + + + + Open for %n more block(s) + + + + + Offline + + + + + Unconfirmed + + + + + Confirming (%1 of %2 recommended confirmations) + + + + + Conflicted + + + + + Immature (%1 confirmations, will be available after %2) + + + + + This block was not received by any other nodes and will probably not be accepted! + + + + + Generated but not accepted + + + + + Received with + + + + + Received from + + + + + Sent to + + + + + Payment to yourself + + + + + Mined + + + + + (n/a) + + + + + Transaction status. Hover over this field to show number of confirmations. + + + + + Date and time that the transaction was received. + + + + + Type of transaction. + + + + + Destination address of transaction. + + + + + Amount removed from or added to balance. + + + + + TransactionView + + + + All + Sve + + + + Today + Danas + + + + This week + + + + + This month + Ovaj mjesec + + + + Last month + Prošli mjesec + + + + This year + Ove godine + + + + Range... + + + + + Received with + + + + + Sent to + + + + + To yourself + + + + + Mined + + + + + Other + + + + + Enter address or label to search + + + + + Min amount + + + + + Copy address + + + + + Copy label + + + + + Copy amount + + + + + Copy transaction ID + + + + + Edit label + + + + + Show transaction details + + + + + Export Transaction Data + + + + + Comma separated file (*.csv) + + + + + Confirmed + + + + + Date + + + + + Type + + + + + Label + + + + + Address + + + + + Amount + + + + + ID + + + + + Error exporting + + + + + Could not write to file %1. + + + + + Range: + + + + + to + + + + + WalletModel + + + Sending... + + + + + bitcoin-core + + + Arepacoin version + + + + + Usage: + + + + + Send command to -server or arepacoind + + + + + List commands + + + + + Get help for a command + + + + + Options: + + + + + Specify configuration file (default: arepacoin.conf) + + + + + Specify pid file (default: arepacoind.pid) + + + + + Specify wallet file (within data directory) + + + + + Specify data directory + + + + + Set database cache size in megabytes (default: 25) + + + + + Set database disk log size in megabytes (default: 100) + + + + + Listen for connections on <port> (default: 9853 or testnet: 19853) + + + + + Maintain at most <n> connections to peers (default: 125) + + + + + Connect to a node to retrieve peer addresses, and disconnect + + + + + Specify your own public address + + + + + Bind to given address. Use [host]:port notation for IPv6 + + + + + Stake your coins to support network and gain reward (default: 1) + + + + + Threshold for disconnecting misbehaving peers (default: 100) + + + + + Number of seconds to keep misbehaving peers from reconnecting (default: 86400) + + + + + An error occurred while setting up the RPC port %u for listening on IPv4: %s + + + + + Detach block and address databases. Increases shutdown time (default: 0) + + + + + 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. + + + + + Error: This transaction requires a transaction fee of at least %s because of its amount, complexity, or use of recently received funds + + + + + Listen for JSON-RPC connections on <port> (default: 9852 or testnet: 19852) + + + + + Accept command line and JSON-RPC commands + + + + + Error: Transaction creation failed + + + + + Error: Wallet locked, unable to create transaction + + + + + Importing blockchain data file. + + + + + Importing bootstrap blockchain data file. + + + + + Run in the background as a daemon and accept commands + + + + + Use the test network + + + + + Accept connections from outside (default: 1 if no -proxy or -connect) + + + + + An error occurred while setting up the RPC port %u for listening on IPv6, falling back to IPv4: %s + + + + + Error initializing database environment %s! To recover, BACKUP THAT DIRECTORY, then remove everything from it except for wallet.dat. + + + + + Set maximum size of high-priority/low-fee transactions in bytes (default: 27000) + + + + + Warning: -paytxfee is set very high! This is the transaction fee you will pay if you send a transaction. + + + + + Warning: Please check that your computer's date and time are correct! If your clock is wrong Arepacoin will not work properly. + + + + + Warning: error reading wallet.dat! All keys read correctly, but transaction data or address book entries might be missing or incorrect. + + + + + Warning: wallet.dat corrupt, data salvaged! Original wallet.dat saved as wallet.{timestamp}.bak in %s; if your balance or transactions are incorrect you should restore from a backup. + + + + + Attempt to recover private keys from a corrupt wallet.dat + + + + + Block creation options: + + + + + Connect only to the specified node(s) + + + + + Discover own IP address (default: 1 when listening and no -externalip) + + + + + Failed to listen on any port. Use -listen=0 if you want this. + + + + + Find peers using DNS lookup (default: 1) + + + + + Sync checkpoints policy (default: strict) + + + + + Invalid -tor address: '%s' + + + + + Invalid amount for -reservebalance=<amount> + + + + + Maximum per-connection receive buffer, <n>*1000 bytes (default: 5000) + + + + + Maximum per-connection send buffer, <n>*1000 bytes (default: 1000) + + + + + Only connect to nodes in network <net> (IPv4, IPv6 or Tor) + + + + + Output extra debugging information. Implies all other -debug* options + + + + + Output extra network debugging information + + + + + Prepend debug output with timestamp + + + + + SSL options: (see the Bitcoin Wiki for SSL setup instructions) + + + + + Select the version of socks proxy to use (4-5, default: 5) + + + + + Send trace/debug info to console instead of debug.log file + + + + + Send trace/debug info to debugger + + + + + Set maximum block size in bytes (default: 250000) + + + + + Set minimum block size in bytes (default: 0) + + + + + Shrink debug.log file on client startup (default: 1 when no -debug) + + + + + Specify connection timeout in milliseconds (default: 5000) + + + + + Unable to sign checkpoint, wrong checkpointkey? + + + + + + Use UPnP to map the listening port (default: 0) + + + + + Use UPnP to map the listening port (default: 1 when listening) + + + + + Use proxy to reach tor hidden services (default: same as -proxy) + + + + + Username for JSON-RPC connections + + + + + Verifying database integrity... + + + + + WARNING: syncronized checkpoint violation detected, but skipped! + + + + + Warning: Disk space is low! + + + + + Warning: This version is obsolete, upgrade required! + + + + + wallet.dat corrupt, salvage failed + + + + + Password for JSON-RPC connections + + + + + %s, you must set a rpcpassword in the configuration file: + %s +It is recommended you use the following random password: +rpcuser=arepacoinrpc +rpcpassword=%s +(you do not need to remember this password) +The username and password MUST NOT be the same. +If the file does not exist, create it with owner-readable-only file permissions. +It is also recommended to set alertnotify so you are notified of problems; +for example: alertnotify=echo %%s | mail -s "Arepacoin Alert" admin@foo.com + + + + + + Find peers using internet relay chat (default: 0) + + + + + Sync time with other nodes. Disable if time on your system is precise e.g. syncing with NTP (default: 1) + + + + + When creating transactions, ignore inputs with value less than this (default: 0.01) + + + + + Allow JSON-RPC connections from specified IP address + + + + + Send commands to node running on <ip> (default: 127.0.0.1) + + + + + Execute command when the best block changes (%s in cmd is replaced by block hash) + + + + + Execute command when a wallet transaction changes (%s in cmd is replaced by TxID) + + + + + Require a confirmations for change (default: 0) + + + + + Enforce transaction scripts to use canonical PUSH operators (default: 1) + + + + + Execute command when a relevant alert is received (%s in cmd is replaced by message) + + + + + Upgrade wallet to latest format + + + + + Set key pool size to <n> (default: 100) + + + + + Rescan the block chain for missing wallet transactions + + + + + How many blocks to check at startup (default: 2500, 0 = all) + + + + + How thorough the block verification is (0-6, default: 1) + + + + + Imports blocks from external blk000?.dat file + + + + + Use OpenSSL (https) for JSON-RPC connections + + + + + Server certificate file (default: server.cert) + + + + + Server private key (default: server.pem) + + + + + Acceptable ciphers (default: TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH) + + + + + Error: Wallet unlocked for staking only, unable to create transaction. + + + + + WARNING: Invalid checkpoint found! Displayed transactions may not be correct! You may need to upgrade, or notify developers. + + + + + This help message + + + + + Wallet %s resides outside data directory %s. + + + + + Cannot obtain a lock on data directory %s. Arepacoin is probably already running. + + + + + Arepacoin + + + + + Unable to bind to %s on this computer (bind returned error %d, %s) + + + + + Connect through socks proxy + + + + + Allow DNS lookups for -addnode, -seednode and -connect + + + + + Loading addresses... + + + + + Error loading blkindex.dat + + + + + Error loading wallet.dat: Wallet corrupted + + + + + Error loading wallet.dat: Wallet requires newer version of Arepacoin + + + + + Wallet needed to be rewritten: restart Arepacoin to complete + + + + + Error loading wallet.dat + + + + + Invalid -proxy address: '%s' + + + + + Unknown network specified in -onlynet: '%s' + + + + + Unknown -socks proxy version requested: %i + + + + + Cannot resolve -bind address: '%s' + + + + + Cannot resolve -externalip address: '%s' + + + + + Invalid amount for -paytxfee=<amount>: '%s' + + + + + Error: could not start node + + + + + Sending... + + + + + Invalid amount + + + + + Insufficient funds + + + + + Loading block index... + + + + + Add a node to connect to and attempt to keep the connection open + + + + + Unable to bind to %s on this computer. Arepacoin is probably already running. + + + + + Fee per KB to add to transactions you send + + + + + Invalid amount for -mininput=<amount>: '%s' + + + + + Loading wallet... + + + + + Cannot downgrade wallet + + + + + Cannot initialize keypool + + + + + Cannot write default address + + + + + Rescanning... + + + + + Done loading + + + + + To use the %s option + + + + + Error + + + + + You must set rpcpassword=<password> in the configuration file: +%s +If the file does not exist, create it with owner-readable-only file permissions. + + + + \ No newline at end of file diff --git a/src/qt/locale/bitcoin_ca.ts b/src/qt/locale/bitcoin_ca.ts new file mode 100755 index 0000000..8f5ca14 --- /dev/null +++ b/src/qt/locale/bitcoin_ca.ts @@ -0,0 +1,3275 @@ + + + AboutDialog + + + About Arepacoin + + + + + <b>Arepacoin</b> version + + + + + Copyright © 2009-2014 The Bitcoin developers +Copyright © 2012-2014 The NovaCoin developers +Copyright © 2014 The Arepacoin developers + + + + + +This is experimental software. + +Distributed under the MIT/X11 software license, see the accompanying file COPYING or http://www.opensource.org/licenses/mit-license.php. + +This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit (http://www.openssl.org/) and cryptographic software written by Eric Young (eay@cryptsoft.com) and UPnP software written by Thomas Bernard. + + + + + AddressBookPage + + + Address Book + + + + + Double-click to edit address or label + Doble click per editar l'adreça o l'etiqueta + + + + Create a new address + Crear una nova adrça + + + + Copy the currently selected address to the system clipboard + Copia la selecció actual al porta-retalls del sistema + + + + &New Address + + + + + These are your Arepacoin addresses for receiving payments. You may want to give a different one to each sender so you can keep track of who is paying you. + + + + + &Copy Address + + + + + Show &QR Code + + + + + Sign a message to prove you own a Arepacoin address + + + + + Sign &Message + + + + + Delete the currently selected address from the list + + + + + Verify a message to ensure it was signed with a specified Arepacoin address + + + + + &Verify Message + + + + + &Delete + &Eliminar + + + + Copy &Label + + + + + &Edit + + + + + Export Address Book Data + + + + + Comma separated file (*.csv) + Fitxer separat per comes (*.csv) + + + + Error exporting + + + + + Could not write to file %1. + + + + + AddressTableModel + + + Label + Etiqueta + + + + Address + Adreça + + + + (no label) + (sense etiqueta) + + + + AskPassphraseDialog + + + Passphrase Dialog + + + + + Enter passphrase + Introduïu la frase-contrasenya + + + + New passphrase + Nova frase-contrasenya + + + + Repeat new passphrase + Repetiu la nova frase-contrasenya + + + + Serves to disable the trivial sendmoney when OS account compromised. Provides no real security. + + + + + For staking only + + + + + Enter the new passphrase to the wallet.<br/>Please use a passphrase of <b>10 or more random characters</b>, or <b>eight or more words</b>. + Introduïu la nova frase-contrasenya per a la cartera.<br/>Empreu una frase-contrasenya de <b>10 o més caràcters aleatoris<b/>, o <b>vuit o més paraules<b/>. + + + + Encrypt wallet + Encriptar cartera + + + + This operation needs your wallet passphrase to unlock the wallet. + Cal que introduïu la frase-contrasenya de la cartera per a desbloquejar-la. + + + + Unlock wallet + Desbloquejar cartera + + + + This operation needs your wallet passphrase to decrypt the wallet. + Cal que introduïu la frase-contrasenya de la cartera per a desencriptar-la. + + + + Decrypt wallet + Desencriptar cartera + + + + Change passphrase + Canviar frase-contrasenya + + + + Enter the old and new passphrase to the wallet. + Introduïu l'antiga i la nova frase-contrasenya per a la cartera. + + + + Confirm wallet encryption + Confirmeu l'encriptació de cartera + + + + Warning: If you encrypt your wallet and lose your passphrase, you will <b>LOSE ALL OF YOUR COINS</b>! + + + + + Are you sure you wish to encrypt your wallet? + + + + + IMPORTANT: Any previous backups you have made of your wallet file should be replaced with the newly generated, encrypted wallet file. For security reasons, previous backups of the unencrypted wallet file will become useless as soon as you start using the new, encrypted wallet. + + + + + + Warning: The Caps Lock key is on! + + + + + + Wallet encrypted + Cartera encriptada + + + + Arepacoin will close now to finish the encryption process. Remember that encrypting your wallet cannot fully protect your coins from being stolen by malware infecting your computer. + + + + + + + + Wallet encryption failed + L'encriptació de cartera ha fallat + + + + Wallet encryption failed due to an internal error. Your wallet was not encrypted. + L'encriptació de cartera ha fallat degut a un error intern. La vostra cartera no ha estat encriptada. + + + + + The supplied passphrases do not match. + Les frases-contrasenya no concorden. + + + + Wallet unlock failed + El desbloqueig de cartera ha fallat + + + + + + The passphrase entered for the wallet decryption was incorrect. + La frase-contrasenya per a la desencriptació de cartera és incorrecta. + + + + Wallet decryption failed + La desencriptació de cartera ha fallat + + + + Wallet passphrase was successfully changed. + + + + + BitcoinGUI + + + Sign &message... + + + + + Synchronizing with network... + Sincronitzant amb la xarxa... + + + + &Overview + &Visió general + + + + Show general overview of wallet + Mostrar visió general de la cartera + + + + &Transactions + &Transaccions + + + + Browse transaction history + Exploreu l'historial de transaccions + + + + &Address Book + + + + + Edit the list of stored addresses and labels + + + + + &Receive coins + + + + + Show the list of addresses for receiving payments + + + + + &Send coins + + + + + E&xit + + + + + Quit application + Sortir de l'aplicació + + + + Show information about Arepacoin + + + + + About &Qt + + + + + Show information about Qt + + + + + &Options... + &Opcions... + + + + &Encrypt Wallet... + + + + + &Backup Wallet... + + + + + &Change Passphrase... + + + + + ~%n block(s) remaining + + + + + Downloaded %1 of %2 blocks of transaction history (%3% done). + + + + + &Export... + + + + + Send coins to a Arepacoin address + + + + + Modify configuration options for Arepacoin + + + + + Export the data in the current tab to a file + + + + + Encrypt or decrypt wallet + + + + + Backup wallet to another location + + + + + Change the passphrase used for wallet encryption + Canviar frase-contrasenya per a l'escriptació de la cartera + + + + &Debug window + + + + + Open debugging and diagnostic console + + + + + &Verify message... + + + + + Arepacoin + + + + + Wallet + + + + + &About Arepacoin + + + + + &Show / Hide + + + + + Unlock wallet + + + + + &Lock Wallet + + + + + Lock wallet + + + + + &File + &Fitxer + + + + &Settings + &Configuració + + + + &Help + &Ajuda + + + + Tabs toolbar + Barra d'eines + + + + Actions toolbar + + + + + + [testnet] + [testnet] + + + + + Arepacoin client + + + + + %n active connection(s) to Arepacoin network + + + + + Downloaded %1 blocks of transaction history. + + + + + Staking.<br>Your weight is %1<br>Network weight is %2<br>Expected time to earn reward is %3 + + + + + Not staking because wallet is locked + + + + + Not staking because wallet is offline + + + + + Not staking because wallet is syncing + + + + + Not staking because you don't have mature coins + + + + + %n second(s) ago + + + + + &Unlock Wallet... + + + + + %n minute(s) ago + + + + + %n hour(s) ago + + + + + %n day(s) ago + + + + + Up to date + + + + + Catching up... + Actualitzant... + + + + Last received block was generated %1. + + + + + This transaction is over the size limit. You can still send it for a fee of %1, which goes to the nodes that process your transaction and helps to support the network. Do you want to pay the fee? + + + + + Confirm transaction fee + + + + + Sent transaction + Transacció enviada + + + + Incoming transaction + Transacció entrant + + + + Date: %1 +Amount: %2 +Type: %3 +Address: %4 + + + + + + + URI handling + + + + + + URI can not be parsed! This can be caused by an invalid Arepacoin address or malformed URI parameters. + + + + + Wallet is <b>encrypted</b> and currently <b>unlocked</b> + La cartera està <b>encriptada<b/> i <b>desbloquejada<b/> + + + + Wallet is <b>encrypted</b> and currently <b>locked</b> + La cartera està <b>encriptada<b/> i <b>bloquejada<b/> + + + + Backup Wallet + + + + + Wallet Data (*.dat) + + + + + Backup Failed + + + + + There was an error trying to save the wallet data to the new location. + + + + + %n second(s) + + + + + %n minute(s) + + + + + %n hour(s) + + + + + %n day(s) + + + + + Not staking + + + + + A fatal error occurred. Arepacoin can no longer continue safely and will quit. + + + + + ClientModel + + + Network Alert + + + + + CoinControlDialog + + + Coin Control + + + + + Quantity: + + + + + Bytes: + + + + + Amount: + + + + + Priority: + + + + + Fee: + + + + + Low Output: + + + + + no + + + + + After Fee: + + + + + Change: + + + + + (un)select all + + + + + Tree mode + + + + + List mode + + + + + Amount + + + + + Label + + + + + Address + Adreça + + + + Date + + + + + Confirmations + + + + + Confirmed + + + + + Priority + + + + + Copy address + + + + + Copy label + + + + + + Copy amount + + + + + Copy transaction ID + + + + + Copy quantity + + + + + Copy fee + + + + + Copy after fee + + + + + Copy bytes + + + + + Copy priority + + + + + Copy low output + + + + + Copy change + + + + + highest + + + + + high + + + + + medium-high + + + + + medium + + + + + low-medium + + + + + low + + + + + lowest + + + + + DUST + + + + + yes + + + + + This label turns red, if the transaction size is bigger than 10000 bytes. + + This means a fee of at least %1 per kb is required. + + Can vary +/- 1 Byte per input. + + + + + Transactions with higher priority get more likely into a block. + +This label turns red, if the priority is smaller than "medium". + + This means a fee of at least %1 per kb is required. + + + + + This label turns red, if any recipient receives an amount smaller than %1. + + This means a fee of at least %2 is required. + + Amounts below 0.546 times the minimum relay fee are shown as DUST. + + + + + This label turns red, if the change is smaller than %1. + + This means a fee of at least %2 is required. + + + + + + (no label) + (sense etiqueta) + + + + change from %1 (%2) + + + + + (change) + + + + + EditAddressDialog + + + Edit Address + Editar adreça + + + + &Label + &Etiqueta + + + + The label associated with this address book entry + + + + + &Address + &Adreça + + + + The address associated with this address book entry. This can only be modified for sending addresses. + + + + + New receiving address + + + + + New sending address + + + + + Edit receiving address + + + + + Edit sending address + + + + + The entered address "%1" is already in the address book. + + + + + The entered address "%1" is not a valid Arepacoin address. + + + + + Could not unlock wallet. + + + + + New key generation failed. + + + + + GUIUtil::HelpMessageBox + + + + Arepacoin-Qt + + + + + version + + + + + Usage: + + + + + command-line options + + + + + UI options + + + + + Set language, for example "de_DE" (default: system locale) + + + + + Start minimized + + + + + Show splash screen on startup (default: 1) + + + + + OptionsDialog + + + Options + + + + + &Main + + + + + Optional transaction fee per kB that helps make sure your transactions are processed quickly. Most transactions are 1 kB. Fee 0.01 recommended. + + + + + Pay transaction &fee + + + + + Reserved amount does not participate in staking and is therefore spendable at any time. + + + + + Reserve + + + + + Automatically start Arepacoin after logging in to the system. + + + + + &Start Arepacoin on system login + + + + + Detach block and address databases at shutdown. This means they can be moved to another data directory, but it slows down shutdown. The wallet is always detached. + + + + + &Detach databases at shutdown + + + + + &Network + + + + + Automatically open the Arepacoin client port on the router. This only works when your router supports UPnP and it is enabled. + + + + + Map port using &UPnP + + + + + Connect to the Arepacoin network through a SOCKS proxy (e.g. when connecting through Tor). + + + + + &Connect through SOCKS proxy: + + + + + Proxy &IP: + + + + + IP address of the proxy (e.g. 127.0.0.1) + + + + + &Port: + + + + + Port of the proxy (e.g. 9050) + + + + + SOCKS &Version: + + + + + SOCKS version of the proxy (e.g. 5) + + + + + &Window + + + + + Show only a tray icon after minimizing the window. + + + + + &Minimize to the tray instead of the taskbar + + + + + Minimize instead of exit the application when the window is closed. When this option is enabled, the application will be closed only after selecting Quit in the menu. + + + + + M&inimize on close + + + + + &Display + + + + + User Interface &language: + + + + + The user interface language can be set here. This setting will take effect after restarting Arepacoin. + + + + + &Unit to show amounts in: + + + + + Choose the default subdivision unit to show in the interface and when sending coins. + + + + + Whether to show Arepacoin addresses in the transaction list or not. + + + + + &Display addresses in transaction list + + + + + Whether to show coin control features or not. + + + + + Display coin &control features (experts only!) + + + + + &OK + + + + + &Cancel + + + + + &Apply + + + + + default + + + + + + Warning + + + + + + This setting will take effect after restarting Arepacoin. + + + + + The supplied proxy address is invalid. + + + + + OverviewPage + + + Form + + + + + + The displayed information may be out of date. Your wallet automatically synchronizes with the Arepacoin network after a connection is established, but this process has not completed yet. + + + + + Stake: + + + + + Unconfirmed: + + + + + Wallet + + + + + Spendable: + + + + + Your current spendable balance + + + + + Immature: + + + + + Mined balance that has not yet matured + + + + + Total: + + + + + Your current total balance + + + + + <b>Recent transactions</b> + + + + + Total of transactions that have yet to be confirmed, and do not yet count toward the current balance + + + + + Total of coins that was staked, and do not yet count toward the current balance + + + + + + out of sync + + + + + QRCodeDialog + + + QR Code Dialog + + + + + Request Payment + + + + + Amount: + + + + + Label: + + + + + Message: + + + + + &Save As... + + + + + Error encoding URI into QR Code. + + + + + The entered amount is invalid, please check. + + + + + Resulting URI too long, try to reduce the text for label / message. + + + + + Save QR Code + + + + + PNG Images (*.png) + + + + + RPCConsole + + + Client name + + + + + + + + + + + + + + N/A + + + + + Client version + + + + + &Information + + + + + Using OpenSSL version + + + + + Startup time + + + + + Network + + + + + Number of connections + + + + + On testnet + + + + + Block chain + + + + + Current number of blocks + + + + + Estimated total blocks + + + + + Last block time + + + + + &Open + + + + + Command-line options + + + + + Show the Arepacoin-Qt help message to get a list with possible Arepacoin command-line options. + + + + + &Show + + + + + &Console + + + + + Build date + + + + + Arepacoin - Debug window + + + + + Arepacoin Core + + + + + Debug log file + + + + + Open the Arepacoin debug log file from the current data directory. This can take a few seconds for large log files. + + + + + Clear console + + + + + Welcome to the Arepacoin RPC console. + + + + + Use up and down arrows to navigate history, and <b>Ctrl-L</b> to clear screen. + + + + + Type <b>help</b> for an overview of available commands. + + + + + SendCoinsDialog + + + + + + + + + + Send Coins + + + + + Coin Control Features + + + + + Inputs... + + + + + automatically selected + + + + + Insufficient funds! + + + + + Quantity: + + + + + + 0 + + + + + Bytes: + + + + + Amount: + + + + + + + + 0.00 BC + + + + + Priority: + + + + + medium + + + + + Fee: + + + + + Low Output: + + + + + no + + + + + After Fee: + + + + + Change + + + + + custom change address + + + + + Send to multiple recipients at once + + + + + Add &Recipient + + + + + Remove all transaction fields + + + + + Clear &All + + + + + Balance: + + + + + 123.456 BC + + + + + Confirm the send action + + + + + S&end + + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Copy quantity + + + + + Copy amount + + + + + Copy fee + + + + + Copy after fee + + + + + Copy bytes + + + + + Copy priority + + + + + Copy low output + + + + + Copy change + + + + + <b>%1</b> to %2 (%3) + + + + + Confirm send coins + + + + + Are you sure you want to send %1? + + + + + and + + + + + The recipient address is not valid, please recheck. + + + + + The amount to pay must be larger than 0. + + + + + The amount exceeds your balance. + + + + + The total exceeds your balance when the %1 transaction fee is included. + + + + + Duplicate address found, can only send to each address once per send operation. + + + + + Error: Transaction creation failed. + + + + + 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. + + + + + WARNING: Invalid Arepacoin address + + + + + (no label) + (sense etiqueta) + + + + WARNING: unknown change address + + + + + SendCoinsEntry + + + Form + + + + + A&mount: + + + + + Pay &To: + + + + + + Enter a label for this address to add it to your address book + + + + + &Label: + + + + + The address to send the payment to (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Choose address from address book + + + + + Alt+A + + + + + Paste address from clipboard + + + + + Alt+P + + + + + Remove this recipient + + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + SignVerifyMessageDialog + + + Signatures - Sign / Verify a Message + + + + + + &Sign Message + + + + + You can sign messages with your addresses to prove you own them. Be careful not to sign anything vague, as phishing attacks may try to trick you into signing your identity over to them. Only sign fully-detailed statements you agree to. + + + + + The address to sign the message with (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + + Choose an address from the address book + + + + + + Alt+A + + + + + Paste address from clipboard + + + + + Alt+P + + + + + Enter the message you want to sign here + + + + + Copy the current signature to the system clipboard + + + + + Sign the message to prove you own this Arepacoin address + + + + + Reset all sign message fields + + + + + + Clear &All + + + + + + &Verify Message + + + + + Enter the signing address, message (ensure you copy line breaks, spaces, tabs, etc. exactly) and signature below to verify the message. Be careful not to read more into the signature than what is in the signed message itself, to avoid being tricked by a man-in-the-middle attack. + + + + + The address the message was signed with (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Verify the message to ensure it was signed with the specified Arepacoin address + + + + + Reset all verify message fields + + + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Click "Sign Message" to generate signature + + + + + Enter Arepacoin signature + + + + + + The entered address is invalid. + + + + + + + + Please check the address and try again. + + + + + + The entered address does not refer to a key. + + + + + Wallet unlock was cancelled. + + + + + Private key for the entered address is not available. + + + + + Message signing failed. + + + + + Message signed. + + + + + The signature could not be decoded. + + + + + + Please check the signature and try again. + + + + + The signature did not match the message digest. + + + + + Message verification failed. + + + + + Message verified. + + + + + TransactionDesc + + + Open until %1 + + + + + Open for %n block(s) + + + + + conflicted + + + + + %1/offline + + + + + %1/unconfirmed + + + + + %1 confirmations + + + + + Status + + + + + , broadcast through %n node(s) + + + + + Date + + + + + Source + + + + + Generated + + + + + + From + + + + + + + To + + + + + + own address + + + + + label + + + + + + + + + Credit + + + + + matures in %n more block(s) + + + + + not accepted + + + + + + + + Debit + + + + + Transaction fee + + + + + Net amount + + + + + Message + + + + + Comment + + + + + Transaction ID + + + + + Generated coins must mature 6 blocks before they can be spent. When you generated this block, it was broadcast to the network to be added to the block chain. If it fails to get into the chain, its state will change to "not accepted" and it won't be spendable. This may occasionally happen if another node generates a block within a few seconds of yours. + + + + + Debug information + + + + + Transaction + + + + + Inputs + + + + + Amount + + + + + true + + + + + false + + + + + , has not been successfully broadcast yet + + + + + unknown + + + + + TransactionDescDialog + + + Transaction details + + + + + This pane shows a detailed description of the transaction + + + + + TransactionTableModel + + + Date + + + + + Type + + + + + Address + Adreça + + + + Amount + + + + + Open until %1 + + + + + Confirmed (%1 confirmations) + + + + + Open for %n more block(s) + + + + + Offline + + + + + Unconfirmed + + + + + Confirming (%1 of %2 recommended confirmations) + + + + + Conflicted + + + + + Immature (%1 confirmations, will be available after %2) + + + + + This block was not received by any other nodes and will probably not be accepted! + + + + + Generated but not accepted + + + + + Received with + + + + + Received from + + + + + Sent to + + + + + Payment to yourself + + + + + Mined + + + + + (n/a) + + + + + Transaction status. Hover over this field to show number of confirmations. + + + + + Date and time that the transaction was received. + + + + + Type of transaction. + + + + + Destination address of transaction. + + + + + Amount removed from or added to balance. + + + + + TransactionView + + + + All + + + + + Today + + + + + This week + + + + + This month + + + + + Last month + + + + + This year + + + + + Range... + + + + + Received with + + + + + Sent to + + + + + To yourself + + + + + Mined + + + + + Other + + + + + Enter address or label to search + + + + + Min amount + + + + + Copy address + + + + + Copy label + + + + + Copy amount + + + + + Copy transaction ID + + + + + Edit label + + + + + Show transaction details + + + + + Export Transaction Data + + + + + Comma separated file (*.csv) + Fitxer separat per comes (*.csv) + + + + Confirmed + + + + + Date + + + + + Type + + + + + Label + Etiqueta + + + + Address + Adreça + + + + Amount + + + + + ID + + + + + Error exporting + + + + + Could not write to file %1. + + + + + Range: + + + + + to + + + + + WalletModel + + + Sending... + + + + + bitcoin-core + + + Arepacoin version + + + + + Usage: + + + + + Send command to -server or arepacoind + + + + + List commands + + + + + Get help for a command + + + + + Options: + + + + + Specify configuration file (default: arepacoin.conf) + + + + + Specify pid file (default: arepacoind.pid) + + + + + Specify wallet file (within data directory) + + + + + Specify data directory + + + + + Set database cache size in megabytes (default: 25) + + + + + Set database disk log size in megabytes (default: 100) + + + + + Listen for connections on <port> (default: 9853 or testnet: 19853) + + + + + Maintain at most <n> connections to peers (default: 125) + + + + + Connect to a node to retrieve peer addresses, and disconnect + + + + + Specify your own public address + + + + + Bind to given address. Use [host]:port notation for IPv6 + + + + + Stake your coins to support network and gain reward (default: 1) + + + + + Threshold for disconnecting misbehaving peers (default: 100) + + + + + Number of seconds to keep misbehaving peers from reconnecting (default: 86400) + + + + + An error occurred while setting up the RPC port %u for listening on IPv4: %s + + + + + Detach block and address databases. Increases shutdown time (default: 0) + + + + + 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. + + + + + Error: This transaction requires a transaction fee of at least %s because of its amount, complexity, or use of recently received funds + + + + + Listen for JSON-RPC connections on <port> (default: 9852 or testnet: 19852) + + + + + Accept command line and JSON-RPC commands + + + + + Error: Transaction creation failed + + + + + Error: Wallet locked, unable to create transaction + + + + + Importing blockchain data file. + + + + + Importing bootstrap blockchain data file. + + + + + Run in the background as a daemon and accept commands + + + + + Use the test network + + + + + Accept connections from outside (default: 1 if no -proxy or -connect) + + + + + An error occurred while setting up the RPC port %u for listening on IPv6, falling back to IPv4: %s + + + + + Error initializing database environment %s! To recover, BACKUP THAT DIRECTORY, then remove everything from it except for wallet.dat. + + + + + Set maximum size of high-priority/low-fee transactions in bytes (default: 27000) + + + + + Warning: -paytxfee is set very high! This is the transaction fee you will pay if you send a transaction. + + + + + Warning: Please check that your computer's date and time are correct! If your clock is wrong Arepacoin will not work properly. + + + + + Warning: error reading wallet.dat! All keys read correctly, but transaction data or address book entries might be missing or incorrect. + + + + + Warning: wallet.dat corrupt, data salvaged! Original wallet.dat saved as wallet.{timestamp}.bak in %s; if your balance or transactions are incorrect you should restore from a backup. + + + + + Attempt to recover private keys from a corrupt wallet.dat + + + + + Block creation options: + + + + + Connect only to the specified node(s) + + + + + Discover own IP address (default: 1 when listening and no -externalip) + + + + + Failed to listen on any port. Use -listen=0 if you want this. + + + + + Find peers using DNS lookup (default: 1) + + + + + Sync checkpoints policy (default: strict) + + + + + Invalid -tor address: '%s' + + + + + Invalid amount for -reservebalance=<amount> + + + + + Maximum per-connection receive buffer, <n>*1000 bytes (default: 5000) + + + + + Maximum per-connection send buffer, <n>*1000 bytes (default: 1000) + + + + + Only connect to nodes in network <net> (IPv4, IPv6 or Tor) + + + + + Output extra debugging information. Implies all other -debug* options + + + + + Output extra network debugging information + + + + + Prepend debug output with timestamp + + + + + SSL options: (see the Bitcoin Wiki for SSL setup instructions) + + + + + Select the version of socks proxy to use (4-5, default: 5) + + + + + Send trace/debug info to console instead of debug.log file + + + + + Send trace/debug info to debugger + + + + + Set maximum block size in bytes (default: 250000) + + + + + Set minimum block size in bytes (default: 0) + + + + + Shrink debug.log file on client startup (default: 1 when no -debug) + + + + + Specify connection timeout in milliseconds (default: 5000) + + + + + Unable to sign checkpoint, wrong checkpointkey? + + + + + + Use UPnP to map the listening port (default: 0) + + + + + Use UPnP to map the listening port (default: 1 when listening) + + + + + Use proxy to reach tor hidden services (default: same as -proxy) + + + + + Username for JSON-RPC connections + + + + + Verifying database integrity... + + + + + WARNING: syncronized checkpoint violation detected, but skipped! + + + + + Warning: Disk space is low! + + + + + Warning: This version is obsolete, upgrade required! + + + + + wallet.dat corrupt, salvage failed + + + + + Password for JSON-RPC connections + + + + + %s, you must set a rpcpassword in the configuration file: + %s +It is recommended you use the following random password: +rpcuser=arepacoinrpc +rpcpassword=%s +(you do not need to remember this password) +The username and password MUST NOT be the same. +If the file does not exist, create it with owner-readable-only file permissions. +It is also recommended to set alertnotify so you are notified of problems; +for example: alertnotify=echo %%s | mail -s "Arepacoin Alert" admin@foo.com + + + + + + Find peers using internet relay chat (default: 0) + + + + + Sync time with other nodes. Disable if time on your system is precise e.g. syncing with NTP (default: 1) + + + + + When creating transactions, ignore inputs with value less than this (default: 0.01) + + + + + Allow JSON-RPC connections from specified IP address + + + + + Send commands to node running on <ip> (default: 127.0.0.1) + + + + + Execute command when the best block changes (%s in cmd is replaced by block hash) + + + + + Execute command when a wallet transaction changes (%s in cmd is replaced by TxID) + + + + + Require a confirmations for change (default: 0) + + + + + Enforce transaction scripts to use canonical PUSH operators (default: 1) + + + + + Execute command when a relevant alert is received (%s in cmd is replaced by message) + + + + + Upgrade wallet to latest format + + + + + Set key pool size to <n> (default: 100) + + + + + Rescan the block chain for missing wallet transactions + + + + + How many blocks to check at startup (default: 2500, 0 = all) + + + + + How thorough the block verification is (0-6, default: 1) + + + + + Imports blocks from external blk000?.dat file + + + + + Use OpenSSL (https) for JSON-RPC connections + + + + + Server certificate file (default: server.cert) + + + + + Server private key (default: server.pem) + + + + + Acceptable ciphers (default: TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH) + + + + + Error: Wallet unlocked for staking only, unable to create transaction. + + + + + WARNING: Invalid checkpoint found! Displayed transactions may not be correct! You may need to upgrade, or notify developers. + + + + + This help message + + + + + Wallet %s resides outside data directory %s. + + + + + Cannot obtain a lock on data directory %s. Arepacoin is probably already running. + + + + + Arepacoin + + + + + Unable to bind to %s on this computer (bind returned error %d, %s) + + + + + Connect through socks proxy + + + + + Allow DNS lookups for -addnode, -seednode and -connect + + + + + Loading addresses... + + + + + Error loading blkindex.dat + + + + + Error loading wallet.dat: Wallet corrupted + + + + + Error loading wallet.dat: Wallet requires newer version of Arepacoin + + + + + Wallet needed to be rewritten: restart Arepacoin to complete + + + + + Error loading wallet.dat + + + + + Invalid -proxy address: '%s' + + + + + Unknown network specified in -onlynet: '%s' + + + + + Unknown -socks proxy version requested: %i + + + + + Cannot resolve -bind address: '%s' + + + + + Cannot resolve -externalip address: '%s' + + + + + Invalid amount for -paytxfee=<amount>: '%s' + + + + + Error: could not start node + + + + + Sending... + + + + + Invalid amount + + + + + Insufficient funds + + + + + Loading block index... + + + + + Add a node to connect to and attempt to keep the connection open + + + + + Unable to bind to %s on this computer. Arepacoin is probably already running. + + + + + Fee per KB to add to transactions you send + + + + + Invalid amount for -mininput=<amount>: '%s' + + + + + Loading wallet... + + + + + Cannot downgrade wallet + + + + + Cannot initialize keypool + + + + + Cannot write default address + + + + + Rescanning... + + + + + Done loading + + + + + To use the %s option + + + + + Error + + + + + You must set rpcpassword=<password> in the configuration file: +%s +If the file does not exist, create it with owner-readable-only file permissions. + + + + \ No newline at end of file diff --git a/src/qt/locale/bitcoin_ca@valencia.ts b/src/qt/locale/bitcoin_ca@valencia.ts new file mode 100755 index 0000000..2bb4a2e --- /dev/null +++ b/src/qt/locale/bitcoin_ca@valencia.ts @@ -0,0 +1,3275 @@ + + + AboutDialog + + + About Arepacoin + + + + + <b>Arepacoin</b> version + + + + + Copyright © 2009-2014 The Bitcoin developers +Copyright © 2012-2014 The NovaCoin developers +Copyright © 2014 The Arepacoin developers + + + + + +This is experimental software. + +Distributed under the MIT/X11 software license, see the accompanying file COPYING or http://www.opensource.org/licenses/mit-license.php. + +This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit (http://www.openssl.org/) and cryptographic software written by Eric Young (eay@cryptsoft.com) and UPnP software written by Thomas Bernard. + + + + + AddressBookPage + + + Address Book + + + + + Double-click to edit address or label + Doble click per editar la direccio o la etiqueta + + + + Create a new address + Crear nova direccio + + + + Copy the currently selected address to the system clipboard + Copieu l'adreça seleccionada al porta-retalls del sistema + + + + &New Address + + + + + These are your Arepacoin addresses for receiving payments. You may want to give a different one to each sender so you can keep track of who is paying you. + + + + + &Copy Address + + + + + Show &QR Code + + + + + Sign a message to prove you own a Arepacoin address + + + + + Sign &Message + + + + + Delete the currently selected address from the list + + + + + Verify a message to ensure it was signed with a specified Arepacoin address + + + + + &Verify Message + + + + + &Delete + Eliminar + + + + Copy &Label + + + + + &Edit + + + + + Export Address Book Data + + + + + Comma separated file (*.csv) + + + + + Error exporting + + + + + Could not write to file %1. + + + + + AddressTableModel + + + Label + + + + + Address + + + + + (no label) + + + + + AskPassphraseDialog + + + Passphrase Dialog + + + + + Enter passphrase + + + + + New passphrase + + + + + Repeat new passphrase + + + + + Serves to disable the trivial sendmoney when OS account compromised. Provides no real security. + + + + + For staking only + + + + + Enter the new passphrase to the wallet.<br/>Please use a passphrase of <b>10 or more random characters</b>, or <b>eight or more words</b>. + + + + + Encrypt wallet + + + + + This operation needs your wallet passphrase to unlock the wallet. + + + + + Unlock wallet + + + + + This operation needs your wallet passphrase to decrypt the wallet. + + + + + Decrypt wallet + + + + + Change passphrase + + + + + Enter the old and new passphrase to the wallet. + + + + + Confirm wallet encryption + + + + + Warning: If you encrypt your wallet and lose your passphrase, you will <b>LOSE ALL OF YOUR COINS</b>! + + + + + Are you sure you wish to encrypt your wallet? + + + + + IMPORTANT: Any previous backups you have made of your wallet file should be replaced with the newly generated, encrypted wallet file. For security reasons, previous backups of the unencrypted wallet file will become useless as soon as you start using the new, encrypted wallet. + + + + + + Warning: The Caps Lock key is on! + + + + + + Wallet encrypted + + + + + Arepacoin will close now to finish the encryption process. Remember that encrypting your wallet cannot fully protect your coins from being stolen by malware infecting your computer. + + + + + + + + Wallet encryption failed + + + + + Wallet encryption failed due to an internal error. Your wallet was not encrypted. + + + + + + The supplied passphrases do not match. + + + + + Wallet unlock failed + + + + + + + The passphrase entered for the wallet decryption was incorrect. + + + + + Wallet decryption failed + + + + + Wallet passphrase was successfully changed. + + + + + BitcoinGUI + + + Sign &message... + + + + + Synchronizing with network... + + + + + &Overview + + + + + Show general overview of wallet + + + + + &Transactions + + + + + Browse transaction history + + + + + &Address Book + + + + + Edit the list of stored addresses and labels + + + + + &Receive coins + + + + + Show the list of addresses for receiving payments + + + + + &Send coins + + + + + E&xit + + + + + Quit application + + + + + Show information about Arepacoin + + + + + About &Qt + + + + + Show information about Qt + + + + + &Options... + + + + + &Encrypt Wallet... + + + + + &Backup Wallet... + + + + + &Change Passphrase... + + + + + ~%n block(s) remaining + + + + + Downloaded %1 of %2 blocks of transaction history (%3% done). + + + + + &Export... + + + + + Send coins to a Arepacoin address + + + + + Modify configuration options for Arepacoin + + + + + Export the data in the current tab to a file + + + + + Encrypt or decrypt wallet + + + + + Backup wallet to another location + + + + + Change the passphrase used for wallet encryption + + + + + &Debug window + + + + + Open debugging and diagnostic console + + + + + &Verify message... + + + + + Arepacoin + + + + + Wallet + + + + + &About Arepacoin + + + + + &Show / Hide + + + + + Unlock wallet + + + + + &Lock Wallet + + + + + Lock wallet + + + + + &File + + + + + &Settings + + + + + &Help + + + + + Tabs toolbar + + + + + Actions toolbar + + + + + + [testnet] + + + + + + Arepacoin client + + + + + %n active connection(s) to Arepacoin network + + + + + Downloaded %1 blocks of transaction history. + + + + + Staking.<br>Your weight is %1<br>Network weight is %2<br>Expected time to earn reward is %3 + + + + + Not staking because wallet is locked + + + + + Not staking because wallet is offline + + + + + Not staking because wallet is syncing + + + + + Not staking because you don't have mature coins + + + + + %n second(s) ago + + + + + &Unlock Wallet... + + + + + %n minute(s) ago + + + + + %n hour(s) ago + + + + + %n day(s) ago + + + + + Up to date + + + + + Catching up... + + + + + Last received block was generated %1. + + + + + This transaction is over the size limit. You can still send it for a fee of %1, which goes to the nodes that process your transaction and helps to support the network. Do you want to pay the fee? + + + + + Confirm transaction fee + + + + + Sent transaction + + + + + Incoming transaction + + + + + Date: %1 +Amount: %2 +Type: %3 +Address: %4 + + + + + + + URI handling + + + + + + URI can not be parsed! This can be caused by an invalid Arepacoin address or malformed URI parameters. + + + + + Wallet is <b>encrypted</b> and currently <b>unlocked</b> + + + + + Wallet is <b>encrypted</b> and currently <b>locked</b> + + + + + Backup Wallet + + + + + Wallet Data (*.dat) + + + + + Backup Failed + + + + + There was an error trying to save the wallet data to the new location. + + + + + %n second(s) + + + + + %n minute(s) + + + + + %n hour(s) + + + + + %n day(s) + + + + + Not staking + + + + + A fatal error occurred. Arepacoin can no longer continue safely and will quit. + + + + + ClientModel + + + Network Alert + + + + + CoinControlDialog + + + Coin Control + + + + + Quantity: + + + + + Bytes: + + + + + Amount: + + + + + Priority: + + + + + Fee: + + + + + Low Output: + + + + + no + + + + + After Fee: + + + + + Change: + + + + + (un)select all + + + + + Tree mode + + + + + List mode + + + + + Amount + + + + + Label + + + + + Address + + + + + Date + + + + + Confirmations + + + + + Confirmed + + + + + Priority + + + + + Copy address + + + + + Copy label + + + + + + Copy amount + + + + + Copy transaction ID + + + + + Copy quantity + + + + + Copy fee + + + + + Copy after fee + + + + + Copy bytes + + + + + Copy priority + + + + + Copy low output + + + + + Copy change + + + + + highest + + + + + high + + + + + medium-high + + + + + medium + + + + + low-medium + + + + + low + + + + + lowest + + + + + DUST + + + + + yes + + + + + This label turns red, if the transaction size is bigger than 10000 bytes. + + This means a fee of at least %1 per kb is required. + + Can vary +/- 1 Byte per input. + + + + + Transactions with higher priority get more likely into a block. + +This label turns red, if the priority is smaller than "medium". + + This means a fee of at least %1 per kb is required. + + + + + This label turns red, if any recipient receives an amount smaller than %1. + + This means a fee of at least %2 is required. + + Amounts below 0.546 times the minimum relay fee are shown as DUST. + + + + + This label turns red, if the change is smaller than %1. + + This means a fee of at least %2 is required. + + + + + + (no label) + + + + + change from %1 (%2) + + + + + (change) + + + + + EditAddressDialog + + + Edit Address + + + + + &Label + + + + + The label associated with this address book entry + + + + + &Address + + + + + The address associated with this address book entry. This can only be modified for sending addresses. + + + + + New receiving address + + + + + New sending address + + + + + Edit receiving address + + + + + Edit sending address + + + + + The entered address "%1" is already in the address book. + + + + + The entered address "%1" is not a valid Arepacoin address. + + + + + Could not unlock wallet. + + + + + New key generation failed. + + + + + GUIUtil::HelpMessageBox + + + + Arepacoin-Qt + + + + + version + + + + + Usage: + + + + + command-line options + + + + + UI options + + + + + Set language, for example "de_DE" (default: system locale) + + + + + Start minimized + + + + + Show splash screen on startup (default: 1) + + + + + OptionsDialog + + + Options + + + + + &Main + + + + + Optional transaction fee per kB that helps make sure your transactions are processed quickly. Most transactions are 1 kB. Fee 0.01 recommended. + + + + + Pay transaction &fee + + + + + Reserved amount does not participate in staking and is therefore spendable at any time. + + + + + Reserve + + + + + Automatically start Arepacoin after logging in to the system. + + + + + &Start Arepacoin on system login + + + + + Detach block and address databases at shutdown. This means they can be moved to another data directory, but it slows down shutdown. The wallet is always detached. + + + + + &Detach databases at shutdown + + + + + &Network + + + + + Automatically open the Arepacoin client port on the router. This only works when your router supports UPnP and it is enabled. + + + + + Map port using &UPnP + + + + + Connect to the Arepacoin network through a SOCKS proxy (e.g. when connecting through Tor). + + + + + &Connect through SOCKS proxy: + + + + + Proxy &IP: + + + + + IP address of the proxy (e.g. 127.0.0.1) + + + + + &Port: + + + + + Port of the proxy (e.g. 9050) + + + + + SOCKS &Version: + + + + + SOCKS version of the proxy (e.g. 5) + + + + + &Window + + + + + Show only a tray icon after minimizing the window. + + + + + &Minimize to the tray instead of the taskbar + + + + + Minimize instead of exit the application when the window is closed. When this option is enabled, the application will be closed only after selecting Quit in the menu. + + + + + M&inimize on close + + + + + &Display + + + + + User Interface &language: + + + + + The user interface language can be set here. This setting will take effect after restarting Arepacoin. + + + + + &Unit to show amounts in: + + + + + Choose the default subdivision unit to show in the interface and when sending coins. + + + + + Whether to show Arepacoin addresses in the transaction list or not. + + + + + &Display addresses in transaction list + + + + + Whether to show coin control features or not. + + + + + Display coin &control features (experts only!) + + + + + &OK + + + + + &Cancel + + + + + &Apply + + + + + default + + + + + + Warning + + + + + + This setting will take effect after restarting Arepacoin. + + + + + The supplied proxy address is invalid. + + + + + OverviewPage + + + Form + + + + + + The displayed information may be out of date. Your wallet automatically synchronizes with the Arepacoin network after a connection is established, but this process has not completed yet. + + + + + Stake: + + + + + Unconfirmed: + + + + + Wallet + + + + + Spendable: + + + + + Your current spendable balance + + + + + Immature: + + + + + Mined balance that has not yet matured + + + + + Total: + + + + + Your current total balance + + + + + <b>Recent transactions</b> + + + + + Total of transactions that have yet to be confirmed, and do not yet count toward the current balance + + + + + Total of coins that was staked, and do not yet count toward the current balance + + + + + + out of sync + + + + + QRCodeDialog + + + QR Code Dialog + + + + + Request Payment + + + + + Amount: + + + + + Label: + + + + + Message: + + + + + &Save As... + + + + + Error encoding URI into QR Code. + + + + + The entered amount is invalid, please check. + + + + + Resulting URI too long, try to reduce the text for label / message. + + + + + Save QR Code + + + + + PNG Images (*.png) + + + + + RPCConsole + + + Client name + + + + + + + + + + + + + + N/A + + + + + Client version + + + + + &Information + + + + + Using OpenSSL version + + + + + Startup time + + + + + Network + + + + + Number of connections + + + + + On testnet + + + + + Block chain + + + + + Current number of blocks + + + + + Estimated total blocks + + + + + Last block time + + + + + &Open + + + + + Command-line options + + + + + Show the Arepacoin-Qt help message to get a list with possible Arepacoin command-line options. + + + + + &Show + + + + + &Console + + + + + Build date + + + + + Arepacoin - Debug window + + + + + Arepacoin Core + + + + + Debug log file + + + + + Open the Arepacoin debug log file from the current data directory. This can take a few seconds for large log files. + + + + + Clear console + + + + + Welcome to the Arepacoin RPC console. + + + + + Use up and down arrows to navigate history, and <b>Ctrl-L</b> to clear screen. + + + + + Type <b>help</b> for an overview of available commands. + + + + + SendCoinsDialog + + + + + + + + + + Send Coins + + + + + Coin Control Features + + + + + Inputs... + + + + + automatically selected + + + + + Insufficient funds! + + + + + Quantity: + + + + + + 0 + + + + + Bytes: + + + + + Amount: + + + + + + + + 0.00 BC + + + + + Priority: + + + + + medium + + + + + Fee: + + + + + Low Output: + + + + + no + + + + + After Fee: + + + + + Change + + + + + custom change address + + + + + Send to multiple recipients at once + + + + + Add &Recipient + + + + + Remove all transaction fields + + + + + Clear &All + + + + + Balance: + + + + + 123.456 BC + + + + + Confirm the send action + + + + + S&end + + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Copy quantity + + + + + Copy amount + + + + + Copy fee + + + + + Copy after fee + + + + + Copy bytes + + + + + Copy priority + + + + + Copy low output + + + + + Copy change + + + + + <b>%1</b> to %2 (%3) + + + + + Confirm send coins + + + + + Are you sure you want to send %1? + + + + + and + + + + + The recipient address is not valid, please recheck. + + + + + The amount to pay must be larger than 0. + + + + + The amount exceeds your balance. + + + + + The total exceeds your balance when the %1 transaction fee is included. + + + + + Duplicate address found, can only send to each address once per send operation. + + + + + Error: Transaction creation failed. + + + + + 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. + + + + + WARNING: Invalid Arepacoin address + + + + + (no label) + + + + + WARNING: unknown change address + + + + + SendCoinsEntry + + + Form + + + + + A&mount: + + + + + Pay &To: + + + + + + Enter a label for this address to add it to your address book + + + + + &Label: + + + + + The address to send the payment to (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Choose address from address book + + + + + Alt+A + + + + + Paste address from clipboard + + + + + Alt+P + + + + + Remove this recipient + + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + SignVerifyMessageDialog + + + Signatures - Sign / Verify a Message + + + + + + &Sign Message + + + + + You can sign messages with your addresses to prove you own them. Be careful not to sign anything vague, as phishing attacks may try to trick you into signing your identity over to them. Only sign fully-detailed statements you agree to. + + + + + The address to sign the message with (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + + Choose an address from the address book + + + + + + Alt+A + + + + + Paste address from clipboard + + + + + Alt+P + + + + + Enter the message you want to sign here + + + + + Copy the current signature to the system clipboard + + + + + Sign the message to prove you own this Arepacoin address + + + + + Reset all sign message fields + + + + + + Clear &All + + + + + + &Verify Message + + + + + Enter the signing address, message (ensure you copy line breaks, spaces, tabs, etc. exactly) and signature below to verify the message. Be careful not to read more into the signature than what is in the signed message itself, to avoid being tricked by a man-in-the-middle attack. + + + + + The address the message was signed with (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Verify the message to ensure it was signed with the specified Arepacoin address + + + + + Reset all verify message fields + + + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Click "Sign Message" to generate signature + + + + + Enter Arepacoin signature + + + + + + The entered address is invalid. + + + + + + + + Please check the address and try again. + + + + + + The entered address does not refer to a key. + + + + + Wallet unlock was cancelled. + + + + + Private key for the entered address is not available. + + + + + Message signing failed. + + + + + Message signed. + + + + + The signature could not be decoded. + + + + + + Please check the signature and try again. + + + + + The signature did not match the message digest. + + + + + Message verification failed. + + + + + Message verified. + + + + + TransactionDesc + + + Open until %1 + + + + + Open for %n block(s) + + + + + conflicted + + + + + %1/offline + + + + + %1/unconfirmed + + + + + %1 confirmations + + + + + Status + + + + + , broadcast through %n node(s) + + + + + Date + + + + + Source + + + + + Generated + + + + + + From + + + + + + + To + + + + + + own address + + + + + label + + + + + + + + + Credit + + + + + matures in %n more block(s) + + + + + not accepted + + + + + + + + Debit + + + + + Transaction fee + + + + + Net amount + + + + + Message + + + + + Comment + + + + + Transaction ID + + + + + Generated coins must mature 6 blocks before they can be spent. When you generated this block, it was broadcast to the network to be added to the block chain. If it fails to get into the chain, its state will change to "not accepted" and it won't be spendable. This may occasionally happen if another node generates a block within a few seconds of yours. + + + + + Debug information + + + + + Transaction + + + + + Inputs + + + + + Amount + + + + + true + + + + + false + + + + + , has not been successfully broadcast yet + + + + + unknown + + + + + TransactionDescDialog + + + Transaction details + + + + + This pane shows a detailed description of the transaction + + + + + TransactionTableModel + + + Date + + + + + Type + + + + + Address + + + + + Amount + + + + + Open until %1 + + + + + Confirmed (%1 confirmations) + + + + + Open for %n more block(s) + + + + + Offline + + + + + Unconfirmed + + + + + Confirming (%1 of %2 recommended confirmations) + + + + + Conflicted + + + + + Immature (%1 confirmations, will be available after %2) + + + + + This block was not received by any other nodes and will probably not be accepted! + + + + + Generated but not accepted + + + + + Received with + + + + + Received from + + + + + Sent to + + + + + Payment to yourself + + + + + Mined + + + + + (n/a) + + + + + Transaction status. Hover over this field to show number of confirmations. + + + + + Date and time that the transaction was received. + + + + + Type of transaction. + + + + + Destination address of transaction. + + + + + Amount removed from or added to balance. + + + + + TransactionView + + + + All + + + + + Today + + + + + This week + + + + + This month + + + + + Last month + + + + + This year + + + + + Range... + + + + + Received with + + + + + Sent to + + + + + To yourself + + + + + Mined + + + + + Other + + + + + Enter address or label to search + + + + + Min amount + + + + + Copy address + + + + + Copy label + + + + + Copy amount + + + + + Copy transaction ID + + + + + Edit label + + + + + Show transaction details + + + + + Export Transaction Data + + + + + Comma separated file (*.csv) + + + + + Confirmed + + + + + Date + + + + + Type + + + + + Label + + + + + Address + + + + + Amount + + + + + ID + + + + + Error exporting + + + + + Could not write to file %1. + + + + + Range: + + + + + to + + + + + WalletModel + + + Sending... + + + + + bitcoin-core + + + Arepacoin version + + + + + Usage: + + + + + Send command to -server or arepacoind + + + + + List commands + + + + + Get help for a command + + + + + Options: + + + + + Specify configuration file (default: arepacoin.conf) + + + + + Specify pid file (default: arepacoind.pid) + + + + + Specify wallet file (within data directory) + + + + + Specify data directory + + + + + Set database cache size in megabytes (default: 25) + + + + + Set database disk log size in megabytes (default: 100) + + + + + Listen for connections on <port> (default: 9853 or testnet: 19853) + + + + + Maintain at most <n> connections to peers (default: 125) + + + + + Connect to a node to retrieve peer addresses, and disconnect + + + + + Specify your own public address + + + + + Bind to given address. Use [host]:port notation for IPv6 + + + + + Stake your coins to support network and gain reward (default: 1) + + + + + Threshold for disconnecting misbehaving peers (default: 100) + + + + + Number of seconds to keep misbehaving peers from reconnecting (default: 86400) + + + + + An error occurred while setting up the RPC port %u for listening on IPv4: %s + + + + + Detach block and address databases. Increases shutdown time (default: 0) + + + + + 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. + + + + + Error: This transaction requires a transaction fee of at least %s because of its amount, complexity, or use of recently received funds + + + + + Listen for JSON-RPC connections on <port> (default: 9852 or testnet: 19852) + + + + + Accept command line and JSON-RPC commands + + + + + Error: Transaction creation failed + + + + + Error: Wallet locked, unable to create transaction + + + + + Importing blockchain data file. + + + + + Importing bootstrap blockchain data file. + + + + + Run in the background as a daemon and accept commands + + + + + Use the test network + + + + + Accept connections from outside (default: 1 if no -proxy or -connect) + + + + + An error occurred while setting up the RPC port %u for listening on IPv6, falling back to IPv4: %s + + + + + Error initializing database environment %s! To recover, BACKUP THAT DIRECTORY, then remove everything from it except for wallet.dat. + + + + + Set maximum size of high-priority/low-fee transactions in bytes (default: 27000) + + + + + Warning: -paytxfee is set very high! This is the transaction fee you will pay if you send a transaction. + + + + + Warning: Please check that your computer's date and time are correct! If your clock is wrong Arepacoin will not work properly. + + + + + Warning: error reading wallet.dat! All keys read correctly, but transaction data or address book entries might be missing or incorrect. + + + + + Warning: wallet.dat corrupt, data salvaged! Original wallet.dat saved as wallet.{timestamp}.bak in %s; if your balance or transactions are incorrect you should restore from a backup. + + + + + Attempt to recover private keys from a corrupt wallet.dat + + + + + Block creation options: + + + + + Connect only to the specified node(s) + + + + + Discover own IP address (default: 1 when listening and no -externalip) + + + + + Failed to listen on any port. Use -listen=0 if you want this. + + + + + Find peers using DNS lookup (default: 1) + + + + + Sync checkpoints policy (default: strict) + + + + + Invalid -tor address: '%s' + + + + + Invalid amount for -reservebalance=<amount> + + + + + Maximum per-connection receive buffer, <n>*1000 bytes (default: 5000) + + + + + Maximum per-connection send buffer, <n>*1000 bytes (default: 1000) + + + + + Only connect to nodes in network <net> (IPv4, IPv6 or Tor) + + + + + Output extra debugging information. Implies all other -debug* options + + + + + Output extra network debugging information + + + + + Prepend debug output with timestamp + + + + + SSL options: (see the Bitcoin Wiki for SSL setup instructions) + + + + + Select the version of socks proxy to use (4-5, default: 5) + + + + + Send trace/debug info to console instead of debug.log file + + + + + Send trace/debug info to debugger + + + + + Set maximum block size in bytes (default: 250000) + + + + + Set minimum block size in bytes (default: 0) + + + + + Shrink debug.log file on client startup (default: 1 when no -debug) + + + + + Specify connection timeout in milliseconds (default: 5000) + + + + + Unable to sign checkpoint, wrong checkpointkey? + + + + + + Use UPnP to map the listening port (default: 0) + + + + + Use UPnP to map the listening port (default: 1 when listening) + + + + + Use proxy to reach tor hidden services (default: same as -proxy) + + + + + Username for JSON-RPC connections + + + + + Verifying database integrity... + + + + + WARNING: syncronized checkpoint violation detected, but skipped! + + + + + Warning: Disk space is low! + + + + + Warning: This version is obsolete, upgrade required! + + + + + wallet.dat corrupt, salvage failed + + + + + Password for JSON-RPC connections + + + + + %s, you must set a rpcpassword in the configuration file: + %s +It is recommended you use the following random password: +rpcuser=arepacoinrpc +rpcpassword=%s +(you do not need to remember this password) +The username and password MUST NOT be the same. +If the file does not exist, create it with owner-readable-only file permissions. +It is also recommended to set alertnotify so you are notified of problems; +for example: alertnotify=echo %%s | mail -s "Arepacoin Alert" admin@foo.com + + + + + + Find peers using internet relay chat (default: 0) + + + + + Sync time with other nodes. Disable if time on your system is precise e.g. syncing with NTP (default: 1) + + + + + When creating transactions, ignore inputs with value less than this (default: 0.01) + + + + + Allow JSON-RPC connections from specified IP address + + + + + Send commands to node running on <ip> (default: 127.0.0.1) + + + + + Execute command when the best block changes (%s in cmd is replaced by block hash) + + + + + Execute command when a wallet transaction changes (%s in cmd is replaced by TxID) + + + + + Require a confirmations for change (default: 0) + + + + + Enforce transaction scripts to use canonical PUSH operators (default: 1) + + + + + Execute command when a relevant alert is received (%s in cmd is replaced by message) + + + + + Upgrade wallet to latest format + + + + + Set key pool size to <n> (default: 100) + + + + + Rescan the block chain for missing wallet transactions + + + + + How many blocks to check at startup (default: 2500, 0 = all) + + + + + How thorough the block verification is (0-6, default: 1) + + + + + Imports blocks from external blk000?.dat file + + + + + Use OpenSSL (https) for JSON-RPC connections + + + + + Server certificate file (default: server.cert) + + + + + Server private key (default: server.pem) + + + + + Acceptable ciphers (default: TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH) + + + + + Error: Wallet unlocked for staking only, unable to create transaction. + + + + + WARNING: Invalid checkpoint found! Displayed transactions may not be correct! You may need to upgrade, or notify developers. + + + + + This help message + + + + + Wallet %s resides outside data directory %s. + + + + + Cannot obtain a lock on data directory %s. Arepacoin is probably already running. + + + + + Arepacoin + + + + + Unable to bind to %s on this computer (bind returned error %d, %s) + + + + + Connect through socks proxy + + + + + Allow DNS lookups for -addnode, -seednode and -connect + + + + + Loading addresses... + + + + + Error loading blkindex.dat + + + + + Error loading wallet.dat: Wallet corrupted + + + + + Error loading wallet.dat: Wallet requires newer version of Arepacoin + + + + + Wallet needed to be rewritten: restart Arepacoin to complete + + + + + Error loading wallet.dat + + + + + Invalid -proxy address: '%s' + + + + + Unknown network specified in -onlynet: '%s' + + + + + Unknown -socks proxy version requested: %i + + + + + Cannot resolve -bind address: '%s' + + + + + Cannot resolve -externalip address: '%s' + + + + + Invalid amount for -paytxfee=<amount>: '%s' + + + + + Error: could not start node + + + + + Sending... + + + + + Invalid amount + + + + + Insufficient funds + + + + + Loading block index... + + + + + Add a node to connect to and attempt to keep the connection open + + + + + Unable to bind to %s on this computer. Arepacoin is probably already running. + + + + + Fee per KB to add to transactions you send + + + + + Invalid amount for -mininput=<amount>: '%s' + + + + + Loading wallet... + + + + + Cannot downgrade wallet + + + + + Cannot initialize keypool + + + + + Cannot write default address + + + + + Rescanning... + + + + + Done loading + + + + + To use the %s option + + + + + Error + + + + + You must set rpcpassword=<password> in the configuration file: +%s +If the file does not exist, create it with owner-readable-only file permissions. + + + + \ No newline at end of file diff --git a/src/qt/locale/bitcoin_ca_ES.ts b/src/qt/locale/bitcoin_ca_ES.ts new file mode 100755 index 0000000..39515b9 --- /dev/null +++ b/src/qt/locale/bitcoin_ca_ES.ts @@ -0,0 +1,3303 @@ + + + AboutDialog + + + About Arepacoin + Sobre Arepacoin + + + + <b>Arepacoin</b> version + versió <b>Arepacoin</b> + + + + Copyright © 2009-2014 The Bitcoin developers +Copyright © 2012-2014 The NovaCoin developers +Copyright © 2014 The Arepacoin developers + Copyright © 2009-2014 The Bitcoin developers +Copyright © 2012-2014 The NovaCoin developers +Copyright © 2014 The Arepacoin developers + + + + +This is experimental software. + +Distributed under the MIT/X11 software license, see the accompanying file COPYING or http://www.opensource.org/licenses/mit-license.php. + +This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit (http://www.openssl.org/) and cryptographic software written by Eric Young (eay@cryptsoft.com) and UPnP software written by Thomas Bernard. + \n Aquest és software experimental.\n\n Distribuït sota llicència de software MIT/11, veure l'arxiu COPYING o http://www.opensource.org/licenses/mit-license.php.\n\nAquest producte inclou software desarrollat pel projecte OpenSSL per a l'ús de OppenSSL Toolkit (http://www.openssl.org/) i de software criptogràfic escrit per l'Eric Young (eay@cryptsoft.com) i software UPnP escrit per en Thomas Bernard. + + + + AddressBookPage + + + Address Book + Llibreta d'adreces + + + + Double-click to edit address or label + Feu doble clic per editar l'adreça o l'etiqueta + + + + Create a new address + Crear una nova adreça + + + + Copy the currently selected address to the system clipboard + Copiar l'adreça seleccionada al porta-retalls del sistema + + + + &New Address + &Nova adreça + + + + These are your Arepacoin addresses for receiving payments. You may want to give a different one to each sender so you can keep track of who is paying you. + Aquestes són les teves adreces de Arepacoin per rebre els pagaments. És possible que vulgueu donar una diferent a cada remitent per a poder realitzar un seguiment de qui li está pagant. + + + + &Copy Address + &Copiar adreça + + + + Show &QR Code + Mostra el códi &QR + + + + Sign a message to prove you own a Arepacoin address + Signar un missatge per demostrar que és propietari d'una adreça Arepacoin + + + + Sign &Message + Signar &Message + + + + Delete the currently selected address from the list + Esborrar l'adreça sel·leccionada + + + + Verify a message to ensure it was signed with a specified Arepacoin address + Comproveu el missatge per assegurar-se que es va signar amb una adreça Arepacoin especificada. + + + + &Verify Message + &Verificar el missatge + + + + &Delete + &Esborrar + + + + Copy &Label + Copiar &Etiqueta + + + + &Edit + &Editar + + + + Export Address Book Data + Exportar dades de la llibreta d'adreces + + + + Comma separated file (*.csv) + Arxiu de separació per comes (*.csv) + + + + Error exporting + Error a l'exportar + + + + Could not write to file %1. + No s'ha pogut escriure al fitxer %1. + + + + AddressTableModel + + + Label + Etiqueta + + + + Address + Adreça + + + + (no label) + (sense etiqueta) + + + + AskPassphraseDialog + + + Passphrase Dialog + Dialeg de contrasenya + + + + Enter passphrase + Introdueix contrasenya + + + + New passphrase + Nova contrasenya + + + + Repeat new passphrase + Repeteix la nova contrasenya + + + + Serves to disable the trivial sendmoney when OS account compromised. Provides no real security. + Serveix per desactivar l'enviament trivial de diners quan el compte del sistema operatiu ha estat compromès. No ofereix seguretat real. + + + + For staking only + Només per a fer "stake" + + + + Enter the new passphrase to the wallet.<br/>Please use a passphrase of <b>10 or more random characters</b>, or <b>eight or more words</b>. + Introdueixi la nova contrasenya al moneder<br/>Si us plau useu una contrasenya de <b>10 o més caracters aleatoris</b>, o <b>vuit o més paraules</b>. + + + + Encrypt wallet + Xifrar el moneder + + + + This operation needs your wallet passphrase to unlock the wallet. + Aquesta operació requereix la seva contrasenya del moneder per a desbloquejar-lo. + + + + Unlock wallet + Desbloqueja el moneder + + + + This operation needs your wallet passphrase to decrypt the wallet. + Aquesta operació requereix la seva contrasenya del moneder per a desencriptar-lo. + + + + Decrypt wallet + Desencripta el moneder + + + + Change passphrase + Canviar la contrasenya + + + + Enter the old and new passphrase to the wallet. + Introdueixi tant l'antiga com la nova contrasenya de moneder. + + + + Confirm wallet encryption + Confirmar l'encriptació del moneder + + + + Warning: If you encrypt your wallet and lose your passphrase, you will <b>LOSE ALL OF YOUR COINS</b>! + Avís: Si xifra el seu moneder i perd la contrasenya, podrà <b> PERDRE TOTES LES SEVES MONEDES </ b>! + + + + Are you sure you wish to encrypt your wallet? + Esteu segur que voleu encriptar el vostre moneder? + + + + IMPORTANT: Any previous backups you have made of your wallet file should be replaced with the newly generated, encrypted wallet file. For security reasons, previous backups of the unencrypted wallet file will become useless as soon as you start using the new, encrypted wallet. + IMPORTANT: Tota copia de seguretat que hagis realitzat hauria de ser reemplaçada pel, recentment generat, arxiu encriptat del moneder. + + + + + Warning: The Caps Lock key is on! + Advertència: Les lletres majúscules estàn activades! + + + + + Wallet encrypted + Moneder encriptat + + + + Arepacoin will close now to finish the encryption process. Remember that encrypting your wallet cannot fully protect your coins from being stolen by malware infecting your computer. + Arepacoin tancarà ara per acabar el procés de xifrat. Recordeu que l'encriptació del seu moneder no pot protegir completament les seves monedes de ser robades pel malware que pugui infectar al seu equip. + + + + + + + Wallet encryption failed + L'encriptació del moneder ha fallat + + + + Wallet encryption failed due to an internal error. Your wallet was not encrypted. + L'encriptació del moneder ha fallat per un error intern. El seu moneder no ha estat encriptat. + + + + + The supplied passphrases do not match. + La contrasenya introduïda no coincideix. + + + + Wallet unlock failed + El desbloqueig del moneder ha fallat + + + + + + The passphrase entered for the wallet decryption was incorrect. + La contrasenya introduïda per a desencriptar el moneder és incorrecte. + + + + Wallet decryption failed + La desencriptació del moneder ha fallat + + + + Wallet passphrase was successfully changed. + La contrasenya del moneder ha estat modificada correctament. + + + + BitcoinGUI + + + Sign &message... + Signar &missatge... + + + + Synchronizing with network... + Sincronitzant amb la xarxa ... + + + + &Overview + &Panorama general + + + + Show general overview of wallet + Mostra panorama general del moneder + + + + &Transactions + &Transaccions + + + + Browse transaction history + Cerca a l'historial de transaccions + + + + &Address Book + &Llibreta d'adreces + + + + Edit the list of stored addresses and labels + Edició de la llista d'adreces i etiquetes emmagatzemades + + + + &Receive coins + &Rebre monedes + + + + Show the list of addresses for receiving payments + Mostra la llista d'adreces per rebre pagaments + + + + &Send coins + &Enviar monedes + + + + E&xit + S&ortir + + + + Quit application + Sortir de l'aplicació + + + + Show information about Arepacoin + Mostra informació sobre Arepacoin + + + + About &Qt + Sobre &Qt + + + + Show information about Qt + Mostra informació sobre Qt + + + + &Options... + &Opcions... + + + + &Encrypt Wallet... + &Xifrar moneder + + + + &Backup Wallet... + &Realitzar copia de seguretat del moneder... + + + + &Change Passphrase... + &Canviar contrasenya... + + + + ~%n block(s) remaining + ~%n bloc restant~%n blocs restants + + + + Downloaded %1 of %2 blocks of transaction history (%3% done). + Descarregats %1 de %2 blocs d'historial de transaccions (%3% completat). + + + + &Export... + &Exportar... + + + + Send coins to a Arepacoin address + Enviar monedes a una adreça Arepacoin + + + + Modify configuration options for Arepacoin + Modificar les opcions de configuració per a Arepacoin + + + + Export the data in the current tab to a file + Exportar les dades de la pestanya actual a un arxiu + + + + Encrypt or decrypt wallet + Xifrar o desxifrar moneder + + + + Backup wallet to another location + Realitzar còpia de seguretat del moneder a un altre directori + + + + Change the passphrase used for wallet encryption + Canviar la constrasenya d'encriptació del moneder + + + + &Debug window + &Finestra de depuració + + + + Open debugging and diagnostic console + Obrir la consola de diagnòstic i depuració + + + + &Verify message... + &Verifica el missatge.. + + + + Arepacoin + Arepacoin + + + + Wallet + Moneder + + + + &About Arepacoin + &Sobre Arepacoin + + + + &Show / Hide + &Mostrar / Amagar + + + + Unlock wallet + Desbloquejar el moneder + + + + &Lock Wallet + &Bloquejar moneder + + + + Lock wallet + Bloquejar moneder + + + + &File + &Arxiu + + + + &Settings + &Configuració + + + + &Help + &Ajuda + + + + Tabs toolbar + Barra d'eines de seccions + + + + Actions toolbar + Barra d'eines d'accions + + + + + [testnet] + [testnet] + + + + + Arepacoin client + Client Arepacoin + + + + %n active connection(s) to Arepacoin network + %n conexió activa a la xarxa Arepacoin%n conexions actives a la xarxa Arepacoin + + + + Downloaded %1 blocks of transaction history. + Descarregats %1 blocs d'historial de transaccions + + + + Staking.<br>Your weight is %1<br>Network weight is %2<br>Expected time to earn reward is %3 + Fent "stake".<br>El teu pes és %1<br>El pes de la xarxa és %2<br>El temps estimat per a guanyar una recompensa és 3% + + + + Not staking because wallet is locked + No s'està fent "stake" perquè el moneder esa bloquejat + + + + Not staking because wallet is offline + No s'està fent "stake" perquè el moneder està fora de línia + + + + Not staking because wallet is syncing + No s'està fent "stake" perquè el moneder està sincronitzant + + + + Not staking because you don't have mature coins + No s'està fent "stake" perquè no tens monedes madures + + + + %n second(s) ago + fa %n segonfa %n segons + + + + &Unlock Wallet... + &Desbloquejar moneder + + + + %n minute(s) ago + fa %n minutfa %n minuts + + + + %n hour(s) ago + fa %n horafa %n hores + + + + %n day(s) ago + fa %n diafa %n dies + + + + Up to date + Al dia + + + + Catching up... + Posar-se al dia ... + + + + Last received block was generated %1. + El darrer bloc rebut s'ha generat %1. + + + + This transaction is over the size limit. You can still send it for a fee of %1, which goes to the nodes that process your transaction and helps to support the network. Do you want to pay the fee? + Aquesta transacció es troba sobre el límit de mida. Encara pot enviar-la amb una comisió de 1%, aquesta va als nodes que processen la seva transacció i ajuda a mantenir la xarxa. Vol pagar la quota? + + + + Confirm transaction fee + Confirmeu comisió + + + + Sent transaction + Transacció enviada + + + + Incoming transaction + Transacció entrant + + + + Date: %1 +Amount: %2 +Type: %3 +Address: %4 + + Data: %1\nQuantitat %2\n Tipus: %3\n Adreça: %4\n + + + + + URI handling + Manejant URI + + + + + URI can not be parsed! This can be caused by an invalid Arepacoin address or malformed URI parameters. + l'URI no es pot analitzar! Això pot ser causat per una adreça Arepacoin no vàlida o paràmetres URI malformats. + + + + Wallet is <b>encrypted</b> and currently <b>unlocked</b> + El moneder està <b>encriptat</b> i actualment <b>desbloquejat</b> + + + + Wallet is <b>encrypted</b> and currently <b>locked</b> + El moneder està <b>encriptat</b> i actualment <b>bloquejat</b> + + + + Backup Wallet + Realitzar còpia de seguretat del moneder + + + + Wallet Data (*.dat) + Dades del moneder (*.dat) + + + + Backup Failed + Còpia de seguretat fallida + + + + There was an error trying to save the wallet data to the new location. + Hi ha un error al tractar de salvar les dades del seu moneder a la nova ubicació. + + + + %n second(s) + %n segon%n segons + + + + %n minute(s) + %n minut%n minuts + + + + %n hour(s) + %n hora%n hores + + + + %n day(s) + %n dia%n dies + + + + Not staking + No s'està fent "stake" + + + + A fatal error occurred. Arepacoin can no longer continue safely and will quit. + S'ha produït un error fatal. Arepacoin ja no pot continuar de forma segura i es tancarà. + + + + ClientModel + + + Network Alert + Alerta de xarxa + + + + CoinControlDialog + + + Coin Control + Opcions del control de monedes + + + + Quantity: + Quantitat: + + + + Bytes: + Bytes: + + + + Amount: + Quantitat: + + + + Priority: + Prioritat: + + + + Fee: + Quota: + + + + Low Output: + Sortida baixa: + + + + no + no + + + + After Fee: + Quota posterior: + + + + Change: + Canvi: + + + + (un)select all + (de)seleccionar tot + + + + Tree mode + Mode arbre + + + + List mode + Mode llista + + + + Amount + Quantitat + + + + Label + Etiqueta + + + + Address + Adreça + + + + Date + Data + + + + Confirmations + Confirmacions + + + + Confirmed + Confirmat + + + + Priority + Prioritat + + + + Copy address + Copiar adreça + + + + Copy label + Copiar etiqueta + + + + + Copy amount + Copiar quantitat + + + + Copy transaction ID + Copiar ID de transacció + + + + Copy quantity + Copiar quantitat + + + + Copy fee + Copiar comisió + + + + Copy after fee + Copiar després de comisió + + + + Copy bytes + Copiar bytes + + + + Copy priority + Copiar prioritat + + + + Copy low output + Copiar sortida baixa + + + + Copy change + Copiar canvi + + + + highest + El més alt + + + + high + Alt + + + + medium-high + mig-alt + + + + medium + mig + + + + low-medium + baix-mig + + + + low + baix + + + + lowest + el més baix + + + + DUST + POLS + + + + yes + si + + + + This label turns red, if the transaction size is bigger than 10000 bytes. + + This means a fee of at least %1 per kb is required. + + Can vary +/- 1 Byte per input. + Aquesta etiqueta es tornarà vermell, si la mida de la transacció és més gran que 10000 bytes. + +En aquest cas es requereix una comisió d'almenys el 1% per kb. + +Pot variar + / - 1 Byte per entrada. + + + + Transactions with higher priority get more likely into a block. + +This label turns red, if the priority is smaller than "medium". + + This means a fee of at least %1 per kb is required. + Les operacions amb més prioritat entren mes facilment a un bloc. + +Aquesta etiqueta es torna vermella, si la prioritat és menor que "mitja". + +En aquest cas es requereix una comisió d'almenys el 1% per kb. + + + + This label turns red, if any recipient receives an amount smaller than %1. + + This means a fee of at least %2 is required. + + Amounts below 0.546 times the minimum relay fee are shown as DUST. + Aquesta etiqueta es torna vermella, si qualsevol beneficiari rep una quantitat inferior a 1%. + +En aquest cas es requereix una comisió d'almenys 2%. + +Les quantitats inferiors a 0.546 vegades la quota mínima del relé es mostren com a POLS. + + + + This label turns red, if the change is smaller than %1. + + This means a fee of at least %2 is required. + Aquesta etiqueta es torna vermella, si el canvi és menor que 1%. + +En aquest cas es requereix una comisió d'almenys 2%. + + + + + (no label) + (sense etiqueta) + + + + change from %1 (%2) + canvi desde %1 (%2) + + + + (change) + (canviar) + + + + EditAddressDialog + + + Edit Address + Editar Adreça + + + + &Label + &Etiqueta + + + + The label associated with this address book entry + L'etiqueta associada amb aquesta entrada de la llibreta d'adreces + + + + &Address + &Direcció + + + + The address associated with this address book entry. This can only be modified for sending addresses. + La direcció associada amb aquesta entrada de la llibreta d'adreces. Només pot ser modificada per a l'enviament d'adreces. + + + + New receiving address + Nova adreça de recepció. + + + + New sending address + Nova adreça d'enviament + + + + Edit receiving address + Editar adreces de recepció + + + + Edit sending address + Editar adreces d'enviament + + + + The entered address "%1" is already in the address book. + L'adreça introduïda "%1" ja és present a la llibreta d'adreces. + + + + The entered address "%1" is not a valid Arepacoin address. + La direcció introduïda "%1" no és una adreça Arepacoin vàlida. + + + + Could not unlock wallet. + No s'ha pogut desbloquejar el moneder. + + + + New key generation failed. + Ha fallat la generació d'una nova clau. + + + + GUIUtil::HelpMessageBox + + + + Arepacoin-Qt + Arepacoin-Qt + + + + version + versió + + + + Usage: + Ús: + + + + command-line options + Opcions de la línia d'ordres + + + + UI options + Opcions de IU + + + + Set language, for example "de_DE" (default: system locale) + Definir llenguatge, per exemple "de_DE" (per defecte: Preferències locals de sistema) + + + + Start minimized + Iniciar minimitzat + + + + Show splash screen on startup (default: 1) + Mostrar finestra de benvinguda a l'inici (per defecte: 1) + + + + OptionsDialog + + + Options + Opcions + + + + &Main + &Principal + + + + Optional transaction fee per kB that helps make sure your transactions are processed quickly. Most transactions are 1 kB. Fee 0.01 recommended. + Comisió opcional per kB que ajuda a assegurar-se que les seves transaccions es processen ràpidament. La majoria de les transaccions són 1 kB. Comisió d'0.01 recomenada. + + + + Pay transaction &fee + Pagar &comisió de transacció + + + + Reserved amount does not participate in staking and is therefore spendable at any time. + La quantitat reservada no participa en fer "stake" i per tant esta disponible en qualsevol moment. + + + + Reserve + Reserva + + + + Automatically start Arepacoin after logging in to the system. + Inicia automàticament Arepacoin després d'entrar en el sistema. + + + + &Start Arepacoin on system login + &Iniciar Arepacoin amb l'inici de sessió + + + + Detach block and address databases at shutdown. This means they can be moved to another data directory, but it slows down shutdown. The wallet is always detached. + Separeu el bloc i les bases de dades d'adreces en apagar l'equip. En aquest cas es pot moure a un altre directori de dades, però alenteix l'apagada. El moneder està sempre separat. + + + + &Detach databases at shutdown + &Separar bases de dades a l'apagar l'equip + + + + &Network + &Xarxa + + + + Automatically open the Arepacoin client port on the router. This only works when your router supports UPnP and it is enabled. + Obrir automàticament el port de client Arepacoin en el router. Això només funciona quan el router és compatible amb UPnP i està habilitat. + + + + Map port using &UPnP + Obrir ports amb &UPnP + + + + Connect to the Arepacoin network through a SOCKS proxy (e.g. when connecting through Tor). + Connecteu-vos a la xarxa Arepacoin través d'un proxy SOCKS (per exemple, quan es connecta a través de Tor). + + + + &Connect through SOCKS proxy: + &Conectar a través d'un proxy SOCKS: + + + + Proxy &IP: + &IP del proxy: + + + + IP address of the proxy (e.g. 127.0.0.1) + Adreça IP del servidor proxy (per exemple, 127.0.0.1) + + + + &Port: + &Port: + + + + Port of the proxy (e.g. 9050) + Port del proxy (per exemple 9050) + + + + SOCKS &Version: + &Versió de SOCKS: + + + + SOCKS version of the proxy (e.g. 5) + Versió SOCKS del proxy (per exemple 5) + + + + &Window + &Finestra + + + + Show only a tray icon after minimizing the window. + Mostrar només l'icona de la barra al minimitzar l'aplicació. + + + + &Minimize to the tray instead of the taskbar + &Minimitzar a la barra d'aplicacions + + + + Minimize instead of exit the application when the window is closed. When this option is enabled, the application will be closed only after selecting Quit in the menu. + Minimitza en comptes de sortir de la aplicació al tancar la finestra. Quan aquesta opció està activa, la aplicació només es tancarà al seleccionar Sortir al menú. + + + + M&inimize on close + M&inimitzar al tancar + + + + &Display + &Pantalla + + + + User Interface &language: + Llenguatge de la Interfície d'Usuari: + + + + The user interface language can be set here. This setting will take effect after restarting Arepacoin. + L'idioma de la interfície d'usuari es pot configurar aquí. Aquesta configuració s'aplicarà després de reiniciar Arepacoin. + + + + &Unit to show amounts in: + &Unitats per mostrar les quantitats en: + + + + Choose the default subdivision unit to show in the interface and when sending coins. + Sel·lecciona la unitat de subdivisió per defecte per mostrar en la interficie quan s'envien monedes. + + + + Whether to show Arepacoin addresses in the transaction list or not. + Per mostrar Arepacoin adreces a la llista de transaccions o no. + + + + &Display addresses in transaction list + &Mostrar adreces al llistat de transaccions + + + + Whether to show coin control features or not. + Per mostrar les característiques de control de la moneda o no. + + + + Display coin &control features (experts only!) + Mostrar controls i característiques de la moneda (només per a experts!) + + + + &OK + &OK + + + + &Cancel + &Cancel·la + + + + &Apply + &Aplicar + + + + default + Per defecte + + + + + Warning + Avís + + + + + This setting will take effect after restarting Arepacoin. + Aquesta configuració s'aplicarà després de reiniciar Arepacoin. + + + + The supplied proxy address is invalid. + L'adreça proxy introduïda és invalida. + + + + OverviewPage + + + Form + Formulari + + + + + The displayed information may be out of date. Your wallet automatically synchronizes with the Arepacoin network after a connection is established, but this process has not completed yet. + La informació mostrada pot estar fora de data. El seu moneder es sincronitza automàticament amb la xarxa Arepacoin després d'establir una connexió, però aquest procés no s'ha completat encara. + + + + Stake: + En "stake": + + + + Unconfirmed: + Sense confirmar: + + + + Wallet + Moneder + + + + Spendable: + Disponible: + + + + Your current spendable balance + El balanç de saldo actual disponible + + + + Immature: + Immatur: + + + + Mined balance that has not yet matured + Balanç minat que encara no ha madurat + + + + Total: + Total: + + + + Your current total balance + El seu balanç total + + + + <b>Recent transactions</b> + <b>Transaccions recents</b> + + + + Total of transactions that have yet to be confirmed, and do not yet count toward the current balance + Total de transaccions que encara no s'han confirmat, i encara no compten per al balanç actual + + + + Total of coins that was staked, and do not yet count toward the current balance + Total de les monedes que s'han posat a fer "stake" (en joc, aposta), i encara no compten per al balanç actual + + + + + out of sync + Fora de sincronia + + + + QRCodeDialog + + + QR Code Dialog + Diàleg de codi QR + + + + Request Payment + Sol·licitud de pagament + + + + Amount: + Quantitat: + + + + Label: + Etiqueta: + + + + Message: + Missatge: + + + + &Save As... + &Desa com ... + + + + Error encoding URI into QR Code. + Error codificant la URI en un codi QR. + + + + The entered amount is invalid, please check. + La quantitat introduïda no és vàlida, comproveu-ho si us plau. + + + + Resulting URI too long, try to reduce the text for label / message. + URI resultant massa llarga, intenta reduir el text per a la etiqueta / missatge + + + + Save QR Code + Desar codi QR + + + + PNG Images (*.png) + Imatges PNG (*.png) + + + + RPCConsole + + + Client name + Nom del client + + + + + + + + + + + + + N/A + N/A + + + + Client version + Versió del client + + + + &Information + &Informació + + + + Using OpenSSL version + Utilitzant OpenSSL versió + + + + Startup time + &Temps d'inici + + + + Network + Xarxa + + + + Number of connections + Nombre de connexions + + + + On testnet + A testnet + + + + Block chain + Bloquejar cadena + + + + Current number of blocks + Nombre de blocs actuals + + + + Estimated total blocks + Total estimat de blocs + + + + Last block time + Últim temps de bloc + + + + &Open + &Obrir + + + + Command-line options + Opcions de la línia d'ordres + + + + Show the Arepacoin-Qt help message to get a list with possible Arepacoin command-line options. + Mostra el missatge d'ajuda de Arepacoin-Qt per obtenir una llista amb les possibles opcions de línia d'ordres Arepacoin. + + + + &Show + &Mostra + + + + &Console + &Consola + + + + Build date + Data de compilació + + + + Arepacoin - Debug window + Arepacoin - Finestra Depuració + + + + Arepacoin Core + Nucli Arepacoin + + + + Debug log file + Dietàri de depuració + + + + Open the Arepacoin debug log file from the current data directory. This can take a few seconds for large log files. + Obriu el fitxer de registre de depuració Arepacoin des del directori de dades actual. Això pot trigar uns segons en els arxius de registre de grans dimensions. + + + + Clear console + Netejar consola + + + + Welcome to the Arepacoin RPC console. + Benvingut a la consola RPC de Arepacoin. + + + + Use up and down arrows to navigate history, and <b>Ctrl-L</b> to clear screen. + Utilitza les fletxes d'amunt i avall per navegar per l'històric, i <b>Ctrl-L<\b> per netejar la pantalla. + + + + Type <b>help</b> for an overview of available commands. + Escriu <b>help<\b> per a obtenir una llistat de les ordres disponibles. + + + + SendCoinsDialog + + + + + + + + + + Send Coins + Enviar monedes + + + + Coin Control Features + (Opcions del control del Coin) + + + + Inputs... + Entrades + + + + automatically selected + Seleccionat automàticament + + + + Insufficient funds! + Fons insuficient + + + + Quantity: + Quantitat: + + + + + 0 + 0 + + + + Bytes: + Bytes: + + + + Amount: + Quantitat: + + + + + + + 0.00 BC + 123.456 BC {0.00 ?} + + + + Priority: + Prioritat: + + + + medium + mig + + + + Fee: + Quota: + + + + Low Output: + Sortida baixa: + + + + no + no + + + + After Fee: + Quota posterior: + + + + Change + Canvi + + + + custom change address + Adreça de canvi pròpia + + + + Send to multiple recipients at once + Enviar a multiples destinataris al mateix temps + + + + Add &Recipient + Afegir &Destinatari + + + + Remove all transaction fields + Traieu tots els camps de transacció + + + + Clear &All + Esborrar &Tot + + + + Balance: + Balanç: + + + + 123.456 BC + 123.456 BC + + + + Confirm the send action + Confirmi l'acció d'enviament + + + + S&end + E&nviar + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + Introdueix una adreça Arepacoin (p.ex. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + Copy quantity + Copiar quantitat + + + + Copy amount + Copiar quantitat + + + + Copy fee + Copiar comisió + + + + Copy after fee + Copiar després de comisió + + + + Copy bytes + Copiar bytes + + + + Copy priority + Copiar prioritat + + + + Copy low output + Copiar sortida baixa + + + + Copy change + Copiar canvi + + + + <b>%1</b> to %2 (%3) + <b>%1</b> a %2 (%3) + + + + Confirm send coins + Confirmar l'enviament de monedes + + + + Are you sure you want to send %1? + Esteu segur que voleu enviar %1? + + + + and + i + + + + The recipient address is not valid, please recheck. + L'adreça remetent no és vàlida, si us plau comprovi-la. + + + + The amount to pay must be larger than 0. + La quantitat a pagar ha de ser major que 0. + + + + The amount exceeds your balance. + Import superi el saldo de la seva compte. + + + + The total exceeds your balance when the %1 transaction fee is included. + El total excedeix el teu balanç quan s'afegeix la comisió a la transacció %1. + + + + Duplicate address found, can only send to each address once per send operation. + S'ha trobat una adreça duplicada, tan sols es pot enviar a cada adreça un cop per ordre de enviament. + + + + Error: Transaction creation failed. + Error: La creació de transacció ha fallat. + + + + 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. + Error: La transacció ha sigut rebutjada. Això pot passar si algunes de les monedes al moneder ja s'han gastat, per exemple, si vostè utilitza una còpia del wallet.dat i les monedes han estat gastades a la cópia pero no s'han marcat com a gastades aqui. + + + + WARNING: Invalid Arepacoin address + ADVERTÈNCIA: Direcció Arepacoin invàlida + + + + (no label) + (sense etiqueta) + + + + WARNING: unknown change address + ADVERTÈNCIA: direcció de canvi desconeguda + + + + SendCoinsEntry + + + Form + Formulari + + + + A&mount: + Q&uantitat: + + + + Pay &To: + Pagar &A: + + + + + Enter a label for this address to add it to your address book + Introdueixi una etiquera per a aquesta adreça per afegir-la a la llibreta d'adreces + + + + &Label: + &Etiqueta: + + + + The address to send the payment to (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + L'adreça per a enviar el pagament (per exemple: AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + Choose address from address book + Trieu la direcció de la llibreta d'adreces + + + + Alt+A + Alta+A + + + + Paste address from clipboard + Enganxar adreça del porta-retalls + + + + Alt+P + Alt+P + + + + Remove this recipient + Eliminar aquest destinatari + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + Introdueix una adreça Arepacoin (p.ex. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + SignVerifyMessageDialog + + + Signatures - Sign / Verify a Message + Signatures .Signar/Verificar un Missatge + + + + + &Sign Message + &Signar Missatge + + + + You can sign messages with your addresses to prove you own them. Be careful not to sign anything vague, as phishing attacks may try to trick you into signing your identity over to them. Only sign fully-detailed statements you agree to. + Pots signar missatges amb la teva adreça per provar que són teus. Sigues cautelòs al signar qualsevol cosa, ja que els atacs phising poden intentar confondre't per a que els hi signis amb la teva identitat. Tan sols signa als documents completament detallats amb els que hi estàs d'acord. + + + + The address to sign the message with (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + L'adreça per a signar el missatge (per exemple AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Choose an address from the address book + Trieu una adreça de la llibreta d'adreces + + + + + Alt+A + Alta+A + + + + Paste address from clipboard + Enganxar adreça del porta-retalls + + + + Alt+P + Alt+P + + + + Enter the message you want to sign here + Introdueix aqui el missatge que vols signar + + + + Copy the current signature to the system clipboard + Copiar la signatura actual al porta-retalls del sistema + + + + Sign the message to prove you own this Arepacoin address + Signar un missatge per demostrar que és propietari d'aquesta adreça Arepacoin + + + + Reset all sign message fields + Neteja tots els camps de clau + + + + + Clear &All + Esborrar &Tot + + + + + &Verify Message + &Verificar el missatge + + + + Enter the signing address, message (ensure you copy line breaks, spaces, tabs, etc. exactly) and signature below to verify the message. Be careful not to read more into the signature than what is in the signed message itself, to avoid being tricked by a man-in-the-middle attack. + Introdueixi l'adreça signant, missatge (assegura't que copies salts de línia, espais, tabuladors, etc excactament tot el text) i la signatura a sota per verificar el missatge. Per evitar ser enganyat per un atac home-entre-mig, vés amb compte de no llegir més en la signatura del que hi ha al missatge signat mateix. + + + + The address the message was signed with (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + La direcció que va ser signada amb un missatge (per exemple AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + Verify the message to ensure it was signed with the specified Arepacoin address + Comproveu el missatge per assegurar-se que es va signar amb l'adreça Arepacoin especificada. + + + + Reset all verify message fields + Neteja tots els camps de verificació de missatge + + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + Introdueix una adreça Arepacoin (p.ex. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + Click "Sign Message" to generate signature + Clica "Signar Missatge" per a generar una signatura + + + + Enter Arepacoin signature + Introduïu la signatura Arepacoin + + + + + The entered address is invalid. + L'adreça intoduïda és invàlida. + + + + + + + Please check the address and try again. + Siu us plau, comprovi l'adreça i provi de nou. + + + + + The entered address does not refer to a key. + L'adreça introduïda no referencia a cap clau. + + + + Wallet unlock was cancelled. + El desbloqueig del moneder ha estat cancelat. + + + + Private key for the entered address is not available. + La clau privada per a la adreça introduïda no està disponible. + + + + Message signing failed. + El signat del missatge ha fallat. + + + + Message signed. + Missatge signat. + + + + The signature could not be decoded. + La signatura no s'ha pogut decodificar . + + + + + Please check the signature and try again. + Su us plau, comprovi la signatura i provi de nou. + + + + The signature did not match the message digest. + La signatura no coincideix amb el resum del missatge. + + + + Message verification failed. + Ha fallat la verificació del missatge. + + + + Message verified. + Missatge verificat. + + + + TransactionDesc + + + Open until %1 + Obert fins %1 + + + + Open for %n block(s) + Obert per a %n blocObert per a %n blocs + + + + conflicted + conflicte + + + + %1/offline + %1/offline + + + + %1/unconfirmed + %1/sense confirmar + + + + %1 confirmations + %1 confrimacions + + + + Status + Estat + + + + , broadcast through %n node(s) + , transmès a través de %n node, transmès a través de %n nodes + + + + Date + Data + + + + Source + Font + + + + Generated + Generat + + + + + From + Des de + + + + + + To + A + + + + + own address + Adreça pròpia + + + + label + etiqueta + + + + + + + + Credit + Crèdit + + + + matures in %n more block(s) + madura en %n bloc mésmadura en %n blocs més + + + + not accepted + no acceptat + + + + + + + Debit + Dèbit + + + + Transaction fee + Comissió de transacció + + + + Net amount + Quantitat neta + + + + Message + Missatge + + + + Comment + Comentar + + + + Transaction ID + ID de transacció + + + + Generated coins must mature 6 blocks before they can be spent. When you generated this block, it was broadcast to the network to be added to the block chain. If it fails to get into the chain, its state will change to "not accepted" and it won't be spendable. This may occasionally happen if another node generates a block within a few seconds of yours. + Les monedes generades han de madurar 6 blocs abans per a poder estar disponibles. En generar aquest bloc, que va ser transmès a la xarxa per ser afegit a la cadena de bloc. Si no aconsegueix entrar a la cadena, el seu estat canviarà a "no acceptat" i no es podrà gastar. Això pot succeir de tant en tant si un altre node genera un bloc a pocs segons del seu. + + + + Debug information + Informació de depuració + + + + Transaction + Transacció + + + + Inputs + Entrades + + + + Amount + Quantitat + + + + true + cert + + + + false + fals + + + + , has not been successfully broadcast yet + , encara no ha estat emès correctement + + + + unknown + desconegut + + + + TransactionDescDialog + + + Transaction details + Detall de la transacció + + + + This pane shows a detailed description of the transaction + Aquest panell mostra una descripció detallada de la transacció + + + + TransactionTableModel + + + Date + Data + + + + Type + Tipus + + + + Address + Direcció + + + + Amount + Quantitat + + + + Open until %1 + Obert fins %1 + + + + Confirmed (%1 confirmations) + Confirmat (%1 confirmacions) + + + + Open for %n more block(s) + Obert per a %n bloc mésObert per a %n blocs més + + + + Offline + Desconnectat + + + + Unconfirmed + Sense confirmar + + + + Confirming (%1 of %2 recommended confirmations) + Confirmant (%1 de %2 confirmacions recomanat) + + + + Conflicted + Conflicte + + + + Immature (%1 confirmations, will be available after %2) + Immadurs (%1 confirmacions, estaran disponibles després de %2) + + + + This block was not received by any other nodes and will probably not be accepted! + Aquest bloc no ha estat rebut per cap altre node i probablement no serà acceptat! + + + + Generated but not accepted + Generat però no acceptat + + + + Received with + Rebut desde + + + + Received from + Rebut de + + + + Sent to + Enviat a + + + + Payment to yourself + Pagament a un mateix + + + + Mined + Minat + + + + (n/a) + (n/a) + + + + Transaction status. Hover over this field to show number of confirmations. + Estat de la transacció. Desplaça't per aquí sobre per mostrar el nombre de confirmacions. + + + + Date and time that the transaction was received. + Data i hora en que la transacció va ser rebuda. + + + + Type of transaction. + Tipus de transacció. + + + + Destination address of transaction. + Adreça del destinatari de la transacció. + + + + Amount removed from or added to balance. + Quantitat extreta o afegida del balanç. + + + + TransactionView + + + + All + Tot + + + + Today + Avui + + + + This week + Aquesta setmana + + + + This month + Aquest mes + + + + Last month + El mes passat + + + + This year + Enguany + + + + Range... + Rang... + + + + Received with + Rebut desde + + + + Sent to + Enviat a + + + + To yourself + A tu mateix + + + + Mined + Minat + + + + Other + Altres + + + + Enter address or label to search + Introdueix una adreça o una etiqueta per cercar + + + + Min amount + Quantitat mínima + + + + Copy address + Copiar adreça + + + + Copy label + Copiar etiqueta + + + + Copy amount + Copiar quantitat + + + + Copy transaction ID + Copiar ID de transacció + + + + Edit label + Editar etiqueta + + + + Show transaction details + Mostra detalls de la transacció + + + + Export Transaction Data + Exportació de dades de transaccions + + + + Comma separated file (*.csv) + Arxiu de separació per comes (*.csv) + + + + Confirmed + Confirmat + + + + Date + Data + + + + Type + Tipus + + + + Label + Etiqueta + + + + Address + Direcció + + + + Amount + Quantitat + + + + ID + ID + + + + Error exporting + Error a l'exportar + + + + Could not write to file %1. + No s'ha pogut escriure al fitxer %1. + + + + Range: + Rang: + + + + to + a + + + + WalletModel + + + Sending... + Enviant... + + + + bitcoin-core + + + Arepacoin version + versió Arepacoin + + + + Usage: + Ús: + + + + Send command to -server or arepacoind + Enviar comandes a -server o arepacoind + + + + List commands + Llista d'ordres + + + + Get help for a command + Obtenir ajuda per a un ordre. + + + + Options: + Opcions: + + + + Specify configuration file (default: arepacoin.conf) + Especifiqueu el fitxer de configuració (per defecte: arepacoin.conf) + + + + Specify pid file (default: arepacoind.pid) + Especificar arxiu pid (per defecte: arepacoind.pid) + + + + Specify wallet file (within data directory) + Especifica un arxiu de moneder (dintre del directori de les dades) + + + + Specify data directory + Especificar directori de dades + + + + Set database cache size in megabytes (default: 25) + Establir tamany de la memoria cau en megabytes (per defecte: 25) + + + + Set database disk log size in megabytes (default: 100) + Configurar la mida del registre en disc de la base de dades en megabytes (per defecte: 100) + + + + Listen for connections on <port> (default: 9853 or testnet: 19853) + Escoltar connexions en <port> (per defecte: 9853 o testnet: 19853) + + + + Maintain at most <n> connections to peers (default: 125) + Mantenir com a molt <n> connexions a peers (per defecte: 125) + + + + Connect to a node to retrieve peer addresses, and disconnect + Connectar al node per obtenir les adreces de les connexions, i desconectar + + + + Specify your own public address + Especificar la teva adreça pública + + + + Bind to given address. Use [host]:port notation for IPv6 + Enllaçar a l'adreça donada. Utilitzeu la notació [host]:port per a IPv6 + + + + Stake your coins to support network and gain reward (default: 1) + Posa les teves monedes a fer "stake" per donar suport a la xarxa i obtenir una recompensa (per defecte: 1) + + + + Threshold for disconnecting misbehaving peers (default: 100) + Límit per a desconectar connexions errònies (per defecte: 100) + + + + Number of seconds to keep misbehaving peers from reconnecting (default: 86400) + Nombre de segons abans de reconectar amb connexions errònies (per defecte: 86400) + + + + An error occurred while setting up the RPC port %u for listening on IPv4: %s + Ha sorgit un error al configurar el port RPC %u escoltant a IPv4: %s + + + + Detach block and address databases. Increases shutdown time (default: 0) + Separeu el bloc i les bases de dades d'adreces. Augmenta el temps d'apagada (per defecte: 0) + + + + 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. + Error: La transacció ha sigut rebutjada. Això pot passar si algunes de les monedes al moneder ja s'han gastat, per exemple, si vostè utilitza una còpia del wallet.dat i les monedes han estat gastades a la cópia pero no s'han marcat com a gastades aqui. + + + + Error: This transaction requires a transaction fee of at least %s because of its amount, complexity, or use of recently received funds + Error: Aquesta transacció requereix una comisió d'almenys %s degut a la seva quantitat, complexitat, o l'ús dels fons rebuts recentment + + + + Listen for JSON-RPC connections on <port> (default: 9852 or testnet: 19852) + Escoltar connexions JSON-RPC al port <port> (per defecte: 9852 o testnet: 19852) + + + + Accept command line and JSON-RPC commands + Acceptar línia d'ordres i ordres JSON-RPC + + + + Error: Transaction creation failed + Error: La creació de transacció ha fallat. + + + + Error: Wallet locked, unable to create transaction + Error: Moneder bloquejat, no es pot de crear la transacció + + + + Importing blockchain data file. + Important fitxer de dades de la cadena de blocs + + + + Importing bootstrap blockchain data file. + Important fitxer de dades d'arrencada de la cadena de blocs + + + + Run in the background as a daemon and accept commands + Executar en segon pla com a programa dimoni i acceptar ordres + + + + Use the test network + Usar la xarxa de prova + + + + Accept connections from outside (default: 1 if no -proxy or -connect) + Aceptar connexions d'afora (per defecte: 1 si no -proxy o -connect) + + + + An error occurred while setting up the RPC port %u for listening on IPv6, falling back to IPv4: %s + Ha sorgit un error al configurar el port RPC %u escoltant a IPv6, retrocedint a IPv4: %s + + + + Error initializing database environment %s! To recover, BACKUP THAT DIRECTORY, then remove everything from it except for wallet.dat. + Error en inicialitzar l'entorn de base de dades %s! Per recuperar, FACI UNA COPIA DE SEGURETAT D'AQUEST DIRECTORI, a continuació, retiri tot d'ella excepte l'arxiu wallet.dat. + + + + Set maximum size of high-priority/low-fee transactions in bytes (default: 27000) + Establir la grandària màxima de les transaccions alta-prioritat/baixa-comisió en bytes (per defecte: 27000) + + + + Warning: -paytxfee is set very high! This is the transaction fee you will pay if you send a transaction. + Advertència: el -paytxfee és molt elevat! Aquesta és la comissió de transacció que pagaràs quan enviis una transacció. + + + + Warning: Please check that your computer's date and time are correct! If your clock is wrong Arepacoin will not work properly. + Avís: Comproveu que la data i hora de l'equip siguin correctes! Si el seu rellotge és erroni Arepacoin no funcionarà correctament. + + + + Warning: error reading wallet.dat! All keys read correctly, but transaction data or address book entries might be missing or incorrect. + Advertència: Error llegint l'arxiu wallet.dat!! Totes les claus es llegeixen correctament, però hi ha dades de transaccions o entrades del llibre d'adreces absents o bé son incorrectes. + + + + Warning: wallet.dat corrupt, data salvaged! Original wallet.dat saved as wallet.{timestamp}.bak in %s; if your balance or transactions are incorrect you should restore from a backup. + Advertència: L'arxiu wallet.dat és corrupte, dades rescatades! L'arxiu wallet.dat original ha estat desat com wallet.{estampa_temporal}.bak al directori %s; si el teu balanç o transaccions son incorrectes hauries de restaurar-lo de un backup. + + + + Attempt to recover private keys from a corrupt wallet.dat + Intentar recuperar les claus privades d'un arxiu wallet.dat corrupte + + + + Block creation options: + Opcions de la creació de blocs: + + + + Connect only to the specified node(s) + Connectar només al(s) node(s) especificats + + + + Discover own IP address (default: 1 when listening and no -externalip) + Descobrir la pròpia adreça IP (per defecte: 1 quan escoltant i no -externalip) + + + + Failed to listen on any port. Use -listen=0 if you want this. + Error al escoltar a qualsevol port. Utilitza -listen=0 si vols això. + + + + Find peers using DNS lookup (default: 1) + Trobar companys utilitzant la recerca de DNS (per defecte: 1) + + + + Sync checkpoints policy (default: strict) + Política dels punts de control de sincronització (per defecte: estricta) + + + + Invalid -tor address: '%s' + Adreça -tor invalida: '%s' + + + + Invalid amount for -reservebalance=<amount> + Quantitat invalida per a -reservebalance=<amount> + + + + Maximum per-connection receive buffer, <n>*1000 bytes (default: 5000) + Mida màxima del buffer de recepció per a cada connexió, <n>*1000 bytes (default: 5000) + + + + Maximum per-connection send buffer, <n>*1000 bytes (default: 1000) + Mida màxima del buffer d'enviament per a cada connexió, <n>*1000 bytes (default: 5000) + + + + Only connect to nodes in network <net> (IPv4, IPv6 or Tor) + Només connectar als nodes de la xarxa <net> (IPv4, IPv6 o Tor) + + + + Output extra debugging information. Implies all other -debug* options + Sortida d'informació de depuració extra. Implica totes les opcions de depuracó -debug* + + + + Output extra network debugging information + Sortida d'informació de depuració de xarxa addicional + + + + Prepend debug output with timestamp + Anteposar marca de temps a la sortida de depuració + + + + SSL options: (see the Bitcoin Wiki for SSL setup instructions) + Opcions SSL: (veure la Wiki de Bitcoin per a instruccions de configuració SSL) + + + + Select the version of socks proxy to use (4-5, default: 5) + Seleccioneu la versió de proxy socks per utilitzar (4-5, per defecte: 5) + + + + Send trace/debug info to console instead of debug.log file + Enviar informació de traça/depuració a la consola en comptes del arxiu debug.log + + + + Send trace/debug info to debugger + Enviar informació de traça/depuració al depurador + + + + Set maximum block size in bytes (default: 250000) + Establir una mida máxima de bloc en bytes (per defecte: 250000) + + + + Set minimum block size in bytes (default: 0) + Establir una mida mínima de bloc en bytes (per defecte: 0) + + + + Shrink debug.log file on client startup (default: 1 when no -debug) + Reduir l'arxiu debug.log al iniciar el client (per defecte 1 quan no -debug) + + + + Specify connection timeout in milliseconds (default: 5000) + Especificar el temps limit per a un intent de connexió en milisegons (per defecte: 5000) + + + + Unable to sign checkpoint, wrong checkpointkey? + + No es pot signar el punt de control, la clau del punt de control esta malament? + + + + + Use UPnP to map the listening port (default: 0) + Utilitza UPnP per a mapejar els ports d'escolta (per defecte: 0) + + + + Use UPnP to map the listening port (default: 1 when listening) + Utilitza UPnP per a mapejar els ports d'escolta (per defecte: 1 quan s'escolta) + + + + Use proxy to reach tor hidden services (default: same as -proxy) + Utilitza proxy per arribar als serveis ocults de Tor (per defecte: la mateixa que -proxy) + + + + Username for JSON-RPC connections + Nom d'usuari per a connexions JSON-RPC + + + + Verifying database integrity... + Comprovant la integritat de la base de dades ... + + + + WARNING: syncronized checkpoint violation detected, but skipped! + ADVERTÈNCIA: violació de punt de control sincronitzat detectada, es saltarà! + + + + Warning: Disk space is low! + Avís: L'espai en disc és baix! + + + + Warning: This version is obsolete, upgrade required! + Advertència: Aquetsa versió està obsoleta, és necessari actualitzar! + + + + wallet.dat corrupt, salvage failed + L'arxiu wallet.data és corrupte, el rescat de les dades ha fallat + + + + Password for JSON-RPC connections + Contrasenya per a connexions JSON-RPC + + + + %s, you must set a rpcpassword in the configuration file: + %s +It is recommended you use the following random password: +rpcuser=arepacoinrpc +rpcpassword=%s +(you do not need to remember this password) +The username and password MUST NOT be the same. +If the file does not exist, create it with owner-readable-only file permissions. +It is also recommended to set alertnotify so you are notified of problems; +for example: alertnotify=echo %%s | mail -s "Arepacoin Alert" admin@foo.com + + %s, ha d'establir un rpcpassword al fitxer de configuració: +%s +Es recomana utilitzar la següent contrasenya aleatòria: +rpcuser=arepacoinrpc +rpcpassword=%s +(No cal recordar aquesta contrasenya) +El nom d'usuari i contrasenya NO HA DE SER el mateix. +Si no hi ha l'arxiu, s'ha de crear amb els permisos de només lectura per al propietari. +També es recomana establir alertnotify per a que se li notifiquin els problemes; +per exemple: alertnotify=echo %%s | mail -s "Arepacoin Alert" admin@foo.com + + + + + Find peers using internet relay chat (default: 0) + Trobar companys utilitzant l'IRC (per defecte: 1) {0)?} + + + + Sync time with other nodes. Disable if time on your system is precise e.g. syncing with NTP (default: 1) + Sincronitzar el temps amb altres nodes. Desactivar si el temps al seu sistema és precís, per exemple, si fa ús de sincronització amb NTP (per defecte: 1) + + + + When creating transactions, ignore inputs with value less than this (default: 0.01) + En crear transaccions, ignorar les entrades amb valor inferior a aquesta (per defecte: 0.01) + + + + Allow JSON-RPC connections from specified IP address + Permetre connexions JSON-RPC d'adreces IP específiques + + + + Send commands to node running on <ip> (default: 127.0.0.1) + Enviar ordre al node en execució a <ip> (per defecte: 127.0.0.1) + + + + Execute command when the best block changes (%s in cmd is replaced by block hash) + Executar orde quan el millor bloc canviï (%s al cmd es reemplaça per un bloc de hash) + + + + Execute command when a wallet transaction changes (%s in cmd is replaced by TxID) + Executar una ordre quan una transacció del moneder canviï (%s in cmd es canvia per TxID) + + + + Require a confirmations for change (default: 0) + Requerir les confirmacions de canvi (per defecte: 0) + + + + Enforce transaction scripts to use canonical PUSH operators (default: 1) + Fer complir als scripts de transaccions d'utilitzar operadors PUSH canòniques (per defecte: 1) + + + + Execute command when a relevant alert is received (%s in cmd is replaced by message) + +Executar una ordre quan es rep un avís rellevant (%s en cmd es substitueix per missatge) + + + + Upgrade wallet to latest format + Actualitzar moneder a l'últim format + + + + Set key pool size to <n> (default: 100) + Establir límit de nombre de claus a <n> (per defecte: 100) + + + + Rescan the block chain for missing wallet transactions + Re-escanejar cadena de blocs en cerca de transaccions de moneder perdudes + + + + How many blocks to check at startup (default: 2500, 0 = all) + Quants blocs s'han de confirmar a l'inici (per defecte: 2500, 0 = tots) + + + + How thorough the block verification is (0-6, default: 1) + Com és de minuciosa la verificació del bloc (0-6, per defecte: 1) + + + + Imports blocks from external blk000?.dat file + Importar blocs desde l'arxiu extern blk000?.dat + + + + Use OpenSSL (https) for JSON-RPC connections + Utilitzar OpenSSL (https) per a connexions JSON-RPC + + + + Server certificate file (default: server.cert) + Arxiu del certificat de servidor (per defecte: server.cert) + + + + Server private key (default: server.pem) + Clau privada del servidor (per defecte: server.pem) + + + + Acceptable ciphers (default: TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH) + Xifres acceptables (per defecte: TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH) + + + + Error: Wallet unlocked for staking only, unable to create transaction. + Error: Cartera bloquejada nomès per a fer "stake", no es pot de crear la transacció + + + + WARNING: Invalid checkpoint found! Displayed transactions may not be correct! You may need to upgrade, or notify developers. + ADVERTÈNCIA: Punt de control invàlid! Les transaccions mostrades podríen no ser correctes! Podria ser necessari actualitzar o notificar-ho als desenvolupadors. + + + + This help message + Aquest misatge d'ajuda + + + + Wallet %s resides outside data directory %s. + El moneder %s resideix fora del directori de dades %s. + + + + Cannot obtain a lock on data directory %s. Arepacoin is probably already running. + No es pot obtenir un bloqueig en el directori de dades %s. Arepacoin probablement ja estigui en funcionament. + + + + Arepacoin + Arepacoin + + + + Unable to bind to %s on this computer (bind returned error %d, %s) + Impossible d'unir %s a aquest ordinador (s'ha retornat l'error %d, %s) + + + + Connect through socks proxy + Conectar a través d'un proxy SOCKS + + + + Allow DNS lookups for -addnode, -seednode and -connect + Permetre consultes DNS per a -addnode, -seednode i -connect + + + + Loading addresses... + Carregant adreces... + + + + Error loading blkindex.dat + Error carregant blkindex.dat + + + + Error loading wallet.dat: Wallet corrupted + Error carregant wallet.dat: Moneder corrupte + + + + Error loading wallet.dat: Wallet requires newer version of Arepacoin + Error en carregar wallet.dat: El moneder requereix la versió més recent de Arepacoin + + + + Wallet needed to be rewritten: restart Arepacoin to complete + El moneder necessita ser reescrita: reiniciar Arepacoin per completar + + + + Error loading wallet.dat + Error carregant wallet.dat + + + + Invalid -proxy address: '%s' + Adreça -proxy invalida: '%s' + + + + Unknown network specified in -onlynet: '%s' + Xarxa desconeguda especificada a -onlynet: '%s' + + + + Unknown -socks proxy version requested: %i + S'ha demanat una versió desconeguda de -socks proxy: %i + + + + Cannot resolve -bind address: '%s' + No es pot resoldre l'adreça -bind: '%s' + + + + Cannot resolve -externalip address: '%s' + No es pot resoldre l'adreça -externalip: '%s' + + + + Invalid amount for -paytxfee=<amount>: '%s' + Quantitat invalida per a -paytxfee=<amount>: '%s' + + + + Error: could not start node + Error: no s'ha pogut iniciar el node + + + + Sending... + Enviant... + + + + Invalid amount + Quanitat invalida + + + + Insufficient funds + Balanç insuficient + + + + Loading block index... + Carregant índex de blocs... + + + + Add a node to connect to and attempt to keep the connection open + Afegir un node per a connectar's-hi i intentar mantenir la connexió oberta + + + + Unable to bind to %s on this computer. Arepacoin is probably already running. + No es pot enllaçar a %s en aquest equip. Arepacoin probablement ja estigui en funcionament. + + + + Fee per KB to add to transactions you send + Comisió per KB per a afegir a les transaccions que enviï + + + + Invalid amount for -mininput=<amount>: '%s' + Quantitat invalida per a -mininput=<amount>: '%s' + + + + Loading wallet... + Carregant moneder... + + + + Cannot downgrade wallet + No es pot reduir la versió del moneder + + + + Cannot initialize keypool + No es pot inicialitzar el keypool + + + + Cannot write default address + No es pot escriure l'adreça per defecte + + + + Rescanning... + Re-escanejant... + + + + Done loading + Càrrega acabada + + + + To use the %s option + Utilitza la opció %s + + + + Error + Error + + + + You must set rpcpassword=<password> in the configuration file: +%s +If the file does not exist, create it with owner-readable-only file permissions. + Has de configurar el rpcpassword=<password> a l'arxiu de configuració:\n %s\n Si l'arxiu no existeix, crea'l amb els permís owner-readable-only. + + + \ No newline at end of file diff --git a/src/qt/locale/bitcoin_cs.ts b/src/qt/locale/bitcoin_cs.ts new file mode 100755 index 0000000..10146c0 --- /dev/null +++ b/src/qt/locale/bitcoin_cs.ts @@ -0,0 +1,3286 @@ + + + AboutDialog + + + About Arepacoin + O Arepacoinu + + + + <b>Arepacoin</b> version + Verze <b>Arepacoinu</b> + + + + Copyright © 2009-2014 The Bitcoin developers +Copyright © 2012-2014 The NovaCoin developers +Copyright © 2014 The Arepacoin developers + + + + + +This is experimental software. + +Distributed under the MIT/X11 software license, see the accompanying file COPYING or http://www.opensource.org/licenses/mit-license.php. + +This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit (http://www.openssl.org/) and cryptographic software written by Eric Young (eay@cryptsoft.com) and UPnP software written by Thomas Bernard. + +Tohle je experimentální program. + +Šířen pod licencí MIT/X11, viz přiložený soubor COPYING nebo http://www.opensource.org/licenses/mit-license.php. + +Tento produkt zahrnuje programy vyvinuté OpenSSL Projektem pro použití v OpenSSL Toolkitu (http://www.openssl.org/) a kryptografický program od Erika Younga (eay@cryptsoft.com) a program UPnP od Thomase Bernarda. + + + + AddressBookPage + + + Address Book + Kniha adres + + + + Double-click to edit address or label + Dvojklikem myši začneš upravovat označení adresy + + + + Create a new address + Vytvoř novou adresu + + + + Copy the currently selected address to the system clipboard + Zkopíruj aktuálně vybranou adresu do systémové schránky + + + + &New Address + &Nová adresa + + + + These are your Arepacoin addresses for receiving payments. You may want to give a different one to each sender so you can keep track of who is paying you. + + + + + &Copy Address + &Kopíruj adresu + + + + Show &QR Code + + + + + Sign a message to prove you own a Arepacoin address + + + + + Sign &Message + + + + + Delete the currently selected address from the list + Smaž zvolenou adresu ze seznamu + + + + Verify a message to ensure it was signed with a specified Arepacoin address + + + + + &Verify Message + &Ověřit správu + + + + &Delete + &Smaž + + + + Copy &Label + Kopíruj &označení + + + + &Edit + &Uprav + + + + Export Address Book Data + + + + + Comma separated file (*.csv) + CSV formát (*.csv) + + + + Error exporting + + + + + Could not write to file %1. + + + + + AddressTableModel + + + Label + Označení + + + + Address + Adresa + + + + (no label) + (bez označení) + + + + AskPassphraseDialog + + + Passphrase Dialog + Změna hesla + + + + Enter passphrase + Zadej platné heslo + + + + New passphrase + Zadej nové heslo + + + + Repeat new passphrase + Totéž heslo ještě jednou + + + + Serves to disable the trivial sendmoney when OS account compromised. Provides no real security. + + + + + For staking only + + + + + Enter the new passphrase to the wallet.<br/>Please use a passphrase of <b>10 or more random characters</b>, or <b>eight or more words</b>. + Zadej nové heslo k peněžence.<br/>Použij <b>alespoň 10 náhodných znaků</b> nebo <b>alespoň osm slov</b>. + + + + Encrypt wallet + Zašifruj peněženku + + + + This operation needs your wallet passphrase to unlock the wallet. + K provedení této operace musíš zadat heslo k peněžence, aby se mohla odemknout. + + + + Unlock wallet + Odemkni peněženku + + + + This operation needs your wallet passphrase to decrypt the wallet. + K provedení této operace musíš zadat heslo k peněžence, aby se mohla dešifrovat. + + + + Decrypt wallet + Dešifruj peněženku + + + + Change passphrase + Změň heslo + + + + Enter the old and new passphrase to the wallet. + Zadej staré a nové heslo k peněžence. + + + + Confirm wallet encryption + Potvrď zašifrování peněženky + + + + Warning: If you encrypt your wallet and lose your passphrase, you will <b>LOSE ALL OF YOUR COINS</b>! + + + + + Are you sure you wish to encrypt your wallet? + Jsi si jistý, že chceš peněženku zašifrovat? + + + + IMPORTANT: Any previous backups you have made of your wallet file should be replaced with the newly generated, encrypted wallet file. For security reasons, previous backups of the unencrypted wallet file will become useless as soon as you start using the new, encrypted wallet. + DŮLEŽITÉ: Všechny předchozí zálohy peněženky by měly být nahrazeny nově vygenerovanou, zašifrovanou peněženkou. Z bezpečnostních důvodů budou předchozí zálohy nešifrované peněženky nepoužitelné, jakmile začneš používat novou zašifrovanou peněženku. + + + + + Warning: The Caps Lock key is on! + Upozornění: Caps Lock je zapnutý! + + + + + Wallet encrypted + Peněženka je zašifrována + + + + Arepacoin will close now to finish the encryption process. Remember that encrypting your wallet cannot fully protect your coins from being stolen by malware infecting your computer. + + + + + + + + Wallet encryption failed + Zašifrování peněženky selhalo + + + + Wallet encryption failed due to an internal error. Your wallet was not encrypted. + Zašifrování peněženky selhalo kvůli vnitřní chybě. Tvá peněženka tedy nebyla zašifrována. + + + + + The supplied passphrases do not match. + Zadaná hesla nejsou shodná. + + + + Wallet unlock failed + Odemčení peněženky selhalo + + + + + + The passphrase entered for the wallet decryption was incorrect. + Nezadal jsi správné heslo pro dešifrování peněženky. + + + + Wallet decryption failed + Dešifrování peněženky selhalo + + + + Wallet passphrase was successfully changed. + Heslo k peněžence bylo v pořádku změněno. + + + + BitcoinGUI + + + Sign &message... + Po&depiš zprávu... + + + + Synchronizing with network... + Synchronizuji se se sítí... + + + + &Overview + &Přehled + + + + Show general overview of wallet + Zobraz celkový přehled peněženky + + + + &Transactions + &Transakce + + + + Browse transaction history + Procházej historii transakcí + + + + &Address Book + + + + + Edit the list of stored addresses and labels + + + + + &Receive coins + + + + + Show the list of addresses for receiving payments + + + + + &Send coins + + + + + E&xit + &Konec + + + + Quit application + Ukonči aplikaci + + + + Show information about Arepacoin + + + + + About &Qt + O &Qt + + + + Show information about Qt + Zobraz informace o Qt + + + + &Options... + &Možnosti... + + + + &Encrypt Wallet... + Zaši&fruj peněženku... + + + + &Backup Wallet... + &Zazálohuj peněženku... + + + + &Change Passphrase... + Změň &heslo... + + + + ~%n block(s) remaining + + + + + Downloaded %1 of %2 blocks of transaction history (%3% done). + + + + + &Export... + + + + + Send coins to a Arepacoin address + + + + + Modify configuration options for Arepacoin + + + + + Export the data in the current tab to a file + + + + + Encrypt or decrypt wallet + + + + + Backup wallet to another location + Zazálohuj peněženku na jiné místo + + + + Change the passphrase used for wallet encryption + Změň heslo k šifrování peněženky + + + + &Debug window + &Ladicí okno + + + + Open debugging and diagnostic console + Otevři ladicí a diagnostickou konzoli + + + + &Verify message... + &Ověř zprávu... + + + + Arepacoin + + + + + Wallet + Peněženka + + + + &About Arepacoin + + + + + &Show / Hide + &Zobraz/Skryj + + + + Unlock wallet + + + + + &Lock Wallet + + + + + Lock wallet + + + + + &File + &Soubor + + + + &Settings + &Nastavení + + + + &Help + Ná&pověda + + + + Tabs toolbar + Panel s listy + + + + Actions toolbar + + + + + + [testnet] + [testnet] + + + + + Arepacoin client + + + + + %n active connection(s) to Arepacoin network + + + + + Downloaded %1 blocks of transaction history. + + + + + Staking.<br>Your weight is %1<br>Network weight is %2<br>Expected time to earn reward is %3 + + + + + Not staking because wallet is locked + + + + + Not staking because wallet is offline + + + + + Not staking because wallet is syncing + + + + + Not staking because you don't have mature coins + + + + + %n second(s) ago + + + + + &Unlock Wallet... + + + + + %n minute(s) ago + + + + + %n hour(s) ago + + + + + %n day(s) ago + + + + + Up to date + Aktuální + + + + Catching up... + Stahuji... + + + + Last received block was generated %1. + + + + + This transaction is over the size limit. You can still send it for a fee of %1, which goes to the nodes that process your transaction and helps to support the network. Do you want to pay the fee? + + + + + Confirm transaction fee + + + + + Sent transaction + Odeslané transakce + + + + Incoming transaction + Příchozí transakce + + + + Date: %1 +Amount: %2 +Type: %3 +Address: %4 + + Datum: %1 +Částka: %2 +Typ: %3 +Adresa: %4 + + + + + + URI handling + + + + + + URI can not be parsed! This can be caused by an invalid Arepacoin address or malformed URI parameters. + + + + + Wallet is <b>encrypted</b> and currently <b>unlocked</b> + Peněženka je <b>zašifrovaná</b> a momentálně <b>odemčená</b> + + + + Wallet is <b>encrypted</b> and currently <b>locked</b> + Peněženka je <b>zašifrovaná</b> a momentálně <b>zamčená</b> + + + + Backup Wallet + + + + + Wallet Data (*.dat) + + + + + Backup Failed + + + + + There was an error trying to save the wallet data to the new location. + + + + + %n second(s) + + + + + %n minute(s) + + + + + %n hour(s) + hodinu%n hodiny%n hodin + + + + %n day(s) + den%n dny%n dnů + + + + Not staking + + + + + A fatal error occurred. Arepacoin can no longer continue safely and will quit. + + + + + ClientModel + + + Network Alert + Upozornění sítě + + + + CoinControlDialog + + + Coin Control + + + + + Quantity: + + + + + Bytes: + + + + + Amount: + Částka: + + + + Priority: + + + + + Fee: + + + + + Low Output: + + + + + no + + + + + After Fee: + + + + + Change: + + + + + (un)select all + + + + + Tree mode + + + + + List mode + + + + + Amount + Částka + + + + Label + + + + + Address + Adresa + + + + Date + Datum + + + + Confirmations + + + + + Confirmed + Potvrzeno + + + + Priority + + + + + Copy address + Kopírovat sdresu + + + + Copy label + Kopírovat popis + + + + + Copy amount + Kopíruj částku + + + + Copy transaction ID + Kopíruj ID transakce + + + + Copy quantity + + + + + Copy fee + + + + + Copy after fee + + + + + Copy bytes + + + + + Copy priority + + + + + Copy low output + + + + + Copy change + + + + + highest + + + + + high + + + + + medium-high + + + + + medium + + + + + low-medium + + + + + low + + + + + lowest + + + + + DUST + + + + + yes + + + + + This label turns red, if the transaction size is bigger than 10000 bytes. + + This means a fee of at least %1 per kb is required. + + Can vary +/- 1 Byte per input. + + + + + Transactions with higher priority get more likely into a block. + +This label turns red, if the priority is smaller than "medium". + + This means a fee of at least %1 per kb is required. + + + + + This label turns red, if any recipient receives an amount smaller than %1. + + This means a fee of at least %2 is required. + + Amounts below 0.546 times the minimum relay fee are shown as DUST. + + + + + This label turns red, if the change is smaller than %1. + + This means a fee of at least %2 is required. + + + + + + (no label) + (bez popisu) + + + + change from %1 (%2) + + + + + (change) + + + + + EditAddressDialog + + + Edit Address + Uprav adresu + + + + &Label + &Označení + + + + The label associated with this address book entry + + + + + &Address + &Adresa + + + + The address associated with this address book entry. This can only be modified for sending addresses. + + + + + New receiving address + Nová přijímací adresa + + + + New sending address + Nová odesílací adresa + + + + Edit receiving address + Uprav přijímací adresu + + + + Edit sending address + Uprav odesílací adresu + + + + The entered address "%1" is already in the address book. + Zadaná adresa "%1" už v adresáři je. + + + + The entered address "%1" is not a valid Arepacoin address. + + + + + Could not unlock wallet. + Nemohu odemknout peněženku. + + + + New key generation failed. + Nepodařilo se mi vygenerovat nový klíč. + + + + GUIUtil::HelpMessageBox + + + + Arepacoin-Qt + + + + + version + + + + + Usage: + + + + + command-line options + + + + + UI options + + + + + Set language, for example "de_DE" (default: system locale) + + + + + Start minimized + + + + + Show splash screen on startup (default: 1) + + + + + OptionsDialog + + + Options + Možnosti + + + + &Main + &Hlavní + + + + Optional transaction fee per kB that helps make sure your transactions are processed quickly. Most transactions are 1 kB. Fee 0.01 recommended. + + + + + Pay transaction &fee + Platit &transakční poplatek + + + + Reserved amount does not participate in staking and is therefore spendable at any time. + + + + + Reserve + + + + + Automatically start Arepacoin after logging in to the system. + + + + + &Start Arepacoin on system login + + + + + Detach block and address databases at shutdown. This means they can be moved to another data directory, but it slows down shutdown. The wallet is always detached. + + + + + &Detach databases at shutdown + + + + + &Network + &Síť + + + + Automatically open the Arepacoin client port on the router. This only works when your router supports UPnP and it is enabled. + + + + + Map port using &UPnP + Namapovat port přes &UPnP + + + + Connect to the Arepacoin network through a SOCKS proxy (e.g. when connecting through Tor). + + + + + &Connect through SOCKS proxy: + + + + + Proxy &IP: + &IP adresa proxy: + + + + IP address of the proxy (e.g. 127.0.0.1) + + + + + &Port: + Por&t: + + + + Port of the proxy (e.g. 9050) + Port proxy (např. 9050) + + + + SOCKS &Version: + &Verze SOCKS: + + + + SOCKS version of the proxy (e.g. 5) + Verze SOCKS proxy (např. 5) + + + + &Window + O&kno + + + + Show only a tray icon after minimizing the window. + Po minimalizaci okna zobrazí pouze ikonu v panelu. + + + + &Minimize to the tray instead of the taskbar + &Minimalizovávat do ikony v panelu + + + + Minimize instead of exit the application when the window is closed. When this option is enabled, the application will be closed only after selecting Quit in the menu. + Zavřením se aplikace minimalizuje. Pokud je tato volba zaškrtnuta, tak se aplikace ukončí pouze zvolením Konec v menu. + + + + M&inimize on close + Za&vřením minimalizovat + + + + &Display + Zobr&azení + + + + User Interface &language: + &Jazyk uživatelského rozhraní: + + + + The user interface language can be set here. This setting will take effect after restarting Arepacoin. + + + + + &Unit to show amounts in: + J&ednotka pro částky: + + + + Choose the default subdivision unit to show in the interface and when sending coins. + Zvol výchozí podjednotku, která se bude zobrazovat v programu a při posílání mincí. + + + + Whether to show Arepacoin addresses in the transaction list or not. + + + + + &Display addresses in transaction list + Ukazo&vat adresy ve výpisu transakcí + + + + Whether to show coin control features or not. + + + + + Display coin &control features (experts only!) + + + + + &OK + &Budiž + + + + &Cancel + &Zrušit + + + + &Apply + + + + + default + výchozí + + + + + Warning + + + + + + This setting will take effect after restarting Arepacoin. + + + + + The supplied proxy address is invalid. + Zadaná adresa proxy je neplatná. + + + + OverviewPage + + + Form + Formulář + + + + + The displayed information may be out of date. Your wallet automatically synchronizes with the Arepacoin network after a connection is established, but this process has not completed yet. + + + + + Stake: + + + + + Unconfirmed: + + + + + Wallet + Peněženka + + + + Spendable: + + + + + Your current spendable balance + Aktuální disponibilní stav tvého účtu + + + + Immature: + Nedozráno: + + + + Mined balance that has not yet matured + Vytěžené mince, které ještě nejsou zralé + + + + Total: + Celkem: + + + + Your current total balance + Celkový stav tvého účtu + + + + <b>Recent transactions</b> + <b>Poslední transakce</b> + + + + Total of transactions that have yet to be confirmed, and do not yet count toward the current balance + + + + + Total of coins that was staked, and do not yet count toward the current balance + + + + + + out of sync + nesynchronizováno + + + + QRCodeDialog + + + QR Code Dialog + + + + + Request Payment + + + + + Amount: + + + + + Label: + + + + + Message: + + + + + &Save As... + + + + + Error encoding URI into QR Code. + + + + + The entered amount is invalid, please check. + + + + + Resulting URI too long, try to reduce the text for label / message. + + + + + Save QR Code + + + + + PNG Images (*.png) + + + + + RPCConsole + + + Client name + Název klienta + + + + + + + + + + + + + N/A + N/A + + + + Client version + Verze klienta + + + + &Information + &Informace + + + + Using OpenSSL version + Používaná verze OpenSSL + + + + Startup time + Čas spuštění + + + + Network + Síť + + + + Number of connections + Počet spojení + + + + On testnet + + + + + Block chain + Řetězec bloků + + + + Current number of blocks + Aktuální počet bloků + + + + Estimated total blocks + Odhad celkového počtu bloků + + + + Last block time + Čas posledního bloku + + + + &Open + &Otevřít + + + + Command-line options + + + + + Show the Arepacoin-Qt help message to get a list with possible Arepacoin command-line options. + + + + + &Show + + + + + &Console + &Konzole + + + + Build date + Datum kompilace + + + + Arepacoin - Debug window + + + + + Arepacoin Core + + + + + Debug log file + Soubor s ladicími záznamy + + + + Open the Arepacoin debug log file from the current data directory. This can take a few seconds for large log files. + + + + + Clear console + Vyčistit konzoli + + + + Welcome to the Arepacoin RPC console. + + + + + Use up and down arrows to navigate history, and <b>Ctrl-L</b> to clear screen. + V historii se pohybuješ šipkami nahoru a dolů a pomocí <b>Ctrl-L</b> čistíš obrazovku. + + + + Type <b>help</b> for an overview of available commands. + Napsáním <b>help</b> si vypíšeš přehled dostupných příkazů. + + + + SendCoinsDialog + + + + + + + + + + Send Coins + Pošli mince + + + + Coin Control Features + + + + + Inputs... + + + + + automatically selected + + + + + Insufficient funds! + + + + + Quantity: + + + + + + 0 + + + + + Bytes: + + + + + Amount: + Částka: + + + + + + + 0.00 BC + + + + + Priority: + + + + + medium + + + + + Fee: + + + + + Low Output: + + + + + no + + + + + After Fee: + + + + + Change + + + + + custom change address + + + + + Send to multiple recipients at once + Pošli více příjemcům naráz + + + + Add &Recipient + Při&dej příjemce + + + + Remove all transaction fields + + + + + Clear &All + Všechno s&maž + + + + Balance: + Stav účtu: + + + + 123.456 BC + + + + + Confirm the send action + Potvrď odeslání + + + + S&end + P&ošli + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Copy quantity + + + + + Copy amount + Kopíruj částku + + + + Copy fee + + + + + Copy after fee + + + + + Copy bytes + + + + + Copy priority + + + + + Copy low output + + + + + Copy change + + + + + <b>%1</b> to %2 (%3) + + + + + Confirm send coins + Potvrď odeslání mincí + + + + Are you sure you want to send %1? + + + + + and + + + + + The recipient address is not valid, please recheck. + Adresa příjemce je neplatná, překontroluj ji prosím. + + + + The amount to pay must be larger than 0. + Odesílaná částka musí být větší než 0. + + + + The amount exceeds your balance. + Částka překračuje stav účtu. + + + + The total exceeds your balance when the %1 transaction fee is included. + Celková částka při připočítání poplatku %1 překročí stav účtu. + + + + Duplicate address found, can only send to each address once per send operation. + Zaznamenána duplikovaná adresa; každá adresa může být v odesílané platbě pouze jednou. + + + + Error: Transaction creation failed. + + + + + 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. + + + + + WARNING: Invalid Arepacoin address + + + + + (no label) + (bez popisu) + + + + WARNING: unknown change address + + + + + SendCoinsEntry + + + Form + + + + + A&mount: + Čás&tka: + + + + Pay &To: + &Komu: + + + + + Enter a label for this address to add it to your address book + Zadej označení této adresy; obojí se ti pak uloží do adresáře + + + + &Label: + O&značení: + + + + The address to send the payment to (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Choose address from address book + + + + + Alt+A + Alt+A + + + + Paste address from clipboard + Vlož adresu ze schránky + + + + Alt+P + Alt+P + + + + Remove this recipient + + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + SignVerifyMessageDialog + + + Signatures - Sign / Verify a Message + Podpisy - podepsat/ověřit zprávu + + + + + &Sign Message + &Podepiš zprávu + + + + You can sign messages with your addresses to prove you own them. Be careful not to sign anything vague, as phishing attacks may try to trick you into signing your identity over to them. Only sign fully-detailed statements you agree to. + Podepsáním zprávy svými adresami můžeš prokázat, že je skutečně vlastníš. Buď opatrný a nepodepisuj nic vágního; například při phishingových útocích můžeš být lákán, abys něco takového podepsal. Podepisuj pouze zcela úplná a detailní prohlášení, se kterými souhlasíš. + + + + The address to sign the message with (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + + Choose an address from the address book + + + + + + Alt+A + Alt+A + + + + Paste address from clipboard + Vlož adresu ze schránky + + + + Alt+P + Alt+P + + + + Enter the message you want to sign here + Sem vepiš zprávu, kterou chceš podepsat + + + + Copy the current signature to the system clipboard + Zkopíruj aktuálně vybraný podpis do systémové schránky + + + + Sign the message to prove you own this Arepacoin address + + + + + Reset all sign message fields + Vymaž všechna pole formuláře pro podepsání zrávy + + + + + Clear &All + Všechno &smaž + + + + + &Verify Message + &Ověř zprávu + + + + Enter the signing address, message (ensure you copy line breaks, spaces, tabs, etc. exactly) and signature below to verify the message. Be careful not to read more into the signature than what is in the signed message itself, to avoid being tricked by a man-in-the-middle attack. + K ověření podpisu zprávy zadej podepisující adresu, zprávu (ověř si, že správně kopíruješ zalomení řádků, mezery, tabulátory apod.) a podpis. Dávej pozor na to, abys nezkopíroval do podpisu víc, než co je v samotné podepsané zprávě, abys nebyl napálen man-in-the-middle útokem. + + + + The address the message was signed with (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Verify the message to ensure it was signed with the specified Arepacoin address + + + + + Reset all verify message fields + Vymaž všechna pole formuláře pro ověření zrávy + + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Click "Sign Message" to generate signature + Kliknutím na "Podepiš zprávu" vygeneruješ podpis + + + + Enter Arepacoin signature + + + + + + The entered address is invalid. + Zadaná adresa je neplatná. + + + + + + + Please check the address and try again. + Zkontroluj ji prosím a zkus to pak znovu. + + + + + The entered address does not refer to a key. + Zadaná adresa nepasuje ke klíči. + + + + Wallet unlock was cancelled. + Odemčení peněženky bylo zrušeno. + + + + Private key for the entered address is not available. + Soukromý klíč pro zadanou adresu není dostupný. + + + + Message signing failed. + Podepisování zprávy selhalo. + + + + Message signed. + Zpráv podepsána. + + + + The signature could not be decoded. + Podpis nejde dekódovat. + + + + + Please check the signature and try again. + Zkontroluj ho prosím a zkus to pak znovu. + + + + The signature did not match the message digest. + Podpis se neshoduje s hašem zprávy. + + + + Message verification failed. + Ověřování zprávy selhalo. + + + + Message verified. + Zpráva ověřena. + + + + TransactionDesc + + + Open until %1 + Otřevřeno dokud %1 + + + + Open for %n block(s) + + + + + conflicted + + + + + %1/offline + %1/offline + + + + %1/unconfirmed + %1/nepotvrzeno + + + + %1 confirmations + %1 potvrzení + + + + Status + Stav + + + + , broadcast through %n node(s) + , rozesláno přes 1 uzel, rozesláno přes %n uzly, rozesláno přes %n uzlů + + + + Date + Datum + + + + Source + Zdroj + + + + Generated + Vygenerováno + + + + + From + Od + + + + + + To + Pro + + + + + own address + vlastní adresa + + + + label + označení + + + + + + + + Credit + Příjem + + + + matures in %n more block(s) + dozraje po jednom blokudozraje po %n blocíchdozraje po %n blocích + + + + not accepted + neakceptováno + + + + + + + Debit + Výdaj + + + + Transaction fee + Transakční poplatek + + + + Net amount + Čistá částka + + + + Message + Zpráva + + + + Comment + Komentář + + + + Transaction ID + ID transakce + + + + Generated coins must mature 6 blocks before they can be spent. When you generated this block, it was broadcast to the network to be added to the block chain. If it fails to get into the chain, its state will change to "not accepted" and it won't be spendable. This may occasionally happen if another node generates a block within a few seconds of yours. + + + + + Debug information + Ladicí informace + + + + Transaction + Transakce + + + + Inputs + Vstupy + + + + Amount + Částka + + + + true + true + + + + false + false + + + + , has not been successfully broadcast yet + , ještě nebylo rozesláno + + + + unknown + neznámo + + + + TransactionDescDialog + + + Transaction details + Detaily transakce + + + + This pane shows a detailed description of the transaction + Toto okno zobrazuje detailní popis transakce + + + + TransactionTableModel + + + Date + Datum + + + + Type + Typ + + + + Address + Adresa + + + + Amount + Částka + + + + Open until %1 + Otřevřeno dokud %1 + + + + Confirmed (%1 confirmations) + Potvrzeno (%1 potvrzení) + + + + Open for %n more block(s) + Otevřeno pro 1 další blokOtevřeno pro %n další blokyOtevřeno pro %n dalších bloků + + + + Offline + + + + + Unconfirmed + + + + + Confirming (%1 of %2 recommended confirmations) + + + + + Conflicted + + + + + Immature (%1 confirmations, will be available after %2) + + + + + This block was not received by any other nodes and will probably not be accepted! + Tento blok nedostal žádný jiný uzel a pravděpodobně nebude akceptován! + + + + Generated but not accepted + Vygenerováno, ale neakceptováno + + + + Received with + Přijato do + + + + Received from + Přijato od + + + + Sent to + Posláno na + + + + Payment to yourself + Platba sama sobě + + + + Mined + Vytěženo + + + + (n/a) + (n/a) + + + + Transaction status. Hover over this field to show number of confirmations. + Stav transakce. Najetím myši na toto políčko si zobrazíš počet potvrzení. + + + + Date and time that the transaction was received. + Datum a čas přijetí transakce. + + + + Type of transaction. + Druh transakce. + + + + Destination address of transaction. + Cílová adresa transakce. + + + + Amount removed from or added to balance. + Částka odečtená z nebo přičtená k účtu. + + + + TransactionView + + + + All + Vše + + + + Today + Dnes + + + + This week + Tento týden + + + + This month + Tento měsíc + + + + Last month + Minulý měsíc + + + + This year + Letos + + + + Range... + Rozsah... + + + + Received with + Přijato + + + + Sent to + Posláno + + + + To yourself + Sám sobě + + + + Mined + Vytěženo + + + + Other + Ostatní + + + + Enter address or label to search + Zadej adresu nebo označení pro její vyhledání + + + + Min amount + Minimální částka + + + + Copy address + Kopíruj adresu + + + + Copy label + Kopíruj její označení + + + + Copy amount + Kopíruj částku + + + + Copy transaction ID + Kopíruj ID transakce + + + + Edit label + Uprav označení + + + + Show transaction details + Zobraz detaily transakce + + + + Export Transaction Data + + + + + Comma separated file (*.csv) + CSV formát (*.csv) + + + + Confirmed + Potvrzeno + + + + Date + Datum + + + + Type + Typ + + + + Label + Označení + + + + Address + Adresa + + + + Amount + Částka + + + + ID + ID + + + + Error exporting + + + + + Could not write to file %1. + + + + + Range: + Rozsah: + + + + to + + + + + WalletModel + + + Sending... + + + + + bitcoin-core + + + Arepacoin version + + + + + Usage: + Užití: + + + + Send command to -server or arepacoind + + + + + List commands + Výpis příkazů + + + + Get help for a command + Získat nápovědu pro příkaz + + + + Options: + Možnosti: + + + + Specify configuration file (default: arepacoin.conf) + + + + + Specify pid file (default: arepacoind.pid) + + + + + Specify wallet file (within data directory) + Udej název souboru s peněženkou (v rámci datového adresáře) + + + + Specify data directory + Adresář pro data + + + + Set database cache size in megabytes (default: 25) + Nastavit velikost databázové vyrovnávací paměti v megabajtech (výchozí: 25) + + + + Set database disk log size in megabytes (default: 100) + + + + + Listen for connections on <port> (default: 9853 or testnet: 19853) + + + + + Maintain at most <n> connections to peers (default: 125) + Povolit nejvýše <n> připojení k uzlům (výchozí: 125) + + + + Connect to a node to retrieve peer addresses, and disconnect + Připojit se k uzlu, získat adresy jeho protějšků a odpojit se + + + + Specify your own public address + Specifikuj svou veřejnou adresu + + + + Bind to given address. Use [host]:port notation for IPv6 + + + + + Stake your coins to support network and gain reward (default: 1) + + + + + Threshold for disconnecting misbehaving peers (default: 100) + Práh pro odpojování zlobivých uzlů (výchozí: 100) + + + + Number of seconds to keep misbehaving peers from reconnecting (default: 86400) + Doba ve vteřinách, po kterou se nebudou moci zlobivé uzly znovu připojit (výchozí: 86400) + + + + An error occurred while setting up the RPC port %u for listening on IPv4: %s + Při nastavování naslouchacího RPC portu %i pro IPv4 nastala chyba: %s + + + + Detach block and address databases. Increases shutdown time (default: 0) + + + + + 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. + + + + + Error: This transaction requires a transaction fee of at least %s because of its amount, complexity, or use of recently received funds + + + + + Listen for JSON-RPC connections on <port> (default: 9852 or testnet: 19852) + + + + + Accept command line and JSON-RPC commands + Akceptovat příkazy z příkazové řádky a přes JSON-RPC + + + + Error: Transaction creation failed + + + + + Error: Wallet locked, unable to create transaction + + + + + Importing blockchain data file. + + + + + Importing bootstrap blockchain data file. + + + + + Run in the background as a daemon and accept commands + Běžet na pozadí jako démon a akceptovat příkazy + + + + Use the test network + Použít testovací síť (testnet) + + + + Accept connections from outside (default: 1 if no -proxy or -connect) + Přijímat spojení zvenčí (výchozí: 1, pokud není zadáno -proxy nebo -connect) + + + + An error occurred while setting up the RPC port %u for listening on IPv6, falling back to IPv4: %s + Při nastavování naslouchacího RPC portu %u pro IPv6 nastala chyba, vracím se k IPv4: %s + + + + Error initializing database environment %s! To recover, BACKUP THAT DIRECTORY, then remove everything from it except for wallet.dat. + + + + + Set maximum size of high-priority/low-fee transactions in bytes (default: 27000) + + + + + Warning: -paytxfee is set very high! This is the transaction fee you will pay if you send a transaction. + Upozornění: -paytxfee je nastaveno velmi vysoko! Toto je transakční poplatek, který zaplatíš za každou poslanou transakci. + + + + Warning: Please check that your computer's date and time are correct! If your clock is wrong Arepacoin will not work properly. + + + + + Warning: error reading wallet.dat! All keys read correctly, but transaction data or address book entries might be missing or incorrect. + Upozornění: nastala chyba při čtení souboru wallet.dat! Všechny klíče se přečetly správně, ale data o transakcích nebo záznamy v adresáři mohou chybět či být nesprávné. + + + + Warning: wallet.dat corrupt, data salvaged! Original wallet.dat saved as wallet.{timestamp}.bak in %s; if your balance or transactions are incorrect you should restore from a backup. + Upozornění: soubor wallet.dat je poškozený, data jsou však zachráněna! Původní soubor wallet.dat je uložený jako wallet.{timestamp}.bak v %s. Pokud je stav tvého účtu nebo transakce nesprávné, zřejmě bys měl obnovit zálohu. + + + + Attempt to recover private keys from a corrupt wallet.dat + Pokusit se zachránit soukromé klíče z poškozeného souboru wallet.dat + + + + Block creation options: + Možnosti vytvoření bloku: + + + + Connect only to the specified node(s) + Připojit se pouze k zadanému uzlu (příp. zadaným uzlům) + + + + Discover own IP address (default: 1 when listening and no -externalip) + Zjistit vlastní IP adresu (výchozí: 1, pokud naslouchá a není zadáno -externalip) + + + + Failed to listen on any port. Use -listen=0 if you want this. + Nepodařilo se naslouchat na žádném portu. Použij -listen=0, pokud to byl tvůj záměr. + + + + Find peers using DNS lookup (default: 1) + + + + + Sync checkpoints policy (default: strict) + + + + + Invalid -tor address: '%s' + + + + + Invalid amount for -reservebalance=<amount> + + + + + Maximum per-connection receive buffer, <n>*1000 bytes (default: 5000) + Maximální velikost přijímacího bufferu pro každé spojení, <n>*1000 bajtů (výchozí: 5000) + + + + Maximum per-connection send buffer, <n>*1000 bytes (default: 1000) + Maximální velikost odesílacího bufferu pro každé spojení, <n>*1000 bajtů (výchozí: 1000) + + + + Only connect to nodes in network <net> (IPv4, IPv6 or Tor) + Připojit se pouze k uzlům v <net> síti (IPv4, IPv6 nebo Tor) + + + + Output extra debugging information. Implies all other -debug* options + + + + + Output extra network debugging information + + + + + Prepend debug output with timestamp + + + + + SSL options: (see the Bitcoin Wiki for SSL setup instructions) + Možnosti SSL: (viz instrukce nastavení SSL v Bitcoin Wiki) + + + + Select the version of socks proxy to use (4-5, default: 5) + + + + + Send trace/debug info to console instead of debug.log file + Posílat stopovací/ladicí informace do konzole místo do souboru debug.log + + + + Send trace/debug info to debugger + + + + + Set maximum block size in bytes (default: 250000) + + + + + Set minimum block size in bytes (default: 0) + Nastavit minimální velikost bloku v bajtech (výchozí: 0) + + + + Shrink debug.log file on client startup (default: 1 when no -debug) + Při spuštění klienta zmenšit soubor debug.log (výchozí: 1, pokud není zadáno -debug) + + + + Specify connection timeout in milliseconds (default: 5000) + Zadej časový limit spojení v milisekundách (výchozí: 5000) + + + + Unable to sign checkpoint, wrong checkpointkey? + + + + + + Use UPnP to map the listening port (default: 0) + Použít UPnP k namapování naslouchacího portu (výchozí: 0) + + + + Use UPnP to map the listening port (default: 1 when listening) + Použít UPnP k namapování naslouchacího portu (výchozí: 1, pokud naslouchá) + + + + Use proxy to reach tor hidden services (default: same as -proxy) + + + + + Username for JSON-RPC connections + Uživatelské jméno pro JSON-RPC spojení + + + + Verifying database integrity... + + + + + WARNING: syncronized checkpoint violation detected, but skipped! + + + + + Warning: Disk space is low! + + + + + Warning: This version is obsolete, upgrade required! + Upozornění: tahle verze je zastaralá, měl bys ji aktualizovat! + + + + wallet.dat corrupt, salvage failed + Soubor wallet.dat je poškozen, jeho záchrana se nezdařila + + + + Password for JSON-RPC connections + Heslo pro JSON-RPC spojení + + + + %s, you must set a rpcpassword in the configuration file: + %s +It is recommended you use the following random password: +rpcuser=arepacoinrpc +rpcpassword=%s +(you do not need to remember this password) +The username and password MUST NOT be the same. +If the file does not exist, create it with owner-readable-only file permissions. +It is also recommended to set alertnotify so you are notified of problems; +for example: alertnotify=echo %%s | mail -s "Arepacoin Alert" admin@foo.com + + + + + + Find peers using internet relay chat (default: 0) + + + + + Sync time with other nodes. Disable if time on your system is precise e.g. syncing with NTP (default: 1) + + + + + When creating transactions, ignore inputs with value less than this (default: 0.01) + + + + + Allow JSON-RPC connections from specified IP address + Povolit JSON-RPC spojení ze specifikované IP adresy + + + + Send commands to node running on <ip> (default: 127.0.0.1) + Posílat příkazy uzlu běžícím na <ip> (výchozí: 127.0.0.1) + + + + Execute command when the best block changes (%s in cmd is replaced by block hash) + Spustit příkaz, když se změní nejlepší blok (%s se v příkazu nahradí hashem bloku) + + + + Execute command when a wallet transaction changes (%s in cmd is replaced by TxID) + Spustit příkaz, když se objeví transakce týkající se peněženky (%s se v příkazu nahradí za TxID) + + + + Require a confirmations for change (default: 0) + + + + + Enforce transaction scripts to use canonical PUSH operators (default: 1) + + + + + Execute command when a relevant alert is received (%s in cmd is replaced by message) + + + + + Upgrade wallet to latest format + Převést peněženku na nejnovější formát + + + + Set key pool size to <n> (default: 100) + Nastavit zásobník klíčů na velikost <n> (výchozí: 100) + + + + Rescan the block chain for missing wallet transactions + Přeskenovat řetězec bloků na chybějící transakce tvé pěněženky + + + + How many blocks to check at startup (default: 2500, 0 = all) + + + + + How thorough the block verification is (0-6, default: 1) + + + + + Imports blocks from external blk000?.dat file + + + + + Use OpenSSL (https) for JSON-RPC connections + Použít OpenSSL (https) pro JSON-RPC spojení + + + + Server certificate file (default: server.cert) + Soubor se serverovým certifikátem (výchozí: server.cert) + + + + Server private key (default: server.pem) + Soubor se serverovým soukromým klíčem (výchozí: server.pem) + + + + Acceptable ciphers (default: TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH) + + + + + Error: Wallet unlocked for staking only, unable to create transaction. + + + + + WARNING: Invalid checkpoint found! Displayed transactions may not be correct! You may need to upgrade, or notify developers. + + + + + This help message + Tato nápověda + + + + Wallet %s resides outside data directory %s. + + + + + Cannot obtain a lock on data directory %s. Arepacoin is probably already running. + + + + + Arepacoin + + + + + Unable to bind to %s on this computer (bind returned error %d, %s) + Nedaří se mi připojit na %s na tomhle počítači (operace bind vrátila chybu %d, %s) + + + + Connect through socks proxy + + + + + Allow DNS lookups for -addnode, -seednode and -connect + Povolit DNS dotazy pro -addnode (přidání uzlu), -seednode a -connect (připojení) + + + + Loading addresses... + Načítám adresy... + + + + Error loading blkindex.dat + + + + + Error loading wallet.dat: Wallet corrupted + Chyba při načítání wallet.dat: peněženka je poškozená + + + + Error loading wallet.dat: Wallet requires newer version of Arepacoin + + + + + Wallet needed to be rewritten: restart Arepacoin to complete + + + + + Error loading wallet.dat + Chyba při načítání wallet.dat + + + + Invalid -proxy address: '%s' + Neplatná -proxy adresa: '%s' + + + + Unknown network specified in -onlynet: '%s' + V -onlynet byla uvedena neznámá síť: '%s' + + + + Unknown -socks proxy version requested: %i + V -socks byla požadována neznámá verze proxy: %i + + + + Cannot resolve -bind address: '%s' + Nemohu přeložit -bind adresu: '%s' + + + + Cannot resolve -externalip address: '%s' + Nemohu přeložit -externalip adresu: '%s' + + + + Invalid amount for -paytxfee=<amount>: '%s' + Neplatná částka pro -paytxfee=<částka>: '%s' + + + + Error: could not start node + + + + + Sending... + + + + + Invalid amount + Neplatná částka + + + + Insufficient funds + Nedostatek prostředků + + + + Loading block index... + Načítám index bloků... + + + + Add a node to connect to and attempt to keep the connection open + Přidat uzel, ke kterému se připojit a snažit se spojení udržet + + + + Unable to bind to %s on this computer. Arepacoin is probably already running. + + + + + Fee per KB to add to transactions you send + + + + + Invalid amount for -mininput=<amount>: '%s' + + + + + Loading wallet... + Načítám peněženku... + + + + Cannot downgrade wallet + Nemohu převést peněženku do staršího formátu + + + + Cannot initialize keypool + + + + + Cannot write default address + Nemohu napsat výchozí adresu + + + + Rescanning... + Přeskenovávám... + + + + Done loading + Načítání dokončeno + + + + To use the %s option + K použití volby %s + + + + Error + Chyba + + + + You must set rpcpassword=<password> in the configuration file: +%s +If the file does not exist, create it with owner-readable-only file permissions. + Musíš nastavit rpcpassword=<heslo> v konfiguračním souboru: +%s +Pokud konfigurační soubor ještě neexistuje, vytvoř ho tak, aby ho mohl číst pouze vlastník. + + + \ No newline at end of file diff --git a/src/qt/locale/bitcoin_cy.ts b/src/qt/locale/bitcoin_cy.ts new file mode 100755 index 0000000..ab7bbed --- /dev/null +++ b/src/qt/locale/bitcoin_cy.ts @@ -0,0 +1,3275 @@ + + + AboutDialog + + + About Arepacoin + + + + + <b>Arepacoin</b> version + + + + + Copyright © 2009-2014 The Bitcoin developers +Copyright © 2012-2014 The NovaCoin developers +Copyright © 2014 The Arepacoin developers + + + + + +This is experimental software. + +Distributed under the MIT/X11 software license, see the accompanying file COPYING or http://www.opensource.org/licenses/mit-license.php. + +This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit (http://www.openssl.org/) and cryptographic software written by Eric Young (eay@cryptsoft.com) and UPnP software written by Thomas Bernard. + + + + + AddressBookPage + + + Address Book + + + + + Double-click to edit address or label + Clicio dwywaith i olygu cyfeiriad neu label + + + + Create a new address + Creu cyfeiriad newydd + + + + Copy the currently selected address to the system clipboard + Copio'r cyfeiriad sydd wedi'i ddewis i'r clipfwrdd system + + + + &New Address + + + + + These are your Arepacoin addresses for receiving payments. You may want to give a different one to each sender so you can keep track of who is paying you. + + + + + &Copy Address + + + + + Show &QR Code + + + + + Sign a message to prove you own a Arepacoin address + + + + + Sign &Message + + + + + Delete the currently selected address from the list + + + + + Verify a message to ensure it was signed with a specified Arepacoin address + + + + + &Verify Message + + + + + &Delete + &Dileu + + + + Copy &Label + + + + + &Edit + + + + + Export Address Book Data + + + + + Comma separated file (*.csv) + + + + + Error exporting + + + + + Could not write to file %1. + + + + + AddressTableModel + + + Label + Label + + + + Address + Cyfeiriad + + + + (no label) + (heb label) + + + + AskPassphraseDialog + + + Passphrase Dialog + + + + + Enter passphrase + Teipiwch gyfrinymadrodd + + + + New passphrase + Cyfrinymadrodd newydd + + + + Repeat new passphrase + Ailadroddwch gyfrinymadrodd newydd + + + + Serves to disable the trivial sendmoney when OS account compromised. Provides no real security. + + + + + For staking only + + + + + Enter the new passphrase to the wallet.<br/>Please use a passphrase of <b>10 or more random characters</b>, or <b>eight or more words</b>. + Dewiswch gyfrinymadrodd newydd ar gyfer y waled. <br/> Defnyddiwch cyfrinymadrodd o <b>10 neu fwy o lythyrennau hapgyrch</b>, neu <b> wyth neu fwy o eiriau. + + + + Encrypt wallet + Amgryptio'r waled + + + + This operation needs your wallet passphrase to unlock the wallet. + Mae angen i'r gweithred hon ddefnyddio'ch cyfrinymadrodd er mwyn datgloi'r waled. + + + + Unlock wallet + Datgloi'r waled + + + + This operation needs your wallet passphrase to decrypt the wallet. + Mae angen i'r gweithred hon ddefnyddio'ch cyfrinymadrodd er mwyn dadgryptio'r waled. + + + + Decrypt wallet + Dadgryptio'r waled + + + + Change passphrase + Newid cyfrinymadrodd + + + + Enter the old and new passphrase to the wallet. + Teipiwch yr hen cyfrinymadrodd a chyfrinymadrodd newydd i mewn i'r waled. + + + + Confirm wallet encryption + Cadarnau amgryptiad y waled + + + + Warning: If you encrypt your wallet and lose your passphrase, you will <b>LOSE ALL OF YOUR COINS</b>! + + + + + Are you sure you wish to encrypt your wallet? + + + + + IMPORTANT: Any previous backups you have made of your wallet file should be replaced with the newly generated, encrypted wallet file. For security reasons, previous backups of the unencrypted wallet file will become useless as soon as you start using the new, encrypted wallet. + + + + + + Warning: The Caps Lock key is on! + + + + + + Wallet encrypted + Waled wedi'i amgryptio + + + + Arepacoin will close now to finish the encryption process. Remember that encrypting your wallet cannot fully protect your coins from being stolen by malware infecting your computer. + + + + + + + + Wallet encryption failed + Amgryptiad waled wedi methu + + + + Wallet encryption failed due to an internal error. Your wallet was not encrypted. + Methodd amgryptiad y waled oherwydd gwall mewnol. Ni amgryptwyd eich waled. + + + + + The supplied passphrases do not match. + Dydy'r cyfrinymadroddion a ddarparwyd ddim yn cyd-fynd â'u gilydd. + + + + Wallet unlock failed + Methodd ddatgloi'r waled + + + + + + The passphrase entered for the wallet decryption was incorrect. + + + + + Wallet decryption failed + Methodd dadgryptiad y waled + + + + Wallet passphrase was successfully changed. + + + + + BitcoinGUI + + + Sign &message... + + + + + Synchronizing with network... + Cysoni â'r rhwydwaith... + + + + &Overview + &Trosolwg + + + + Show general overview of wallet + Dangos trosolwg cyffredinol y waled + + + + &Transactions + &Trafodion + + + + Browse transaction history + Pori hanes trafodion + + + + &Address Book + + + + + Edit the list of stored addresses and labels + + + + + &Receive coins + + + + + Show the list of addresses for receiving payments + + + + + &Send coins + + + + + E&xit + + + + + Quit application + Gadael rhaglen + + + + Show information about Arepacoin + + + + + About &Qt + + + + + Show information about Qt + + + + + &Options... + &Opsiynau + + + + &Encrypt Wallet... + + + + + &Backup Wallet... + + + + + &Change Passphrase... + + + + + ~%n block(s) remaining + + + + + Downloaded %1 of %2 blocks of transaction history (%3% done). + + + + + &Export... + + + + + Send coins to a Arepacoin address + + + + + Modify configuration options for Arepacoin + + + + + Export the data in the current tab to a file + + + + + Encrypt or decrypt wallet + + + + + Backup wallet to another location + + + + + Change the passphrase used for wallet encryption + Newid y cyfrinymadrodd a ddefnyddiwyd ar gyfer amgryptio'r waled + + + + &Debug window + + + + + Open debugging and diagnostic console + + + + + &Verify message... + + + + + Arepacoin + + + + + Wallet + + + + + &About Arepacoin + + + + + &Show / Hide + + + + + Unlock wallet + + + + + &Lock Wallet + + + + + Lock wallet + + + + + &File + &Ffeil + + + + &Settings + &Gosodiadau + + + + &Help + &Cymorth + + + + Tabs toolbar + Bar offer tabiau + + + + Actions toolbar + + + + + + [testnet] + [testnet] + + + + + Arepacoin client + + + + + %n active connection(s) to Arepacoin network + + + + + Downloaded %1 blocks of transaction history. + + + + + Staking.<br>Your weight is %1<br>Network weight is %2<br>Expected time to earn reward is %3 + + + + + Not staking because wallet is locked + + + + + Not staking because wallet is offline + + + + + Not staking because wallet is syncing + + + + + Not staking because you don't have mature coins + + + + + %n second(s) ago + + + + + &Unlock Wallet... + + + + + %n minute(s) ago + + + + + %n hour(s) ago + + + + + %n day(s) ago + + + + + Up to date + Cyfamserol + + + + Catching up... + Dal i fyny + + + + Last received block was generated %1. + + + + + This transaction is over the size limit. You can still send it for a fee of %1, which goes to the nodes that process your transaction and helps to support the network. Do you want to pay the fee? + + + + + Confirm transaction fee + + + + + Sent transaction + Trafodiad a anfonwyd + + + + Incoming transaction + Trafodiad sy'n cyrraedd + + + + Date: %1 +Amount: %2 +Type: %3 +Address: %4 + + + + + + + URI handling + + + + + + URI can not be parsed! This can be caused by an invalid Arepacoin address or malformed URI parameters. + + + + + Wallet is <b>encrypted</b> and currently <b>unlocked</b> + Mae'r waled <b>wedi'i amgryptio</b> ac <b>heb ei gloi</b> ar hyn o bryd + + + + Wallet is <b>encrypted</b> and currently <b>locked</b> + Mae'r waled <b>wedi'i amgryptio</b> ac <b>ar glo</b> ar hyn o bryd + + + + Backup Wallet + + + + + Wallet Data (*.dat) + + + + + Backup Failed + + + + + There was an error trying to save the wallet data to the new location. + + + + + %n second(s) + + + + + %n minute(s) + + + + + %n hour(s) + + + + + %n day(s) + + + + + Not staking + + + + + A fatal error occurred. Arepacoin can no longer continue safely and will quit. + + + + + ClientModel + + + Network Alert + + + + + CoinControlDialog + + + Coin Control + + + + + Quantity: + + + + + Bytes: + + + + + Amount: + + + + + Priority: + + + + + Fee: + + + + + Low Output: + + + + + no + + + + + After Fee: + + + + + Change: + + + + + (un)select all + + + + + Tree mode + + + + + List mode + + + + + Amount + + + + + Label + + + + + Address + Cyfeiriad + + + + Date + Dyddiad + + + + Confirmations + + + + + Confirmed + + + + + Priority + + + + + Copy address + + + + + Copy label + + + + + + Copy amount + + + + + Copy transaction ID + + + + + Copy quantity + + + + + Copy fee + + + + + Copy after fee + + + + + Copy bytes + + + + + Copy priority + + + + + Copy low output + + + + + Copy change + + + + + highest + + + + + high + + + + + medium-high + + + + + medium + + + + + low-medium + + + + + low + + + + + lowest + + + + + DUST + + + + + yes + + + + + This label turns red, if the transaction size is bigger than 10000 bytes. + + This means a fee of at least %1 per kb is required. + + Can vary +/- 1 Byte per input. + + + + + Transactions with higher priority get more likely into a block. + +This label turns red, if the priority is smaller than "medium". + + This means a fee of at least %1 per kb is required. + + + + + This label turns red, if any recipient receives an amount smaller than %1. + + This means a fee of at least %2 is required. + + Amounts below 0.546 times the minimum relay fee are shown as DUST. + + + + + This label turns red, if the change is smaller than %1. + + This means a fee of at least %2 is required. + + + + + + (no label) + (heb label) + + + + change from %1 (%2) + + + + + (change) + + + + + EditAddressDialog + + + Edit Address + Golygu'r cyfeiriad + + + + &Label + &Label + + + + The label associated with this address book entry + + + + + &Address + &Cyfeiriad + + + + The address associated with this address book entry. This can only be modified for sending addresses. + + + + + New receiving address + Cyfeiriad derbyn newydd + + + + New sending address + Cyfeiriad anfon newydd + + + + Edit receiving address + Golygu'r cyfeiriad derbyn + + + + Edit sending address + Golygu'r cyfeiriad anfon + + + + The entered address "%1" is already in the address book. + Mae'r cyfeiriad "%1" sydd newydd gael ei geisio gennych yn y llyfr cyfeiriad yn barod. + + + + The entered address "%1" is not a valid Arepacoin address. + + + + + Could not unlock wallet. + Methodd ddatgloi'r waled. + + + + New key generation failed. + Methodd gynhyrchu allwedd newydd. + + + + GUIUtil::HelpMessageBox + + + + Arepacoin-Qt + + + + + version + + + + + Usage: + + + + + command-line options + + + + + UI options + + + + + Set language, for example "de_DE" (default: system locale) + + + + + Start minimized + + + + + Show splash screen on startup (default: 1) + + + + + OptionsDialog + + + Options + Opsiynau + + + + &Main + + + + + Optional transaction fee per kB that helps make sure your transactions are processed quickly. Most transactions are 1 kB. Fee 0.01 recommended. + + + + + Pay transaction &fee + + + + + Reserved amount does not participate in staking and is therefore spendable at any time. + + + + + Reserve + + + + + Automatically start Arepacoin after logging in to the system. + + + + + &Start Arepacoin on system login + + + + + Detach block and address databases at shutdown. This means they can be moved to another data directory, but it slows down shutdown. The wallet is always detached. + + + + + &Detach databases at shutdown + + + + + &Network + + + + + Automatically open the Arepacoin client port on the router. This only works when your router supports UPnP and it is enabled. + + + + + Map port using &UPnP + + + + + Connect to the Arepacoin network through a SOCKS proxy (e.g. when connecting through Tor). + + + + + &Connect through SOCKS proxy: + + + + + Proxy &IP: + + + + + IP address of the proxy (e.g. 127.0.0.1) + + + + + &Port: + + + + + Port of the proxy (e.g. 9050) + + + + + SOCKS &Version: + + + + + SOCKS version of the proxy (e.g. 5) + + + + + &Window + + + + + Show only a tray icon after minimizing the window. + + + + + &Minimize to the tray instead of the taskbar + + + + + Minimize instead of exit the application when the window is closed. When this option is enabled, the application will be closed only after selecting Quit in the menu. + + + + + M&inimize on close + + + + + &Display + + + + + User Interface &language: + + + + + The user interface language can be set here. This setting will take effect after restarting Arepacoin. + + + + + &Unit to show amounts in: + + + + + Choose the default subdivision unit to show in the interface and when sending coins. + + + + + Whether to show Arepacoin addresses in the transaction list or not. + + + + + &Display addresses in transaction list + + + + + Whether to show coin control features or not. + + + + + Display coin &control features (experts only!) + + + + + &OK + + + + + &Cancel + + + + + &Apply + + + + + default + + + + + + Warning + + + + + + This setting will take effect after restarting Arepacoin. + + + + + The supplied proxy address is invalid. + + + + + OverviewPage + + + Form + Ffurflen + + + + + The displayed information may be out of date. Your wallet automatically synchronizes with the Arepacoin network after a connection is established, but this process has not completed yet. + + + + + Stake: + + + + + Unconfirmed: + + + + + Wallet + + + + + Spendable: + + + + + Your current spendable balance + + + + + Immature: + + + + + Mined balance that has not yet matured + + + + + Total: + + + + + Your current total balance + + + + + <b>Recent transactions</b> + <b>Trafodion diweddar</b> + + + + Total of transactions that have yet to be confirmed, and do not yet count toward the current balance + + + + + Total of coins that was staked, and do not yet count toward the current balance + + + + + + out of sync + + + + + QRCodeDialog + + + QR Code Dialog + + + + + Request Payment + + + + + Amount: + + + + + Label: + + + + + Message: + + + + + &Save As... + + + + + Error encoding URI into QR Code. + + + + + The entered amount is invalid, please check. + + + + + Resulting URI too long, try to reduce the text for label / message. + + + + + Save QR Code + + + + + PNG Images (*.png) + + + + + RPCConsole + + + Client name + + + + + + + + + + + + + + N/A + + + + + Client version + + + + + &Information + + + + + Using OpenSSL version + + + + + Startup time + + + + + Network + + + + + Number of connections + + + + + On testnet + + + + + Block chain + + + + + Current number of blocks + + + + + Estimated total blocks + + + + + Last block time + + + + + &Open + + + + + Command-line options + + + + + Show the Arepacoin-Qt help message to get a list with possible Arepacoin command-line options. + + + + + &Show + + + + + &Console + + + + + Build date + + + + + Arepacoin - Debug window + + + + + Arepacoin Core + + + + + Debug log file + + + + + Open the Arepacoin debug log file from the current data directory. This can take a few seconds for large log files. + + + + + Clear console + + + + + Welcome to the Arepacoin RPC console. + + + + + Use up and down arrows to navigate history, and <b>Ctrl-L</b> to clear screen. + + + + + Type <b>help</b> for an overview of available commands. + + + + + SendCoinsDialog + + + + + + + + + + Send Coins + Anfon arian + + + + Coin Control Features + + + + + Inputs... + + + + + automatically selected + + + + + Insufficient funds! + + + + + Quantity: + + + + + + 0 + + + + + Bytes: + + + + + Amount: + + + + + + + + 0.00 BC + + + + + Priority: + + + + + medium + + + + + Fee: + + + + + Low Output: + + + + + no + + + + + After Fee: + + + + + Change + + + + + custom change address + + + + + Send to multiple recipients at once + Anfon at pobl lluosog ar yr un pryd + + + + Add &Recipient + + + + + Remove all transaction fields + + + + + Clear &All + + + + + Balance: + Gweddill: + + + + 123.456 BC + + + + + Confirm the send action + Cadarnhau'r gweithrediad anfon + + + + S&end + + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Copy quantity + + + + + Copy amount + + + + + Copy fee + + + + + Copy after fee + + + + + Copy bytes + + + + + Copy priority + + + + + Copy low output + + + + + Copy change + + + + + <b>%1</b> to %2 (%3) + + + + + Confirm send coins + + + + + Are you sure you want to send %1? + + + + + and + + + + + The recipient address is not valid, please recheck. + + + + + The amount to pay must be larger than 0. + + + + + The amount exceeds your balance. + + + + + The total exceeds your balance when the %1 transaction fee is included. + + + + + Duplicate address found, can only send to each address once per send operation. + + + + + Error: Transaction creation failed. + + + + + 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. + + + + + WARNING: Invalid Arepacoin address + + + + + (no label) + (heb label) + + + + WARNING: unknown change address + + + + + SendCoinsEntry + + + Form + + + + + A&mount: + &Maint + + + + Pay &To: + + + + + + Enter a label for this address to add it to your address book + + + + + &Label: + &Label: + + + + The address to send the payment to (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Choose address from address book + + + + + Alt+A + Alt+A + + + + Paste address from clipboard + Gludo cyfeiriad o'r glipfwrdd + + + + Alt+P + Alt+P + + + + Remove this recipient + + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + SignVerifyMessageDialog + + + Signatures - Sign / Verify a Message + + + + + + &Sign Message + + + + + You can sign messages with your addresses to prove you own them. Be careful not to sign anything vague, as phishing attacks may try to trick you into signing your identity over to them. Only sign fully-detailed statements you agree to. + + + + + The address to sign the message with (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + + Choose an address from the address book + + + + + + Alt+A + Alt+A + + + + Paste address from clipboard + Gludo cyfeiriad o'r glipfwrdd + + + + Alt+P + Alt+P + + + + Enter the message you want to sign here + + + + + Copy the current signature to the system clipboard + + + + + Sign the message to prove you own this Arepacoin address + + + + + Reset all sign message fields + + + + + + Clear &All + + + + + + &Verify Message + + + + + Enter the signing address, message (ensure you copy line breaks, spaces, tabs, etc. exactly) and signature below to verify the message. Be careful not to read more into the signature than what is in the signed message itself, to avoid being tricked by a man-in-the-middle attack. + + + + + The address the message was signed with (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Verify the message to ensure it was signed with the specified Arepacoin address + + + + + Reset all verify message fields + + + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Click "Sign Message" to generate signature + + + + + Enter Arepacoin signature + + + + + + The entered address is invalid. + + + + + + + + Please check the address and try again. + + + + + + The entered address does not refer to a key. + + + + + Wallet unlock was cancelled. + + + + + Private key for the entered address is not available. + + + + + Message signing failed. + + + + + Message signed. + + + + + The signature could not be decoded. + + + + + + Please check the signature and try again. + + + + + The signature did not match the message digest. + + + + + Message verification failed. + + + + + Message verified. + + + + + TransactionDesc + + + Open until %1 + Agor tan %1 + + + + Open for %n block(s) + + + + + conflicted + + + + + %1/offline + + + + + %1/unconfirmed + + + + + %1 confirmations + + + + + Status + + + + + , broadcast through %n node(s) + + + + + Date + Dyddiad + + + + Source + + + + + Generated + + + + + + From + + + + + + + To + + + + + + own address + + + + + label + + + + + + + + + Credit + + + + + matures in %n more block(s) + + + + + not accepted + + + + + + + + Debit + + + + + Transaction fee + + + + + Net amount + + + + + Message + Neges + + + + Comment + + + + + Transaction ID + + + + + Generated coins must mature 6 blocks before they can be spent. When you generated this block, it was broadcast to the network to be added to the block chain. If it fails to get into the chain, its state will change to "not accepted" and it won't be spendable. This may occasionally happen if another node generates a block within a few seconds of yours. + + + + + Debug information + + + + + Transaction + + + + + Inputs + + + + + Amount + + + + + true + + + + + false + + + + + , has not been successfully broadcast yet + + + + + unknown + + + + + TransactionDescDialog + + + Transaction details + + + + + This pane shows a detailed description of the transaction + + + + + TransactionTableModel + + + Date + Dyddiad + + + + Type + Math + + + + Address + Cyfeiriad + + + + Amount + + + + + Open until %1 + Agor tan %1 + + + + Confirmed (%1 confirmations) + + + + + Open for %n more block(s) + + + + + Offline + + + + + Unconfirmed + + + + + Confirming (%1 of %2 recommended confirmations) + + + + + Conflicted + + + + + Immature (%1 confirmations, will be available after %2) + + + + + This block was not received by any other nodes and will probably not be accepted! + + + + + Generated but not accepted + + + + + Received with + + + + + Received from + + + + + Sent to + + + + + Payment to yourself + + + + + Mined + + + + + (n/a) + + + + + Transaction status. Hover over this field to show number of confirmations. + + + + + Date and time that the transaction was received. + + + + + Type of transaction. + + + + + Destination address of transaction. + + + + + Amount removed from or added to balance. + + + + + TransactionView + + + + All + + + + + Today + Heddiw + + + + This week + + + + + This month + + + + + Last month + + + + + This year + Eleni + + + + Range... + + + + + Received with + + + + + Sent to + + + + + To yourself + + + + + Mined + + + + + Other + + + + + Enter address or label to search + + + + + Min amount + + + + + Copy address + + + + + Copy label + + + + + Copy amount + + + + + Copy transaction ID + + + + + Edit label + + + + + Show transaction details + + + + + Export Transaction Data + + + + + Comma separated file (*.csv) + + + + + Confirmed + + + + + Date + Dyddiad + + + + Type + Math + + + + Label + Label + + + + Address + Cyfeiriad + + + + Amount + + + + + ID + + + + + Error exporting + + + + + Could not write to file %1. + + + + + Range: + + + + + to + + + + + WalletModel + + + Sending... + + + + + bitcoin-core + + + Arepacoin version + + + + + Usage: + + + + + Send command to -server or arepacoind + + + + + List commands + + + + + Get help for a command + + + + + Options: + + + + + Specify configuration file (default: arepacoin.conf) + + + + + Specify pid file (default: arepacoind.pid) + + + + + Specify wallet file (within data directory) + + + + + Specify data directory + + + + + Set database cache size in megabytes (default: 25) + + + + + Set database disk log size in megabytes (default: 100) + + + + + Listen for connections on <port> (default: 9853 or testnet: 19853) + + + + + Maintain at most <n> connections to peers (default: 125) + + + + + Connect to a node to retrieve peer addresses, and disconnect + + + + + Specify your own public address + + + + + Bind to given address. Use [host]:port notation for IPv6 + + + + + Stake your coins to support network and gain reward (default: 1) + + + + + Threshold for disconnecting misbehaving peers (default: 100) + + + + + Number of seconds to keep misbehaving peers from reconnecting (default: 86400) + + + + + An error occurred while setting up the RPC port %u for listening on IPv4: %s + + + + + Detach block and address databases. Increases shutdown time (default: 0) + + + + + 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. + + + + + Error: This transaction requires a transaction fee of at least %s because of its amount, complexity, or use of recently received funds + + + + + Listen for JSON-RPC connections on <port> (default: 9852 or testnet: 19852) + + + + + Accept command line and JSON-RPC commands + + + + + Error: Transaction creation failed + + + + + Error: Wallet locked, unable to create transaction + + + + + Importing blockchain data file. + + + + + Importing bootstrap blockchain data file. + + + + + Run in the background as a daemon and accept commands + + + + + Use the test network + + + + + Accept connections from outside (default: 1 if no -proxy or -connect) + + + + + An error occurred while setting up the RPC port %u for listening on IPv6, falling back to IPv4: %s + + + + + Error initializing database environment %s! To recover, BACKUP THAT DIRECTORY, then remove everything from it except for wallet.dat. + + + + + Set maximum size of high-priority/low-fee transactions in bytes (default: 27000) + + + + + Warning: -paytxfee is set very high! This is the transaction fee you will pay if you send a transaction. + + + + + Warning: Please check that your computer's date and time are correct! If your clock is wrong Arepacoin will not work properly. + + + + + Warning: error reading wallet.dat! All keys read correctly, but transaction data or address book entries might be missing or incorrect. + + + + + Warning: wallet.dat corrupt, data salvaged! Original wallet.dat saved as wallet.{timestamp}.bak in %s; if your balance or transactions are incorrect you should restore from a backup. + + + + + Attempt to recover private keys from a corrupt wallet.dat + + + + + Block creation options: + + + + + Connect only to the specified node(s) + + + + + Discover own IP address (default: 1 when listening and no -externalip) + + + + + Failed to listen on any port. Use -listen=0 if you want this. + + + + + Find peers using DNS lookup (default: 1) + + + + + Sync checkpoints policy (default: strict) + + + + + Invalid -tor address: '%s' + + + + + Invalid amount for -reservebalance=<amount> + + + + + Maximum per-connection receive buffer, <n>*1000 bytes (default: 5000) + + + + + Maximum per-connection send buffer, <n>*1000 bytes (default: 1000) + + + + + Only connect to nodes in network <net> (IPv4, IPv6 or Tor) + + + + + Output extra debugging information. Implies all other -debug* options + + + + + Output extra network debugging information + + + + + Prepend debug output with timestamp + + + + + SSL options: (see the Bitcoin Wiki for SSL setup instructions) + + + + + Select the version of socks proxy to use (4-5, default: 5) + + + + + Send trace/debug info to console instead of debug.log file + + + + + Send trace/debug info to debugger + + + + + Set maximum block size in bytes (default: 250000) + + + + + Set minimum block size in bytes (default: 0) + + + + + Shrink debug.log file on client startup (default: 1 when no -debug) + + + + + Specify connection timeout in milliseconds (default: 5000) + + + + + Unable to sign checkpoint, wrong checkpointkey? + + + + + + Use UPnP to map the listening port (default: 0) + + + + + Use UPnP to map the listening port (default: 1 when listening) + + + + + Use proxy to reach tor hidden services (default: same as -proxy) + + + + + Username for JSON-RPC connections + + + + + Verifying database integrity... + + + + + WARNING: syncronized checkpoint violation detected, but skipped! + + + + + Warning: Disk space is low! + + + + + Warning: This version is obsolete, upgrade required! + + + + + wallet.dat corrupt, salvage failed + + + + + Password for JSON-RPC connections + + + + + %s, you must set a rpcpassword in the configuration file: + %s +It is recommended you use the following random password: +rpcuser=arepacoinrpc +rpcpassword=%s +(you do not need to remember this password) +The username and password MUST NOT be the same. +If the file does not exist, create it with owner-readable-only file permissions. +It is also recommended to set alertnotify so you are notified of problems; +for example: alertnotify=echo %%s | mail -s "Arepacoin Alert" admin@foo.com + + + + + + Find peers using internet relay chat (default: 0) + + + + + Sync time with other nodes. Disable if time on your system is precise e.g. syncing with NTP (default: 1) + + + + + When creating transactions, ignore inputs with value less than this (default: 0.01) + + + + + Allow JSON-RPC connections from specified IP address + + + + + Send commands to node running on <ip> (default: 127.0.0.1) + + + + + Execute command when the best block changes (%s in cmd is replaced by block hash) + + + + + Execute command when a wallet transaction changes (%s in cmd is replaced by TxID) + + + + + Require a confirmations for change (default: 0) + + + + + Enforce transaction scripts to use canonical PUSH operators (default: 1) + + + + + Execute command when a relevant alert is received (%s in cmd is replaced by message) + + + + + Upgrade wallet to latest format + + + + + Set key pool size to <n> (default: 100) + + + + + Rescan the block chain for missing wallet transactions + + + + + How many blocks to check at startup (default: 2500, 0 = all) + + + + + How thorough the block verification is (0-6, default: 1) + + + + + Imports blocks from external blk000?.dat file + + + + + Use OpenSSL (https) for JSON-RPC connections + + + + + Server certificate file (default: server.cert) + + + + + Server private key (default: server.pem) + + + + + Acceptable ciphers (default: TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH) + + + + + Error: Wallet unlocked for staking only, unable to create transaction. + + + + + WARNING: Invalid checkpoint found! Displayed transactions may not be correct! You may need to upgrade, or notify developers. + + + + + This help message + + + + + Wallet %s resides outside data directory %s. + + + + + Cannot obtain a lock on data directory %s. Arepacoin is probably already running. + + + + + Arepacoin + + + + + Unable to bind to %s on this computer (bind returned error %d, %s) + + + + + Connect through socks proxy + + + + + Allow DNS lookups for -addnode, -seednode and -connect + + + + + Loading addresses... + + + + + Error loading blkindex.dat + + + + + Error loading wallet.dat: Wallet corrupted + + + + + Error loading wallet.dat: Wallet requires newer version of Arepacoin + + + + + Wallet needed to be rewritten: restart Arepacoin to complete + + + + + Error loading wallet.dat + + + + + Invalid -proxy address: '%s' + + + + + Unknown network specified in -onlynet: '%s' + + + + + Unknown -socks proxy version requested: %i + + + + + Cannot resolve -bind address: '%s' + + + + + Cannot resolve -externalip address: '%s' + + + + + Invalid amount for -paytxfee=<amount>: '%s' + + + + + Error: could not start node + + + + + Sending... + + + + + Invalid amount + + + + + Insufficient funds + + + + + Loading block index... + + + + + Add a node to connect to and attempt to keep the connection open + + + + + Unable to bind to %s on this computer. Arepacoin is probably already running. + + + + + Fee per KB to add to transactions you send + + + + + Invalid amount for -mininput=<amount>: '%s' + + + + + Loading wallet... + + + + + Cannot downgrade wallet + + + + + Cannot initialize keypool + + + + + Cannot write default address + + + + + Rescanning... + + + + + Done loading + + + + + To use the %s option + + + + + Error + Gwall + + + + You must set rpcpassword=<password> in the configuration file: +%s +If the file does not exist, create it with owner-readable-only file permissions. + + + + \ No newline at end of file diff --git a/src/qt/locale/bitcoin_da.ts b/src/qt/locale/bitcoin_da.ts new file mode 100755 index 0000000..1c79fd0 --- /dev/null +++ b/src/qt/locale/bitcoin_da.ts @@ -0,0 +1,3313 @@ + + + AboutDialog + + + About Arepacoin + Om Arepacoin + + + + <b>Arepacoin</b> version + <b>Arepacoin</b> version + + + + Copyright © 2009-2014 The Bitcoin developers +Copyright © 2012-2014 The NovaCoin developers +Copyright © 2014 The Arepacoin developers + Copyright © 2009-2014 The Bitcoin developers +Copyright © 2012-2014 The NovaCoin developers +Copyright © 2014 The Arepacoin developers + + + + +This is experimental software. + +Distributed under the MIT/X11 software license, see the accompanying file COPYING or http://www.opensource.org/licenses/mit-license.php. + +This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit (http://www.openssl.org/) and cryptographic software written by Eric Young (eay@cryptsoft.com) and UPnP software written by Thomas Bernard. + +Dette program er eksperimentelt. + +Det er gjort tilgængeligt under MIT/X11-softwarelicensen. Se den medfølgende fil "COPYING" eller http://www.opensource.org/licenses/mit-license.php. + +Produktet indeholder software, som er udviklet af OpenSSL Project til brug i OpenSSL Toolkit (http://www.openssl.org/). Kryptografisk software er skrevet af Eric Young (eay@cryptsoft.com), og UPnP-software er skrevet af Thomas Bernard. + + + + AddressBookPage + + + Address Book + Adressebog + + + + Double-click to edit address or label + Dobbeltklik for at redigere adresse eller mærkat + + + + Create a new address + Opret en ny adresse + + + + Copy the currently selected address to the system clipboard + Kopier den valgte adresse til udklipsholder + + + + &New Address + &Ny adresse + + + + These are your Arepacoin addresses for receiving payments. You may want to give a different one to each sender so you can keep track of who is paying you. + Dette er dine Arepacoin adresser til at modtage betalinger. Du ønsker måske at give en anden en til af hver afsender, så du kan holde styr på hvem der betaler dig. + + + + &Copy Address + &Kopier adresse + + + + Show &QR Code + Vis &QR kode + + + + Sign a message to prove you own a Arepacoin address + Signerer en meddelelse for at bevise du ejer en Arepacoin adresse + + + + Sign &Message + Signere & Besked + + + + Delete the currently selected address from the list + Slet den markerede adresse fra listen + + + + Verify a message to ensure it was signed with a specified Arepacoin address + Bekræft en meddelelse for at sikre, den blev underskrevet med en specificeret Arepacoin adresse + + + + &Verify Message + Bekræft Meddelse + + + + &Delete + &Slet + + + + Copy &Label + Kopier mærkat + + + + &Edit + Rediger + + + + Export Address Book Data + Eksporter Adresse Bog + + + + Comma separated file (*.csv) + Kommasepareret fil (*.csv) + + + + Error exporting + Fejl ved eksportering + + + + Could not write to file %1. + Kunne ikke skrive til fil% 1. + + + + AddressTableModel + + + Label + Mærkat + + + + Address + Adresse + + + + (no label) + (ingen mærkat) + + + + AskPassphraseDialog + + + Passphrase Dialog + Adgangskodedialog + + + + Enter passphrase + Indtast adgangskode + + + + New passphrase + Ny adgangskode + + + + Repeat new passphrase + Gentag ny adgangskode + + + + Serves to disable the trivial sendmoney when OS account compromised. Provides no real security. + Deaktivere trivielle sendmoney når OS konto er kompromitteret. Giver ingen reel sikkerhed. + + + + For staking only + Kun til renteberegning + + + + Enter the new passphrase to the wallet.<br/>Please use a passphrase of <b>10 or more random characters</b>, or <b>eight or more words</b>. + Indtast den nye adgangskode til tegnebogen.<br/>Brug venligst en adgangskode på <b>10 eller flere tilfældige tegn</b> eller <b>otte eller flere ord</b>. + + + + Encrypt wallet + Krypter tegnebog + + + + This operation needs your wallet passphrase to unlock the wallet. + Denne funktion har brug for din tegnebogs adgangskode for at låse tegnebogen op. + + + + Unlock wallet + Lås tegnebog op + + + + This operation needs your wallet passphrase to decrypt the wallet. + Denne funktion har brug for din tegnebogs adgangskode for at dekryptere tegnebogen. + + + + Decrypt wallet + Dekrypter tegnebog + + + + Change passphrase + Skift adgangskode + + + + Enter the old and new passphrase to the wallet. + Indtast den gamle og den nye adgangskode til tegnebogen. + + + + Confirm wallet encryption + Bekræft tegnebogskryptering + + + + Warning: If you encrypt your wallet and lose your passphrase, you will <b>LOSE ALL OF YOUR COINS</b>! + Advarsel: Hvis du krypterer din tegnebog og mister din adgangskode, vil du <b> miste alle dine mønter </ b>! + + + + Are you sure you wish to encrypt your wallet? + Er du sikker på, at du ønsker at kryptere din tegnebog? + + + + IMPORTANT: Any previous backups you have made of your wallet file should be replaced with the newly generated, encrypted wallet file. For security reasons, previous backups of the unencrypted wallet file will become useless as soon as you start using the new, encrypted wallet. + VIGTIGT: Enhver tidligere sikkerhedskopi, som du har lavet af tegnebogsfilen, bør blive erstattet af den nyligt genererede, krypterede tegnebogsfil. Af sikkerhedsmæssige årsager vil tidligere sikkerhedskopier af den ikke-krypterede tegnebogsfil blive ubrugelig i det øjeblik, du starter med at anvende den nye, krypterede tegnebog. + + + + + Warning: The Caps Lock key is on! + Advarsel: Caps Lock-tasten er aktiveret! + + + + + Wallet encrypted + Tegnebog krypteret + + + + Arepacoin will close now to finish the encryption process. Remember that encrypting your wallet cannot fully protect your coins from being stolen by malware infecting your computer. + Arepacoin lukker nu for at afslutte krypteringen. Husk at en krypteret tegnebog ikke fuldt ud beskytter dine mønter mod at blive stjålet af malware som har inficeret din computer. + + + + + + + Wallet encryption failed + Tegnebogskryptering mislykkedes + + + + Wallet encryption failed due to an internal error. Your wallet was not encrypted. + Tegnebogskryptering mislykkedes på grund af en intern fejl. Din tegnebog blev ikke krypteret. + + + + + The supplied passphrases do not match. + De angivne adgangskoder stemmer ikke overens. + + + + Wallet unlock failed + Tegnebogsoplåsning mislykkedes + + + + + + The passphrase entered for the wallet decryption was incorrect. + Den angivne adgangskode for tegnebogsdekrypteringen er forkert. + + + + Wallet decryption failed + Tegnebogsdekryptering mislykkedes + + + + Wallet passphrase was successfully changed. + Tegnebogens adgangskode blev ændret. + + + + BitcoinGUI + + + Sign &message... + Underskriv besked... + + + + Synchronizing with network... + Synkroniserer med netværk... + + + + &Overview + &Oversigt + + + + Show general overview of wallet + Vis generel oversigt over tegnebog + + + + &Transactions + &Transaktioner + + + + Browse transaction history + Gennemse transaktionshistorik + + + + &Address Book + &Adressebog + + + + Edit the list of stored addresses and labels + Redigere listen over gemte adresser og etiketter + + + + &Receive coins + &Modtag mønter + + + + Show the list of addresses for receiving payments + Vis listen over adresser for modtagne betalinger + + + + &Send coins + &Send mønter + + + + E&xit + Luk + + + + Quit application + Afslut program + + + + Show information about Arepacoin + Vis oplysninger om Arepacoin + + + + About &Qt + Om Qt + + + + Show information about Qt + Vis informationer om Qt + + + + &Options... + &Indstillinger... + + + + &Encrypt Wallet... + Krypter tegnebog... + + + + &Backup Wallet... + Sikkerhedskopier tegnebog... + + + + &Change Passphrase... + Skift adgangskode... + + + + ~%n block(s) remaining + ~%n blok resterer~%n blokke resterende + + + + Downloaded %1 of %2 blocks of transaction history (%3% done). + Overført %1 af %2 blokke af transaktions historie (%3% færdig). + + + + &Export... + &Eksporter... + + + + Send coins to a Arepacoin address + Send mønter til en Arepacoin adresse + + + + Modify configuration options for Arepacoin + Ændre indstillingsmuligheder for Arepacoin + + + + Export the data in the current tab to a file + Eksportere data i den aktuelle fane til en fil + + + + Encrypt or decrypt wallet + Kryptere eller dekryptere tegnebog + + + + Backup wallet to another location + Lav sikkerhedskopi af tegnebogen til et andet sted + + + + Change the passphrase used for wallet encryption + Skift adgangskode anvendt til tegnebogskryptering + + + + &Debug window + Fejlsøgningsvindue + + + + Open debugging and diagnostic console + Åbn fejlsøgnings- og diagnosticeringskonsollen + + + + &Verify message... + Verificér besked... + + + + Arepacoin + Arepacoin + + + + Wallet + Tegnebog + + + + &About Arepacoin + &Om Arepacoin + + + + &Show / Hide + Vis / skjul + + + + Unlock wallet + Lås tegnebog + + + + &Lock Wallet + &Lås tegnebog + + + + Lock wallet + Lås tegnebog + + + + &File + Fil + + + + &Settings + Indstillinger + + + + &Help + Hjælp + + + + Tabs toolbar + Faneværktøjslinje + + + + Actions toolbar + Fanværktøjslinje + + + + + [testnet] + [testnetværk] + + + + + Arepacoin client + Arepacoin klient + + + + %n active connection(s) to Arepacoin network + %n aktiv forbindelse til Arepacoin netværk%n aktive forbindelser til Arepacoin netværk + + + + Downloaded %1 blocks of transaction history. + Downloadet %1 blokke af transaktions historie. + + + + Staking.<br>Your weight is %1<br>Network weight is %2<br>Expected time to earn reward is %3 + Renter.<br> Din andel er% 1 <br> Netværkets andel er% 2 <br> Forventet tid til at modtage rente %3 + + + + Not staking because wallet is locked + Ingen rente fordi tegnebog er låst + + + + Not staking because wallet is offline + Ingen rente fordi tegnebog er offline + + + + Not staking because wallet is syncing + Ingen rente fordi tegnebog er ved at synkronisere + + + + Not staking because you don't have mature coins + Ingen rente fordi der ingen modne mønter eksistere + + + + %n second(s) ago + %n sekund siden%n sekunder siden + + + + &Unlock Wallet... + Lås tegnebog op + + + + %n minute(s) ago + %n minut siden%n minutter siden + + + + %n hour(s) ago + %n time siden%n timer siden + + + + %n day(s) ago + %n dag siden%n dage siden + + + + Up to date + Opdateret + + + + Catching up... + Indhenter... + + + + Last received block was generated %1. + Sidst modtagne blok blev genereret %1. + + + + This transaction is over the size limit. You can still send it for a fee of %1, which goes to the nodes that process your transaction and helps to support the network. Do you want to pay the fee? + Denne transaktion er over grænsen størrelse. Du kan stadig sende det for et gebyr på %1, der går til de noder, der behandler din transaktion og hjælper med at støtte netværket. Ønsker du at betale gebyret? + + + + Confirm transaction fee + Bekræft transaktionsgebyr + + + + Sent transaction + Afsendt transaktion + + + + Incoming transaction + Indgående transaktion + + + + Date: %1 +Amount: %2 +Type: %3 +Address: %4 + + Dato: %1 +Beløb: %2 +Type: %3 +Adresse: %4 + + + + + + URI handling + URI håndtering + + + + + URI can not be parsed! This can be caused by an invalid Arepacoin address or malformed URI parameters. + URI kan ikke tolkes! Dette kan skyldes en ugyldig Arepacoin adresse eller misdannede URI parametre. + + + + Wallet is <b>encrypted</b> and currently <b>unlocked</b> + Tegnebog er <b>krypteret</b> og i øjeblikket <b>ulåst</b> + + + + Wallet is <b>encrypted</b> and currently <b>locked</b> + Tegnebog er <b>krypteret</b> og i øjeblikket <b>låst</b> + + + + Backup Wallet + Sikkerhedskopier Tegnebog + + + + Wallet Data (*.dat) + Tegnebogsdata (*.dat) + + + + Backup Failed + Sikkerhedskopiering Mislykkedes + + + + There was an error trying to save the wallet data to the new location. + Der opstod en fejl under forsøg på at gemme data i tegnebogen til den nye placering. + + + + %n second(s) + %n sekund%n sekunder + + + + %n minute(s) + %n minut%n minutter + + + + %n hour(s) + %n time(r)%n time(r) + + + + %n day(s) + %n dag(e)%n dag(e) + + + + Not staking + Ingen rente + + + + A fatal error occurred. Arepacoin can no longer continue safely and will quit. + Der opstod en fejl under forsøg på at gemme dataene i tegnebogen til den nye placering. + + + + ClientModel + + + Network Alert + Netværksadvarsel + + + + CoinControlDialog + + + Coin Control + Mønt Kontrol + + + + Quantity: + Antal: + + + + Bytes: + Bytes: + + + + Amount: + Beløb: + + + + Priority: + Prioritet: + + + + Fee: + Gebyr: + + + + Low Output: + Lav Udgangseffekt: + + + + no + nej + + + + After Fee: + Efter Gebyr: + + + + Change: + Ændre: + + + + (un)select all + (fra)vælg alle + + + + Tree mode + Træ tilstand + + + + List mode + Liste tilstand + + + + Amount + Beløb + + + + Label + Mærkat + + + + Address + Adresse + + + + Date + Dato + + + + Confirmations + Bekræftelser + + + + Confirmed + Bekræftet + + + + Priority + Prioritet + + + + Copy address + Kopier adresse + + + + Copy label + Kopier mærkat + + + + + Copy amount + Kopier beløb + + + + Copy transaction ID + Kopier transaktionens ID + + + + Copy quantity + Kopier antal + + + + Copy fee + Kopier transkationsgebyr + + + + Copy after fee + Kopier efter transkationsgebyr + + + + Copy bytes + Kopier bytes + + + + Copy priority + Kopier prioritet + + + + Copy low output + Lav udgangseffekt + + + + Copy change + Kopier ændring + + + + highest + højeste + + + + high + høj + + + + medium-high + medium-høj + + + + medium + medium + + + + low-medium + lav-medium + + + + low + lav + + + + lowest + lavest + + + + DUST + DUST + + + + yes + ja + + + + This label turns red, if the transaction size is bigger than 10000 bytes. + + This means a fee of at least %1 per kb is required. + + Can vary +/- 1 Byte per input. + Denne etiket bliver rød, hvis transaktionen størrelse er større end 10000 byte. + +Det betyder, at et gebyr på mindst %1 per kb er påkrævet. + +Kan variere + / - 1 byte per indgang. + + + + Transactions with higher priority get more likely into a block. + +This label turns red, if the priority is smaller than "medium". + + This means a fee of at least %1 per kb is required. + Transaktioner med højere prioritet får mere sandsynligt en blok. + +Denne etiket bliver rød, hvis prioritet er mindre end "medium". + +Det betyder, at et gebyr på mindst %1 per kb er påkrævet. + + + + This label turns red, if any recipient receives an amount smaller than %1. + + This means a fee of at least %2 is required. + + Amounts below 0.546 times the minimum relay fee are shown as DUST. + Denne etiket bliver rød, hvis nogen modtager et beløb, der er mindre end %1. + +Det betyder, at et gebyr på mindst %2 er påkrævet. + +Beløb under 0,546 gange det minimale gebyr er vist som DUST. + + + + This label turns red, if the change is smaller than %1. + + This means a fee of at least %2 is required. + Denne etiket bliver rød, hvis ændringen er mindre end %1. + +Det betyder, at et gebyr på mindst %2 er påkrævet. + + + + + (no label) + (ingen mærkat) + + + + change from %1 (%2) + skift fra %1 (%2) + + + + (change) + (skift) + + + + EditAddressDialog + + + Edit Address + Rediger adresse + + + + &Label + Mærkat + + + + The label associated with this address book entry + Etiketten er forbundet med denne post i adressekartoteket + + + + &Address + Adresse + + + + The address associated with this address book entry. This can only be modified for sending addresses. + Adressen er forbundet med denne post i adressekartoteket. Dette kan kun ændres til sende adresser. + + + + New receiving address + Ny modtagelsesadresse + + + + New sending address + Ny afsendelsesadresse + + + + Edit receiving address + Rediger modtagelsesadresse + + + + Edit sending address + Rediger afsendelsesadresse + + + + The entered address "%1" is already in the address book. + Den indtastede adresse "%1" er allerede i adressebogen. + + + + The entered address "%1" is not a valid Arepacoin address. + Den indtastede adresse "%1" er ikke en gyldig Arepacoin adresse. + + + + Could not unlock wallet. + Kunne ikke låse tegnebog op. + + + + New key generation failed. + Ny nøglegenerering mislykkedes. + + + + GUIUtil::HelpMessageBox + + + + Arepacoin-Qt + Arepacoin-Qt + + + + version + version + + + + Usage: + Anvendelse: + + + + command-line options + Kommandolinjeparametrene + + + + UI options + UI opsætning + + + + Set language, for example "de_DE" (default: system locale) + Indstil sprog, for eksempel "de_DE" (standard: system locale) + + + + Start minimized + Start minimeret + + + + Show splash screen on startup (default: 1) + Vis splash skærm ved opstart (default: 1) + + + + OptionsDialog + + + Options + Indstillinger + + + + &Main + Generelt + + + + Optional transaction fee per kB that helps make sure your transactions are processed quickly. Most transactions are 1 kB. Fee 0.01 recommended. + Valgfri transaktionsgebyr pr kB, som hjælper med at sikre dine transaktioner bliver behandlet hurtigt. De fleste transaktioner er 1 kB. Gebyr 0,01 anbefales. + + + + Pay transaction &fee + Betal transaktionsgebyr + + + + Reserved amount does not participate in staking and is therefore spendable at any time. + Reserveret beløb deltager ikke i forrentning og er derfor tilrådighed til enhver tid. + + + + Reserve + Reserve + + + + Automatically start Arepacoin after logging in to the system. + Automatisk start Arepacoin efter at have logget ind på systemet. + + + + &Start Arepacoin on system login + &Start Arepacoin ved systems login + + + + Detach block and address databases at shutdown. This means they can be moved to another data directory, but it slows down shutdown. The wallet is always detached. + Frigør blok og adressedatabaser ved lukning. Det betyder, at de kan flyttes til et anden data-bibliotek, men det sinker lukning. Tegnebogen er altid frigjort. + + + + &Detach databases at shutdown + &Frigør databaser ved lukning + + + + &Network + Netværk + + + + Automatically open the Arepacoin client port on the router. This only works when your router supports UPnP and it is enabled. + Automatisk åbne Arepacoin klient-port på routeren. Dette virker kun, når din router understøtter UPnP og er det er aktiveret. + + + + Map port using &UPnP + Konfigurer port vha. UPnP + + + + Connect to the Arepacoin network through a SOCKS proxy (e.g. when connecting through Tor). + Opret forbindelse til Arepacoin netværk via en SOCKS proxy (fx ved tilslutning gennem Tor). + + + + &Connect through SOCKS proxy: + &Tilslut gennem SOCKS proxy: + + + + Proxy &IP: + Proxy-IP: + + + + IP address of the proxy (e.g. 127.0.0.1) + IP-adressen på proxy (f.eks 127.0.0.1) + + + + &Port: + Port: + + + + Port of the proxy (e.g. 9050) + Porten på proxyen (f.eks. 9050) + + + + SOCKS &Version: + SOCKS-version + + + + SOCKS version of the proxy (e.g. 5) + SOCKS-version af proxyen (f.eks. 5) + + + + &Window + Vindue + + + + Show only a tray icon after minimizing the window. + Vis kun et statusikon efter minimering af vinduet. + + + + &Minimize to the tray instead of the taskbar + Minimer til statusfeltet i stedet for proceslinjen + + + + Minimize instead of exit the application when the window is closed. When this option is enabled, the application will be closed only after selecting Quit in the menu. + Minimer i stedet for at afslutte programmet, når vinduet lukkes. Når denne indstilling er valgt, vil programmet kun blive lukket, når du har valgt Afslut i menuen. + + + + M&inimize on close + Minimer ved lukning + + + + &Display + Visning + + + + User Interface &language: + Brugergrænsefladesprog: + + + + The user interface language can be set here. This setting will take effect after restarting Arepacoin. + Sproget i brugergrænsefladen kan indstilles her. Denne indstilling vil træde i kraft efter genstart af Arepacoin tegnebog. + + + + &Unit to show amounts in: + Enhed at vise beløb i: + + + + Choose the default subdivision unit to show in the interface and when sending coins. + Vælg den standard underopdelingsenhed, som skal vises i brugergrænsefladen og ved afsendelse af bitcoins. + + + + Whether to show Arepacoin addresses in the transaction list or not. + Få vist Arepacoin adresser på listen over transaktioner eller ej. + + + + &Display addresses in transaction list + Vis adresser i transaktionsliste + + + + Whether to show coin control features or not. + Vis mønt kontrol funktioner eller ej. + + + + Display coin &control features (experts only!) + Vis mønt & kontrol funktioner (kun for eksperter!) + + + + &OK + OK + + + + &Cancel + Annuller + + + + &Apply + &Anvend + + + + default + standard + + + + + Warning + Advarsel + + + + + This setting will take effect after restarting Arepacoin. + Denne indstilling vil træde i kraft efter genstart af Arepacoin. + + + + The supplied proxy address is invalid. + Ugyldig proxy-adresse + + + + OverviewPage + + + Form + Formular + + + + + The displayed information may be out of date. Your wallet automatically synchronizes with the Arepacoin network after a connection is established, but this process has not completed yet. + De viste oplysninger kan være forældet. Din tegnebog synkroniserer automatisk med Arepacoin netværket efter en forbindelse er etableret, men denne proces er ikke afsluttet endnu. + + + + Stake: + Rente: + + + + Unconfirmed: + Ubekræftede: + + + + Wallet + Tegnebog + + + + Spendable: + Brugbar: + + + + Your current spendable balance + Din nuværende tilgængelige saldo + + + + Immature: + Umodne: + + + + Mined balance that has not yet matured + Udvunden saldo, som endnu ikke er modnet + + + + Total: + Total: + + + + Your current total balance + Din nuværende totale saldo + + + + <b>Recent transactions</b> + <b>Nyeste transaktioner</b> + + + + Total of transactions that have yet to be confirmed, and do not yet count toward the current balance + Summen af ​​transaktioner, der endnu mangler at blive bekræftet, og ikke tæller mod den nuværende balance + + + + Total of coins that was staked, and do not yet count toward the current balance + I alt mønter, der bliver berentet, og endnu ikke tæller mod den nuværende balance + + + + + out of sync + ikke synkroniseret + + + + QRCodeDialog + + + QR Code Dialog + QR Kode Dialog + + + + Request Payment + Betalingsanmodning + + + + Amount: + Antal: + + + + Label: + Label: + + + + Message: + Besked: + + + + &Save As... + &Gem Som... + + + + Error encoding URI into QR Code. + Fejl kode URI i QR kode. + + + + The entered amount is invalid, please check. + Det indtastede beløb er ugyldig, venligst tjek igen. + + + + Resulting URI too long, try to reduce the text for label / message. + Resulterende URI for lang, prøv at reducere teksten til etiketten / besked. + + + + Save QR Code + Gem QR kode + + + + PNG Images (*.png) + PNG billede (*.png) + + + + RPCConsole + + + Client name + Klientnavn + + + + + + + + + + + + + N/A + N/A + + + + Client version + Klientversion + + + + &Information + Information + + + + Using OpenSSL version + Anvender OpenSSL-version + + + + Startup time + Opstartstid + + + + Network + Netværk + + + + Number of connections + Antal forbindelser + + + + On testnet + På testnet + + + + Block chain + Blokkæde + + + + Current number of blocks + Nuværende antal blokke + + + + Estimated total blocks + Estimeret antal blokke + + + + Last block time + Tidsstempel for seneste blok + + + + &Open + Åbn + + + + Command-line options + Kommandolinjeparametrene + + + + Show the Arepacoin-Qt help message to get a list with possible Arepacoin command-line options. + Vis Arepacoin-Qt hjælpe besked for at få en liste med mulige Arepacoin kommandolinjeparametre. + + + + &Show + &Vis + + + + &Console + Konsol + + + + Build date + Byggedato + + + + Arepacoin - Debug window + Arepacoin - Debug vindue + + + + Arepacoin Core + Arepacoin Kerne + + + + Debug log file + Fejlsøgningslogfil + + + + Open the Arepacoin debug log file from the current data directory. This can take a few seconds for large log files. + Åbn Arepacoin debug logfilen fra den nuværende data mappe. Dette kan tage et par sekunder for store logfiler. + + + + Clear console + Ryd konsol + + + + Welcome to the Arepacoin RPC console. + Velkommen til Arepacoin RPC-konsol. + + + + Use up and down arrows to navigate history, and <b>Ctrl-L</b> to clear screen. + Brug op og ned-piletasterne til at navigere historikken og <b>Ctrl-L</b> til at rydde skærmen. + + + + Type <b>help</b> for an overview of available commands. + Tast <b>help</b> for en oversigt over de tilgængelige kommandoer. + + + + SendCoinsDialog + + + + + + + + + + Send Coins + Send bitcoins + + + + Coin Control Features + Mønt Kontrol Egenskaber + + + + Inputs... + Input ... + + + + automatically selected + Automatisk valgt + + + + Insufficient funds! + Utilstrækkelig midler! + + + + Quantity: + Antal: + + + + + 0 + 0 + + + + Bytes: + Bytes: + + + + Amount: + Beløb: + + + + + + + 0.00 BC + 123.456 BC {0.00 ?} + + + + Priority: + Prioritet: + + + + medium + medium + + + + Fee: + Gebyr + + + + Low Output: + Lav udgangseffekt + + + + no + nej + + + + After Fee: + Efter gebyr + + + + Change + Skift + + + + custom change address + Ændre adresse + + + + Send to multiple recipients at once + Send til flere modtagere på en gang + + + + Add &Recipient + Tilføj modtager + + + + Remove all transaction fields + Fjern alle transaktions omkostnings felter + + + + Clear &All + Ryd alle + + + + Balance: + Saldo: + + + + 123.456 BC + 123.456 BC + + + + Confirm the send action + Bekræft afsendelsen + + + + S&end + Afsend + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + Indtast en Arepacoin-adresse (f.eks AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + Copy quantity + Kopier antal + + + + Copy amount + Kopier beløb + + + + Copy fee + Kopier transkationsgebyr + + + + Copy after fee + Kopier efter transkationsgebyr + + + + Copy bytes + Kopier bytes + + + + Copy priority + Kopier prioritet + + + + Copy low output + Kopier lav produktion + + + + Copy change + Kopier forandring + + + + <b>%1</b> to %2 (%3) + <b>%1</b> til %2 (%3) + + + + Confirm send coins + Bekræft afsendelse af bitcoins + + + + Are you sure you want to send %1? + Er du sikker på du vil sende% 1? + + + + and + og + + + + The recipient address is not valid, please recheck. + Modtagerens adresse er ikke gyldig. Tjek venligst adressen igen. + + + + The amount to pay must be larger than 0. + Beløbet til betaling skal være større end 0. + + + + The amount exceeds your balance. + Beløbet overstiger din saldo. + + + + The total exceeds your balance when the %1 transaction fee is included. + Totalen overstiger din saldo, når %1 transaktionsgebyr er inkluderet. + + + + Duplicate address found, can only send to each address once per send operation. + Duplikeret adresse fundet. Du kan kun sende til hver adresse en gang pr. afsendelse. + + + + Error: Transaction creation failed. + Fejl: Transaktion oprettelse mislykkedes. + + + + 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. + Fejl: Transaktionen blev afvist. Dette kan ske, hvis nogle af mønterne i din tegnebog allerede er blevet brugt, som hvis du brugte en kopi af wallet.dat og mønterne blev brugt i kopien, men ikke markeret som brugt her. + + + + WARNING: Invalid Arepacoin address + ADVARSEL: Ugyldig Arepacoin adresse + + + + (no label) + (ingen mærkat) + + + + WARNING: unknown change address + ADVARSEL: ukendt adresse forandring + + + + SendCoinsEntry + + + Form + Form + + + + A&mount: + Beløb: + + + + Pay &To: + Betal til: + + + + + Enter a label for this address to add it to your address book + Indtast en mærkat for denne adresse for at føje den til din adressebog + + + + &Label: + Mærkat: + + + + The address to send the payment to (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + Adressen til at sende betalingen til (f.eks AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + Choose address from address book + Vælg adresse fra adressebogen + + + + Alt+A + Alt+A + + + + Paste address from clipboard + Indsæt adresse fra udklipsholderen + + + + Alt+P + Alt+P + + + + Remove this recipient + Fjern denne modtager + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + Indtast en Arepacoin-adresse (f.eks AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + SignVerifyMessageDialog + + + Signatures - Sign / Verify a Message + Signature - Underskriv/verificér en besked + + + + + &Sign Message + Underskriv besked + + + + You can sign messages with your addresses to prove you own them. Be careful not to sign anything vague, as phishing attacks may try to trick you into signing your identity over to them. Only sign fully-detailed statements you agree to. + Du kan underskrive beskeder med dine Bitcoin-adresser for at bevise, at de tilhører dig. Pas på ikke at underskrive noget vagt, da phisingangreb kan narre dig til at overdrage din identitet. Underskriv kun fuldt detaljerede udsagn, du er enig i. + + + + The address to sign the message with (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + Adresse til at underskrive meddelelsen med (f.eks AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Choose an address from the address book + Vælg en adresse fra adressebogen + + + + + Alt+A + Alt+A + + + + Paste address from clipboard + Indsæt adresse fra udklipsholderen + + + + Alt+P + Alt+P + + + + Enter the message you want to sign here + Indtast beskeden, du ønsker at underskrive + + + + Copy the current signature to the system clipboard + Kopier den nuværende underskrift til systemets udklipsholder + + + + Sign the message to prove you own this Arepacoin address + Underskriv brevet for at bevise du ejer denne Arepacoin adresse + + + + Reset all sign message fields + Nulstil alle "underskriv besked"-felter + + + + + Clear &All + Ryd alle + + + + + &Verify Message + Verificér besked + + + + Enter the signing address, message (ensure you copy line breaks, spaces, tabs, etc. exactly) and signature below to verify the message. Be careful not to read more into the signature than what is in the signed message itself, to avoid being tricked by a man-in-the-middle attack. + Indtast den underskrevne adresse, beskeden (inkluder linjeskift, mellemrum mv. nøjagtigt, som de fremgår) og underskriften for at verificére beskeden. Vær forsigtig med ikke at lægge mere i underskriften end besked selv, så du undgår at blive narret af et man-in-the-middle-angreb. + + + + The address the message was signed with (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + Adressen meddelelse blev underskrevet med (f.eks AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + Verify the message to ensure it was signed with the specified Arepacoin address + Kontroller meddelelsen for at sikre, at den blev indgået med den angivne Arepacoin adresse + + + + Reset all verify message fields + Nulstil alle "verificér besked"-felter + + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + Indtast en Arepacoin-adresse (f.eks AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + Click "Sign Message" to generate signature + Klik "Underskriv besked" for at generere underskriften + + + + Enter Arepacoin signature + Indtast Arepacoin underskrift + + + + + The entered address is invalid. + Den indtastede adresse er ugyldig. + + + + + + + Please check the address and try again. + Tjek venligst adressen, og forsøg igen. + + + + + The entered address does not refer to a key. + Den indtastede adresse henviser ikke til en nøgle. + + + + Wallet unlock was cancelled. + Tegnebogsoplåsning annulleret. + + + + Private key for the entered address is not available. + Den private nøgle for den indtastede adresse er ikke tilgængelig. + + + + Message signing failed. + Underskrivning af besked mislykkedes. + + + + Message signed. + Besked underskrevet. + + + + The signature could not be decoded. + Underskriften kunne ikke afkodes. + + + + + Please check the signature and try again. + Tjek venligst underskriften, og forsøg igen. + + + + The signature did not match the message digest. + Underskriften matcher ikke beskedens indhold. + + + + Message verification failed. + Verificéring af besked mislykkedes. + + + + Message verified. + Besked verificéret. + + + + TransactionDesc + + + Open until %1 + Åben indtil %1 + + + + Open for %n block(s) + Åben for %n blokÅben for %n blok(ke) + + + + conflicted + konflikt + + + + %1/offline + %1/offline + + + + %1/unconfirmed + %1/ubekræftet + + + + %1 confirmations + %1 bekræftelser + + + + Status + Status + + + + , broadcast through %n node(s) + , transmitteret igennem %n knude(r), transmitteret igennem %n knude(r) + + + + Date + Dato + + + + Source + Kilde + + + + Generated + Genereret + + + + + From + Fra + + + + + + To + Til + + + + + own address + egen adresse + + + + label + mærkat + + + + + + + + Credit + Kredit + + + + matures in %n more block(s) + modner efter yderligere %n blok(ke)modner efter yderligere %n blok(ke) + + + + not accepted + ikke accepteret + + + + + + + Debit + Debet + + + + Transaction fee + Transaktionsgebyr + + + + Net amount + Nettobeløb + + + + Message + Besked + + + + Comment + Kommentar + + + + Transaction ID + Transaktionens ID + + + + Generated coins must mature 6 blocks before they can be spent. When you generated this block, it was broadcast to the network to be added to the block chain. If it fails to get into the chain, its state will change to "not accepted" and it won't be spendable. This may occasionally happen if another node generates a block within a few seconds of yours. + Generet mønter skal modne 6 blokke, før de kan blive brugt. Når du genererede denne blok blev det transmitteret til netværket, der tilføjes til blokkæden. Hvis det mislykkes at komme ind i kæden, vil dens tilstand ændres til "ikke godkendt", og det vil ikke være brugbar. Dette kan lejlighedsvis ske, hvis en anden node genererer en blok et par sekunder efter din. + + + + Debug information + Fejlsøgningsinformation + + + + Transaction + Transaktion + + + + Inputs + Input + + + + Amount + Beløb + + + + true + sand + + + + false + falsk + + + + , has not been successfully broadcast yet + , er ikke blevet transmitteret endnu + + + + unknown + ukendt + + + + TransactionDescDialog + + + Transaction details + Transaktionsdetaljer + + + + This pane shows a detailed description of the transaction + Denne rude viser en detaljeret beskrivelse af transaktionen + + + + TransactionTableModel + + + Date + Dato + + + + Type + Type + + + + Address + Adresse + + + + Amount + Beløb + + + + Open until %1 + Åben indtil %1 + + + + Confirmed (%1 confirmations) + Bekræftet (%1 bekræftelser) + + + + Open for %n more block(s) + Åben %n blok(ke) yderligereÅben %n blok(ke) yderligere + + + + Offline + Offline + + + + Unconfirmed + Ubekræftede + + + + Confirming (%1 of %2 recommended confirmations) + Bekræftelse (% 1 af% 2 anbefalede bekræftelser) + + + + Conflicted + Konflikt + + + + Immature (%1 confirmations, will be available after %2) + Umodne (% 1 bekræftelser, vil være tilgængelige efter% 2) + + + + This block was not received by any other nodes and will probably not be accepted! + Denne blok blev ikke modtaget af nogen andre knuder og vil formentlig ikke blive accepteret! + + + + Generated but not accepted + Genereret, men ikke accepteret + + + + Received with + Modtaget med + + + + Received from + Modtaget fra + + + + Sent to + Sendt til + + + + Payment to yourself + Betaling til dig selv + + + + Mined + Udvundne + + + + (n/a) + (n/a) + + + + Transaction status. Hover over this field to show number of confirmations. + Transaktionsstatus. Hold musen over dette felt for at vise antallet af bekræftelser. + + + + Date and time that the transaction was received. + Dato og klokkeslæt for modtagelse af transaktionen. + + + + Type of transaction. + Transaktionstype. + + + + Destination address of transaction. + Destinationsadresse for transaktion. + + + + Amount removed from or added to balance. + Beløb fjernet eller tilføjet balance. + + + + TransactionView + + + + All + Alle + + + + Today + I dag + + + + This week + Denne uge + + + + This month + Denne måned + + + + Last month + Sidste måned + + + + This year + Dette år + + + + Range... + Interval... + + + + Received with + Modtaget med + + + + Sent to + Sendt til + + + + To yourself + Til dig selv + + + + Mined + Udvundne + + + + Other + Andet + + + + Enter address or label to search + Indtast adresse eller mærkat for at søge + + + + Min amount + Minimumsbeløb + + + + Copy address + Kopier adresse + + + + Copy label + Kopier mærkat + + + + Copy amount + Kopier beløb + + + + Copy transaction ID + Kopier transaktionens ID + + + + Edit label + Rediger mærkat + + + + Show transaction details + Vis transaktionsdetaljer + + + + Export Transaction Data + Exportere transaktionsdata + + + + Comma separated file (*.csv) + Kommasepareret fil (*.csv) + + + + Confirmed + Bekræftet + + + + Date + Dato + + + + Type + Type + + + + Label + Mærkat + + + + Address + Adresse + + + + Amount + Beløb + + + + ID + ID + + + + Error exporting + Fejl exporting + + + + Could not write to file %1. + Kunne ikke skrive til filen% 1. + + + + Range: + Interval: + + + + to + til + + + + WalletModel + + + Sending... + Sender... + + + + bitcoin-core + + + Arepacoin version + Arepacoin version + + + + Usage: + Anvendelse: + + + + Send command to -server or arepacoind + Send kommando til-server eller arepacoind + + + + List commands + Liste over kommandoer + + + + Get help for a command + Få hjælp til en kommando + + + + Options: + Indstillinger: + + + + Specify configuration file (default: arepacoin.conf) + Angiv konfigurationsfil (default: arepacoin.conf) + + + + Specify pid file (default: arepacoind.pid) + Angiv pid fil (standard: arepacoind.pid) + + + + Specify wallet file (within data directory) + Angiv tegnebogs fil (indenfor data mappe) + + + + Specify data directory + Angiv datakatalog + + + + Set database cache size in megabytes (default: 25) + Angiv databasecachestørrelse i megabytes (standard: 25) + + + + Set database disk log size in megabytes (default: 100) + Set database disk logstørrelsen i megabyte (standard: 100) + + + + Listen for connections on <port> (default: 9853 or testnet: 19853) + Lyt efter forbindelser på <port> (default: 9853 eller Testnet: 19853) + + + + Maintain at most <n> connections to peers (default: 125) + Oprethold højest <n> forbindelser til andre i netværket (standard: 125) + + + + Connect to a node to retrieve peer addresses, and disconnect + Forbind til en knude for at modtage adresse, og afbryd + + + + Specify your own public address + Angiv din egen offentlige adresse + + + + Bind to given address. Use [host]:port notation for IPv6 + Binder til en given adresse. Brug [host]: port notation for IPv6 + + + + Stake your coins to support network and gain reward (default: 1) + Opbevar dine mønter for at støtte netværket og få belønning (default: 1) + + + + Threshold for disconnecting misbehaving peers (default: 100) + Grænse for afbrydelse til dårlige forbindelser (standard: 100) + + + + Number of seconds to keep misbehaving peers from reconnecting (default: 86400) + Antal sekunder dårlige forbindelser skal vente før reetablering (standard: 86400) + + + + An error occurred while setting up the RPC port %u for listening on IPv4: %s + Der opstod en fejl ved angivelse af RPC-porten %u til at lytte på IPv4: %s + + + + Detach block and address databases. Increases shutdown time (default: 0) + Frigør blok og adresse databaser. Øg shutdown tid (default: 0) + + + + 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. + Fejl: Transaktionen blev afvist. Dette kan ske, hvis nogle af mønterne i din pung allerede er blevet brugt, som hvis du brugte en kopi af wallet.dat og mønterne blev brugt i kopien, men ikke markeret her. + + + + Error: This transaction requires a transaction fee of at least %s because of its amount, complexity, or use of recently received funds + Fejl: Denne transaktion kræver et transaktionsgebyr på mindst% s på grund af dens størrelse, kompleksitet, eller anvendelse af nylig modtaget midler + + + + Listen for JSON-RPC connections on <port> (default: 9852 or testnet: 19852) + Spor efter JSON-RPC-forbindelser på <port> (default: 9852 eller Testnet: 19852) + + + + Accept command line and JSON-RPC commands + Accepter kommandolinje- og JSON-RPC-kommandoer + + + + Error: Transaction creation failed + Fejl: Transaktion oprettelse mislykkedes + + + + Error: Wallet locked, unable to create transaction + Fejl: Wallet låst, ude af stand til at skabe transaktion + + + + Importing blockchain data file. + Importerer blockchain datafil. + + + + Importing bootstrap blockchain data file. + Import af bootstrap blockchain datafil. + + + + Run in the background as a daemon and accept commands + Kør i baggrunden som en service, og accepter kommandoer + + + + Use the test network + Brug testnetværket + + + + Accept connections from outside (default: 1 if no -proxy or -connect) + Accepter forbindelser udefra (standard: 1 hvis hverken -proxy eller -connect) + + + + An error occurred while setting up the RPC port %u for listening on IPv6, falling back to IPv4: %s + Der opstod en fejl ved angivelse af RPC-porten %u til at lytte på IPv6, falder tilbage til IPv4: %s + + + + Error initializing database environment %s! To recover, BACKUP THAT DIRECTORY, then remove everything from it except for wallet.dat. + Fejl initialisering database miljø% s! For at gendanne, BACKUP denne mappe, og derefter fjern alt bortset fra wallet.dat. + + + + Set maximum size of high-priority/low-fee transactions in bytes (default: 27000) + Angiv maksimal størrelse på high-priority/low-fee transaktioner i bytes (standard: 27000) + + + + Warning: -paytxfee is set very high! This is the transaction fee you will pay if you send a transaction. + Advarsel: -paytxfee er sat meget højt! Dette er det gebyr du vil betale, hvis du sender en transaktion. + + + + Warning: Please check that your computer's date and time are correct! If your clock is wrong Arepacoin will not work properly. + Advarsel: Kontroller venligst, at computerens dato og klokkeslæt er korrekt! Hvis dit ur er forkert vil Arepacoin ikke fungere korrekt. + + + + Warning: error reading wallet.dat! All keys read correctly, but transaction data or address book entries might be missing or incorrect. + Advarsel: fejl under læsning af wallet.dat! Alle nøgler blev læst korrekt, men transaktionsdata eller adressebogsposter kan mangle eller være forkerte. + + + + Warning: wallet.dat corrupt, data salvaged! Original wallet.dat saved as wallet.{timestamp}.bak in %s; if your balance or transactions are incorrect you should restore from a backup. + Advarsel: wallet.dat ødelagt, data reddet! Oprindelig wallet.net gemt som wallet.{timestamp}.bak i %s; hvis din saldo eller dine transaktioner er forkert, bør du genskabe fra en sikkerhedskopi. + + + + Attempt to recover private keys from a corrupt wallet.dat + Forsøg at genskabe private nøgler fra ødelagt wallet.dat + + + + Block creation options: + Blokoprettelsestilvalg: + + + + Connect only to the specified node(s) + Tilslut kun til de(n) angivne knude(r) + + + + Discover own IP address (default: 1 when listening and no -externalip) + Find egen IP-adresse (standard: 1 når lytter og ingen -externalip) + + + + Failed to listen on any port. Use -listen=0 if you want this. + Lytning på enhver port mislykkedes. Brug -listen=0, hvis du ønsker dette. + + + + Find peers using DNS lookup (default: 1) + Find peer bruges DNS-opslag (default: 1) + + + + Sync checkpoints policy (default: strict) + Synkroniser checkpoints politik (default: streng) + + + + Invalid -tor address: '%s' + Ugyldig-tor-adresse: '% s' + + + + Invalid amount for -reservebalance=<amount> + Ugyldigt beløb for-reservebalance = <beløb> + + + + Maximum per-connection receive buffer, <n>*1000 bytes (default: 5000) + Maksimum for modtagelsesbuffer pr. forbindelse, <n>*1000 bytes (standard: 5000) + + + + Maximum per-connection send buffer, <n>*1000 bytes (default: 1000) + Maksimum for afsendelsesbuffer pr. forbindelse, <n>*1000 bytes (standard: 1000) + + + + Only connect to nodes in network <net> (IPv4, IPv6 or Tor) + Tilslut kun til knuder i netværk <net> (IPv4, IPv6 eller Tor) + + + + Output extra debugging information. Implies all other -debug* options + Output ekstra debugging information. Indebærer alle andre-debug * muligheder + + + + Output extra network debugging information + Output ekstra netværk debugging information + + + + Prepend debug output with timestamp + Prepend debug output med tidsstempel + + + + SSL options: (see the Bitcoin Wiki for SSL setup instructions) + SSL-indstillinger: (se Bitcoin Wiki for SSL-opsætningsinstruktioner) + + + + Select the version of socks proxy to use (4-5, default: 5) + Vælg den version af socks proxy du vil bruge (4-5, standard: 5) + + + + Send trace/debug info to console instead of debug.log file + Send sporings-/fejlsøgningsinformation til konsollen i stedet for debug.log filen + + + + Send trace/debug info to debugger + Send trace / debug info til debugger + + + + Set maximum block size in bytes (default: 250000) + Indstil maks. blok størrelse i bytes (standard: 250000) + + + + Set minimum block size in bytes (default: 0) + Angiv minimumsblokstørrelse i bytes (standard: 0) + + + + Shrink debug.log file on client startup (default: 1 when no -debug) + Formindsk debug.log filen ved klientopstart (standard: 1 hvis ikke -debug) + + + + Specify connection timeout in milliseconds (default: 5000) + Angiv tilslutningstimeout i millisekunder (standard: 5000) + + + + Unable to sign checkpoint, wrong checkpointkey? + + Kan ikke logge checkpoint, forkert checkpointkey? + + + + + Use UPnP to map the listening port (default: 0) + Forsøg at bruge UPnP til at konfigurere den lyttende port (standard: 0) + + + + Use UPnP to map the listening port (default: 1 when listening) + Forsøg at bruge UPnP til at konfigurere den lyttende port (standard: 1 når lytter) + + + + Use proxy to reach tor hidden services (default: same as -proxy) + Brug proxy til at nå tor skjulte services (Standard: samme som-proxy) + + + + Username for JSON-RPC connections + Brugernavn til JSON-RPC-forbindelser + + + + Verifying database integrity... + Bekræfter database integritet ... + + + + WARNING: syncronized checkpoint violation detected, but skipped! + ADVARSEL: synkroniseret checkpoint overtrædelse opdaget, men skibbet! + + + + Warning: Disk space is low! + Advarsel: Diskplads lav! + + + + Warning: This version is obsolete, upgrade required! + Advarsel: Denne version er forældet, opgradering påkrævet! + + + + wallet.dat corrupt, salvage failed + wallet.dat ødelagt, redning af data mislykkedes + + + + Password for JSON-RPC connections + Adgangskode til JSON-RPC-forbindelser + + + + %s, you must set a rpcpassword in the configuration file: + %s +It is recommended you use the following random password: +rpcuser=arepacoinrpc +rpcpassword=%s +(you do not need to remember this password) +The username and password MUST NOT be the same. +If the file does not exist, create it with owner-readable-only file permissions. +It is also recommended to set alertnotify so you are notified of problems; +for example: alertnotify=echo %%s | mail -s "Arepacoin Alert" admin@foo.com + + % s, skal du indstille et rpcpassword i konfigurationsfilen: +% s +Det anbefales at bruge følgende tilfældig adgangskode: +rpcuser = arepacoinrpc +rpcpassword =% s +(du behøver ikke at huske denne adgangskode) +Brugernavn og adgangskode må ikke være den samme. +Hvis filen ikke findes, skal du oprette den med filtilladelser ejer-læsbar-kun. +Det kan også anbefales at sætte alertnotify så du får besked om problemer; +for eksempel: alertnotify = echo%% s | mail-s "Arepacoin Alert" admin@foo.com + + + + + Find peers using internet relay chat (default: 0) + Find peers der bruger internet relay chat (default: 1) {? 0)} + + + + Sync time with other nodes. Disable if time on your system is precise e.g. syncing with NTP (default: 1) + Synkroniser tid med andre noder. Deaktiver, hvis tiden på dit system er præcis eksempelvis synkroniseret med NTP (default: 1) + + + + When creating transactions, ignore inputs with value less than this (default: 0.01) + Når du opretter transaktioner ignoreres input med værdi mindre end dette (standard: 0,01) + + + + Allow JSON-RPC connections from specified IP address + Tillad JSON-RPC-forbindelser fra bestemt IP-adresse + + + + Send commands to node running on <ip> (default: 127.0.0.1) + Send kommandoer til knude, der kører på <ip> (standard: 127.0.0.1) + + + + Execute command when the best block changes (%s in cmd is replaced by block hash) + Udfør kommando, når den bedste blok ændres (%s i kommandoen erstattes med blokhash) + + + + Execute command when a wallet transaction changes (%s in cmd is replaced by TxID) + Udfør kommando, når en transaktion i tegnebogen ændres (%s i kommandoen erstattes med TxID) + + + + Require a confirmations for change (default: 0) + Kræver en bekræftelser for forandring (default: 0) + + + + Enforce transaction scripts to use canonical PUSH operators (default: 1) + Gennemtving transaktions omkostninger scripts til at bruge canoniske PUSH operatører (default: 1) + + + + Execute command when a relevant alert is received (%s in cmd is replaced by message) + Udfør kommando, når en relevant advarsel er modtaget (% s i cmd erstattes af meddelelse) + + + + Upgrade wallet to latest format + Opgrader tegnebog til seneste format + + + + Set key pool size to <n> (default: 100) + Angiv nøglepoolstørrelse til <n> (standard: 100) + + + + Rescan the block chain for missing wallet transactions + Gennemsøg blokkæden for manglende tegnebogstransaktioner + + + + How many blocks to check at startup (default: 2500, 0 = all) + Hvor mange blokke til at kontrollere ved opstart (standard: 2500, 0 = alle) + + + + How thorough the block verification is (0-6, default: 1) + Hvor grundig blok verifikation er (0-6, default: 1) + + + + Imports blocks from external blk000?.dat file + Importere blokke fra ekstern blk000?. Dat fil + + + + Use OpenSSL (https) for JSON-RPC connections + Brug OpenSSL (https) for JSON-RPC-forbindelser + + + + Server certificate file (default: server.cert) + Servercertifikat-fil (standard: server.cert) + + + + Server private key (default: server.pem) + Serverens private nøgle (standard: server.pem) + + + + Acceptable ciphers (default: TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH) + Acceptable ciphers (default: TLSv1 + HØJ:! SSLv2: aNULL: eNULL: AH: 3DES: @ styrke) + + + + Error: Wallet unlocked for staking only, unable to create transaction. + Fejl: Pung låst for at udregne rente, ude af stand til at skabe transaktion. + + + + WARNING: Invalid checkpoint found! Displayed transactions may not be correct! You may need to upgrade, or notify developers. + ADVARSEL: Ugyldig checkpoint fundet! Viste transaktioner er måske ikke korrekte! Du kan være nødt til at opgradere, eller underrette udviklerne. + + + + This help message + Denne hjælpebesked + + + + Wallet %s resides outside data directory %s. + Wallet% s placeret udenfor data mappe% s. + + + + Cannot obtain a lock on data directory %s. Arepacoin is probably already running. + Kan ikke få en lås på data mappe% s. Arepacoin kører sikkert allerede. + + + + Arepacoin + Arepacoin + + + + Unable to bind to %s on this computer (bind returned error %d, %s) + Kunne ikke tildele %s på denne computer (bind returnerede fejl %d, %s) + + + + Connect through socks proxy + Tilslut gennem socks proxy + + + + Allow DNS lookups for -addnode, -seednode and -connect + Tillad DNS-opslag for -addnode, -seednode og -connect + + + + Loading addresses... + Indlæser adresser... + + + + Error loading blkindex.dat + Fejl ved indlæsning af blkindex.dat + + + + Error loading wallet.dat: Wallet corrupted + Fejl ved indlæsning af wallet.dat: Tegnebog ødelagt + + + + Error loading wallet.dat: Wallet requires newer version of Arepacoin + Fejl ved indlæsning af wallet.dat: Wallet kræver en nyere version af Arepacoin + + + + Wallet needed to be rewritten: restart Arepacoin to complete + Det er nødvendig for wallet at blive omskrevet: Genstart Arepacoin for fuldføre + + + + Error loading wallet.dat + Fejl ved indlæsning af wallet.dat + + + + Invalid -proxy address: '%s' + Ugyldig -proxy adresse: '%s' + + + + Unknown network specified in -onlynet: '%s' + Ukendt netværk anført i -onlynet: '%s' + + + + Unknown -socks proxy version requested: %i + Ukendt -socks proxy-version: %i + + + + Cannot resolve -bind address: '%s' + Kan ikke finde -bind adressen: '%s' + + + + Cannot resolve -externalip address: '%s' + Kan ikke finde -externalip adressen: '%s' + + + + Invalid amount for -paytxfee=<amount>: '%s' + Ugyldigt beløb for -paytxfee=<amount>: '%s' + + + + Error: could not start node + Fejl: kunne ikke starte node + + + + Sending... + Sender... + + + + Invalid amount + Ugyldigt beløb + + + + Insufficient funds + Manglende dækning + + + + Loading block index... + Indlæser blokindeks... + + + + Add a node to connect to and attempt to keep the connection open + Tilføj en knude til at forbinde til og forsøg at holde forbindelsen åben + + + + Unable to bind to %s on this computer. Arepacoin is probably already running. + Kunne ikke binde sig til% s på denne computer. Arepacoin kører sikkert allerede. + + + + Fee per KB to add to transactions you send + Gebyr pr KB som tilføjes til transaktioner, du sender + + + + Invalid amount for -mininput=<amount>: '%s' + Ugyldigt beløb for-mininput = <beløb>: '% s' + + + + Loading wallet... + Indlæser tegnebog... + + + + Cannot downgrade wallet + Kan ikke nedgradere tegnebog + + + + Cannot initialize keypool + Kan ikke initialisere keypool + + + + Cannot write default address + Kan ikke skrive standardadresse + + + + Rescanning... + Genindlæser... + + + + Done loading + Indlæsning gennemført + + + + To use the %s option + For at bruge %s mulighed + + + + Error + Fejl + + + + You must set rpcpassword=<password> in the configuration file: +%s +If the file does not exist, create it with owner-readable-only file permissions. + Du skal angive rpcpassword=<password> i konfigurationsfilen: +%s +Hvis filen ikke eksisterer, opret den og giv ingen andre end ejeren læserettighed. + + + \ No newline at end of file diff --git a/src/qt/locale/bitcoin_de.ts b/src/qt/locale/bitcoin_de.ts new file mode 100755 index 0000000..e8787b8 --- /dev/null +++ b/src/qt/locale/bitcoin_de.ts @@ -0,0 +1,3285 @@ + + + AboutDialog + + + About Arepacoin + Über Arepacoin + + + + <b>Arepacoin</b> version + <b>Arepacoin</b> Version + + + + Copyright © 2009-2014 The Bitcoin developers +Copyright © 2012-2014 The NovaCoin developers +Copyright © 2014 The Arepacoin developers + + + + + +This is experimental software. + +Distributed under the MIT/X11 software license, see the accompanying file COPYING or http://www.opensource.org/licenses/mit-license.php. + +This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit (http://www.openssl.org/) and cryptographic software written by Eric Young (eay@cryptsoft.com) and UPnP software written by Thomas Bernard. + +Dies ist experimentelle Software. + +Veröffentlicht unter der MIT/X11-Softwarelizenz, siehe beiligende Datei COPYING oder http://www.opensource.org/licenses/mit-license.php. + +Dieses Produkt enthält Software, die vom OpenSSL-Projekt zur Verwendung im OpenSSL-Toolkit (http://www.openssl.org/) entwickelt wurde, sowie kryptographische Software geschrieben von Eric Young (eay@cryptsoft.com) und UPnP-Software geschrieben von Thomas Bernard. + + + + AddressBookPage + + + Address Book + Adressbuch + + + + Double-click to edit address or label + Doppelklicken, um die Adresse oder die Bezeichnung zu bearbeiten + + + + Create a new address + Eine neue Adresse erstellen + + + + Copy the currently selected address to the system clipboard + Ausgewählte Adresse in die Zwischenablage kopieren + + + + &New Address + &Neue Adresse + + + + These are your Arepacoin addresses for receiving payments. You may want to give a different one to each sender so you can keep track of who is paying you. + Das sind Ihre Arepacoin Adressen um Zahlungen zu erhalten. Sie werden vielleicht verschiedene an jeden Sender vergeben, damit Sie im Auge behalten können wer sie bezahlt. + + + + &Copy Address + Adresse &kopieren + + + + Show &QR Code + &QR Code anzeigen + + + + Sign a message to prove you own a Arepacoin address + + + + + Sign &Message + + + + + Delete the currently selected address from the list + Ausgewählte Adresse aus der Liste entfernen + + + + Verify a message to ensure it was signed with a specified Arepacoin address + + + + + &Verify Message + + + + + &Delete + &Löschen + + + + Copy &Label + &Bezeichnung kopieren + + + + &Edit + &Editieren + + + + Export Address Book Data + + + + + Comma separated file (*.csv) + Kommagetrennte-Datei (*.csv) + + + + Error exporting + + + + + Could not write to file %1. + + + + + AddressTableModel + + + Label + Bezeichnung + + + + Address + Adresse + + + + (no label) + (keine Bezeichnung) + + + + AskPassphraseDialog + + + Passphrase Dialog + Passphrasendialog + + + + Enter passphrase + Passphrase eingeben + + + + New passphrase + Neue Passphrase + + + + Repeat new passphrase + Neue Passphrase wiederholen + + + + Serves to disable the trivial sendmoney when OS account compromised. Provides no real security. + + + + + For staking only + Anteil der im Netz reift und nur Zinsen kreiert. + + + + Enter the new passphrase to the wallet.<br/>Please use a passphrase of <b>10 or more random characters</b>, or <b>eight or more words</b>. + Geben Sie die neue Passphrase für die Wallet ein.<br>Bitte benutzen Sie eine Passphrase bestehend aus <b>10 oder mehr zufälligen Zeichen</b> oder <b>8 oder mehr Wörtern</b>. + + + + Encrypt wallet + Wallet verschlüsseln + + + + This operation needs your wallet passphrase to unlock the wallet. + Dieser Vorgang benötigt ihre Passphrase, um die Wallet zu entsperren. + + + + Unlock wallet + Wallet entsperren + + + + This operation needs your wallet passphrase to decrypt the wallet. + Dieser Vorgang benötigt ihre Passphrase, um die Wallet zu entschlüsseln. + + + + Decrypt wallet + Wallet entschlüsseln + + + + Change passphrase + Passphrase ändern + + + + Enter the old and new passphrase to the wallet. + Geben Sie die alte und neue Wallet-Passphrase ein. + + + + Confirm wallet encryption + Wallet-Verschlüsselung bestätigen + + + + Warning: If you encrypt your wallet and lose your passphrase, you will <b>LOSE ALL OF YOUR COINS</b>! + + + + + Are you sure you wish to encrypt your wallet? + Sind Sie sich sicher, dass Sie ihre Wallet verschlüsseln möchten? + + + + IMPORTANT: Any previous backups you have made of your wallet file should be replaced with the newly generated, encrypted wallet file. For security reasons, previous backups of the unencrypted wallet file will become useless as soon as you start using the new, encrypted wallet. + WICHTIG: Alle vorherigen Wallet-Sicherungen sollten durch die neu erzeugte, verschlüsselte Wallet ersetzt werden. Aus Sicherheitsgründen werden vorherige Sicherungen der unverschlüsselten Wallet nutzlos, sobald Sie die neue, verschlüsselte Wallet verwenden. + + + + + Warning: The Caps Lock key is on! + Warnung: Die Feststelltaste ist aktiviert! + + + + + Wallet encrypted + Wallet verschlüsselt + + + + Arepacoin will close now to finish the encryption process. Remember that encrypting your wallet cannot fully protect your coins from being stolen by malware infecting your computer. + + + + + + + + Wallet encryption failed + Wallet-Verschlüsselung fehlgeschlagen + + + + Wallet encryption failed due to an internal error. Your wallet was not encrypted. + Die Wallet-Verschlüsselung ist aufgrund eines internen Fehlers fehlgeschlagen. Ihre Wallet wurde nicht verschlüsselt. + + + + + The supplied passphrases do not match. + Die eingegebenen Passphrasen stimmen nicht überein. + + + + Wallet unlock failed + Wallet-Entsperrung fehlgeschlagen + + + + + + The passphrase entered for the wallet decryption was incorrect. + Die eingegebene Passphrase zur Wallet-Entschlüsselung war nicht korrekt. + + + + Wallet decryption failed + Wallet-Entschlüsselung fehlgeschlagen + + + + Wallet passphrase was successfully changed. + Die Wallet-Passphrase wurde erfolgreich geändert. + + + + BitcoinGUI + + + Sign &message... + Nachricht &signieren... + + + + Synchronizing with network... + Synchronisiere mit Netzwerk... + + + + &Overview + &Übersicht + + + + Show general overview of wallet + Allgemeine Wallet-Übersicht anzeigen + + + + &Transactions + &Transaktionen + + + + Browse transaction history + Transaktionsverlauf durchsehen + + + + &Address Book + + + + + Edit the list of stored addresses and labels + + + + + &Receive coins + + + + + Show the list of addresses for receiving payments + + + + + &Send coins + + + + + E&xit + &Beenden + + + + Quit application + Anwendung beenden + + + + Show information about Arepacoin + + + + + About &Qt + Über &Qt + + + + Show information about Qt + Informationen über Qt anzeigen + + + + &Options... + &Konfiguration... + + + + &Encrypt Wallet... + Wallet &verschlüsseln... + + + + &Backup Wallet... + Wallet &sichern... + + + + &Change Passphrase... + Passphrase &ändern... + + + + ~%n block(s) remaining + + + + + Downloaded %1 of %2 blocks of transaction history (%3% done). + + + + + &Export... + + + + + Send coins to a Arepacoin address + + + + + Modify configuration options for Arepacoin + + + + + Export the data in the current tab to a file + + + + + Encrypt or decrypt wallet + + + + + Backup wallet to another location + Eine Wallet-Sicherungskopie erstellen und abspeichern + + + + Change the passphrase used for wallet encryption + Ändert die Passphrase, die für die Wallet-Verschlüsselung benutzt wird + + + + &Debug window + &Debugfenster + + + + Open debugging and diagnostic console + Debugging- und Diagnosekonsole öffnen + + + + &Verify message... + Nachricht &verifizieren... + + + + Arepacoin + + + + + Wallet + Wallet + + + + &About Arepacoin + + + + + &Show / Hide + &Anzeigen / Verstecken + + + + Unlock wallet + + + + + &Lock Wallet + + + + + Lock wallet + + + + + &File + &Datei + + + + &Settings + &Einstellungen + + + + &Help + &Hilfe + + + + Tabs toolbar + Registerkartenleiste + + + + Actions toolbar + + + + + + [testnet] + [Testnetz] + + + + + Arepacoin client + + + + + %n active connection(s) to Arepacoin network + + + + + Downloaded %1 blocks of transaction history. + + + + + Staking.<br>Your weight is %1<br>Network weight is %2<br>Expected time to earn reward is %3 + + + + + Not staking because wallet is locked + + + + + Not staking because wallet is offline + + + + + Not staking because wallet is syncing + + + + + Not staking because you don't have mature coins + + + + + %n second(s) ago + + + + + &Unlock Wallet... + + + + + %n minute(s) ago + + + + + %n hour(s) ago + + + + + %n day(s) ago + + + + + Up to date + Auf aktuellem Stand + + + + Catching up... + Hole auf... + + + + Last received block was generated %1. + + + + + This transaction is over the size limit. You can still send it for a fee of %1, which goes to the nodes that process your transaction and helps to support the network. Do you want to pay the fee? + + + + + Confirm transaction fee + + + + + Sent transaction + Gesendete Transaktion + + + + Incoming transaction + Eingehende Transaktion + + + + Date: %1 +Amount: %2 +Type: %3 +Address: %4 + + Datum: %1 +Betrag: %2 +Typ: %3 +Adresse: %4 + + + + + URI handling + + + + + + URI can not be parsed! This can be caused by an invalid Arepacoin address or malformed URI parameters. + + + + + Wallet is <b>encrypted</b> and currently <b>unlocked</b> + Wallet ist <b>verschlüsselt</b> und aktuell <b>entsperrt</b> + + + + Wallet is <b>encrypted</b> and currently <b>locked</b> + Wallet ist <b>verschlüsselt</b> und aktuell <b>gesperrt</b> + + + + Backup Wallet + + + + + Wallet Data (*.dat) + + + + + Backup Failed + + + + + There was an error trying to save the wallet data to the new location. + + + + + %n second(s) + + + + + %n minute(s) + + + + + %n hour(s) + %n Stunde%n Stunden + + + + %n day(s) + %n Tag%n Tage + + + + Not staking + + + + + A fatal error occurred. Arepacoin can no longer continue safely and will quit. + + + + + ClientModel + + + Network Alert + Netzwerkalarm + + + + CoinControlDialog + + + Coin Control + + + + + Quantity: + Anzahl: + + + + Bytes: + Byte: + + + + Amount: + Betrag: + + + + Priority: + Priorität: + + + + Fee: + Gebühr: + + + + Low Output: + Zu geringer Ausgabebetrag: + + + + no + nein + + + + After Fee: + Abzüglich Gebühr: + + + + Change: + Wechselgeld: + + + + (un)select all + Alles (de)selektieren + + + + Tree mode + Baumansicht + + + + List mode + Listenansicht + + + + Amount + Betrag + + + + Label + Bezeichnung + + + + Address + Adresse + + + + Date + Datum + + + + Confirmations + Bestätigungen + + + + Confirmed + Bestätigt + + + + Priority + Priorität + + + + Copy address + Adresse kopieren + + + + Copy label + Bezeichnung kopieren + + + + + Copy amount + Betrag kopieren + + + + Copy transaction ID + Transaktions-ID kopieren + + + + Copy quantity + Anzahl kopieren + + + + Copy fee + Gebühr kopieren + + + + Copy after fee + Abzüglich Gebühr kopieren + + + + Copy bytes + Byte kopieren + + + + Copy priority + Priorität kopieren + + + + Copy low output + Zu geringen Ausgabebetrag kopieren + + + + Copy change + Wechselgeld kopieren + + + + highest + am höchsten + + + + high + hoch + + + + medium-high + mittel-hoch + + + + medium + mittel + + + + low-medium + niedrig-mittel + + + + low + niedrig + + + + lowest + am niedrigsten + + + + DUST + STAUB + + + + yes + ja + + + + This label turns red, if the transaction size is bigger than 10000 bytes. + + This means a fee of at least %1 per kb is required. + + Can vary +/- 1 Byte per input. + + + + + Transactions with higher priority get more likely into a block. + +This label turns red, if the priority is smaller than "medium". + + This means a fee of at least %1 per kb is required. + + + + + This label turns red, if any recipient receives an amount smaller than %1. + + This means a fee of at least %2 is required. + + Amounts below 0.546 times the minimum relay fee are shown as DUST. + + + + + This label turns red, if the change is smaller than %1. + + This means a fee of at least %2 is required. + + + + + + (no label) + (keine Bezeichnung) + + + + change from %1 (%2) + Wechselgeld von %1 (%2) + + + + (change) + (Wechselgeld) + + + + EditAddressDialog + + + Edit Address + Adresse bearbeiten + + + + &Label + &Bezeichnung + + + + The label associated with this address book entry + Die Kennzeichnung verbunden mit diesem Adressbucheintrag. + + + + &Address + &Adresse + + + + The address associated with this address book entry. This can only be modified for sending addresses. + Die Adresse verknüpft mit diesem Adressbucheintrag. Kann nur bei Ausgangsadressen verändert werden. + + + + New receiving address + Neue Empfangsadresse + + + + New sending address + Neue Zahlungsadresse + + + + Edit receiving address + Empfangsadresse bearbeiten + + + + Edit sending address + Zahlungsadresse bearbeiten + + + + The entered address "%1" is already in the address book. + Die eingegebene Adresse "%1" befindet sich bereits im Adressbuch. + + + + The entered address "%1" is not a valid Arepacoin address. + Die eingegebene Adresse "%1" ist keine gültige Arepacoin Adresse. + + + + Could not unlock wallet. + Wallet konnte nicht entsperrt werden. + + + + New key generation failed. + Generierung eines neuen Schlüssels fehlgeschlagen. + + + + GUIUtil::HelpMessageBox + + + + Arepacoin-Qt + + + + + version + version + + + + Usage: + Benutzung: + + + + command-line options + Kommandozeilen optionen + + + + UI options + + + + + Set language, for example "de_DE" (default: system locale) + + + + + Start minimized + Minimiert starten + + + + Show splash screen on startup (default: 1) + + + + + OptionsDialog + + + Options + Erweiterte Einstellungen + + + + &Main + &Allgemein + + + + Optional transaction fee per kB that helps make sure your transactions are processed quickly. Most transactions are 1 kB. Fee 0.01 recommended. + + + + + Pay transaction &fee + Transaktions&gebühr bezahlen + + + + Reserved amount does not participate in staking and is therefore spendable at any time. + + + + + Reserve + Reserviert + + + + Automatically start Arepacoin after logging in to the system. + Automatisch Arepacoin starten beim Einloggen in das System. + + + + &Start Arepacoin on system login + &Starte Arepacoin bei Systemstart + + + + Detach block and address databases at shutdown. This means they can be moved to another data directory, but it slows down shutdown. The wallet is always detached. + + + + + &Detach databases at shutdown + + + + + &Network + &Netzwerk + + + + Automatically open the Arepacoin client port on the router. This only works when your router supports UPnP and it is enabled. + Automatisch den Arepacoin client port auf dem Router öffnen. Das funktioniert nur wenn der Router UPnP unterstützt und UPnP aktiviert ist. + + + + Map port using &UPnP + Portweiterleitung via &UPnP + + + + Connect to the Arepacoin network through a SOCKS proxy (e.g. when connecting through Tor). + + + + + &Connect through SOCKS proxy: + + + + + Proxy &IP: + Proxy-&IP: + + + + IP address of the proxy (e.g. 127.0.0.1) + IP Adresse des Proxy (z.B. 127.0.01) + + + + &Port: + &Port: + + + + Port of the proxy (e.g. 9050) + Port des Proxies (z.B. 9050) + + + + SOCKS &Version: + SOCKS-&Version: + + + + SOCKS version of the proxy (e.g. 5) + SOCKS-Version des Proxies (z.B. 5) + + + + &Window + &Programmfenster + + + + Show only a tray icon after minimizing the window. + Nur ein Symbol im Infobereich anzeigen, nachdem das Programmfenster minimiert wurde. + + + + &Minimize to the tray instead of the taskbar + In den Infobereich anstatt in die Taskleiste &minimieren + + + + Minimize instead of exit the application when the window is closed. When this option is enabled, the application will be closed only after selecting Quit in the menu. + Minimiert die Anwendung anstatt sie zu beenden wenn das Fenster geschlossen wird. Wenn dies aktiviert ist, müssen Sie das Programm über "Beenden" im Menü schließen. + + + + M&inimize on close + Beim Schließen m&inimieren + + + + &Display + &Anzeige + + + + User Interface &language: + &Sprache der Benutzeroberfläche: + + + + The user interface language can be set here. This setting will take effect after restarting Arepacoin. + Die Sprache der GUI kann hier verändert werden. Die Einstellung wird nach einem Neustart übernommen. + + + + &Unit to show amounts in: + &Einheit der Beträge: + + + + Choose the default subdivision unit to show in the interface and when sending coins. + Wählen Sie die Standarduntereinheit, die in der Benutzeroberfläche und beim Überweisen von Bitcoins angezeigt werden soll. + + + + Whether to show Arepacoin addresses in the transaction list or not. + Arepacoin Adressen in der Überweisung anzeigen oder nicht. + + + + &Display addresses in transaction list + Adressen in der Transaktionsliste &anzeigen + + + + Whether to show coin control features or not. + Legt fest, ob die "Coin Control"-Funktionen angezeigt werden. + + + + Display coin &control features (experts only!) + Coin &control features anzeigen (nur experten!) + + + + &OK + &OK + + + + &Cancel + &Abbrechen + + + + &Apply + &Anwenden + + + + default + Standard + + + + + Warning + Warnung + + + + + This setting will take effect after restarting Arepacoin. + Diese Einstellung wird nach einem Neustart übernommen. + + + + The supplied proxy address is invalid. + Die eingegebene Proxyadresse ist ungültig. + + + + OverviewPage + + + Form + Formular + + + + + The displayed information may be out of date. Your wallet automatically synchronizes with the Arepacoin network after a connection is established, but this process has not completed yet. + Die angezeigte Information kann falsch sein. Die Brieftasche synchronisiert automatisch mit dem Arepacoin Netzwerk nachdem eine Verbindung zustande gekommen ist, aber dieser Prozess ist nicht abgeschlossen. + + + + Stake: + + + + + Unconfirmed: + Unbestätigt: + + + + Wallet + Wallet + + + + Spendable: + Ausgabebereit: + + + + Your current spendable balance + Ihr aktuell verfügbarer Kontostand + + + + Immature: + Unreif: + + + + Mined balance that has not yet matured + Erarbeiteter Betrag der noch nicht gereift ist + + + + Total: + Gesamtbetrag: + + + + Your current total balance + Aktueller Gesamtbetrag aus obigen Kategorien + + + + <b>Recent transactions</b> + <b>Letzte Transaktionen</b> + + + + Total of transactions that have yet to be confirmed, and do not yet count toward the current balance + Anzahl der unbestätigten Transaktionen die somit noch nicht zum aktuellen Kontostand zählen. + + + + Total of coins that was staked, and do not yet count toward the current balance + + + + + + out of sync + nicht synchron + + + + QRCodeDialog + + + QR Code Dialog + QR Code Dialog + + + + Request Payment + Zahlung anfordern + + + + Amount: + Betrag: + + + + Label: + Bezeichnung: + + + + Message: + Nachricht: + + + + &Save As... + & Speichern als... + + + + Error encoding URI into QR Code. + Fehler beim Kodieren der URI in den QR-Code. + + + + The entered amount is invalid, please check. + Der eingegebene Betrag ist ungültig, bitte überprüfen. + + + + Resulting URI too long, try to reduce the text for label / message. + Resultierende URI zu lang, bitte den Text für Bezeichnung / Nachricht kürzen. + + + + Save QR Code + QR Code Speichern + + + + PNG Images (*.png) + PNG Grafik (*.png) + + + + RPCConsole + + + Client name + Clientname + + + + + + + + + + + + + N/A + k.A. + + + + Client version + Clientversion + + + + &Information + &Information + + + + Using OpenSSL version + Verwendete OpenSSL-Version + + + + Startup time + Startzeit + + + + Network + Netzwerk + + + + Number of connections + Anzahl Verbindungen + + + + On testnet + Am Testnetz + + + + Block chain + Block kette + + + + Current number of blocks + Aktuelle Anzahl Blöcke + + + + Estimated total blocks + Geschätzte Gesamtzahl Blöcke + + + + Last block time + Letzte Blockzeit + + + + &Open + &Öffnen + + + + Command-line options + Kommandozeilen Optionen: + + + + Show the Arepacoin-Qt help message to get a list with possible Arepacoin command-line options. + + + + + &Show + &Zeigen + + + + &Console + &Konsole + + + + Build date + Erstellungsdatum + + + + Arepacoin - Debug window + Arepacoin - Debug Fenster + + + + Arepacoin Core + Arepacoin Kern + + + + Debug log file + Debugprotokolldatei + + + + Open the Arepacoin debug log file from the current data directory. This can take a few seconds for large log files. + + + + + Clear console + Konsole zurücksetzen + + + + Welcome to the Arepacoin RPC console. + + + + + Use up and down arrows to navigate history, and <b>Ctrl-L</b> to clear screen. + Pfeiltaste hoch und runter, um den Verlauf durchzublättern und <b>Strg-L</b>, um die Konsole zurückzusetzen. + + + + Type <b>help</b> for an overview of available commands. + Bitte <b>help</b> eingeben, um eine Übersicht verfügbarer Befehle zu erhalten. + + + + SendCoinsDialog + + + + + + + + + + Send Coins + Bitcoins überweisen + + + + Coin Control Features + "Coin Control"-Funktionen + + + + Inputs... + Eingaben... + + + + automatically selected + automatisch ausgewählt + + + + Insufficient funds! + Unzureichender Kontostand! + + + + Quantity: + Anzahl: + + + + + 0 + + + + + Bytes: + Byte: + + + + Amount: + Betrag: + + + + + + + 0.00 BC + + + + + Priority: + Priorität: + + + + medium + + + + + Fee: + Gebühr: + + + + Low Output: + Zu geringer Ausgabebetrag: + + + + no + + + + + After Fee: + Abzüglich Gebühr: + + + + Change + + + + + custom change address + + + + + Send to multiple recipients at once + In einer Transaktion an mehrere Empfänger auf einmal überweisen + + + + Add &Recipient + Empfänger &hinzufügen + + + + Remove all transaction fields + + + + + Clear &All + &Zurücksetzen + + + + Balance: + Kontostand: + + + + 123.456 BC + + + + + Confirm the send action + Überweisung bestätigen + + + + S&end + &Überweisen + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Copy quantity + Anzahl kopieren + + + + Copy amount + Betrag kopieren + + + + Copy fee + Gebühr kopieren + + + + Copy after fee + Abzüglich Gebühr kopieren + + + + Copy bytes + Byte kopieren + + + + Copy priority + Priorität kopieren + + + + Copy low output + Zu geringen Ausgabebetrag kopieren + + + + Copy change + Wechselgeld kopieren + + + + <b>%1</b> to %2 (%3) + + + + + Confirm send coins + Überweisung bestätigen + + + + Are you sure you want to send %1? + + + + + and + + + + + The recipient address is not valid, please recheck. + Die Zahlungsadresse ist ungültig, bitte nochmals überprüfen. + + + + The amount to pay must be larger than 0. + Der zu zahlende Betrag muss größer als 0 sein. + + + + The amount exceeds your balance. + Der angegebene Betrag übersteigt ihren Kontostand. + + + + The total exceeds your balance when the %1 transaction fee is included. + Der angegebene Betrag übersteigt aufgrund der Transaktionsgebühr in Höhe von %1 ihren Kontostand. + + + + Duplicate address found, can only send to each address once per send operation. + Doppelte Adresse gefunden, pro Überweisung kann an jede Adresse nur einmalig etwas überwiesen werden. + + + + Error: Transaction creation failed. + + + + + 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. + + + + + WARNING: Invalid Arepacoin address + + + + + (no label) + (keine Bezeichnung) + + + + WARNING: unknown change address + + + + + SendCoinsEntry + + + Form + + + + + A&mount: + &Betrag: + + + + Pay &To: + &Empfänger: + + + + + Enter a label for this address to add it to your address book + Adressbezeichnung eingeben (diese wird zusammen mit der Adresse dem Adressbuch hinzugefügt) + + + + &Label: + &Bezeichnung: + + + + The address to send the payment to (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + Empfängeradresse (z.b. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + Choose address from address book + Adresse aus dem Adressbuch auswählen + + + + Alt+A + Alt+A + + + + Paste address from clipboard + Adresse aus der Zwischenablage einfügen + + + + Alt+P + Alt+P + + + + Remove this recipient + + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + SignVerifyMessageDialog + + + Signatures - Sign / Verify a Message + Signaturen - eine Nachricht signieren / verifizieren + + + + + &Sign Message + Nachricht &signieren + + + + You can sign messages with your addresses to prove you own them. Be careful not to sign anything vague, as phishing attacks may try to trick you into signing your identity over to them. Only sign fully-detailed statements you agree to. + Sie können Nachrichten mit ihren Adressen signieren, um den Besitz dieser Adressen zu beweisen. Bitte nutzen Sie diese Funktion mit Vorsicht und nehmen Sie sich vor Phishingangriffen in Acht. Signieren Sie nur Nachrichten, mit denen Sie vollständig einverstanden sind. + + + + The address to sign the message with (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + + Choose an address from the address book + Eine Adresse aus dem Adressbuch wählen + + + + + Alt+A + Alt+A + + + + Paste address from clipboard + Adresse aus der Zwischenablage einfügen + + + + Alt+P + Alt+P + + + + Enter the message you want to sign here + Zu signierende Nachricht hier eingeben + + + + Copy the current signature to the system clipboard + Aktuelle Signatur in die Zwischenablage kopieren + + + + Sign the message to prove you own this Arepacoin address + Signiere die Nachricht um zu beweisen das du Besitzer dieser Arepacoin Adresse bist. + + + + Reset all sign message fields + Alle "Nachricht signieren"-Felder zurücksetzen + + + + + Clear &All + &Zurücksetzen + + + + + &Verify Message + Nachricht &verifizieren + + + + Enter the signing address, message (ensure you copy line breaks, spaces, tabs, etc. exactly) and signature below to verify the message. Be careful not to read more into the signature than what is in the signed message itself, to avoid being tricked by a man-in-the-middle attack. + Geben Sie die signierende Adresse, Nachricht (achten Sie darauf Zeilenumbrüche, Leerzeichen, Tabulatoren usw. exakt zu kopieren) und Signatur unten ein, um die Nachricht zu verifizieren. Vorsicht, interpretieren Sie nicht mehr in die Signatur, als in der signierten Nachricht selber enthalten ist, um nicht von einem Man-in-the-middle-Angriff hinters Licht geführt zu werden. + + + + The address the message was signed with (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Verify the message to ensure it was signed with the specified Arepacoin address + + + + + Reset all verify message fields + Alle "Nachricht verifizieren"-Felder zurücksetzen + + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Click "Sign Message" to generate signature + Auf "Nachricht signieren" klicken, um die Signatur zu erzeugen + + + + Enter Arepacoin signature + Arepacoin Signatur eingeben + + + + + The entered address is invalid. + Die eingegebene Adresse ist ungültig. + + + + + + + Please check the address and try again. + Bitte überprüfen Sie die Adresse und versuchen Sie es erneut. + + + + + The entered address does not refer to a key. + Die eingegebene Adresse verweist nicht auf einen Schlüssel. + + + + Wallet unlock was cancelled. + Wallet-Entsperrung wurde abgebrochen. + + + + Private key for the entered address is not available. + Privater Schlüssel zur eingegebenen Adresse ist nicht verfügbar. + + + + Message signing failed. + Signierung der Nachricht fehlgeschlagen. + + + + Message signed. + Nachricht signiert. + + + + The signature could not be decoded. + Die Signatur konnte nicht dekodiert werden. + + + + + Please check the signature and try again. + Bitte überprüfen Sie die Signatur und versuchen Sie es erneut. + + + + The signature did not match the message digest. + Die Signatur entspricht nicht dem Message Digest. + + + + Message verification failed. + Verifikation der Nachricht fehlgeschlagen. + + + + Message verified. + Nachricht verifiziert. + + + + TransactionDesc + + + Open until %1 + Offen bis %1 + + + + Open for %n block(s) + Offen für %n weitere BlöckeOffen für %n weitere Blöcke + + + + conflicted + kollidiert + + + + %1/offline + %1/offline + + + + %1/unconfirmed + %1/unbestätigt + + + + %1 confirmations + %1 Bestätigungen + + + + Status + Status + + + + , broadcast through %n node(s) + , über %n Knoten übertragen, über %n Knoten übertragen + + + + Date + Datum + + + + Source + Quelle + + + + Generated + Generiert + + + + + From + Von + + + + + + To + An + + + + + own address + eigene Adresse + + + + label + Bezeichnung + + + + + + + + Credit + Gutschrift + + + + matures in %n more block(s) + reift noch %n weiteren Blockreift noch %n weitere Blöcke + + + + not accepted + nicht angenommen + + + + + + + Debit + Belastung + + + + Transaction fee + Transaktionsgebühr + + + + Net amount + Nettobetrag + + + + Message + Nachricht signieren + + + + Comment + Kommentar + + + + Transaction ID + Transaktions-ID + + + + Generated coins must mature 6 blocks before they can be spent. When you generated this block, it was broadcast to the network to be added to the block chain. If it fails to get into the chain, its state will change to "not accepted" and it won't be spendable. This may occasionally happen if another node generates a block within a few seconds of yours. + Generierte Coins müssen 6 Bestätigungen erhalten bevor sie verfügbar sind. Dieser Block wurde ans Netzwerk gesendet und der Blockkette angehängt als der Block generiert wurde. Wenn er der Blockkette nicht erfolgreich angehängt werden konnte, wird er den Status in "nicht Akzeptiert" ändern und wird nicht verfügbar sein. Das kann zufällig geschehen wenn eine andere Leitung den Block innerhalb von ein paar Sekunden generiert. + + + + Debug information + Debuginformationen + + + + Transaction + Transaktion + + + + Inputs + Eingaben + + + + Amount + Betrag + + + + true + wahr + + + + false + falsch + + + + , has not been successfully broadcast yet + , wurde noch nicht erfolgreich übertragen + + + + unknown + unbekannt + + + + TransactionDescDialog + + + Transaction details + Transaktionsdetails + + + + This pane shows a detailed description of the transaction + Dieser Bereich zeigt eine detaillierte Beschreibung der Transaktion an + + + + TransactionTableModel + + + Date + Datum + + + + Type + Typ + + + + Address + Adresse + + + + Amount + Betrag + + + + Open until %1 + Offen bis %1 + + + + Confirmed (%1 confirmations) + Bestätigt (%1 Bestätigungen) + + + + Open for %n more block(s) + Offen für %n weiteren BlockOffen für %n weitere Blöcke + + + + Offline + + + + + Unconfirmed + Unbestätigt: + + + + Confirming (%1 of %2 recommended confirmations) + wird Bestätigt (%1 von %2 Bestätigungen) + + + + Conflicted + Konflikt + + + + Immature (%1 confirmations, will be available after %2) + Unreif (%1 Bestätigungen, wird verfügbar sein nach %2) + + + + This block was not received by any other nodes and will probably not be accepted! + Dieser Block wurde von keinem anderen Knoten empfangen und wird wahrscheinlich nicht angenommen werden! + + + + Generated but not accepted + Generiert, jedoch nicht angenommen + + + + Received with + Empfangen über + + + + Received from + Empfangen von + + + + Sent to + Überwiesen an + + + + Payment to yourself + Eigenüberweisung + + + + Mined + Erarbeitet + + + + (n/a) + (k.A.) + + + + Transaction status. Hover over this field to show number of confirmations. + Transaktionsstatus. Fahren Sie mit der Maus über dieses Feld, um die Anzahl der Bestätigungen zu sehen. + + + + Date and time that the transaction was received. + Datum und Uhrzeit als die Transaktion empfangen wurde. + + + + Type of transaction. + Art der Transaktion + + + + Destination address of transaction. + Zieladresse der Transaktion + + + + Amount removed from or added to balance. + Der Betrag, der dem Kontostand abgezogen oder hinzugefügt wurde. + + + + TransactionView + + + + All + Alle + + + + Today + Heute + + + + This week + Diese Woche + + + + This month + Diesen Monat + + + + Last month + Letzten Monat + + + + This year + Dieses Jahr + + + + Range... + Zeitraum... + + + + Received with + Empfangen über + + + + Sent to + Überwiesen an + + + + To yourself + Eigenüberweisung + + + + Mined + Erarbeitet + + + + Other + Andere + + + + Enter address or label to search + Zu suchende Adresse oder Bezeichnung eingeben + + + + Min amount + Minimaler Betrag + + + + Copy address + Adresse kopieren + + + + Copy label + Bezeichnung kopieren + + + + Copy amount + Betrag kopieren + + + + Copy transaction ID + Transaktions-ID kopieren + + + + Edit label + Bezeichnung bearbeiten + + + + Show transaction details + Transaktionsdetails anzeigen + + + + Export Transaction Data + Exportiere Transaktionsdaten + + + + Comma separated file (*.csv) + Kommagetrennte-Datei (*.csv) + + + + Confirmed + Bestätigt + + + + Date + Datum + + + + Type + Typ + + + + Label + Bezeichnung + + + + Address + Adresse + + + + Amount + Betrag + + + + ID + ID + + + + Error exporting + Fehler beim Exportieren + + + + Could not write to file %1. + Kann Datei nicht schreiben %1. + + + + Range: + Zeitraum: + + + + to + bis + + + + WalletModel + + + Sending... + Wird gesendet... + + + + bitcoin-core + + + Arepacoin version + + + + + Usage: + Benutzung: + + + + Send command to -server or arepacoind + Kommando versenden an -server oder arepacoind + + + + List commands + Befehle auflisten + + + + Get help for a command + Hilfe zu einem Befehl erhalten + + + + Options: + Optionen: + + + + Specify configuration file (default: arepacoin.conf) + Konfigurationsdatei angeben (Standard: arepacoin.conf) + + + + Specify pid file (default: arepacoind.pid) + PID Datei angeben (Standard: arepacoin.pid) + + + + Specify wallet file (within data directory) + Wallet-Datei festlegen (innerhalb des Datenverzeichnisses) + + + + Specify data directory + Datenverzeichnis festlegen + + + + Set database cache size in megabytes (default: 25) + Größe des Datenbankcaches in MB festlegen (Standard: 25) + + + + Set database disk log size in megabytes (default: 100) + + + + + Listen for connections on <port> (default: 9853 or testnet: 19853) + + + + + Maintain at most <n> connections to peers (default: 125) + Maximal <n> Verbindungen zu Gegenstellen aufrechterhalten (Standard: 125) + + + + Connect to a node to retrieve peer addresses, and disconnect + Mit dem Knoten verbinden um Adressen von Gegenstellen abzufragen, danach trennen + + + + Specify your own public address + Die eigene öffentliche Adresse angeben + + + + Bind to given address. Use [host]:port notation for IPv6 + + + + + Stake your coins to support network and gain reward (default: 1) + + + + + Threshold for disconnecting misbehaving peers (default: 100) + Schwellenwert, um Verbindungen zu sich nicht konform verhaltenden Gegenstellen zu beenden (Standard: 100) + + + + Number of seconds to keep misbehaving peers from reconnecting (default: 86400) + Anzahl Sekunden, während denen sich nicht konform verhaltenden Gegenstellen die Wiederverbindung verweigert wird (Standard: 86400) + + + + An error occurred while setting up the RPC port %u for listening on IPv4: %s + Beim Einrichten des abzuhörenden RPC-Ports %u für IPv4 ist ein Fehler aufgetreten: %s + + + + Detach block and address databases. Increases shutdown time (default: 0) + + + + + 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. + Fehler: Transaktion wurde abgelehnt. Das kann geschehen wenn einige Coins in der Brieftasche bereits ausgegeben wurden, wenn von einer Kopie der wallet.dat Coins ausgegeben wurden werden sie hier nicht als Ausgabe aufgeführt. + + + + Error: This transaction requires a transaction fee of at least %s because of its amount, complexity, or use of recently received funds + Fehler: Diese Transaktion benötigt eine Transaktionsgebühr von mindestens %s wegen der Anzahl, Komplexität oder Benutzung von neuerlich erhaltenen Beträgen. + + + + Listen for JSON-RPC connections on <port> (default: 9852 or testnet: 19852) + + + + + Accept command line and JSON-RPC commands + Kommandozeilenbefehle und JSON-RPC-Befehle annehmen + + + + Error: Transaction creation failed + Fehler: Erstellung der Transaktion fehlgeschlagen + + + + Error: Wallet locked, unable to create transaction + Fehler: Brieftasche verschlüsselt, unfähig Transaktion zu erstellen + + + + Importing blockchain data file. + Importiere Block Kette aus Datei + + + + Importing bootstrap blockchain data file. + + + + + Run in the background as a daemon and accept commands + Als Hintergrunddienst starten und Befehle annehmen + + + + Use the test network + Das Testnetz verwenden + + + + Accept connections from outside (default: 1 if no -proxy or -connect) + Eingehende Verbindungen annehmen (Standard: 1, wenn nicht -proxy oder -connect) + + + + An error occurred while setting up the RPC port %u for listening on IPv6, falling back to IPv4: %s + Beim Einrichten des abzuhörenden RPC-Ports %u für IPv6 ist ein Fehler aufgetreten, es wird auf IPv4 zurückgegriffen: %s + + + + Error initializing database environment %s! To recover, BACKUP THAT DIRECTORY, then remove everything from it except for wallet.dat. + + + + + Set maximum size of high-priority/low-fee transactions in bytes (default: 27000) + + + + + Warning: -paytxfee is set very high! This is the transaction fee you will pay if you send a transaction. + Warnung: -paytxfee ist auf einen sehr hohen Wert festgelegt! Dies ist die Gebühr die beim Senden einer Transaktion fällig wird. + + + + Warning: Please check that your computer's date and time are correct! If your clock is wrong Arepacoin will not work properly. + Wanung : Bitte prüfen Sie ob Datum und Uhrzeit richtig eingestellt sind. Wenn das Datum falsch ist Arepacoin nicht richtig funktionieren. + + + + Warning: error reading wallet.dat! All keys read correctly, but transaction data or address book entries might be missing or incorrect. + Warnung: Lesen von wallet.dat fehlgeschlagen! Alle Schlüssel wurden korrekt gelesen, Transaktionsdaten bzw. Adressbucheinträge fehlen aber möglicherweise oder sind inkorrekt. + + + + Warning: wallet.dat corrupt, data salvaged! Original wallet.dat saved as wallet.{timestamp}.bak in %s; if your balance or transactions are incorrect you should restore from a backup. + Warnung: wallet.dat beschädigt, Rettung erfolgreich! Original wallet.dat wurde als wallet.{Zeitstempel}.dat in %s gespeichert. Falls ihr Kontostand oder Transaktionen nicht korrekt sind, sollten Sie von einer Datensicherung wiederherstellen. + + + + Attempt to recover private keys from a corrupt wallet.dat + Versucht private Schlüssel aus einer beschädigten wallet.dat wiederherzustellen + + + + Block creation options: + Blockerzeugungsoptionen: + + + + Connect only to the specified node(s) + Nur mit dem/den angegebenen Knoten verbinden + + + + Discover own IP address (default: 1 when listening and no -externalip) + Eigene IP-Adresse erkennen (Standard: 1, wenn abgehört wird und nicht -externalip) + + + + Failed to listen on any port. Use -listen=0 if you want this. + Fehler, es konnte kein Port abgehört werden. Wenn dies so gewünscht wird -listen=0 verwenden. + + + + Find peers using DNS lookup (default: 1) + + + + + Sync checkpoints policy (default: strict) + + + + + Invalid -tor address: '%s' + + + + + Invalid amount for -reservebalance=<amount> + + + + + Maximum per-connection receive buffer, <n>*1000 bytes (default: 5000) + Maximale Größe, <n> * 1000 Byte, des Empfangspuffers pro Verbindung (Standard: 5000) + + + + Maximum per-connection send buffer, <n>*1000 bytes (default: 1000) + Maximale Größe, <n> * 1000 Byte, des Sendepuffers pro Verbindung (Standard: 1000) + + + + Only connect to nodes in network <net> (IPv4, IPv6 or Tor) + Verbinde nur zu Knoten des Netztyps <net> (IPv4, IPv6 oder Tor) + + + + Output extra debugging information. Implies all other -debug* options + + + + + Output extra network debugging information + + + + + Prepend debug output with timestamp + + + + + SSL options: (see the Bitcoin Wiki for SSL setup instructions) + SSL-Optionen: (siehe Bitcoin-Wiki für SSL-Installationsanweisungen) + + + + Select the version of socks proxy to use (4-5, default: 5) + + + + + Send trace/debug info to console instead of debug.log file + Rückverfolgungs- und Debuginformationen an die Konsole senden anstatt sie in die Datei debug.log zu schreiben + + + + Send trace/debug info to debugger + + + + + Set maximum block size in bytes (default: 250000) + + + + + Set minimum block size in bytes (default: 0) + Minimale Blockgröße in Byte festlegen (Standard: 0) + + + + Shrink debug.log file on client startup (default: 1 when no -debug) + Verkleinere Datei debug.log beim Starten des Clients (Standard: 1, wenn kein -debug) + + + + Specify connection timeout in milliseconds (default: 5000) + Verbindungstimeout in Millisekunden festlegen (Standard: 5000) + + + + Unable to sign checkpoint, wrong checkpointkey? + + + + + + Use UPnP to map the listening port (default: 0) + UPnP verwenden, um die Portweiterleitung einzurichten (Standard: 0) + + + + Use UPnP to map the listening port (default: 1 when listening) + UPnP verwenden, um die Portweiterleitung einzurichten (Standard: 1, wenn abgehört wird) + + + + Use proxy to reach tor hidden services (default: same as -proxy) + Proxy benutzen um versteckte Services zu erreichen (Standard: selbe Einstellung wie Proxy) + + + + Username for JSON-RPC connections + Benutzername für JSON-RPC-Verbindungen + + + + Verifying database integrity... + Überprüfe Datenbank Integrität... + + + + WARNING: syncronized checkpoint violation detected, but skipped! + + + + + Warning: Disk space is low! + Warnung: Festplatte hat wenig freien Speicher + + + + Warning: This version is obsolete, upgrade required! + Warnung: Diese Version is veraltet, Aktualisierung erforderlich! + + + + wallet.dat corrupt, salvage failed + wallet.dat beschädigt, Rettung fehlgeschlagen + + + + Password for JSON-RPC connections + Passwort für JSON-RPC-Verbindungen + + + + %s, you must set a rpcpassword in the configuration file: + %s +It is recommended you use the following random password: +rpcuser=arepacoinrpc +rpcpassword=%s +(you do not need to remember this password) +The username and password MUST NOT be the same. +If the file does not exist, create it with owner-readable-only file permissions. +It is also recommended to set alertnotify so you are notified of problems; +for example: alertnotify=echo %%s | mail -s "Arepacoin Alert" admin@foo.com + + + + + + Find peers using internet relay chat (default: 0) + Knoten die IRC Chat nutzen auffinden (Standard: 1) (0)?) + + + + Sync time with other nodes. Disable if time on your system is precise e.g. syncing with NTP (default: 1) + + + + + When creating transactions, ignore inputs with value less than this (default: 0.01) + Beim erstellen einer Transaktion werden eingaben kleiner als dieser Wert ignoriert (Standard 0,01) + + + + Allow JSON-RPC connections from specified IP address + JSON-RPC-Verbindungen von der angegebenen IP-Adresse erlauben + + + + Send commands to node running on <ip> (default: 127.0.0.1) + Sende Befehle an Knoten <ip> (Standard: 127.0.0.1) + + + + Execute command when the best block changes (%s in cmd is replaced by block hash) + Kommando ausführen wenn der beste Block wechselt (%s im Kommando wird durch den Hash des Blocks ersetzt) + + + + Execute command when a wallet transaction changes (%s in cmd is replaced by TxID) + Kommando ausführen wenn sich eine Wallet-Transaktion verändert (%s im Kommando wird durch die TxID ersetzt) + + + + Require a confirmations for change (default: 0) + Benötigt eine Bestätigung zur Änderung (Standard: 0) + + + + Enforce transaction scripts to use canonical PUSH operators (default: 1) + + + + + Execute command when a relevant alert is received (%s in cmd is replaced by message) + Kommando ausführen wenn eine relevante Meldung eingeht (%s in cmd wird von der Meldung ausgetauscht) + + + + Upgrade wallet to latest format + Wallet auf das neueste Format aktualisieren + + + + Set key pool size to <n> (default: 100) + Größe des Schlüsselpools festlegen auf <n> (Standard: 100) + + + + Rescan the block chain for missing wallet transactions + Blockkette erneut nach fehlenden Wallet-Transaktionen durchsuchen + + + + How many blocks to check at startup (default: 2500, 0 = all) + Anzahl der zu prüfenden Blöcke bei Programmstart (Standard: 2500, 0 = alle) + + + + How thorough the block verification is (0-6, default: 1) + + + + + Imports blocks from external blk000?.dat file + Importiere Blöcke aus externer blk000?.dat Datei. + + + + Use OpenSSL (https) for JSON-RPC connections + OpenSSL (https) für JSON-RPC-Verbindungen verwenden + + + + Server certificate file (default: server.cert) + Serverzertifikat (Standard: server.cert) + + + + Server private key (default: server.pem) + Privater Serverschlüssel (Standard: server.pem) + + + + Acceptable ciphers (default: TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH) + + + + + Error: Wallet unlocked for staking only, unable to create transaction. + + + + + WARNING: Invalid checkpoint found! Displayed transactions may not be correct! You may need to upgrade, or notify developers. + WARNUNG : Ungültiger Checkpunkt gefunden! Angezeigte Transaktionen können falsch sein! Du musst vielleicht updaten oder die Entwickler benachrichtigen. + + + + This help message + Dieser Hilfetext + + + + Wallet %s resides outside data directory %s. + Wallet %s liegt außerhalb des Daten Verzeichnisses %s. + + + + Cannot obtain a lock on data directory %s. Arepacoin is probably already running. + Kann das Verzeichniss nicht einbinden %s. Arepacoin Brieftasche läuft wahrscheinlich bereits. + + + + Arepacoin + Arepacoin + + + + Unable to bind to %s on this computer (bind returned error %d, %s) + Kann auf diesem Computer nicht an %s binden (von bind zurückgegebener Fehler %d, %s) + + + + Connect through socks proxy + Verbinde über socks proxy + + + + Allow DNS lookups for -addnode, -seednode and -connect + Erlaube DNS-Namensauflösung für -addnode, -seednode und -connect + + + + Loading addresses... + Lade Adressen... + + + + Error loading blkindex.dat + Fehler beim laden von blkindex.dat + + + + Error loading wallet.dat: Wallet corrupted + Fehler beim Laden von wallet.dat: Wallet beschädigt + + + + Error loading wallet.dat: Wallet requires newer version of Arepacoin + Fehler beim Laden wallet.dat. Brieftasche benötigt neuere Version der Arepacoin Brieftasche. + + + + Wallet needed to be rewritten: restart Arepacoin to complete + Brieftasche muss neu geschrieben werden. Starte die Arepacoin Brieftasche neu zum komplettieren. + + + + Error loading wallet.dat + Fehler beim Laden von wallet.dat + + + + Invalid -proxy address: '%s' + Ungültige Adresse in -proxy: '%s' + + + + Unknown network specified in -onlynet: '%s' + Unbekannter Netztyp in -onlynet angegeben: '%s' + + + + Unknown -socks proxy version requested: %i + Unbekannte Proxyversion in -socks angefordert: %i + + + + Cannot resolve -bind address: '%s' + Kann Adresse in -bind nicht auflösen: '%s' + + + + Cannot resolve -externalip address: '%s' + Kann Adresse in -externalip nicht auflösen: '%s' + + + + Invalid amount for -paytxfee=<amount>: '%s' + Ungültiger Betrag für -paytxfee=<amount>: '%s' + + + + Error: could not start node + Fehler: Node konnte nicht gestartet werden + + + + Sending... + Wird gesendet... + + + + Invalid amount + Ungültiger Betrag + + + + Insufficient funds + Unzureichender Kontostand + + + + Loading block index... + Lade Blockindex... + + + + Add a node to connect to and attempt to keep the connection open + Mit dem Knoten verbinden und versuchen die Verbindung aufrecht zu halten + + + + Unable to bind to %s on this computer. Arepacoin is probably already running. + Fehler beim anbinden %s auf diesem Computer. BlaclCoin Client läuft wahrscheinlich bereits. + + + + Fee per KB to add to transactions you send + Gebühr pro KB, zusätzlich zur ausgehenden Transaktion + + + + Invalid amount for -mininput=<amount>: '%s' + Ungültiger Betrag für -mininput=<amount>:'%s' + + + + Loading wallet... + Lade Wallet... + + + + Cannot downgrade wallet + Wallet kann nicht auf eine ältere Version herabgestuft werden + + + + Cannot initialize keypool + Keypool kann nicht initialisiert werden + + + + Cannot write default address + Standardadresse kann nicht geschrieben werden + + + + Rescanning... + Durchsuche erneut... + + + + Done loading + Laden abgeschlossen + + + + To use the %s option + Zur Nutzung der %s Option + + + + Error + Fehler + + + + You must set rpcpassword=<password> in the configuration file: +%s +If the file does not exist, create it with owner-readable-only file permissions. + Sie müssen den Wert rpcpassword=<passwort> in der Konfigurationsdatei angeben: +%s +Falls die Konfigurationsdatei nicht existiert, erzeugen Sie diese bitte mit Leserechten nur für den Dateibesitzer. + + + \ No newline at end of file diff --git a/src/qt/locale/bitcoin_el_GR.ts b/src/qt/locale/bitcoin_el_GR.ts new file mode 100755 index 0000000..bf88903 --- /dev/null +++ b/src/qt/locale/bitcoin_el_GR.ts @@ -0,0 +1,3285 @@ + + + AboutDialog + + + About Arepacoin + + + + + <b>Arepacoin</b> version + + + + + Copyright © 2009-2014 The Bitcoin developers +Copyright © 2012-2014 The NovaCoin developers +Copyright © 2014 The Arepacoin developers + + + + + +This is experimental software. + +Distributed under the MIT/X11 software license, see the accompanying file COPYING or http://www.opensource.org/licenses/mit-license.php. + +This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit (http://www.openssl.org/) and cryptographic software written by Eric Young (eay@cryptsoft.com) and UPnP software written by Thomas Bernard. + +This is experimental software. + +Distributed under the MIT/X11 software license, see the accompanying file COPYING or http://www.opensource.org/licenses/mit-license.php. + +This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit (http://www.openssl.org/) and cryptographic software written by Eric Young (eay@cryptsoft.com) and UPnP software written by Thomas Bernard. + + + + AddressBookPage + + + Address Book + + + + + Double-click to edit address or label + Διπλό-κλικ για επεξεργασία της διεύθυνσης ή της ετικέτας + + + + Create a new address + Δημιούργησε νέα διεύθυνση + + + + Copy the currently selected address to the system clipboard + Αντέγραψε την επιλεγμένη διεύθυνση στο πρόχειρο του συστήματος + + + + &New Address + + + + + These are your Arepacoin addresses for receiving payments. You may want to give a different one to each sender so you can keep track of who is paying you. + + + + + &Copy Address + &Αντιγραφή διεύθυνσης + + + + Show &QR Code + + + + + Sign a message to prove you own a Arepacoin address + + + + + Sign &Message + + + + + Delete the currently selected address from the list + Αντιγραφη της επιλεγμενης διεύθυνσης στο πρόχειρο του συστηματος + + + + Verify a message to ensure it was signed with a specified Arepacoin address + + + + + &Verify Message + + + + + &Delete + &Διαγραφή + + + + Copy &Label + Αντιγραφή &επιγραφής + + + + &Edit + &Επεξεργασία + + + + Export Address Book Data + + + + + Comma separated file (*.csv) + Αρχείο οριοθετημένο με κόμματα (*.csv) + + + + Error exporting + + + + + Could not write to file %1. + + + + + AddressTableModel + + + Label + Ετικέτα + + + + Address + Διεύθυνση + + + + (no label) + (χωρίς ετικέτα) + + + + AskPassphraseDialog + + + Passphrase Dialog + Φράση πρόσβασης + + + + Enter passphrase + Βάλτε κωδικό πρόσβασης + + + + New passphrase + Νέος κωδικός πρόσβασης + + + + Repeat new passphrase + Επανέλαβε τον νέο κωδικό πρόσβασης + + + + Serves to disable the trivial sendmoney when OS account compromised. Provides no real security. + + + + + For staking only + + + + + Enter the new passphrase to the wallet.<br/>Please use a passphrase of <b>10 or more random characters</b>, or <b>eight or more words</b>. + Εισάγετε τον νέο κωδικό πρόσβασης στον πορτοφόλι <br/> Παρακαλώ χρησιμοποιείστε ένα κωδικό με <b> 10 ή περισσότερους τυχαίους χαρακτήρες</b> ή <b> οχτώ ή παραπάνω λέξεις</b>. + + + + Encrypt wallet + Κρυπτογράφησε το πορτοφόλι + + + + This operation needs your wallet passphrase to unlock the wallet. + Αυτη η ενεργεία χρειάζεται τον κωδικό του πορτοφολιού για να ξεκλειδώσει το πορτοφόλι. + + + + Unlock wallet + Ξεκλειδωσε το πορτοφολι + + + + This operation needs your wallet passphrase to decrypt the wallet. + Αυτη η ενεργεια χρειάζεται τον κωδικο του πορτοφολιου για να αποκρυπτογραφησειι το πορτοφολι. + + + + Decrypt wallet + Αποκρυπτογράφησε το πορτοφολι + + + + Change passphrase + Άλλαξε κωδικο πρόσβασης + + + + Enter the old and new passphrase to the wallet. + Εισάγετε τον παλιό και τον νεο κωδικο στο πορτοφολι. + + + + Confirm wallet encryption + Επιβεβαίωσε την κρυπτογραφηση του πορτοφολιού + + + + Warning: If you encrypt your wallet and lose your passphrase, you will <b>LOSE ALL OF YOUR COINS</b>! + + + + + Are you sure you wish to encrypt your wallet? + Είστε σίγουροι ότι θέλετε να κρυπτογραφήσετε το πορτοφόλι σας; + + + + IMPORTANT: Any previous backups you have made of your wallet file should be replaced with the newly generated, encrypted wallet file. For security reasons, previous backups of the unencrypted wallet file will become useless as soon as you start using the new, encrypted wallet. + ΣΗΜΑΝΤΙΚΟ: Τα προηγούμενα αντίγραφα ασφαλείας που έχετε κάνει από το αρχείο του πορτοφόλιου σας θα πρέπει να αντικατασταθουν με το νέο που δημιουργείται, κρυπτογραφημένο αρχείο πορτοφόλιου. Για λόγους ασφαλείας, τα προηγούμενα αντίγραφα ασφαλείας του μη κρυπτογραφημένου αρχείου πορτοφόλιου θα καταστουν άχρηστα μόλις αρχίσετε να χρησιμοποιείτε το νέο κρυπτογραφημένο πορτοφόλι. + + + + + Warning: The Caps Lock key is on! + Προσοχη: το πλήκτρο Caps Lock είναι ενεργο. + + + + + Wallet encrypted + Κρυπτογραφημενο πορτοφολι + + + + Arepacoin will close now to finish the encryption process. Remember that encrypting your wallet cannot fully protect your coins from being stolen by malware infecting your computer. + + + + + + + + Wallet encryption failed + Η κρυπτογραφηση του πορτοφολιού απέτυχε + + + + Wallet encryption failed due to an internal error. Your wallet was not encrypted. + Η κρυπτογράφηση του πορτοφολιού απέτυχε λογω εσωτερικού σφάλματος. Το πορτοφολι δεν κρυπτογραφηθηκε. + + + + + The supplied passphrases do not match. + Οι εισαχθέντες κωδικοί δεν ταιριάζουν. + + + + Wallet unlock failed + το ξεκλείδωμα του πορτοφολιού απέτυχε + + + + + + The passphrase entered for the wallet decryption was incorrect. + Ο κωδικος που εισήχθη για την αποκρυπτογραφηση του πορτοφολιού ήταν λαθος. + + + + Wallet decryption failed + Η αποκρυπτογραφηση του πορτοφολιού απέτυχε + + + + Wallet passphrase was successfully changed. + Ο κωδικος του πορτοφολιού άλλαξε με επιτυχία. + + + + BitcoinGUI + + + Sign &message... + Υπογραφή &Μηνύματος... + + + + Synchronizing with network... + Συγχρονισμός με το δίκτυο... + + + + &Overview + &Επισκόπηση + + + + Show general overview of wallet + Εμφάνισε τη γενική εικόνα του πορτοφολιού + + + + &Transactions + &Συναλλαγές + + + + Browse transaction history + Περιήγηση στο ιστορικό συναλλαγών + + + + &Address Book + + + + + Edit the list of stored addresses and labels + + + + + &Receive coins + + + + + Show the list of addresses for receiving payments + + + + + &Send coins + + + + + E&xit + Έ&ξοδος + + + + Quit application + Εξοδος από την εφαρμογή + + + + Show information about Arepacoin + + + + + About &Qt + Σχετικά με &Qt + + + + Show information about Qt + Εμφάνισε πληροφορίες σχετικά με Qt + + + + &Options... + &Επιλογές... + + + + &Encrypt Wallet... + &Κρυπτογράφησε το πορτοφόλι + + + + &Backup Wallet... + &Αντίγραφο ασφαλείας του πορτοφολιού + + + + &Change Passphrase... + &Άλλαξε κωδικο πρόσβασης + + + + ~%n block(s) remaining + + + + + Downloaded %1 of %2 blocks of transaction history (%3% done). + + + + + &Export... + + + + + Send coins to a Arepacoin address + + + + + Modify configuration options for Arepacoin + + + + + Export the data in the current tab to a file + + + + + Encrypt or decrypt wallet + + + + + Backup wallet to another location + Δημιουργία αντιγράφου ασφαλείας πορτοφολιού σε άλλη τοποθεσία + + + + Change the passphrase used for wallet encryption + Αλλαγή του κωδικού κρυπτογράφησης του πορτοφολιού + + + + &Debug window + &Παράθυρο αποσφαλμάτωσης + + + + Open debugging and diagnostic console + Άνοιγμα κονσόλας αποσφαλμάτωσης και διαγνωστικών + + + + &Verify message... + &Επιβεβαίωση μηνύματος + + + + Arepacoin + + + + + Wallet + Πορτοφόλι + + + + &About Arepacoin + + + + + &Show / Hide + &Εμφάνισε/Κρύψε + + + + Unlock wallet + + + + + &Lock Wallet + + + + + Lock wallet + + + + + &File + &Αρχείο + + + + &Settings + &Ρυθμίσεις + + + + &Help + &Βοήθεια + + + + Tabs toolbar + Εργαλειοθήκη καρτελών + + + + Actions toolbar + + + + + + [testnet] + [testnet] + + + + + Arepacoin client + + + + + %n active connection(s) to Arepacoin network + + + + + Downloaded %1 blocks of transaction history. + + + + + Staking.<br>Your weight is %1<br>Network weight is %2<br>Expected time to earn reward is %3 + + + + + Not staking because wallet is locked + + + + + Not staking because wallet is offline + + + + + Not staking because wallet is syncing + + + + + Not staking because you don't have mature coins + + + + + %n second(s) ago + + + + + &Unlock Wallet... + + + + + %n minute(s) ago + + + + + %n hour(s) ago + + + + + %n day(s) ago + + + + + Up to date + Ενημερωμένο + + + + Catching up... + Ενημέρωση... + + + + Last received block was generated %1. + + + + + This transaction is over the size limit. You can still send it for a fee of %1, which goes to the nodes that process your transaction and helps to support the network. Do you want to pay the fee? + + + + + Confirm transaction fee + + + + + Sent transaction + Η συναλλαγή απεστάλη + + + + Incoming transaction + Εισερχόμενη συναλλαγή + + + + Date: %1 +Amount: %2 +Type: %3 +Address: %4 + + Ημερομηνία: %1 +Ποσό: %2 +Τύπος: %3 +Διεύθυνση: %4 + + + + + + URI handling + + + + + + URI can not be parsed! This can be caused by an invalid Arepacoin address or malformed URI parameters. + + + + + Wallet is <b>encrypted</b> and currently <b>unlocked</b> + Το πορτοφόλι είναι <b>κρυπτογραφημένο</b> και <b>ξεκλείδωτο</b> + + + + Wallet is <b>encrypted</b> and currently <b>locked</b> + Το πορτοφόλι είναι <b>κρυπτογραφημένο</b> και <b>κλειδωμένο</b> + + + + Backup Wallet + + + + + Wallet Data (*.dat) + + + + + Backup Failed + + + + + There was an error trying to save the wallet data to the new location. + + + + + %n second(s) + + + + + %n minute(s) + + + + + %n hour(s) + %n ώρες %n ώρες + + + + %n day(s) + %n ημέρες %n ημέρες + + + + Not staking + + + + + A fatal error occurred. Arepacoin can no longer continue safely and will quit. + + + + + ClientModel + + + Network Alert + Ειδοποίηση Δικτύου + + + + CoinControlDialog + + + Coin Control + + + + + Quantity: + + + + + Bytes: + + + + + Amount: + Ποσό: + + + + Priority: + + + + + Fee: + + + + + Low Output: + + + + + no + + + + + After Fee: + + + + + Change: + + + + + (un)select all + + + + + Tree mode + + + + + List mode + + + + + Amount + Ποσό + + + + Label + + + + + Address + Διεύθυνση + + + + Date + Ημερομηνία + + + + Confirmations + + + + + Confirmed + Επικυρωμένες + + + + Priority + + + + + Copy address + Αντιγραφή διεύθυνσης + + + + Copy label + Αντιγραφή επιγραφής + + + + + Copy amount + Αντιγραφή ποσού + + + + Copy transaction ID + Αντιγραφη του ID Συναλλαγής + + + + Copy quantity + + + + + Copy fee + + + + + Copy after fee + + + + + Copy bytes + + + + + Copy priority + + + + + Copy low output + + + + + Copy change + + + + + highest + + + + + high + + + + + medium-high + + + + + medium + + + + + low-medium + + + + + low + + + + + lowest + + + + + DUST + + + + + yes + + + + + This label turns red, if the transaction size is bigger than 10000 bytes. + + This means a fee of at least %1 per kb is required. + + Can vary +/- 1 Byte per input. + + + + + Transactions with higher priority get more likely into a block. + +This label turns red, if the priority is smaller than "medium". + + This means a fee of at least %1 per kb is required. + + + + + This label turns red, if any recipient receives an amount smaller than %1. + + This means a fee of at least %2 is required. + + Amounts below 0.546 times the minimum relay fee are shown as DUST. + + + + + This label turns red, if the change is smaller than %1. + + This means a fee of at least %2 is required. + + + + + + (no label) + (χωρίς ετικέτα) + + + + change from %1 (%2) + + + + + (change) + + + + + EditAddressDialog + + + Edit Address + Επεξεργασία Διεύθυνσης + + + + &Label + &Επιγραφή + + + + The label associated with this address book entry + + + + + &Address + &Διεύθυνση + + + + The address associated with this address book entry. This can only be modified for sending addresses. + + + + + New receiving address + Νέα διεύθυνση λήψης + + + + New sending address + Νέα διεύθυνση αποστολής + + + + Edit receiving address + Επεξεργασία διεύθυνσης λήψης + + + + Edit sending address + Επεξεργασία διεύθυνσης αποστολής + + + + The entered address "%1" is already in the address book. + Η διεύθυνση "%1" βρίσκεται ήδη στο βιβλίο διευθύνσεων. + + + + The entered address "%1" is not a valid Arepacoin address. + + + + + Could not unlock wallet. + Δεν είναι δυνατό το ξεκλείδωμα του πορτοφολιού. + + + + New key generation failed. + Η δημιουργία νέου κλειδιού απέτυχε. + + + + GUIUtil::HelpMessageBox + + + + Arepacoin-Qt + + + + + version + + + + + Usage: + + + + + command-line options + + + + + UI options + + + + + Set language, for example "de_DE" (default: system locale) + + + + + Start minimized + + + + + Show splash screen on startup (default: 1) + + + + + OptionsDialog + + + Options + Ρυθμίσεις + + + + &Main + &Κύριο + + + + Optional transaction fee per kB that helps make sure your transactions are processed quickly. Most transactions are 1 kB. Fee 0.01 recommended. + + + + + Pay transaction &fee + Αμοιβή &συναλλαγής + + + + Reserved amount does not participate in staking and is therefore spendable at any time. + + + + + Reserve + + + + + Automatically start Arepacoin after logging in to the system. + + + + + &Start Arepacoin on system login + + + + + Detach block and address databases at shutdown. This means they can be moved to another data directory, but it slows down shutdown. The wallet is always detached. + + + + + &Detach databases at shutdown + + + + + &Network + &Δίκτυο + + + + Automatically open the Arepacoin client port on the router. This only works when your router supports UPnP and it is enabled. + + + + + Map port using &UPnP + Απόδοση θυρών με χρήστη &UPnP + + + + Connect to the Arepacoin network through a SOCKS proxy (e.g. when connecting through Tor). + + + + + &Connect through SOCKS proxy: + + + + + Proxy &IP: + &IP διαμεσολαβητή: + + + + IP address of the proxy (e.g. 127.0.0.1) + + + + + &Port: + &Θύρα: + + + + Port of the proxy (e.g. 9050) + Θύρα διαμεσολαβητή + + + + SOCKS &Version: + SOCKS &Έκδοση: + + + + SOCKS version of the proxy (e.g. 5) + SOCKS εκδοση του διαμεσολαβητη (e.g. 5) + + + + &Window + &Παράθυρο + + + + Show only a tray icon after minimizing the window. + Εμφάνιση μόνο εικονιδίου στην περιοχή ειδοποιήσεων κατά την ελαχιστοποίηση + + + + &Minimize to the tray instead of the taskbar + &Ελαχιστοποίηση στην περιοχή ειδοποιήσεων αντί της γραμμής εργασιών + + + + Minimize instead of exit the application when the window is closed. When this option is enabled, the application will be closed only after selecting Quit in the menu. + Ελαχιστοποίηση αντί για έξοδο κατά το κλείσιμο του παραθύρου + + + + M&inimize on close + Ε&λαχιστοποίηση κατά το κλείσιμο + + + + &Display + &Απεικόνιση + + + + User Interface &language: + Γλώσσα περιβάλλοντος εργασίας: + + + + The user interface language can be set here. This setting will take effect after restarting Arepacoin. + + + + + &Unit to show amounts in: + &Μονάδα μέτρησης: + + + + Choose the default subdivision unit to show in the interface and when sending coins. + Διαλέξτε την προεπιλεγμένη υποδιαίρεση που θα εμφανίζεται όταν στέλνετε νομίσματα. + + + + Whether to show Arepacoin addresses in the transaction list or not. + + + + + &Display addresses in transaction list + Εμφάνιση διευθύνσεων στη λίστα συναλλαγών + + + + Whether to show coin control features or not. + + + + + Display coin &control features (experts only!) + + + + + &OK + &ΟΚ + + + + &Cancel + &Ακύρωση + + + + &Apply + + + + + default + προεπιλογή + + + + + Warning + + + + + + This setting will take effect after restarting Arepacoin. + + + + + The supplied proxy address is invalid. + Δεν είναι έγκυρη η διεύθυνση διαμεσολαβητή + + + + OverviewPage + + + Form + Φόρμα + + + + + The displayed information may be out of date. Your wallet automatically synchronizes with the Arepacoin network after a connection is established, but this process has not completed yet. + + + + + Stake: + + + + + Unconfirmed: + + + + + Wallet + Πορτοφόλι + + + + Spendable: + + + + + Your current spendable balance + Το τρέχον διαθέσιμο υπόλοιπο + + + + Immature: + Ανώριμος + + + + Mined balance that has not yet matured + Εξορυγμενο υπόλοιπο που δεν έχει ακόμα ωριμάσει + + + + Total: + Σύνολο: + + + + Your current total balance + Το τρέχον συνολικό υπόλοιπο + + + + <b>Recent transactions</b> + <b>Πρόσφατες συναλλαγές</b> + + + + Total of transactions that have yet to be confirmed, and do not yet count toward the current balance + + + + + Total of coins that was staked, and do not yet count toward the current balance + + + + + + out of sync + εκτός συγχρονισμού + + + + QRCodeDialog + + + QR Code Dialog + + + + + Request Payment + + + + + Amount: + + + + + Label: + + + + + Message: + + + + + &Save As... + + + + + Error encoding URI into QR Code. + + + + + The entered amount is invalid, please check. + + + + + Resulting URI too long, try to reduce the text for label / message. + + + + + Save QR Code + + + + + PNG Images (*.png) + + + + + RPCConsole + + + Client name + Όνομα Πελάτη + + + + + + + + + + + + + N/A + Μη διαθέσιμο + + + + Client version + Έκδοση Πελάτη + + + + &Information + &Πληροφορία + + + + Using OpenSSL version + Χρησιμοποιηση της OpenSSL εκδοσης + + + + Startup time + Χρόνος εκκίνησης + + + + Network + Δίκτυο + + + + Number of connections + Αριθμός συνδέσεων + + + + On testnet + + + + + Block chain + Αλυσίδα μπλοκ + + + + Current number of blocks + Τρέχον αριθμός μπλοκ + + + + Estimated total blocks + Κατ' εκτίμηση συνολικά μπλοκς + + + + Last block time + Χρόνος τελευταίου μπλοκ + + + + &Open + &Άνοιγμα + + + + Command-line options + + + + + Show the Arepacoin-Qt help message to get a list with possible Arepacoin command-line options. + + + + + &Show + + + + + &Console + &Κονσόλα + + + + Build date + Ημερομηνία κατασκευής + + + + Arepacoin - Debug window + + + + + Arepacoin Core + + + + + Debug log file + Αρχείο καταγραφής εντοπισμού σφαλμάτων + + + + Open the Arepacoin debug log file from the current data directory. This can take a few seconds for large log files. + + + + + Clear console + Καθαρισμός κονσόλας + + + + Welcome to the Arepacoin RPC console. + + + + + Use up and down arrows to navigate history, and <b>Ctrl-L</b> to clear screen. + Χρησιμοποιήστε το πάνω και κάτω βέλος για να περιηγηθείτε στο ιστορικο, και <b>Ctrl-L</b> για εκκαθαριση οθονης. + + + + Type <b>help</b> for an overview of available commands. + Γράψτε <b>help</b> για μια επισκόπηση των διαθέσιμων εντολών + + + + SendCoinsDialog + + + + + + + + + + Send Coins + Αποστολή νομισμάτων + + + + Coin Control Features + + + + + Inputs... + + + + + automatically selected + + + + + Insufficient funds! + + + + + Quantity: + + + + + + 0 + + + + + Bytes: + + + + + Amount: + Ποσό: + + + + + + + 0.00 BC + + + + + Priority: + + + + + medium + + + + + Fee: + + + + + Low Output: + + + + + no + + + + + After Fee: + + + + + Change + + + + + custom change address + + + + + Send to multiple recipients at once + Αποστολή σε πολλούς αποδέκτες ταυτόχρονα + + + + Add &Recipient + &Προσθήκη αποδέκτη + + + + Remove all transaction fields + + + + + Clear &All + Καθαρισμός &Όλων + + + + Balance: + Υπόλοιπο: + + + + 123.456 BC + + + + + Confirm the send action + Επιβεβαίωση αποστολής + + + + S&end + Αποστολη + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Copy quantity + + + + + Copy amount + Αντιγραφή ποσού + + + + Copy fee + + + + + Copy after fee + + + + + Copy bytes + + + + + Copy priority + + + + + Copy low output + + + + + Copy change + + + + + <b>%1</b> to %2 (%3) + + + + + Confirm send coins + Επιβεβαίωση αποστολής νομισμάτων + + + + Are you sure you want to send %1? + + + + + and + + + + + The recipient address is not valid, please recheck. + Η διεύθυνση του αποδέκτη δεν είναι σωστή. Παρακαλώ ελέγξτε ξανά. + + + + The amount to pay must be larger than 0. + Το ποσό πληρωμής πρέπει να είναι μεγαλύτερο από 0. + + + + The amount exceeds your balance. + Το ποσό ξεπερνάει το διαθέσιμο υπόλοιπο + + + + The total exceeds your balance when the %1 transaction fee is included. + Το σύνολο υπερβαίνει το υπόλοιπό σας όταν συμπεριληφθεί και η αμοιβή %1 + + + + Duplicate address found, can only send to each address once per send operation. + Βρέθηκε η ίδια διεύθυνση δύο φορές. Επιτρέπεται μία μόνο εγγραφή για κάθε διεύθυνση, σε κάθε διαδικασία αποστολής. + + + + Error: Transaction creation failed. + + + + + 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. + + + + + WARNING: Invalid Arepacoin address + + + + + (no label) + (χωρίς ετικέτα) + + + + WARNING: unknown change address + + + + + SendCoinsEntry + + + Form + + + + + A&mount: + &Ποσό: + + + + Pay &To: + Πληρωμή &σε: + + + + + Enter a label for this address to add it to your address book + Εισάγετε μια επιγραφή για αυτή τη διεύθυνση ώστε να καταχωρηθεί στο βιβλίο διευθύνσεων + + + + &Label: + &Επιγραφή + + + + The address to send the payment to (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Choose address from address book + + + + + Alt+A + Alt+A + + + + Paste address from clipboard + Επικόλληση διεύθυνσης από το πρόχειρο + + + + Alt+P + Alt+P + + + + Remove this recipient + + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + SignVerifyMessageDialog + + + Signatures - Sign / Verify a Message + Υπογραφές - Είσοδος / Επαλήθευση μήνυματος + + + + + &Sign Message + &Υπογραφή Μηνύματος + + + + You can sign messages with your addresses to prove you own them. Be careful not to sign anything vague, as phishing attacks may try to trick you into signing your identity over to them. Only sign fully-detailed statements you agree to. + Μπορείτε να υπογράφετε μηνύματα με τις διευθύνσεις σας, ώστε ν' αποδεικνύετε πως αυτές σας ανήκουν. Αποφεύγετε να υπογράφετε κάτι αόριστο καθώς ενδέχεται να εξαπατηθείτε. Υπογράφετε μόνο πλήρης δηλώσεις με τις οποίες συμφωνείτε. + + + + The address to sign the message with (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + + Choose an address from the address book + + + + + + Alt+A + Alt+A + + + + Paste address from clipboard + Επικόλληση διεύθυνσης από το βιβλίο διευθύνσεων + + + + Alt+P + Alt+P + + + + Enter the message you want to sign here + Εισάγετε εδώ το μήνυμα που θέλετε να υπογράψετε + + + + Copy the current signature to the system clipboard + Αντέγραφη της επιλεγμενης διεύθυνσης στο πρόχειρο του συστηματος + + + + Sign the message to prove you own this Arepacoin address + + + + + Reset all sign message fields + Επαναφορά όλων των πεδίων μήνυματος + + + + + Clear &All + Καθαρισμός &Όλων + + + + + &Verify Message + &Επιβεβαίωση μηνύματος + + + + Enter the signing address, message (ensure you copy line breaks, spaces, tabs, etc. exactly) and signature below to verify the message. Be careful not to read more into the signature than what is in the signed message itself, to avoid being tricked by a man-in-the-middle attack. + Πληκτρολογήστε την υπογραφή διεύθυνσης, μήνυμα (βεβαιωθείτε ότι έχετε αντιγράψει τις αλλαγές γραμμής, κενά, tabs, κ.λπ. ακριβώς) και την υπογραφή παρακάτω, για να ελέγξει το μήνυμα. Να είστε προσεκτικοί για να μην διαβάσετε περισσότερα στην υπογραφή ό, τι είναι στην υπογραφή ίδιο το μήνυμα , για να μην εξαπατηθούν από έναν άνθρωπο -in - the-middle επίθεση. + + + + The address the message was signed with (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Verify the message to ensure it was signed with the specified Arepacoin address + + + + + Reset all verify message fields + Επαναφορά όλων επαλήθευμενων πεδίων μήνυματος + + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Click "Sign Message" to generate signature + Κάντε κλικ στο "Υπογραφή Μηνύματος" για να λάβετε την υπογραφή + + + + Enter Arepacoin signature + + + + + + The entered address is invalid. + Η διεύθυνση που εισήχθη είναι λάθος. + + + + + + + Please check the address and try again. + Παρακαλούμε ελέγξτε την διεύθυνση και δοκιμάστε ξανά. + + + + + The entered address does not refer to a key. + Η διεύθυνση που έχει εισαχθεί δεν αναφέρεται σε ένα πλήκτρο. + + + + Wallet unlock was cancelled. + το ξεκλείδωμα του πορτοφολιού απέτυχε + + + + Private key for the entered address is not available. + Το προσωπικό κλειδί εισαγμενης διευθυνσης δεν είναι διαθέσιμο. + + + + Message signing failed. + Η υπογραφή του μηνύματος απέτυχε. + + + + Message signed. + Μήνυμα υπεγράφη. + + + + The signature could not be decoded. + Η υπογραφή δεν μπόρεσε να αποκρυπτογραφηθεί. + + + + + Please check the signature and try again. + Παρακαλούμε ελέγξτε την υπογραφή και δοκιμάστε ξανά. + + + + The signature did not match the message digest. + Η υπογραφή δεν ταιριάζει με το μήνυμα. + + + + Message verification failed. + Η επιβεβαίωση του μηνύματος απέτυχε + + + + Message verified. + Μήνυμα επιβεβαιώθηκε. + + + + TransactionDesc + + + Open until %1 + Ανοιχτό μέχρι %1 + + + + Open for %n block(s) + + + + + conflicted + + + + + %1/offline + %1/χωρίς σύνδεση; + + + + %1/unconfirmed + %1/χωρίς επιβεβαίωση + + + + %1 confirmations + %1 επιβεβαιώσεις + + + + Status + Κατάσταση + + + + , broadcast through %n node(s) + , έχει μεταδοθεί μέσω %n κόμβων, έχει μεταδοθεί μέσω %n κόμβων + + + + Date + Ημερομηνία + + + + Source + Πηγή + + + + Generated + Δημιουργία + + + + + From + Από + + + + + + To + Προς + + + + + own address + δική σας διεύθυνση + + + + label + eπιγραφή + + + + + + + + Credit + Πίστωση + + + + matures in %n more block(s) + ωρίμανση σε %n επιπλέον μπλοκωρίμανση σε %n επιπλέον μπλοκ + + + + not accepted + μη αποδεκτό + + + + + + + Debit + Debit + + + + Transaction fee + Τέλος συναλλαγής + + + + Net amount + Καθαρό ποσό + + + + Message + Μήνυμα + + + + Comment + Σχόλιο: + + + + Transaction ID + ID Συναλλαγής: + + + + Generated coins must mature 6 blocks before they can be spent. When you generated this block, it was broadcast to the network to be added to the block chain. If it fails to get into the chain, its state will change to "not accepted" and it won't be spendable. This may occasionally happen if another node generates a block within a few seconds of yours. + + + + + Debug information + Πληροφορίες αποσφαλμάτωσης + + + + Transaction + Συναλλαγή + + + + Inputs + εισροές + + + + Amount + Ποσό + + + + true + αληθής + + + + false + αναληθής + + + + , has not been successfully broadcast yet + , δεν έχει ακόμα μεταδοθεί μ' επιτυχία + + + + unknown + άγνωστο + + + + TransactionDescDialog + + + Transaction details + Λεπτομέρειες συναλλαγής + + + + This pane shows a detailed description of the transaction + Αυτό το παράθυρο δείχνει μια λεπτομερή περιγραφή της συναλλαγής + + + + TransactionTableModel + + + Date + Ημερομηνία + + + + Type + Τύπος + + + + Address + Διεύθυνση + + + + Amount + Ποσό + + + + Open until %1 + Ανοιχτό μέχρι %1 + + + + Confirmed (%1 confirmations) + Επικυρωμένη (%1 επικυρώσεις) + + + + Open for %n more block(s) + Ανοιχτό για %n μπλοκΑνοιχτό για %n μπλοκ + + + + Offline + + + + + Unconfirmed + + + + + Confirming (%1 of %2 recommended confirmations) + + + + + Conflicted + + + + + Immature (%1 confirmations, will be available after %2) + + + + + This block was not received by any other nodes and will probably not be accepted! + Αυτό το μπλοκ δεν έχει παραληφθεί από κανέναν άλλο κόμβο και κατά πάσα πιθανότητα θα απορριφθεί! + + + + Generated but not accepted + Δημιουργήθηκε αλλά απορρίφθηκε + + + + Received with + Παραλαβή με + + + + Received from + Ελήφθη από + + + + Sent to + Αποστολή προς + + + + Payment to yourself + Πληρωμή προς εσάς + + + + Mined + Εξόρυξη + + + + (n/a) + (δ/α) + + + + Transaction status. Hover over this field to show number of confirmations. + Κατάσταση συναλλαγής. Πηγαίνετε το ποντίκι πάνω από αυτό το πεδίο για να δείτε τον αριθμό των επικυρώσεων + + + + Date and time that the transaction was received. + Ημερομηνία κι ώρα λήψης της συναλλαγής. + + + + Type of transaction. + Είδος συναλλαγής. + + + + Destination address of transaction. + Διεύθυνση αποστολής της συναλλαγής. + + + + Amount removed from or added to balance. + Ποσό που αφαιρέθηκε ή προστέθηκε στο υπόλοιπο. + + + + TransactionView + + + + All + Όλα + + + + Today + Σήμερα + + + + This week + Αυτή την εβδομάδα + + + + This month + Αυτόν τον μήνα + + + + Last month + Τον προηγούμενο μήνα + + + + This year + Αυτό το έτος + + + + Range... + Έκταση... + + + + Received with + Ελήφθη με + + + + Sent to + Απεστάλη προς + + + + To yourself + Προς εσάς + + + + Mined + Εξόρυξη + + + + Other + Άλλο + + + + Enter address or label to search + Αναζήτηση με βάση τη διεύθυνση ή την επιγραφή + + + + Min amount + Ελάχιστο ποσό + + + + Copy address + Αντιγραφή διεύθυνσης + + + + Copy label + Αντιγραφή επιγραφής + + + + Copy amount + Αντιγραφή ποσού + + + + Copy transaction ID + Αντιγραφη του ID Συναλλαγής + + + + Edit label + Επεξεργασία επιγραφής + + + + Show transaction details + Εμφάνιση λεπτομερειών συναλλαγής + + + + Export Transaction Data + + + + + Comma separated file (*.csv) + Αρχείο οριοθετημένο με κόμματα (*.csv) + + + + Confirmed + Επικυρωμένες + + + + Date + Ημερομηνία + + + + Type + Τύπος + + + + Label + Επιγραφή + + + + Address + Διεύθυνση + + + + Amount + Ποσό + + + + ID + ID + + + + Error exporting + + + + + Could not write to file %1. + + + + + Range: + Έκταση: + + + + to + έως + + + + WalletModel + + + Sending... + + + + + bitcoin-core + + + Arepacoin version + + + + + Usage: + Χρήση: + + + + Send command to -server or arepacoind + + + + + List commands + Λίστα εντολών + + + + Get help for a command + Επεξήγηση εντολής + + + + Options: + Επιλογές: + + + + Specify configuration file (default: arepacoin.conf) + + + + + Specify pid file (default: arepacoind.pid) + + + + + Specify wallet file (within data directory) + + + + + Specify data directory + Ορισμός φακέλου δεδομένων + + + + Set database cache size in megabytes (default: 25) + Όρισε το μέγεθος της βάσης προσωρινής αποθήκευσης σε megabytes(προεπιλογή:25) + + + + Set database disk log size in megabytes (default: 100) + + + + + Listen for connections on <port> (default: 9853 or testnet: 19853) + + + + + Maintain at most <n> connections to peers (default: 125) + Μέγιστες αριθμός συνδέσεων με τους peers <n> (προεπιλογή: 125) + + + + Connect to a node to retrieve peer addresses, and disconnect + Σύνδεση σε έναν κόμβο για την ανάκτηση διευθύνσεων από ομοτίμους, και αποσυνδέσh + + + + Specify your own public address + Διευκρινίστε τη δικιά σας δημόσια διεύθυνση. + + + + Bind to given address. Use [host]:port notation for IPv6 + + + + + Stake your coins to support network and gain reward (default: 1) + + + + + Threshold for disconnecting misbehaving peers (default: 100) + Όριο αποσύνδεσης προβληματικών peers (προεπιλογή: 100) + + + + Number of seconds to keep misbehaving peers from reconnecting (default: 86400) + Δευτερόλεπτα πριν επιτραπεί ξανά η σύνδεση των προβληματικών peers (προεπιλογή: 86400) + + + + An error occurred while setting up the RPC port %u for listening on IPv4: %s + Ένα σφάλμα συνέβη καθώς προετοιμαζόταν η πόρτα RPC %u για αναμονή IPv4: %s + + + + Detach block and address databases. Increases shutdown time (default: 0) + + + + + 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. + + + + + Error: This transaction requires a transaction fee of at least %s because of its amount, complexity, or use of recently received funds + + + + + Listen for JSON-RPC connections on <port> (default: 9852 or testnet: 19852) + + + + + Accept command line and JSON-RPC commands + Αποδοχή εντολών κονσόλας και JSON-RPC + + + + Error: Transaction creation failed + + + + + Error: Wallet locked, unable to create transaction + + + + + Importing blockchain data file. + + + + + Importing bootstrap blockchain data file. + + + + + Run in the background as a daemon and accept commands + Εκτέλεση στο παρασκήνιο κι αποδοχή εντολών + + + + Use the test network + Χρήση του δοκιμαστικού δικτύου + + + + Accept connections from outside (default: 1 if no -proxy or -connect) + Να δέχεσαι συνδέσεις από έξω(προεπιλογή:1) + + + + An error occurred while setting up the RPC port %u for listening on IPv6, falling back to IPv4: %s + Ένα σφάλμα συνέβη καθώς προετοιμαζόταν η υποδοχη RPC %u για αναμονη του IPv6, επεσε πισω στο IPv4:%s + + + + Error initializing database environment %s! To recover, BACKUP THAT DIRECTORY, then remove everything from it except for wallet.dat. + + + + + Set maximum size of high-priority/low-fee transactions in bytes (default: 27000) + + + + + Warning: -paytxfee is set very high! This is the transaction fee you will pay if you send a transaction. + Προειδοποίηση: Η παράμετρος -paytxfee είναι πολύ υψηλή. Πρόκειται για την αμοιβή που θα πληρώνετε για κάθε συναλλαγή που θα στέλνετε. + + + + Warning: Please check that your computer's date and time are correct! If your clock is wrong Arepacoin will not work properly. + + + + + Warning: error reading wallet.dat! All keys read correctly, but transaction data or address book entries might be missing or incorrect. + Προειδοποίηση : Σφάλμα wallet.dat κατα την ανάγνωση ! Όλα τα κλειδιά αναγνωρισθηκαν σωστά, αλλά τα δεδομένα των συναλλαγών ή καταχωρήσεις στο βιβλίο διευθύνσεων μπορεί να είναι ελλιπείς ή λανθασμένα. + + + + Warning: wallet.dat corrupt, data salvaged! Original wallet.dat saved as wallet.{timestamp}.bak in %s; if your balance or transactions are incorrect you should restore from a backup. + Προειδοποίηση : το αρχειο wallet.dat ειναι διεφθαρμένο, τα δεδομένα σώζονται ! Original wallet.dat αποθηκεύονται ως wallet.{timestamp}.bak στο %s . Αν το υπόλοιπο του ή τις συναλλαγές σας, είναι λάθος θα πρέπει να επαναφέρετε από ένα αντίγραφο ασφαλείας + + + + Attempt to recover private keys from a corrupt wallet.dat + Προσπάθεια για ανακτησει ιδιωτικων κλειδιων από ενα διεφθαρμένο αρχειο wallet.dat + + + + Block creation options: + Αποκλεισμός επιλογων δημιουργίας: + + + + Connect only to the specified node(s) + Σύνδεση μόνο με ορισμένους κόμβους + + + + Discover own IP address (default: 1 when listening and no -externalip) + Ανακαλύψτε την δικη σας IP διεύθυνση (προεπιλογή: 1 όταν ακούει και δεν - externalip) + + + + Failed to listen on any port. Use -listen=0 if you want this. + ταλαιπωρηθειτε για να ακούσετε σε οποιαδήποτε θύρα. Χρήση - ακούστε = 0 , αν θέλετε αυτό. + + + + Find peers using DNS lookup (default: 1) + + + + + Sync checkpoints policy (default: strict) + + + + + Invalid -tor address: '%s' + + + + + Invalid amount for -reservebalance=<amount> + + + + + Maximum per-connection receive buffer, <n>*1000 bytes (default: 5000) + Μέγιστος buffer λήψης ανά σύνδεση, <n>*1000 bytes (προεπιλογή: 5000) + + + + Maximum per-connection send buffer, <n>*1000 bytes (default: 1000) + Μέγιστος buffer αποστολής ανά σύνδεση, <n>*1000 bytes (προεπιλογή: 1000) + + + + Only connect to nodes in network <net> (IPv4, IPv6 or Tor) + Συνδέση μόνο σε κόμβους του δικτύου <net> (IPv4, IPv6 ή Tor) + + + + Output extra debugging information. Implies all other -debug* options + + + + + Output extra network debugging information + + + + + Prepend debug output with timestamp + + + + + SSL options: (see the Bitcoin Wiki for SSL setup instructions) + Ρυθμίσεις SSL: (ανατρέξτε στο Bitcoin Wiki για οδηγίες ρυθμίσεων SSL) + + + + Select the version of socks proxy to use (4-5, default: 5) + + + + + Send trace/debug info to console instead of debug.log file + Αποστολή πληροφοριών εντοπισμού σφαλμάτων στην κονσόλα αντί του αρχείου debug.log + + + + Send trace/debug info to debugger + + + + + Set maximum block size in bytes (default: 250000) + + + + + Set minimum block size in bytes (default: 0) + Ορίστε το μέγιστο μέγεθος μπλοκ σε bytes (προεπιλογή: 0) + + + + Shrink debug.log file on client startup (default: 1 when no -debug) + Συρρίκνωση του αρχείο debug.log κατα την εκκίνηση του πελάτη (προεπιλογή: 1 όταν δεν-debug) + + + + Specify connection timeout in milliseconds (default: 5000) + Ορισμός λήξης χρονικού ορίου σε χιλιοστά του δευτερολέπτου(προεπιλογή:5000) + + + + Unable to sign checkpoint, wrong checkpointkey? + + + + + + Use UPnP to map the listening port (default: 0) + Χρησιμοποίηση του UPnP για την χρήση της πόρτας αναμονής (προεπιλογή:0) + + + + Use UPnP to map the listening port (default: 1 when listening) + Χρησιμοποίηση του UPnP για την χρήση της πόρτας αναμονής (προεπιλογή:1) + + + + Use proxy to reach tor hidden services (default: same as -proxy) + + + + + Username for JSON-RPC connections + Όνομα χρήστη για τις συνδέσεις JSON-RPC + + + + Verifying database integrity... + + + + + WARNING: syncronized checkpoint violation detected, but skipped! + + + + + Warning: Disk space is low! + + + + + Warning: This version is obsolete, upgrade required! + Προειδοποίηση: Αυτή η έκδοση είναι ξεπερασμένη, απαιτείται αναβάθμιση + + + + wallet.dat corrupt, salvage failed + Το αρχειο wallet.dat ειναι διεφθαρμένο, η διάσωση απέτυχε + + + + Password for JSON-RPC connections + Κωδικός για τις συνδέσεις JSON-RPC + + + + %s, you must set a rpcpassword in the configuration file: + %s +It is recommended you use the following random password: +rpcuser=arepacoinrpc +rpcpassword=%s +(you do not need to remember this password) +The username and password MUST NOT be the same. +If the file does not exist, create it with owner-readable-only file permissions. +It is also recommended to set alertnotify so you are notified of problems; +for example: alertnotify=echo %%s | mail -s "Arepacoin Alert" admin@foo.com + + + + + + Find peers using internet relay chat (default: 0) + + + + + Sync time with other nodes. Disable if time on your system is precise e.g. syncing with NTP (default: 1) + + + + + When creating transactions, ignore inputs with value less than this (default: 0.01) + + + + + Allow JSON-RPC connections from specified IP address + Αποδοχή συνδέσεων JSON-RPC από συγκεκριμένη διεύθυνση IP + + + + Send commands to node running on <ip> (default: 127.0.0.1) + Αποστολή εντολών στον κόμβο <ip> (προεπιλογή: 127.0.0.1) + + + + Execute command when the best block changes (%s in cmd is replaced by block hash) + Εκτέλεσε την εντολή όταν το καλύτερο μπλοκ αλλάξει(%s στην εντολή αντικαθίσταται από το hash του μπλοκ) + + + + Execute command when a wallet transaction changes (%s in cmd is replaced by TxID) + Εκτέλεσε την εντολή όταν το καλύτερο μπλοκ αλλάξει(%s στην εντολή αντικαθίσταται από το hash του μπλοκ) + + + + Require a confirmations for change (default: 0) + + + + + Enforce transaction scripts to use canonical PUSH operators (default: 1) + + + + + Execute command when a relevant alert is received (%s in cmd is replaced by message) + + + + + Upgrade wallet to latest format + Αναβάθμισε το πορτοφόλι στην τελευταία έκδοση + + + + Set key pool size to <n> (default: 100) + Όριο πλήθους κλειδιών pool <n> (προεπιλογή: 100) + + + + Rescan the block chain for missing wallet transactions + Επανέλεγχος της αλυσίδας μπλοκ για απούσες συναλλαγές + + + + How many blocks to check at startup (default: 2500, 0 = all) + + + + + How thorough the block verification is (0-6, default: 1) + + + + + Imports blocks from external blk000?.dat file + + + + + Use OpenSSL (https) for JSON-RPC connections + Χρήση του OpenSSL (https) για συνδέσεις JSON-RPC + + + + Server certificate file (default: server.cert) + Αρχείο πιστοποιητικού του διακομιστή (προεπιλογή: server.cert) + + + + Server private key (default: server.pem) + Προσωπικό κλειδί του διακομιστή (προεπιλογή: server.pem) + + + + Acceptable ciphers (default: TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH) + + + + + Error: Wallet unlocked for staking only, unable to create transaction. + + + + + WARNING: Invalid checkpoint found! Displayed transactions may not be correct! You may need to upgrade, or notify developers. + + + + + This help message + Αυτό το κείμενο βοήθειας + + + + Wallet %s resides outside data directory %s. + + + + + Cannot obtain a lock on data directory %s. Arepacoin is probably already running. + + + + + Arepacoin + + + + + Unable to bind to %s on this computer (bind returned error %d, %s) + Αδύνατη η σύνδεση με τη θύρα %s αυτού του υπολογιστή (bind returned error %d, %s) + + + + Connect through socks proxy + + + + + Allow DNS lookups for -addnode, -seednode and -connect + Να επιτρέπονται οι έλεγχοι DNS για προσθήκη και σύνδεση κόμβων + + + + Loading addresses... + Φόρτωση διευθύνσεων... + + + + Error loading blkindex.dat + + + + + Error loading wallet.dat: Wallet corrupted + Σφάλμα φόρτωσης wallet.dat: Κατεστραμμένο Πορτοφόλι + + + + Error loading wallet.dat: Wallet requires newer version of Arepacoin + + + + + Wallet needed to be rewritten: restart Arepacoin to complete + + + + + Error loading wallet.dat + Σφάλμα φόρτωσης αρχείου wallet.dat + + + + Invalid -proxy address: '%s' + Δεν είναι έγκυρη η διεύθυνση διαμεσολαβητή: '%s' + + + + Unknown network specified in -onlynet: '%s' + Άγνωστo δίκτυο ορίζεται σε onlynet: '%s' + + + + Unknown -socks proxy version requested: %i + Άγνωστo δίκτυο ορίζεται: %i + + + + Cannot resolve -bind address: '%s' + Δεν μπορώ να γράψω την προεπιλεγμένη διεύθυνση: '%s' + + + + Cannot resolve -externalip address: '%s' + Δεν μπορώ να γράψω την προεπιλεγμένη διεύθυνση: '%s' + + + + Invalid amount for -paytxfee=<amount>: '%s' + Μη έγκυρο ποσό για την παράμετρο -paytxfee=<amount>: '%s' + + + + Error: could not start node + + + + + Sending... + + + + + Invalid amount + Λάθος ποσότητα + + + + Insufficient funds + Ανεπαρκές κεφάλαιο + + + + Loading block index... + Φόρτωση ευρετηρίου μπλοκ... + + + + Add a node to connect to and attempt to keep the connection open + Προσέθεσε ένα κόμβο για σύνδεση και προσπάθησε να κρατήσεις την σύνδεση ανοιχτή + + + + Unable to bind to %s on this computer. Arepacoin is probably already running. + + + + + Fee per KB to add to transactions you send + + + + + Invalid amount for -mininput=<amount>: '%s' + + + + + Loading wallet... + Φόρτωση πορτοφολιού... + + + + Cannot downgrade wallet + Δεν μπορώ να υποβαθμίσω το πορτοφόλι + + + + Cannot initialize keypool + + + + + Cannot write default address + Δεν μπορώ να γράψω την προεπιλεγμένη διεύθυνση + + + + Rescanning... + Ανίχνευση... + + + + Done loading + Η φόρτωση ολοκληρώθηκε + + + + To use the %s option + Χρήση της %s επιλογής + + + + Error + Σφάλμα + + + + You must set rpcpassword=<password> in the configuration file: +%s +If the file does not exist, create it with owner-readable-only file permissions. + Πρέπει να βάλεις ένα κωδικό στο αρχείο παραμέτρων: %s +Εάν το αρχείο δεν υπάρχει, δημιούργησε το με δικαιώματα μόνο για ανάγνωση από τον δημιουργό + + + \ No newline at end of file diff --git a/src/qt/locale/bitcoin_en.ts b/src/qt/locale/bitcoin_en.ts new file mode 100755 index 0000000..a01ab3d --- /dev/null +++ b/src/qt/locale/bitcoin_en.ts @@ -0,0 +1,3335 @@ + + + + + AboutDialog + + + About Arepacoin + About Arepacoin + + + + <b>Arepacoin</b> version + <b>Arepacoin</b> version + + + + Copyright © 2009-2014 The Bitcoin developers +Copyright © 2012-2014 The NovaCoin developers +Copyright © 2014 The Arepacoin developers + + + + + +This is experimental software. + +Distributed under the MIT/X11 software license, see the accompanying file COPYING or http://www.opensource.org/licenses/mit-license.php. + +This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit (http://www.openssl.org/) and cryptographic software written by Eric Young (eay@cryptsoft.com) and UPnP software written by Thomas Bernard. + +This is experimental software. + +Distributed under the MIT/X11 software license, see the accompanying file COPYING or http://www.opensource.org/licenses/mit-license.php. + +This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit (http://www.openssl.org/) and cryptographic software written by Eric Young (eay@cryptsoft.com) and UPnP software written by Thomas Bernard. + + + + AddressBookPage + + + Address Book + Address Book + + + + Double-click to edit address or label + Double-click to edit address or label + + + + Create a new address + Create a new address + + + + Copy the currently selected address to the system clipboard + Copy the currently selected address to the system clipboard + + + + &New Address + &New Address + + + + These are your Arepacoin addresses for receiving payments. You may want to give a different one to each sender so you can keep track of who is paying you. + These are your Arepacoin addresses for receiving payments. You may want to give a different one to each sender so you can keep track of who is paying you. + + + + &Copy Address + &Copy Address + + + + Show &QR Code + Show &QR Code + + + + Sign a message to prove you own a Arepacoin address + Sign a message to prove you own a Arepacoin address + + + + Sign &Message + + + + + Delete the currently selected address from the list + + + + + Verify a message to ensure it was signed with a specified Arepacoin address + Verify a message to ensure it was signed with a specified Arepacoin address + + + + &Verify Message + &Verify Message + + + + &Delete + &Delete + + + + Copy &Label + Copy &Label + + + + &Edit + &Edit + + + + Export Address Book Data + Export Address Book Data + + + + Comma separated file (*.csv) + Comma separated file (*.csv) + + + + Error exporting + Error exporting + + + + Could not write to file %1. + Could not write to file %1. + + + + AddressTableModel + + + Label + Label + + + + Address + Address + + + + (no label) + (no label) + + + + AskPassphraseDialog + + + Passphrase Dialog + Passphrase Dialog + + + + Enter passphrase + Enter passphrase + + + + New passphrase + New passphrase + + + + Repeat new passphrase + Repeat new passphrase + + + + Serves to disable the trivial sendmoney when OS account compromised. Provides no real security. + + + + + For staking only + + + + + Enter the new passphrase to the wallet.<br/>Please use a passphrase of <b>10 or more random characters</b>, or <b>eight or more words</b>. + Enter the new passphrase to the wallet.<br/>Please use a passphrase of <b>10 or more random characters</b>, or <b>eight or more words</b>. + + + + Encrypt wallet + Encrypt wallet + + + + This operation needs your wallet passphrase to unlock the wallet. + This operation needs your wallet passphrase to unlock the wallet. + + + + Unlock wallet + Unlock wallet + + + + This operation needs your wallet passphrase to decrypt the wallet. + This operation needs your wallet passphrase to decrypt the wallet. + + + + Decrypt wallet + Decrypt wallet + + + + Change passphrase + Change passphrase + + + + Enter the old and new passphrase to the wallet. + Enter the old and new passphrase to the wallet. + + + + Confirm wallet encryption + Confirm wallet encryption + + + + Warning: If you encrypt your wallet and lose your passphrase, you will <b>LOSE ALL OF YOUR COINS</b>! + Warning: If you encrypt your wallet and lose your passphrase, you will <b>LOSE ALL OF YOUR COINS</b>! + + + + Are you sure you wish to encrypt your wallet? + Are you sure you wish to encrypt your wallet? + + + + IMPORTANT: Any previous backups you have made of your wallet file should be replaced with the newly generated, encrypted wallet file. For security reasons, previous backups of the unencrypted wallet file will become useless as soon as you start using the new, encrypted wallet. + + + + + + Warning: The Caps Lock key is on! + Warning: The Caps Lock key is on! + + + + + Wallet encrypted + Wallet encrypted + + + + Arepacoin will close now to finish the encryption process. Remember that encrypting your wallet cannot fully protect your coins from being stolen by malware infecting your computer. + Arepacoin will close now to finish the encryption process. Remember that encrypting your wallet cannot fully protect your coins from being stolen by malware infecting your computer. + + + + + + + Wallet encryption failed + Wallet encryption failed + + + + Wallet encryption failed due to an internal error. Your wallet was not encrypted. + Wallet encryption failed due to an internal error. Your wallet was not encrypted. + + + + + The supplied passphrases do not match. + The supplied passphrases do not match. + + + + Wallet unlock failed + Wallet unlock failed + + + + + + The passphrase entered for the wallet decryption was incorrect. + The passphrase entered for the wallet decryption was incorrect. + + + + Wallet decryption failed + Wallet decryption failed + + + + Wallet passphrase was successfully changed. + Wallet passphrase was successfully changed. + + + + BitcoinGUI + + + Sign &message... + Sign &message... + + + + Synchronizing with network... + Synchronizing with network... + + + + &Overview + &Overview + + + + Show general overview of wallet + Show general overview of wallet + + + + &Transactions + &Transactions + + + + Browse transaction history + Browse transaction history + + + + &Address Book + &Address Book + + + + Edit the list of stored addresses and labels + Edit the list of stored addresses and labels + + + + &Receive coins + &Receive coins + + + + Show the list of addresses for receiving payments + Show the list of addresses for receiving payments + + + + &Send coins + &Send coins + + + + E&xit + E&xit + + + + Quit application + Quit application + + + + Show information about Arepacoin + Show information about Arepacoin + + + + About &Qt + About &Qt + + + + Show information about Qt + Show information about Qt + + + + &Options... + &Options... + + + + &Encrypt Wallet... + &Encrypt Wallet... + + + + &Backup Wallet... + &Backup Wallet... + + + + &Change Passphrase... + &Change Passphrase... + + + + ~%n block(s) remaining + + ~%n block remaining + ~%n blocks remaining + + + + + Processed %1 of %2 (estimated) blocks of transaction history. + Processed %1 of %2 (estimated) blocks of transaction history. + + + + Processed %1 blocks of transaction history. + Processed %1 blocks of transaction history. + + + + &Export... + &Export... + + + + Send coins to a Arepacoin address + Send coins to a Arepacoin address + + + + Modify configuration options for Arepacoin + Modify configuration options for Arepacoin + + + + Export the data in the current tab to a file + Export the data in the current tab to a file + + + + Encrypt or decrypt wallet + Encrypt or decrypt wallet + + + + Backup wallet to another location + Backup wallet to another location + + + + Change the passphrase used for wallet encryption + Change the passphrase used for wallet encryption + + + + &Debug window + &Debug window + + + + Open debugging and diagnostic console + Open debugging and diagnostic console + + + + &Verify message... + &Verify message... + + + + Arepacoin + Arepacoin + + + + Wallet + Wallet + + + + &About Arepacoin + &About Arepacoin + + + + &Show / Hide + &Show / Hide + + + + Unlock wallet + Unlock wallet + + + + &Lock Wallet + + + + + Lock wallet + + + + + &File + &File + + + + &Settings + &Settings + + + + &Help + &Help + + + + Tabs toolbar + Tabs toolbar + + + + Actions toolbar + Actions toolbar + + + + + [testnet] + [testnet] + + + + + Arepacoin client + Arepacoin client + + + + %n active connection(s) to Arepacoin network + + %n active connection to Arepacoin network + %n active connections to Arepacoin network + + + + + Downloaded %1 blocks of transaction history. + Downloaded %1 blocks of transaction history. + + + + Staking.<br>Your weight is %1<br>Network weight is %2<br>Expected time to earn reward is %3 + + + + + Not staking because wallet is locked + + + + + Not staking because wallet is offline + + + + + Not staking because wallet is syncing + + + + + Not staking because you don't have mature coins + + + + + %n second(s) ago + + %n second ago + %n seconds ago + + + + + &Unlock Wallet... + + + + + %n minute(s) ago + + %n minute ago + %n minutes ago + + + + + %n hour(s) ago + + %n hour ago + %n hours ago + + + + + %n day(s) ago + + %n day ago + %n days ago + + + + + Up to date + Up to date + + + + Catching up... + Catching up... + + + + Last received block was generated %1. + Last received block was generated %1. + + + + This transaction is over the size limit. You can still send it for a fee of %1, which goes to the nodes that process your transaction and helps to support the network. Do you want to pay the fee? + + + + + Confirm transaction fee + Confirm transaction fee + + + + Sent transaction + Sent transaction + + + + Incoming transaction + Incoming transaction + + + + Date: %1 +Amount: %2 +Type: %3 +Address: %4 + + Date: %1 +Amount: %2 +Type: %3 +Address: %4 + + + + + + URI handling + URI handling + + + + + URI can not be parsed! This can be caused by an invalid Arepacoin address or malformed URI parameters. + URI can not be parsed! This can be caused by an invalid Arepacoin address or malformed URI parameters. + + + + Wallet is <b>encrypted</b> and currently <b>unlocked</b> + Wallet is <b>encrypted</b> and currently <b>unlocked</b> + + + + Wallet is <b>encrypted</b> and currently <b>locked</b> + Wallet is <b>encrypted</b> and currently <b>locked</b> + + + + Backup Wallet + Backup Wallet + + + + Wallet Data (*.dat) + Wallet Data (*.dat) + + + + Backup Failed + Backup Failed + + + + There was an error trying to save the wallet data to the new location. + There was an error trying to save the wallet data to the new location. + + + + %n second(s) + + %n second + %n seconds + + + + + %n minute(s) + + %n minute + %n minutes + + + + + %n hour(s) + + %n hour + %n hours + + + + + %n day(s) + + %n day + %n days + + + + + Not staking + + + + + A fatal error occurred. Arepacoin can no longer continue safely and will quit. + A fatal error occurred. Arepacoin can no longer continue safely and will quit. + + + + ClientModel + + + Network Alert + Network Alert + + + + CoinControlDialog + + + Coin Control + + + + + Quantity: + + + + + Bytes: + + + + + Amount: + Amount: + + + + Priority: + + + + + Fee: + + + + + Low Output: + + + + + no + + + + + After Fee: + + + + + Change: + + + + + (un)select all + + + + + Tree mode + + + + + List mode + + + + + Amount + Amount + + + + Label + Label + + + + Address + Address + + + + Date + Date + + + + Confirmations + + + + + Confirmed + Confirmed + + + + Priority + + + + + Copy address + Copy address + + + + Copy label + Copy label + + + + + Copy amount + Copy amount + + + + Copy transaction ID + Copy transaction ID + + + + Copy quantity + + + + + Copy fee + + + + + Copy after fee + + + + + Copy bytes + + + + + Copy priority + + + + + Copy low output + + + + + Copy change + + + + + highest + + + + + high + + + + + medium-high + + + + + medium + + + + + low-medium + + + + + low + + + + + lowest + + + + + DUST + + + + + yes + + + + + This label turns red, if the transaction size is bigger than 10000 bytes. + + This means a fee of at least %1 per kb is required. + + Can vary +/- 1 Byte per input. + + + + + Transactions with higher priority get more likely into a block. + +This label turns red, if the priority is smaller than "medium". + + This means a fee of at least %1 per kb is required. + + + + + This label turns red, if any recipient receives an amount smaller than %1. + + This means a fee of at least %2 is required. + + Amounts below 0.546 times the minimum relay fee are shown as DUST. + + + + + This label turns red, if the change is smaller than %1. + + This means a fee of at least %2 is required. + + + + + + (no label) + (no label) + + + + change from %1 (%2) + + + + + (change) + + + + + EditAddressDialog + + + Edit Address + Edit Address + + + + &Label + &Label + + + + The label associated with this address book entry + The label associated with this address book entry + + + + &Address + &Address + + + + The address associated with this address book entry. This can only be modified for sending addresses. + The address associated with this address book entry. This can only be modified for sending addresses. + + + + New receiving address + New receiving address + + + + New sending address + New sending address + + + + Edit receiving address + Edit receiving address + + + + Edit sending address + Edit sending address + + + + The entered address "%1" is already in the address book. + The entered address "%1" is already in the address book. + + + + The entered address "%1" is not a valid Arepacoin address. + The entered address "%1" is not a valid Arepacoin address. + + + + Could not unlock wallet. + Could not unlock wallet. + + + + New key generation failed. + New key generation failed. + + + + GUIUtil::HelpMessageBox + + + + Arepacoin-Qt + Arepacoin-Qt + + + + version + version + + + + Usage: + Usage: + + + + command-line options + command-line options + + + + UI options + UI options + + + + Set language, for example "de_DE" (default: system locale) + Set language, for example "de_DE" (default: system locale) + + + + Start minimized + Start minimized + + + + Show splash screen on startup (default: 1) + Show splash screen on startup (default: 1) + + + + OptionsDialog + + + Options + Options + + + + &Main + &Main + + + + Optional transaction fee per kB that helps make sure your transactions are processed quickly. Most transactions are 1 kB. Fee 0.01 recommended. + Optional transaction fee per kB that helps make sure your transactions are processed quickly. Most transactions are 1 kB. Fee 0.01 recommended. + + + + Pay transaction &fee + Pay transaction &fee + + + + Reserved amount does not participate in staking and is therefore spendable at any time. + + + + + Reserve + + + + + Automatically start Arepacoin after logging in to the system. + Automatically start Arepacoin after logging in to the system. + + + + &Start Arepacoin on system login + &Start Arepacoin on system login + + + + Detach block and address databases at shutdown. This means they can be moved to another data directory, but it slows down shutdown. The wallet is always detached. + Detach block and address databases at shutdown. This means they can be moved to another data directory, but it slows down shutdown. The wallet is always detached. + + + + &Detach databases at shutdown + &Detach databases at shutdown + + + + &Network + &Network + + + + Automatically open the Arepacoin client port on the router. This only works when your router supports UPnP and it is enabled. + Automatically open the Arepacoin client port on the router. This only works when your router supports UPnP and it is enabled. + + + + Map port using &UPnP + Map port using &UPnP + + + + Connect to the Arepacoin network through a SOCKS proxy (e.g. when connecting through Tor). + Connect to the Arepacoin network through a SOCKS proxy (e.g. when connecting through Tor). + + + + &Connect through SOCKS proxy: + &Connect through SOCKS proxy: + + + + Proxy &IP: + Proxy &IP: + + + + IP address of the proxy (e.g. 127.0.0.1) + IP address of the proxy (e.g. 127.0.0.1) + + + + &Port: + &Port: + + + + Port of the proxy (e.g. 9050) + Port of the proxy (e.g. 9050) + + + + SOCKS &Version: + SOCKS &Version: + + + + SOCKS version of the proxy (e.g. 5) + SOCKS version of the proxy (e.g. 5) + + + + &Window + &Window + + + + Show only a tray icon after minimizing the window. + Show only a tray icon after minimizing the window. + + + + &Minimize to the tray instead of the taskbar + &Minimize to the tray instead of the taskbar + + + + Minimize instead of exit the application when the window is closed. When this option is enabled, the application will be closed only after selecting Quit in the menu. + Minimize instead of exit the application when the window is closed. When this option is enabled, the application will be closed only after selecting Quit in the menu. + + + + M&inimize on close + M&inimize on close + + + + &Display + &Display + + + + User Interface &language: + User Interface &language: + + + + The user interface language can be set here. This setting will take effect after restarting Arepacoin. + The user interface language can be set here. This setting will take effect after restarting Arepacoin. + + + + &Unit to show amounts in: + &Unit to show amounts in: + + + + Choose the default subdivision unit to show in the interface and when sending coins. + Choose the default subdivision unit to show in the interface and when sending coins. + + + + Whether to show Arepacoin addresses in the transaction list or not. + Whether to show Arepacoin addresses in the transaction list or not. + + + + &Display addresses in transaction list + &Display addresses in transaction list + + + + Whether to show coin control features or not. + + + + + Display coin &control features (experts only!) + + + + + &OK + &OK + + + + &Cancel + &Cancel + + + + &Apply + &Apply + + + + default + default + + + + + Warning + Warning + + + + + This setting will take effect after restarting Arepacoin. + This setting will take effect after restarting Arepacoin. + + + + The supplied proxy address is invalid. + The supplied proxy address is invalid. + + + + OverviewPage + + + Form + Form + + + + + The displayed information may be out of date. Your wallet automatically synchronizes with the Arepacoin network after a connection is established, but this process has not completed yet. + The displayed information may be out of date. Your wallet automatically synchronizes with the Arepacoin network after a connection is established, but this process has not completed yet. + + + + Stake: + Stake: + + + + Unconfirmed: + Unconfirmed: + + + + Wallet + Wallet + + + + Spendable: + + + + + Your current spendable balance + + + + + Immature: + Immature: + + + + Mined balance that has not yet matured + Mined balance that has not yet matured + + + + Total: + + + + + Your current total balance + + + + + <b>Recent transactions</b> + <b>Recent transactions</b> + + + + Total of transactions that have yet to be confirmed, and do not yet count toward the current balance + Total of transactions that have yet to be confirmed, and do not yet count toward the current balance + + + + Total of coins that was staked, and do not yet count toward the current balance + Total of coins that was staked, and do not yet count toward the current balance + + + + + out of sync + out of sync + + + + QRCodeDialog + + + QR Code Dialog + QR Code Dialog + + + + Request Payment + Request Payment + + + + Amount: + Amount: + + + + Label: + Label: + + + + Message: + Message: + + + + &Save As... + &Save As... + + + + Error encoding URI into QR Code. + Error encoding URI into QR Code. + + + + The entered amount is invalid, please check. + The entered amount is invalid, please check. + + + + Resulting URI too long, try to reduce the text for label / message. + Resulting URI too long, try to reduce the text for label / message. + + + + Save QR Code + Save QR Code + + + + PNG Images (*.png) + PNG Images (*.png) + + + + RPCConsole + + + Client name + Client name + + + + + + + + + + + + + N/A + N/A + + + + Client version + Client version + + + + &Information + &Information + + + + Using OpenSSL version + Using OpenSSL version + + + + Startup time + Startup time + + + + Network + Network + + + + Number of connections + Number of connections + + + + On testnet + On testnet + + + + Block chain + Block chain + + + + Current number of blocks + Current number of blocks + + + + Estimated total blocks + Estimated total blocks + + + + Last block time + Last block time + + + + &Open + &Open + + + + Command-line options + Command-line options + + + + Show the Arepacoin-Qt help message to get a list with possible Arepacoin command-line options. + Show the Arepacoin-Qt help message to get a list with possible Arepacoin command-line options. + + + + &Show + &Show + + + + &Console + &Console + + + + Build date + Build date + + + + Arepacoin - Debug window + Arepacoin - Debug window + + + + Arepacoin Core + Arepacoin Core + + + + Debug log file + Debug log file + + + + Open the Arepacoin debug log file from the current data directory. This can take a few seconds for large log files. + Open the Arepacoin debug log file from the current data directory. This can take a few seconds for large log files. + + + + Clear console + Clear console + + + + Welcome to the Arepacoin RPC console. + Welcome to the Arepacoin RPC console. + + + + Use up and down arrows to navigate history, and <b>Ctrl-L</b> to clear screen. + Use up and down arrows to navigate history, and <b>Ctrl-L</b> to clear screen. + + + + Type <b>help</b> for an overview of available commands. + Type <b>help</b> for an overview of available commands. + + + + SendCoinsDialog + + + + + + + + + + Send Coins + Send Coins + + + + Coin Control Features + + + + + Inputs... + + + + + automatically selected + + + + + Insufficient funds! + + + + + Quantity: + + + + + + 0 + + + + + Bytes: + + + + + Amount: + Amount: + + + + + + + 0.00 BC + 123.456 BC {0.00 ?} + + + + Priority: + + + + + medium + + + + + Fee: + + + + + Low Output: + + + + + no + + + + + After Fee: + + + + + Change + + + + + custom change address + + + + + Send to multiple recipients at once + Send to multiple recipients at once + + + + Add &Recipient + + + + + Remove all transaction fields + Remove all transaction fields + + + + Clear &All + Clear &All + + + + Balance: + Balance: + + + + 123.456 BC + 123.456 BC + + + + Confirm the send action + Confirm the send action + + + + S&end + + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + Copy quantity + + + + + Copy amount + Copy amount + + + + Copy fee + + + + + Copy after fee + + + + + Copy bytes + + + + + Copy priority + + + + + Copy low output + + + + + Copy change + + + + + <b>%1</b> to %2 (%3) + <b>%1</b> to %2 (%3) + + + + Confirm send coins + Confirm send coins + + + + Are you sure you want to send %1? + Are you sure you want to send %1? + + + + and + and + + + + The recipient address is not valid, please recheck. + The recipient address is not valid, please recheck. + + + + The amount to pay must be larger than 0. + The amount to pay must be larger than 0. + + + + The amount exceeds your balance. + The amount exceeds your balance. + + + + The total exceeds your balance when the %1 transaction fee is included. + The total exceeds your balance when the %1 transaction fee is included. + + + + Duplicate address found, can only send to each address once per send operation. + Duplicate address found, can only send to each address once per send operation. + + + + Error: Transaction creation failed. + Error: Transaction creation failed. + + + + 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. + 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. + + + + WARNING: Invalid Arepacoin address + + + + + (no label) + (no label) + + + + WARNING: unknown change address + + + + + SendCoinsEntry + + + Form + Form + + + + A&mount: + A&mount: + + + + Pay &To: + Pay &To: + + + + + Enter a label for this address to add it to your address book + Enter a label for this address to add it to your address book + + + + &Label: + &Label: + + + + The address to send the payment to (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Choose address from address book + Choose address from address book + + + + Alt+A + Alt+A + + + + Paste address from clipboard + Paste address from clipboard + + + + Alt+P + Alt+P + + + + Remove this recipient + Remove this recipient + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + SignVerifyMessageDialog + + + Signatures - Sign / Verify a Message + Signatures - Sign / Verify a Message + + + + + &Sign Message + &Sign Message + + + + You can sign messages with your addresses to prove you own them. Be careful not to sign anything vague, as phishing attacks may try to trick you into signing your identity over to them. Only sign fully-detailed statements you agree to. + You can sign messages with your addresses to prove you own them. Be careful not to sign anything vague, as phishing attacks may try to trick you into signing your identity over to them. Only sign fully-detailed statements you agree to. + + + + The address to sign the message with (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + The address to sign the message with (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Choose an address from the address book + Choose an address from the address book + + + + + Alt+A + Alt+A + + + + Paste address from clipboard + Paste address from clipboard + + + + Alt+P + Alt+P + + + + Enter the message you want to sign here + Enter the message you want to sign here + + + + Copy the current signature to the system clipboard + Copy the current signature to the system clipboard + + + + Sign the message to prove you own this Arepacoin address + Sign the message to prove you own this Arepacoin address + + + + Reset all sign message fields + Reset all sign message fields + + + + + Clear &All + Clear &All + + + + + &Verify Message + &Verify Message + + + + Enter the signing address, message (ensure you copy line breaks, spaces, tabs, etc. exactly) and signature below to verify the message. Be careful not to read more into the signature than what is in the signed message itself, to avoid being tricked by a man-in-the-middle attack. + Enter the signing address, message (ensure you copy line breaks, spaces, tabs, etc. exactly) and signature below to verify the message. Be careful not to read more into the signature than what is in the signed message itself, to avoid being tricked by a man-in-the-middle attack. + + + + The address the message was signed with (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + The address the message was signed with (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + Verify the message to ensure it was signed with the specified Arepacoin address + Verify the message to ensure it was signed with the specified Arepacoin address + + + + Reset all verify message fields + Reset all verify message fields + + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + Click "Sign Message" to generate signature + Click "Sign Message" to generate signature + + + + Enter Arepacoin signature + Enter Arepacoin signature + + + + + The entered address is invalid. + The entered address is invalid. + + + + + + + Please check the address and try again. + Please check the address and try again. + + + + + The entered address does not refer to a key. + The entered address does not refer to a key. + + + + Wallet unlock was cancelled. + Wallet unlock was cancelled. + + + + Private key for the entered address is not available. + Private key for the entered address is not available. + + + + Message signing failed. + Message signing failed. + + + + Message signed. + Message signed. + + + + The signature could not be decoded. + The signature could not be decoded. + + + + + Please check the signature and try again. + Please check the signature and try again. + + + + The signature did not match the message digest. + The signature did not match the message digest. + + + + Message verification failed. + Message verification failed. + + + + Message verified. + Message verified. + + + + TransactionDesc + + + Open until %1 + Open until %1 + + + + Open for %n block(s) + + Open for %n block + Open for %n blocks + + + + + conflicted + + + + + %1/offline + %1/offline + + + + %1/unconfirmed + %1/unconfirmed + + + + %1 confirmations + %1 confirmations + + + + Status + Status + + + + , broadcast through %n node(s) + + , broadcast through %n node + , broadcast through %n nodes + + + + + Date + Date + + + + Source + Source + + + + Generated + Generated + + + + + From + From + + + + + + To + To + + + + + own address + own address + + + + label + label + + + + + + + + Credit + Credit + + + + matures in %n more block(s) + + matures in %n more block + matures in %n more blocks + + + + + not accepted + not accepted + + + + + + + Debit + Debit + + + + Transaction fee + Transaction fee + + + + Net amount + Net amount + + + + Message + Message + + + + Comment + Comment + + + + Transaction ID + Transaction ID + + + + Generated coins must mature 6 blocks before they can be spent. When you generated this block, it was broadcast to the network to be added to the block chain. If it fails to get into the chain, its state will change to "not accepted" and it won't be spendable. This may occasionally happen if another node generates a block within a few seconds of yours. + Generated coins must mature 6 blocks before they can be spent. When you generated this block, it was broadcast to the network to be added to the block chain. If it fails to get into the chain, its state will change to "not accepted" and it won't be spendable. This may occasionally happen if another node generates a block within a few seconds of yours. + + + + Debug information + Debug information + + + + Transaction + Transaction + + + + Inputs + Inputs + + + + Amount + Amount + + + + true + true + + + + false + false + + + + , has not been successfully broadcast yet + , has not been successfully broadcast yet + + + + unknown + unknown + + + + TransactionDescDialog + + + Transaction details + Transaction details + + + + This pane shows a detailed description of the transaction + This pane shows a detailed description of the transaction + + + + TransactionTableModel + + + Date + Date + + + + Type + Type + + + + Address + Address + + + + Amount + Amount + + + + Open until %1 + Open until %1 + + + + Confirmed (%1 confirmations) + Confirmed (%1 confirmations) + + + + Open for %n more block(s) + + Open for %n more block + Open for %n more blocks + + + + + Offline + + + + + Unconfirmed + + + + + Confirming (%1 of %2 recommended confirmations) + + + + + Conflicted + + + + + Immature (%1 confirmations, will be available after %2) + + + + + This block was not received by any other nodes and will probably not be accepted! + This block was not received by any other nodes and will probably not be accepted! + + + + Generated but not accepted + Generated but not accepted + + + + Received with + Received with + + + + Received from + Received from + + + + Sent to + Sent to + + + + Payment to yourself + Payment to yourself + + + + Mined + Mined + + + + (n/a) + (n/a) + + + + Transaction status. Hover over this field to show number of confirmations. + Transaction status. Hover over this field to show number of confirmations. + + + + Date and time that the transaction was received. + Date and time that the transaction was received. + + + + Type of transaction. + Type of transaction. + + + + Destination address of transaction. + Destination address of transaction. + + + + Amount removed from or added to balance. + Amount removed from or added to balance. + + + + TransactionView + + + + All + All + + + + Today + Today + + + + This week + This week + + + + This month + This month + + + + Last month + Last month + + + + This year + This year + + + + Range... + Range... + + + + Received with + Received with + + + + Sent to + Sent to + + + + To yourself + To yourself + + + + Mined + Mined + + + + Other + Other + + + + Enter address or label to search + Enter address or label to search + + + + Min amount + Min amount + + + + Copy address + Copy address + + + + Copy label + Copy label + + + + Copy amount + Copy amount + + + + Copy transaction ID + Copy transaction ID + + + + Edit label + Edit label + + + + Show transaction details + Show transaction details + + + + Export Transaction Data + Export Transaction Data + + + + Comma separated file (*.csv) + Comma separated file (*.csv) + + + + Confirmed + Confirmed + + + + Date + Date + + + + Type + Type + + + + Label + Label + + + + Address + Address + + + + Amount + Amount + + + + ID + ID + + + + Error exporting + Error exporting + + + + Could not write to file %1. + Could not write to file %1. + + + + Range: + Range: + + + + to + to + + + + WalletModel + + + Sending... + Sending... + + + + bitcoin-core + + + Arepacoin version + Arepacoin version + + + + Usage: + Usage: + + + + Send command to -server or arepacoind + Send command to -server or arepacoind + + + + List commands + List commands + + + + Get help for a command + Get help for a command + + + + Options: + Options: + + + + Specify configuration file (default: arepacoin.conf) + Specify configuration file (default: arepacoin.conf) + + + + Specify pid file (default: arepacoind.pid) + Specify pid file (default: arepacoind.pid) + + + + Specify wallet file (within data directory) + Specify wallet file (within data directory) + + + + Specify data directory + Specify data directory + + + + Set database cache size in megabytes (default: 25) + Set database cache size in megabytes (default: 25) + + + + Set database disk log size in megabytes (default: 100) + Set database disk log size in megabytes (default: 100) + + + + Listen for connections on <port> (default: 9853 or testnet: 19853) + Listen for connections on <port> (default: 9853 or testnet: 19853) + + + + Maintain at most <n> connections to peers (default: 125) + Maintain at most <n> connections to peers (default: 125) + + + + Connect to a node to retrieve peer addresses, and disconnect + Connect to a node to retrieve peer addresses, and disconnect + + + + Specify your own public address + Specify your own public address + + + + Bind to given address. Use [host]:port notation for IPv6 + Bind to given address. Use [host]:port notation for IPv6 + + + + Stake your coins to support network and gain reward (default: 1) + + + + + Threshold for disconnecting misbehaving peers (default: 100) + Threshold for disconnecting misbehaving peers (default: 100) + + + + Number of seconds to keep misbehaving peers from reconnecting (default: 86400) + Number of seconds to keep misbehaving peers from reconnecting (default: 86400) + + + + An error occurred while setting up the RPC port %u for listening on IPv4: %s + + + + + Detach block and address databases. Increases shutdown time (default: 0) + Detach block and address databases. Increases shutdown time (default: 0) + + + + 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. + + + + + Error: This transaction requires a transaction fee of at least %s because of its amount, complexity, or use of recently received funds + + + + + Listen for JSON-RPC connections on <port> (default: 9852 or testnet: 19852) + + + + + Accept command line and JSON-RPC commands + Accept command line and JSON-RPC commands + + + + Error: Transaction creation failed + + + + + Error: Wallet locked, unable to create transaction + + + + + Importing blockchain data file. + + + + + Importing bootstrap blockchain data file. + + + + + Run in the background as a daemon and accept commands + Run in the background as a daemon and accept commands + + + + Use the test network + Use the test network + + + + Accept connections from outside (default: 1 if no -proxy or -connect) + Accept connections from outside (default: 1 if no -proxy or -connect) + + + + An error occurred while setting up the RPC port %u for listening on IPv6, falling back to IPv4: %s + + + + + Error initializing database environment %s! To recover, BACKUP THAT DIRECTORY, then remove everything from it except for wallet.dat. + + + + + Set maximum size of high-priority/low-fee transactions in bytes (default: 27000) + Set maximum size of high-priority/low-fee transactions in bytes (default: 27000) + + + + Warning: -paytxfee is set very high! This is the transaction fee you will pay if you send a transaction. + Warning: -paytxfee is set very high! This is the transaction fee you will pay if you send a transaction. + + + + Warning: Please check that your computer's date and time are correct! If your clock is wrong Arepacoin will not work properly. + Warning: Please check that your computer's date and time are correct! If your clock is wrong Arepacoin will not work properly. + + + + Warning: error reading wallet.dat! All keys read correctly, but transaction data or address book entries might be missing or incorrect. + Warning: error reading wallet.dat! All keys read correctly, but transaction data or address book entries might be missing or incorrect. + + + + Warning: wallet.dat corrupt, data salvaged! Original wallet.dat saved as wallet.{timestamp}.bak in %s; if your balance or transactions are incorrect you should restore from a backup. + Warning: wallet.dat corrupt, data salvaged! Original wallet.dat saved as wallet.{timestamp}.bak in %s; if your balance or transactions are incorrect you should restore from a backup. + + + + Attempt to recover private keys from a corrupt wallet.dat + Attempt to recover private keys from a corrupt wallet.dat + + + + Block creation options: + Block creation options: + + + + Connect only to the specified node(s) + Connect only to the specified node(s) + + + + Discover own IP address (default: 1 when listening and no -externalip) + Discover own IP address (default: 1 when listening and no -externalip) + + + + Failed to listen on any port. Use -listen=0 if you want this. + Failed to listen on any port. Use -listen=0 if you want this. + + + + Find peers using DNS lookup (default: 1) + Find peers using DNS lookup (default: 1) + + + + Sync checkpoints policy (default: strict) + Sync checkpoints policy (default: strict) + + + + Invalid -tor address: '%s' + Invalid -tor address: '%s' + + + + Invalid amount for -reservebalance=<amount> + + + + + Maximum per-connection receive buffer, <n>*1000 bytes (default: 5000) + Maximum per-connection receive buffer, <n>*1000 bytes (default: 5000) + + + + Maximum per-connection send buffer, <n>*1000 bytes (default: 1000) + Maximum per-connection send buffer, <n>*1000 bytes (default: 1000) + + + + Only connect to nodes in network <net> (IPv4, IPv6 or Tor) + Only connect to nodes in network <net> (IPv4, IPv6 or Tor) + + + + Output extra debugging information. Implies all other -debug* options + Output extra debugging information. Implies all other -debug* options + + + + Output extra network debugging information + Output extra network debugging information + + + + Prepend debug output with timestamp + Prepend debug output with timestamp + + + + SSL options: (see the Bitcoin Wiki for SSL setup instructions) + SSL options: (see the Bitcoin Wiki for SSL setup instructions) + + + + Select the version of socks proxy to use (4-5, default: 5) + Select the version of socks proxy to use (4-5, default: 5) + + + + Send trace/debug info to console instead of debug.log file + Send trace/debug info to console instead of debug.log file + + + + Send trace/debug info to debugger + Send trace/debug info to debugger + + + + Set maximum block size in bytes (default: 250000) + Set maximum block size in bytes (default: 250000) + + + + Set minimum block size in bytes (default: 0) + Set minimum block size in bytes (default: 0) + + + + Shrink debug.log file on client startup (default: 1 when no -debug) + Shrink debug.log file on client startup (default: 1 when no -debug) + + + + Specify connection timeout in milliseconds (default: 5000) + Specify connection timeout in milliseconds (default: 5000) + + + + Unable to sign checkpoint, wrong checkpointkey? + + + + + + Use UPnP to map the listening port (default: 0) + Use UPnP to map the listening port (default: 0) + + + + Use UPnP to map the listening port (default: 1 when listening) + Use UPnP to map the listening port (default: 1 when listening) + + + + Use proxy to reach tor hidden services (default: same as -proxy) + Use proxy to reach tor hidden services (default: same as -proxy) + + + + Username for JSON-RPC connections + Username for JSON-RPC connections + + + + Verifying database integrity... + + + + + WARNING: syncronized checkpoint violation detected, but skipped! + + + + + Warning: Disk space is low! + Warning: Disk space is low! + + + + Warning: This version is obsolete, upgrade required! + Warning: This version is obsolete, upgrade required! + + + + wallet.dat corrupt, salvage failed + + + + + Password for JSON-RPC connections + Password for JSON-RPC connections + + + + %s, you must set a rpcpassword in the configuration file: + %s +It is recommended you use the following random password: +rpcuser=arepacoinrpc +rpcpassword=%s +(you do not need to remember this password) +The username and password MUST NOT be the same. +If the file does not exist, create it with owner-readable-only file permissions. +It is also recommended to set alertnotify so you are notified of problems; +for example: alertnotify=echo %%s | mail -s "Arepacoin Alert" admin@foo.com + + + + + + Find peers using internet relay chat (default: 0) + Find peers using internet relay chat (default: 1) {0)?} + + + + Sync time with other nodes. Disable if time on your system is precise e.g. syncing with NTP (default: 1) + + + + + When creating transactions, ignore inputs with value less than this (default: 0.01) + + + + + Allow JSON-RPC connections from specified IP address + Allow JSON-RPC connections from specified IP address + + + + Send commands to node running on <ip> (default: 127.0.0.1) + Send commands to node running on <ip> (default: 127.0.0.1) + + + + Execute command when the best block changes (%s in cmd is replaced by block hash) + Execute command when the best block changes (%s in cmd is replaced by block hash) + + + + Execute command when a wallet transaction changes (%s in cmd is replaced by TxID) + Execute command when a wallet transaction changes (%s in cmd is replaced by TxID) + + + + Require a confirmations for change (default: 0) + + + + + Enforce transaction scripts to use canonical PUSH operators (default: 1) + + + + + Execute command when a relevant alert is received (%s in cmd is replaced by message) + + + + + Upgrade wallet to latest format + Upgrade wallet to latest format + + + + Set key pool size to <n> (default: 100) + Set key pool size to <n> (default: 100) + + + + Rescan the block chain for missing wallet transactions + Rescan the block chain for missing wallet transactions + + + + How many blocks to check at startup (default: 2500, 0 = all) + How many blocks to check at startup (default: 2500, 0 = all) + + + + How thorough the block verification is (0-6, default: 1) + How thorough the block verification is (0-6, default: 1) + + + + Imports blocks from external blk000?.dat file + Imports blocks from external blk000?.dat file + + + + Use OpenSSL (https) for JSON-RPC connections + Use OpenSSL (https) for JSON-RPC connections + + + + Server certificate file (default: server.cert) + Server certificate file (default: server.cert) + + + + Server private key (default: server.pem) + Server private key (default: server.pem) + + + + Acceptable ciphers (default: TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH) + Acceptable ciphers (default: TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH) + + + + Error: Wallet unlocked for staking only, unable to create transaction. + + + + + WARNING: Invalid checkpoint found! Displayed transactions may not be correct! You may need to upgrade, or notify developers. + + + + + This help message + This help message + + + + Wallet %s resides outside data directory %s. + Wallet %s resides outside data directory %s. + + + + Cannot obtain a lock on data directory %s. Arepacoin is probably already running. + Cannot obtain a lock on data directory %s. Arepacoin is probably already running. + + + + Arepacoin + Arepacoin + + + + Unable to bind to %s on this computer (bind returned error %d, %s) + Unable to bind to %s on this computer (bind returned error %d, %s) + + + + Connect through socks proxy + Connect through socks proxy + + + + Allow DNS lookups for -addnode, -seednode and -connect + Allow DNS lookups for -addnode, -seednode and -connect + + + + Loading addresses... + Loading addresses... + + + + Error loading blkindex.dat + Error loading blkindex.dat + + + + Error loading wallet.dat: Wallet corrupted + Error loading wallet.dat: Wallet corrupted + + + + Error loading wallet.dat: Wallet requires newer version of Arepacoin + Error loading wallet.dat: Wallet requires newer version of Arepacoin + + + + Wallet needed to be rewritten: restart Arepacoin to complete + Wallet needed to be rewritten: restart Arepacoin to complete + + + + Error loading wallet.dat + Error loading wallet.dat + + + + Invalid -proxy address: '%s' + Invalid -proxy address: '%s' + + + + Unknown network specified in -onlynet: '%s' + Unknown network specified in -onlynet: '%s' + + + + Unknown -socks proxy version requested: %i + Unknown -socks proxy version requested: %i + + + + Cannot resolve -bind address: '%s' + Cannot resolve -bind address: '%s' + + + + Cannot resolve -externalip address: '%s' + Cannot resolve -externalip address: '%s' + + + + Invalid amount for -paytxfee=<amount>: '%s' + Invalid amount for -paytxfee=<amount>: '%s' + + + + Error: could not start node + Error: could not start node + + + + Sending... + Sending... + + + + Invalid amount + Invalid amount + + + + Insufficient funds + Insufficient funds + + + + Loading block index... + Loading block index... + + + + Add a node to connect to and attempt to keep the connection open + Add a node to connect to and attempt to keep the connection open + + + + Unable to bind to %s on this computer. Arepacoin is probably already running. + Unable to bind to %s on this computer. Arepacoin is probably already running. + + + + Fee per KB to add to transactions you send + Fee per KB to add to transactions you send + + + + Invalid amount for -mininput=<amount>: '%s' + + + + + Loading wallet... + Loading wallet... + + + + Cannot downgrade wallet + Cannot downgrade wallet + + + + Cannot initialize keypool + Cannot initialize keypool + + + + Cannot write default address + Cannot write default address + + + + Rescanning... + Rescanning... + + + + Done loading + Done loading + + + + To use the %s option + To use the %s option + + + + Error + Error + + + + You must set rpcpassword=<password> in the configuration file: +%s +If the file does not exist, create it with owner-readable-only file permissions. + You must set rpcpassword=<password> in the configuration file: +%s +If the file does not exist, create it with owner-readable-only file permissions. + + + diff --git a/src/qt/locale/bitcoin_eo.ts b/src/qt/locale/bitcoin_eo.ts new file mode 100755 index 0000000..f28137f --- /dev/null +++ b/src/qt/locale/bitcoin_eo.ts @@ -0,0 +1,3286 @@ + + + AboutDialog + + + About Arepacoin + + + + + <b>Arepacoin</b> version + + + + + Copyright © 2009-2014 The Bitcoin developers +Copyright © 2012-2014 The NovaCoin developers +Copyright © 2014 The Arepacoin developers + + + + + +This is experimental software. + +Distributed under the MIT/X11 software license, see the accompanying file COPYING or http://www.opensource.org/licenses/mit-license.php. + +This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit (http://www.openssl.org/) and cryptographic software written by Eric Young (eay@cryptsoft.com) and UPnP software written by Thomas Bernard. + +Tio ĉi estas eksperimenta programo. + +Eldonita laŭ la permesilo MIT/X11. Vidu la kunan dosieron COPYING aŭ http://www.opensource.org/licenses/mit-license.php. + +Tiu ĉi produkto enhavas erojn kreitajn de la "OpenSSL Project" por uzo en la "OpenSSL Toolkit" (http://www.openssl.org/) kaj ĉifrajn erojn kreitajn de Eric Young (eay@cryptsoft.com) kaj UPnP-erojn kreitajn de Thomas Bernard. + + + + AddressBookPage + + + Address Book + + + + + Double-click to edit address or label + Duoble-klaku por redakti adreson aŭ etikedon + + + + Create a new address + Krei novan adreson + + + + Copy the currently selected address to the system clipboard + Kopii elektitan adreson al la tondejo + + + + &New Address + + + + + These are your Arepacoin addresses for receiving payments. You may want to give a different one to each sender so you can keep track of who is paying you. + + + + + &Copy Address + &Kopii Adreson + + + + Show &QR Code + + + + + Sign a message to prove you own a Arepacoin address + + + + + Sign &Message + + + + + Delete the currently selected address from the list + Forigi la elektitan adreson el la listo + + + + Verify a message to ensure it was signed with a specified Arepacoin address + + + + + &Verify Message + + + + + &Delete + &Forigi + + + + Copy &Label + Kopii &Etikedon + + + + &Edit + &Redakti + + + + Export Address Book Data + + + + + Comma separated file (*.csv) + Perkome disigita dosiero (*.csv) + + + + Error exporting + + + + + Could not write to file %1. + + + + + AddressTableModel + + + Label + Etikedo + + + + Address + Adreso + + + + (no label) + (neniu etikedo) + + + + AskPassphraseDialog + + + Passphrase Dialog + Dialogo pri pasfrazo + + + + Enter passphrase + Enigu pasfrazon + + + + New passphrase + Nova pasfrazo + + + + Repeat new passphrase + Ripetu la novan pasfrazon + + + + Serves to disable the trivial sendmoney when OS account compromised. Provides no real security. + + + + + For staking only + + + + + Enter the new passphrase to the wallet.<br/>Please use a passphrase of <b>10 or more random characters</b>, or <b>eight or more words</b>. + Enigu novan pasfrazon por la monujo.<br/>Bonvolu uzi pasfrazon kun <b>almenaŭ 10 hazardaj signoj</b>, aŭ <b>almenaŭ ok vortoj</b>. + + + + Encrypt wallet + Ĉifri la monujon + + + + This operation needs your wallet passphrase to unlock the wallet. + Ĉi tiu operacio bezonas vian monujan pasfrazon, por malŝlosi la monujon. + + + + Unlock wallet + Malŝlosi la monujon + + + + This operation needs your wallet passphrase to decrypt the wallet. + Ĉi tiu operacio bezonas vian monujan pasfrazon, por malĉifri la monujon. + + + + Decrypt wallet + Malĉifri la monujon + + + + Change passphrase + Ŝanĝi la pasfrazon + + + + Enter the old and new passphrase to the wallet. + Tajpu la malnovan kaj novan monujajn pasfrazojn. + + + + Confirm wallet encryption + Konfirmo de ĉifrado de la monujo + + + + Warning: If you encrypt your wallet and lose your passphrase, you will <b>LOSE ALL OF YOUR COINS</b>! + + + + + Are you sure you wish to encrypt your wallet? + Ĉu vi certas, ke vi volas ĉifri la monujon? + + + + IMPORTANT: Any previous backups you have made of your wallet file should be replaced with the newly generated, encrypted wallet file. For security reasons, previous backups of the unencrypted wallet file will become useless as soon as you start using the new, encrypted wallet. + GRAVE: antaŭaj sekur-kopioj de via monujo-dosiero estas forigindaj kiam vi havas nove kreitan ĉifritan monujo-dosieron. Pro sekureco, antaŭaj kopioj de la neĉifrita dosiero ne plu funkcios tuj kiam vi ekuzos la novan ĉifritan dosieron. + + + + + Warning: The Caps Lock key is on! + Atentu: la majuskla baskulo estas ŝaltita! + + + + + Wallet encrypted + La monujo estas ĉifrita + + + + Arepacoin will close now to finish the encryption process. Remember that encrypting your wallet cannot fully protect your coins from being stolen by malware infecting your computer. + + + + + + + + Wallet encryption failed + Ĉifrado de la monujo fiaskis + + + + Wallet encryption failed due to an internal error. Your wallet was not encrypted. + Ĉifrado de monujo fiaskis pro interna eraro. Via monujo ne estas ĉifrita. + + + + + The supplied passphrases do not match. + La pasfrazoj entajpitaj ne samas. + + + + Wallet unlock failed + Malŝloso de la monujo fiaskis + + + + + + The passphrase entered for the wallet decryption was incorrect. + La pasfrazo enigita por ĉifrado de monujo ne ĝustas. + + + + Wallet decryption failed + Malĉifrado de la monujo fiaskis + + + + Wallet passphrase was successfully changed. + Vi sukcese ŝanĝis la pasfrazon de la monujo. + + + + BitcoinGUI + + + Sign &message... + Subskribi &mesaĝon... + + + + Synchronizing with network... + Sinkronigante kun reto... + + + + &Overview + &Superrigardo + + + + Show general overview of wallet + Vidigi ĝeneralan superrigardon de la monujo + + + + &Transactions + &Transakcioj + + + + Browse transaction history + Esplori historion de transakcioj + + + + &Address Book + + + + + Edit the list of stored addresses and labels + + + + + &Receive coins + + + + + Show the list of addresses for receiving payments + + + + + &Send coins + + + + + E&xit + &Eliri + + + + Quit application + Eliri la aplikaĵon + + + + Show information about Arepacoin + + + + + About &Qt + Pri &Qt + + + + Show information about Qt + Vidigi informojn pri Qt + + + + &Options... + &Agordoj... + + + + &Encrypt Wallet... + Ĉifri &Monujon... + + + + &Backup Wallet... + &Krei sekurkopion de la monujo... + + + + &Change Passphrase... + Ŝanĝi &Pasfrazon... + + + + ~%n block(s) remaining + + + + + Downloaded %1 of %2 blocks of transaction history (%3% done). + + + + + &Export... + + + + + Send coins to a Arepacoin address + + + + + Modify configuration options for Arepacoin + + + + + Export the data in the current tab to a file + + + + + Encrypt or decrypt wallet + + + + + Backup wallet to another location + Krei alilokan sekurkopion de monujo + + + + Change the passphrase used for wallet encryption + Ŝanĝi la pasfrazon por ĉifri la monujon + + + + &Debug window + Sen&cimiga fenestro + + + + Open debugging and diagnostic console + Malfermi konzolon de sencimigo kaj diagnozo + + + + &Verify message... + &Kontroli mesaĝon... + + + + Arepacoin + + + + + Wallet + Monujo + + + + &About Arepacoin + + + + + &Show / Hide + &Montri / Kaŝi + + + + Unlock wallet + + + + + &Lock Wallet + + + + + Lock wallet + + + + + &File + &Dosiero + + + + &Settings + &Agordoj + + + + &Help + &Helpo + + + + Tabs toolbar + Langeto-breto + + + + Actions toolbar + + + + + + [testnet] + [testnet] + + + + + Arepacoin client + + + + + %n active connection(s) to Arepacoin network + + + + + Downloaded %1 blocks of transaction history. + + + + + Staking.<br>Your weight is %1<br>Network weight is %2<br>Expected time to earn reward is %3 + + + + + Not staking because wallet is locked + + + + + Not staking because wallet is offline + + + + + Not staking because wallet is syncing + + + + + Not staking because you don't have mature coins + + + + + %n second(s) ago + + + + + &Unlock Wallet... + + + + + %n minute(s) ago + + + + + %n hour(s) ago + + + + + %n day(s) ago + + + + + Up to date + Ĝisdata + + + + Catching up... + Ĝisdatigante... + + + + Last received block was generated %1. + + + + + This transaction is over the size limit. You can still send it for a fee of %1, which goes to the nodes that process your transaction and helps to support the network. Do you want to pay the fee? + + + + + Confirm transaction fee + + + + + Sent transaction + Sendita transakcio + + + + Incoming transaction + Envenanta transakcio + + + + Date: %1 +Amount: %2 +Type: %3 +Address: %4 + + Dato: %1 +Sumo: %2 +Tipo: %3 +Adreso: %4 + + + + + + URI handling + + + + + + URI can not be parsed! This can be caused by an invalid Arepacoin address or malformed URI parameters. + + + + + Wallet is <b>encrypted</b> and currently <b>unlocked</b> + Monujo estas <b>ĉifrita</b> kaj aktuale <b>malŝlosita</b> + + + + Wallet is <b>encrypted</b> and currently <b>locked</b> + Monujo estas <b>ĉifrita</b> kaj aktuale <b>ŝlosita</b> + + + + Backup Wallet + + + + + Wallet Data (*.dat) + + + + + Backup Failed + + + + + There was an error trying to save the wallet data to the new location. + + + + + %n second(s) + + + + + %n minute(s) + + + + + %n hour(s) + %n horo%n horoj + + + + %n day(s) + %n tago%n tagoj + + + + Not staking + + + + + A fatal error occurred. Arepacoin can no longer continue safely and will quit. + + + + + ClientModel + + + Network Alert + Reta Averto + + + + CoinControlDialog + + + Coin Control + + + + + Quantity: + Kvanto: + + + + Bytes: + Bajtoj: + + + + Amount: + Sumo: + + + + Priority: + Prioritato: + + + + Fee: + Krompago: + + + + Low Output: + Malalta Eligo: + + + + no + ne + + + + After Fee: + Post krompago: + + + + Change: + Restmono: + + + + (un)select all + (mal)elekti ĉion + + + + Tree mode + Arboreĝimo + + + + List mode + Listreĝimo + + + + Amount + Sumo + + + + Label + + + + + Address + Adreso + + + + Date + Dato + + + + Confirmations + Konfirmoj + + + + Confirmed + Konfirmita + + + + Priority + Prioritato + + + + Copy address + Kopii adreson + + + + Copy label + Kopii etikedon + + + + + Copy amount + Kopii sumon + + + + Copy transaction ID + Kopii transakcian ID-on + + + + Copy quantity + Kopii kvanton + + + + Copy fee + Kopii krompagon + + + + Copy after fee + Kopii post krompago + + + + Copy bytes + Kopii bajtojn + + + + Copy priority + Kopii prioritaton + + + + Copy low output + Kopii malaltan eligon + + + + Copy change + Kopii restmonon + + + + highest + plej alta + + + + high + alta + + + + medium-high + mezalta + + + + medium + meza + + + + low-medium + mezmalalta + + + + low + malalta + + + + lowest + plej malalta + + + + DUST + + + + + yes + jes + + + + This label turns red, if the transaction size is bigger than 10000 bytes. + + This means a fee of at least %1 per kb is required. + + Can vary +/- 1 Byte per input. + + + + + Transactions with higher priority get more likely into a block. + +This label turns red, if the priority is smaller than "medium". + + This means a fee of at least %1 per kb is required. + + + + + This label turns red, if any recipient receives an amount smaller than %1. + + This means a fee of at least %2 is required. + + Amounts below 0.546 times the minimum relay fee are shown as DUST. + + + + + This label turns red, if the change is smaller than %1. + + This means a fee of at least %2 is required. + + + + + + (no label) + (neniu etikedo) + + + + change from %1 (%2) + restmono de %1 (%2) + + + + (change) + (restmono) + + + + EditAddressDialog + + + Edit Address + Redakti Adreson + + + + &Label + &Etikedo + + + + The label associated with this address book entry + + + + + &Address + &Adreso + + + + The address associated with this address book entry. This can only be modified for sending addresses. + + + + + New receiving address + Nova adreso por ricevi + + + + New sending address + Nova adreso por sendi + + + + Edit receiving address + Redakti adreson por ricevi + + + + Edit sending address + Redakti adreson por sendi + + + + The entered address "%1" is already in the address book. + La adreso enigita "%1" jam ekzistas en la adresaro. + + + + The entered address "%1" is not a valid Arepacoin address. + + + + + Could not unlock wallet. + Ne eblis malŝlosi monujon. + + + + New key generation failed. + Fiaskis kreo de nova ŝlosilo. + + + + GUIUtil::HelpMessageBox + + + + Arepacoin-Qt + + + + + version + + + + + Usage: + + + + + command-line options + + + + + UI options + + + + + Set language, for example "de_DE" (default: system locale) + + + + + Start minimized + + + + + Show splash screen on startup (default: 1) + + + + + OptionsDialog + + + Options + Agordaĵoj + + + + &Main + Ĉ&efa + + + + Optional transaction fee per kB that helps make sure your transactions are processed quickly. Most transactions are 1 kB. Fee 0.01 recommended. + + + + + Pay transaction &fee + Krompago + + + + Reserved amount does not participate in staking and is therefore spendable at any time. + + + + + Reserve + + + + + Automatically start Arepacoin after logging in to the system. + + + + + &Start Arepacoin on system login + + + + + Detach block and address databases at shutdown. This means they can be moved to another data directory, but it slows down shutdown. The wallet is always detached. + + + + + &Detach databases at shutdown + + + + + &Network + &Reto + + + + Automatically open the Arepacoin client port on the router. This only works when your router supports UPnP and it is enabled. + + + + + Map port using &UPnP + Mapigi pordon per &UPnP + + + + Connect to the Arepacoin network through a SOCKS proxy (e.g. when connecting through Tor). + + + + + &Connect through SOCKS proxy: + + + + + Proxy &IP: + Prokurila &IP: + + + + IP address of the proxy (e.g. 127.0.0.1) + + + + + &Port: + &Pordo: + + + + Port of the proxy (e.g. 9050) + la pordo de la prokurilo (ekz. 9050) + + + + SOCKS &Version: + Versio de SOCKS: + + + + SOCKS version of the proxy (e.g. 5) + la versio de SOCKS ĉe la prokurilo (ekz. 5) + + + + &Window + &Fenestro + + + + Show only a tray icon after minimizing the window. + Montri nur sistempletan piktogramon post minimumigo de la fenestro. + + + + &Minimize to the tray instead of the taskbar + &Minimumigi al la sistempleto anstataŭ al la taskopleto + + + + Minimize instead of exit the application when the window is closed. When this option is enabled, the application will be closed only after selecting Quit in the menu. + Minimumigi la aplikaĵon anstataŭ eliri kaj ĉesi kiam la fenestro estas fermita. Se tiu ĉi estas agordita, la aplikaĵo ĉesas nur kiam oni elektas "Eliri" el la menuo. + + + + M&inimize on close + M&inimumigi je fermo + + + + &Display + &Aspekto + + + + User Interface &language: + &Lingvo de la fasado: + + + + The user interface language can be set here. This setting will take effect after restarting Arepacoin. + + + + + &Unit to show amounts in: + &Unuo por vidigi sumojn: + + + + Choose the default subdivision unit to show in the interface and when sending coins. + Elekti la defaŭltan manieron por montri bitmonajn sumojn en la interfaco, kaj kiam vi sendos bitmonon. + + + + Whether to show Arepacoin addresses in the transaction list or not. + + + + + &Display addresses in transaction list + &Montri adresojn en la listo de transakcioj + + + + Whether to show coin control features or not. + Ĉu montri detalan adres-regilon, aŭ ne. + + + + Display coin &control features (experts only!) + + + + + &OK + &Bone + + + + &Cancel + &Nuligi + + + + &Apply + + + + + default + defaŭlta + + + + + Warning + + + + + + This setting will take effect after restarting Arepacoin. + + + + + The supplied proxy address is invalid. + La prokurila adreso estas malvalida. + + + + OverviewPage + + + Form + Formularo + + + + + The displayed information may be out of date. Your wallet automatically synchronizes with the Arepacoin network after a connection is established, but this process has not completed yet. + + + + + Stake: + + + + + Unconfirmed: + + + + + Wallet + Monujo + + + + Spendable: + + + + + Your current spendable balance + via aktuala elspezebla saldo + + + + Immature: + Nematura: + + + + Mined balance that has not yet matured + Minita saldo, kiu ankoraŭ ne maturiĝis + + + + Total: + Totalo: + + + + Your current total balance + via aktuala totala saldo + + + + <b>Recent transactions</b> + <b>Lastaj transakcioj</b> + + + + Total of transactions that have yet to be confirmed, and do not yet count toward the current balance + + + + + Total of coins that was staked, and do not yet count toward the current balance + + + + + + out of sync + nesinkronigita + + + + QRCodeDialog + + + QR Code Dialog + + + + + Request Payment + + + + + Amount: + + + + + Label: + + + + + Message: + + + + + &Save As... + + + + + Error encoding URI into QR Code. + + + + + The entered amount is invalid, please check. + + + + + Resulting URI too long, try to reduce the text for label / message. + + + + + Save QR Code + + + + + PNG Images (*.png) + + + + + RPCConsole + + + Client name + Nomo de kliento + + + + + + + + + + + + + N/A + neaplikebla + + + + Client version + Versio de kliento + + + + &Information + &Informoj + + + + Using OpenSSL version + uzas OpenSSL-version + + + + Startup time + Horo de lanĉo + + + + Network + Reto + + + + Number of connections + Nombro de konektoj + + + + On testnet + + + + + Block chain + Blokĉeno + + + + Current number of blocks + Aktuala nombro de blokoj + + + + Estimated total blocks + Supozita totalo da blokoj + + + + Last block time + Horo de la lasta bloko + + + + &Open + &Malfermi + + + + Command-line options + + + + + Show the Arepacoin-Qt help message to get a list with possible Arepacoin command-line options. + + + + + &Show + + + + + &Console + &Konzolo + + + + Build date + Dato de kompilado + + + + Arepacoin - Debug window + + + + + Arepacoin Core + + + + + Debug log file + Sencimiga protokoldosiero + + + + Open the Arepacoin debug log file from the current data directory. This can take a few seconds for large log files. + + + + + Clear console + Malplenigi konzolon + + + + Welcome to the Arepacoin RPC console. + + + + + Use up and down arrows to navigate history, and <b>Ctrl-L</b> to clear screen. + Uzu la sagojn supran kaj malsupran por esplori la historion, kaj <b>stir-L</b> por malplenigi la ekranon. + + + + Type <b>help</b> for an overview of available commands. + Tajpu <b>help</b> por superrigardo de la disponeblaj komandoj. + + + + SendCoinsDialog + + + + + + + + + + Send Coins + Sendi Monon + + + + Coin Control Features + Monregaj Opcioj + + + + Inputs... + Enigoj... + + + + automatically selected + + + + + Insufficient funds! + Nesufiĉa mono! + + + + Quantity: + Kvanto: + + + + + 0 + + + + + Bytes: + Bajtoj: + + + + Amount: + Sumo: + + + + + + + 0.00 BC + + + + + Priority: + Prioritato: + + + + medium + + + + + Fee: + Krompago: + + + + Low Output: + Malalta Eligo: + + + + no + + + + + After Fee: + Post krompago: + + + + Change + + + + + custom change address + + + + + Send to multiple recipients at once + Sendi samtempe al pluraj ricevantoj + + + + Add &Recipient + Aldoni &Ricevonton + + + + Remove all transaction fields + + + + + Clear &All + &Forigi ĉion + + + + Balance: + Saldo: + + + + 123.456 BC + + + + + Confirm the send action + Konfirmi la sendon + + + + S&end + Ŝendi + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Copy quantity + Kopii kvanton + + + + Copy amount + Kopii sumon + + + + Copy fee + Kopii krompagon + + + + Copy after fee + Kopii post krompago + + + + Copy bytes + Kopii bajtojn + + + + Copy priority + Kopii prioritaton + + + + Copy low output + Kopii malaltan eligon + + + + Copy change + Kopii restmonon + + + + <b>%1</b> to %2 (%3) + + + + + Confirm send coins + Konfirmi sendon de bitmono + + + + Are you sure you want to send %1? + + + + + and + + + + + The recipient address is not valid, please recheck. + La adreso de la ricevonto ne validas. Bonvolu kontroli. + + + + The amount to pay must be larger than 0. + La pagenda sumo devas esti pli ol 0. + + + + The amount exceeds your balance. + La sumo estas pli granda ol via saldo. + + + + The total exceeds your balance when the %1 transaction fee is included. + La sumo kun la %1 krompago estas pli granda ol via saldo. + + + + Duplicate address found, can only send to each address once per send operation. + Iu adreso estas ripetita. Vi povas sendi al ĉiu adreso po unufoje en iu send-operacio. + + + + Error: Transaction creation failed. + + + + + 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. + + + + + WARNING: Invalid Arepacoin address + + + + + (no label) + (neniu etikedo) + + + + WARNING: unknown change address + + + + + SendCoinsEntry + + + Form + + + + + A&mount: + &Sumo: + + + + Pay &To: + &Ricevonto: + + + + + Enter a label for this address to add it to your address book + Tajpu etikedon por tiu ĉi adreso kaj aldonu ĝin al via adresaro + + + + &Label: + &Etikedo: + + + + The address to send the payment to (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Choose address from address book + + + + + Alt+A + Alt+A + + + + Paste address from clipboard + Alglui adreson el tondejo + + + + Alt+P + Alt+P + + + + Remove this recipient + + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + SignVerifyMessageDialog + + + Signatures - Sign / Verify a Message + Subskriboj - Subskribi / Kontroli mesaĝon + + + + + &Sign Message + &Subskribi Mesaĝon + + + + You can sign messages with your addresses to prove you own them. Be careful not to sign anything vague, as phishing attacks may try to trick you into signing your identity over to them. Only sign fully-detailed statements you agree to. + Vi povas subskribi mesaĝon per viaj adresoj, por pravigi ke vi estas la posedanto de tiuj adresoj. Atentu, ke vi ne subskriu ion neprecizan, ĉar trompisto povus ruzi kontraŭ vi kaj ŝteli vian identecon. Subskribu nur plene detaligitaj deklaroj pri kiuj vi konsentas. + + + + The address to sign the message with (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + + Choose an address from the address book + + + + + + Alt+A + Alt+A + + + + Paste address from clipboard + Alglui adreson de tondejo + + + + Alt+P + Alt+P + + + + Enter the message you want to sign here + Tajpu la mesaĝon, kiun vi volas sendi, cîi tie + + + + Copy the current signature to the system clipboard + Kopii la aktualan subskribon al la tondejo + + + + Sign the message to prove you own this Arepacoin address + + + + + Reset all sign message fields + Reagordigi ĉiujn prisubskribajn kampojn + + + + + Clear &All + &Forigi Ĉion + + + + + &Verify Message + &Kontroli Mesaĝon + + + + Enter the signing address, message (ensure you copy line breaks, spaces, tabs, etc. exactly) and signature below to verify the message. Be careful not to read more into the signature than what is in the signed message itself, to avoid being tricked by a man-in-the-middle attack. + Enmeti la subskriban adreson, la mesaĝon (kune kun ĉiu linisalto, spaceto, taboj, ktp. precize) kaj la subskribon ĉi sube por kontroli la mesaĝon. Atentu, ke vi ne komprenu per la subskribo pli ol la enhavo de la mesaĝo mem, por eviti homo-en-la-mezo-atakon. + + + + The address the message was signed with (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Verify the message to ensure it was signed with the specified Arepacoin address + + + + + Reset all verify message fields + Reagordigi ĉiujn prikontrolajn kampojn + + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Click "Sign Message" to generate signature + Klaku "Subskribi Mesaĝon" por krei subskribon + + + + Enter Arepacoin signature + + + + + + The entered address is invalid. + La adreso, kiun vi enmetis, estas nevalida. + + + + + + + Please check the address and try again. + Bonvolu kontroli la adreson kaj reprovi. + + + + + The entered address does not refer to a key. + La adreso, kiun vi enmetis, referencas neniun ŝlosilon. + + + + Wallet unlock was cancelled. + Malŝloso de monujo estas nuligita. + + + + Private key for the entered address is not available. + La privata ŝlosilo por la enigita adreso ne disponeblas. + + + + Message signing failed. + Subskribo de mesaĝo fiaskis. + + + + Message signed. + Mesaĝo estas subskribita. + + + + The signature could not be decoded. + Ne eblis malĉifri la subskribon. + + + + + Please check the signature and try again. + Bonvolu kontroli la subskribon kaj reprovu. + + + + The signature did not match the message digest. + La subskribo ne kongruis kun la mesaĝ-kompilaĵo. + + + + Message verification failed. + Kontrolo de mesaĝo malsukcesis. + + + + Message verified. + Mesaĝo sukcese kontrolita. + + + + TransactionDesc + + + Open until %1 + Malferma ĝis %1 + + + + Open for %n block(s) + + + + + conflicted + + + + + %1/offline + %1/senkonekte + + + + %1/unconfirmed + %1/nekonfirmite + + + + %1 confirmations + %1 konfirmoj + + + + Status + Stato + + + + , broadcast through %n node(s) + , elsendita(j) tra %n nodo, elsendita(j) tra %n nodoj + + + + Date + Dato + + + + Source + Fonto + + + + Generated + Kreita + + + + + From + De + + + + + + To + Al + + + + + own address + propra adreso + + + + label + etikedo + + + + + + + + Credit + Kredito + + + + matures in %n more block(s) + maturiĝos post %n blokomaturiĝos post %n blokoj + + + + not accepted + ne akceptita + + + + + + + Debit + Debeto + + + + Transaction fee + Krompago + + + + Net amount + Neta sumo + + + + Message + Mesaĝo + + + + Comment + Komento + + + + Transaction ID + Transakcia ID + + + + Generated coins must mature 6 blocks before they can be spent. When you generated this block, it was broadcast to the network to be added to the block chain. If it fails to get into the chain, its state will change to "not accepted" and it won't be spendable. This may occasionally happen if another node generates a block within a few seconds of yours. + + + + + Debug information + Sencimigaj informoj + + + + Transaction + Transakcio + + + + Inputs + Enigoj + + + + Amount + Sumo + + + + true + vera + + + + false + malvera + + + + , has not been successfully broadcast yet + , ankoraŭ ne elsendita sukcese + + + + unknown + nekonata + + + + TransactionDescDialog + + + Transaction details + Transakciaj detaloj + + + + This pane shows a detailed description of the transaction + Tiu ĉi panelo montras detalan priskribon de la transakcio + + + + TransactionTableModel + + + Date + Dato + + + + Type + Tipo + + + + Address + Adreso + + + + Amount + Sumo + + + + Open until %1 + Malferma ĝis %1 + + + + Confirmed (%1 confirmations) + Konfirmita (%1 konfirmoj) + + + + Open for %n more block(s) + Malferma dum ankoraŭ %n blokoMalferma dum ankoraŭ %n blokoj + + + + Offline + Senkonekte + + + + Unconfirmed + Nekonfirmita + + + + Confirming (%1 of %2 recommended confirmations) + + + + + Conflicted + + + + + Immature (%1 confirmations, will be available after %2) + + + + + This block was not received by any other nodes and will probably not be accepted! + Tiun ĉi blokon ne ricevis ajna alia nodo, kaj ĝi verŝajne ne akceptiĝos! + + + + Generated but not accepted + Kreita sed ne akceptita + + + + Received with + Ricevita kun + + + + Received from + Ricevita de + + + + Sent to + Sendita al + + + + Payment to yourself + Pago al vi mem + + + + Mined + Minita + + + + (n/a) + neaplikebla + + + + Transaction status. Hover over this field to show number of confirmations. + Transakcia stato. Ŝvebi super tiu ĉi kampo por montri la nombron de konfirmoj. + + + + Date and time that the transaction was received. + Dato kaj horo kiam la transakcio alvenis. + + + + Type of transaction. + Tipo de transakcio. + + + + Destination address of transaction. + Celadreso de la transakcio. + + + + Amount removed from or added to balance. + Sumo elprenita de aŭ aldonita al la saldo. + + + + TransactionView + + + + All + Ĉiuj + + + + Today + Hodiaŭ + + + + This week + Ĉi-semajne + + + + This month + Ĉi-monate + + + + Last month + Pasintmonate + + + + This year + Ĉi-jare + + + + Range... + Intervalo... + + + + Received with + Ricevita kun + + + + Sent to + Sendita al + + + + To yourself + Al vi mem + + + + Mined + Minita + + + + Other + Aliaj + + + + Enter address or label to search + Tajpu adreson aŭ etikedon por serĉi + + + + Min amount + Minimuma sumo + + + + Copy address + Kopii adreson + + + + Copy label + Kopii etikedon + + + + Copy amount + Kopii sumon + + + + Copy transaction ID + Kopii transakcian ID-on + + + + Edit label + Redakti etikedon + + + + Show transaction details + Montri detalojn de transakcio + + + + Export Transaction Data + + + + + Comma separated file (*.csv) + Perkome disigita dosiero (*.csv) + + + + Confirmed + Konfirmita + + + + Date + Dato + + + + Type + Tipo + + + + Label + Etikedo + + + + Address + Adreso + + + + Amount + Sumo + + + + ID + ID + + + + Error exporting + + + + + Could not write to file %1. + + + + + Range: + Intervalo: + + + + to + al + + + + WalletModel + + + Sending... + + + + + bitcoin-core + + + Arepacoin version + + + + + Usage: + Uzado: + + + + Send command to -server or arepacoind + + + + + List commands + Listigi komandojn + + + + Get help for a command + Vidigi helpon pri iu komando + + + + Options: + Agordoj: + + + + Specify configuration file (default: arepacoin.conf) + + + + + Specify pid file (default: arepacoind.pid) + + + + + Specify wallet file (within data directory) + Specifi monujan dosieron (ene de dosierujo por datumoj) + + + + Specify data directory + Specifi dosieron por datumoj + + + + Set database cache size in megabytes (default: 25) + Specifi grandon de datumbazo je megabajtoj (defaŭlte: 25) + + + + Set database disk log size in megabytes (default: 100) + + + + + Listen for connections on <port> (default: 9853 or testnet: 19853) + + + + + Maintain at most <n> connections to peers (default: 125) + Subteni maksimume <n> konektojn al samtavolanoj (defaŭlte: 125) + + + + Connect to a node to retrieve peer addresses, and disconnect + Konekti al nodo por ricevi adresojn de samtavolanoj, kaj malkonekti + + + + Specify your own public address + Specifi vian propran publikan adreson + + + + Bind to given address. Use [host]:port notation for IPv6 + + + + + Stake your coins to support network and gain reward (default: 1) + + + + + Threshold for disconnecting misbehaving peers (default: 100) + Sojlo por malkonekti misagantajn samtavolanojn (defaŭlte: 100) + + + + Number of seconds to keep misbehaving peers from reconnecting (default: 86400) + Nombro da sekundoj por rifuzi rekonekton de misagantaj samtavolanoj (defaŭlte: 86400) + + + + An error occurred while setting up the RPC port %u for listening on IPv4: %s + Eraro okazis dum estigo de RPC-pordo %u por aŭskulti per IPv4: %s + + + + Detach block and address databases. Increases shutdown time (default: 0) + + + + + 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. + + + + + Error: This transaction requires a transaction fee of at least %s because of its amount, complexity, or use of recently received funds + + + + + Listen for JSON-RPC connections on <port> (default: 9852 or testnet: 19852) + + + + + Accept command line and JSON-RPC commands + Akcepti komandojn JSON-RPC kaj el komandlinio + + + + Error: Transaction creation failed + + + + + Error: Wallet locked, unable to create transaction + + + + + Importing blockchain data file. + + + + + Importing bootstrap blockchain data file. + + + + + Run in the background as a daemon and accept commands + Ruli fone kiel demono kaj akcepti komandojn + + + + Use the test network + Uzi la test-reton + + + + Accept connections from outside (default: 1 if no -proxy or -connect) + Akcepti konektojn el ekstere (defaŭlte: 1 se ne estas -proxy nek -connect) + + + + An error occurred while setting up the RPC port %u for listening on IPv6, falling back to IPv4: %s + Eraro okazis dum estigo de RPC-pordo %u por aŭskulti per IPv6; retrodefaŭltas al IPv4: %s + + + + Error initializing database environment %s! To recover, BACKUP THAT DIRECTORY, then remove everything from it except for wallet.dat. + + + + + Set maximum size of high-priority/low-fee transactions in bytes (default: 27000) + + + + + Warning: -paytxfee is set very high! This is the transaction fee you will pay if you send a transaction. + Averto: -paytxfee estas agordita per tre alta valoro! Tio estas la krompago, kion vi pagos se vi sendas la transakcion. + + + + Warning: Please check that your computer's date and time are correct! If your clock is wrong Arepacoin will not work properly. + + + + + Warning: error reading wallet.dat! All keys read correctly, but transaction data or address book entries might be missing or incorrect. + Averto: okazis eraro dum lego de wallet.dat! Ĉiuj ŝlosiloj sukcese legiĝis, sed la transakciaj datumoj aŭ la adresaro eble mankas aŭ malĝustas. + + + + Warning: wallet.dat corrupt, data salvaged! Original wallet.dat saved as wallet.{timestamp}.bak in %s; if your balance or transactions are incorrect you should restore from a backup. + Averto: via wallet.dat estas difektita, sed la datumoj sukcese saviĝis! La originala wallet.dat estas nun konservita kiel wallet.{timestamp}.bak en %s; se via saldo aŭ transakcioj estas malĝustaj vi devus restaŭri per alia sekurkopio. + + + + Attempt to recover private keys from a corrupt wallet.dat + Provo ripari privatajn ŝlosilojn el difektita wallet.dat + + + + Block creation options: + Blok-kreaj agordaĵoj: + + + + Connect only to the specified node(s) + Konekti nur al specifita(j) nodo(j) + + + + Discover own IP address (default: 1 when listening and no -externalip) + Malkovri la propran IP-adreson (defaŭlte: 1 dum aŭskultado sen -externalip) + + + + Failed to listen on any port. Use -listen=0 if you want this. + Ne sukcesis aŭskulti ajnan pordon. Uzu -listen=0 se tion vi volas. + + + + Find peers using DNS lookup (default: 1) + + + + + Sync checkpoints policy (default: strict) + + + + + Invalid -tor address: '%s' + + + + + Invalid amount for -reservebalance=<amount> + + + + + Maximum per-connection receive buffer, <n>*1000 bytes (default: 5000) + Maksimuma po riceva bufro por konektoj, <n>*1000 bajtoj (defaŭlte: 5000) + + + + Maximum per-connection send buffer, <n>*1000 bytes (default: 1000) + Maksimuma po senda bufro por konektoj, <n>*1000 bajtoj (defaŭlte: 1000) + + + + Only connect to nodes in network <net> (IPv4, IPv6 or Tor) + Konekti nur la nodoj en la reto <net> (IPv4, IPv6 aŭ Tor) + + + + Output extra debugging information. Implies all other -debug* options + + + + + Output extra network debugging information + + + + + Prepend debug output with timestamp + + + + + SSL options: (see the Bitcoin Wiki for SSL setup instructions) + SSL-agordaĵoj: (vidu la vikio de Bitmono por instrukcioj pri agordado de SSL) + + + + Select the version of socks proxy to use (4-5, default: 5) + + + + + Send trace/debug info to console instead of debug.log file + Sendi spurajn/sencimigajn informojn al la konzolo anstataŭ al dosiero debug.log + + + + Send trace/debug info to debugger + + + + + Set maximum block size in bytes (default: 250000) + + + + + Set minimum block size in bytes (default: 0) + Agordi minimuman grandon de blokoj je bajtoj (defaŭlte: 0) + + + + Shrink debug.log file on client startup (default: 1 when no -debug) + Malpligrandigi la sencimigan protokol-dosieron kiam kliento lanĉiĝas (defaŭlte: 1 kiam mankas -debug) + + + + Specify connection timeout in milliseconds (default: 5000) + Specifi konektan tempolimon je milisekundoj (defaŭlte: 5000) + + + + Unable to sign checkpoint, wrong checkpointkey? + + + + + + Use UPnP to map the listening port (default: 0) + Uzi UPnP por mapi la aŭskultan pordon (defaŭlte: 0) + + + + Use UPnP to map the listening port (default: 1 when listening) + Uzi UPnP por mapi la aŭskultan pordon (defaŭlte: 1 dum aŭskultado) + + + + Use proxy to reach tor hidden services (default: same as -proxy) + + + + + Username for JSON-RPC connections + Salutnomo por konektoj JSON-RPC + + + + Verifying database integrity... + + + + + WARNING: syncronized checkpoint violation detected, but skipped! + + + + + Warning: Disk space is low! + + + + + Warning: This version is obsolete, upgrade required! + Averto: tiu ĉi versio estas eksdata. Vi bezonas ĝisdatigon! + + + + wallet.dat corrupt, salvage failed + wallet.dat estas difektita, riparo malsukcesis + + + + Password for JSON-RPC connections + Pasvorto por konektoj JSON-RPC + + + + %s, you must set a rpcpassword in the configuration file: + %s +It is recommended you use the following random password: +rpcuser=arepacoinrpc +rpcpassword=%s +(you do not need to remember this password) +The username and password MUST NOT be the same. +If the file does not exist, create it with owner-readable-only file permissions. +It is also recommended to set alertnotify so you are notified of problems; +for example: alertnotify=echo %%s | mail -s "Arepacoin Alert" admin@foo.com + + + + + + Find peers using internet relay chat (default: 0) + + + + + Sync time with other nodes. Disable if time on your system is precise e.g. syncing with NTP (default: 1) + + + + + When creating transactions, ignore inputs with value less than this (default: 0.01) + + + + + Allow JSON-RPC connections from specified IP address + Permesi konektojn JSON-RPC de specifa IP-adreso + + + + Send commands to node running on <ip> (default: 127.0.0.1) + Sendi komandon al nodo ĉe <ip> (defaŭlte: 127.0.0.1) + + + + Execute command when the best block changes (%s in cmd is replaced by block hash) + Plenumi komandon kiam plej bona bloko ŝanĝiĝas (%s en cmd anstataŭiĝas per bloka haketaĵo) + + + + Execute command when a wallet transaction changes (%s in cmd is replaced by TxID) + Plenumi komandon kiam monuja transakcio ŝanĝiĝas (%s en cmd anstataŭiĝas per TxID) + + + + Require a confirmations for change (default: 0) + + + + + Enforce transaction scripts to use canonical PUSH operators (default: 1) + + + + + Execute command when a relevant alert is received (%s in cmd is replaced by message) + + + + + Upgrade wallet to latest format + Ĝisdatigi monujon al plej lasta formato + + + + Set key pool size to <n> (default: 100) + Agordi la grandon de la ŝlosilo-vico al <n> (defaŭlte: 100) + + + + Rescan the block chain for missing wallet transactions + Reskani la blokĉenon por mankantaj monujaj transakcioj + + + + How many blocks to check at startup (default: 2500, 0 = all) + + + + + How thorough the block verification is (0-6, default: 1) + + + + + Imports blocks from external blk000?.dat file + + + + + Use OpenSSL (https) for JSON-RPC connections + Uzi OpenSSL (https) por konektoj JSON-RPC + + + + Server certificate file (default: server.cert) + Dosiero de servila atestilo (defaŭlte: server.cert) + + + + Server private key (default: server.pem) + Dosiero de servila privata ŝlosilo (defaŭlte: server.pem) + + + + Acceptable ciphers (default: TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH) + + + + + Error: Wallet unlocked for staking only, unable to create transaction. + + + + + WARNING: Invalid checkpoint found! Displayed transactions may not be correct! You may need to upgrade, or notify developers. + + + + + This help message + Tiu ĉi helpmesaĝo + + + + Wallet %s resides outside data directory %s. + + + + + Cannot obtain a lock on data directory %s. Arepacoin is probably already running. + + + + + Arepacoin + + + + + Unable to bind to %s on this computer (bind returned error %d, %s) + Ne eblis bindi al %s en tiu ĉi komputilo (bind resendis eraron %d, %s) + + + + Connect through socks proxy + + + + + Allow DNS lookups for -addnode, -seednode and -connect + Permesi DNS-elserĉojn por -addnote, -seednote kaj -connect + + + + Loading addresses... + Ŝarĝante adresojn... + + + + Error loading blkindex.dat + + + + + Error loading wallet.dat: Wallet corrupted + Eraro dum ŝargado de wallet.dat: monujo difektita + + + + Error loading wallet.dat: Wallet requires newer version of Arepacoin + + + + + Wallet needed to be rewritten: restart Arepacoin to complete + + + + + Error loading wallet.dat + Eraro dum ŝargado de wallet.dat + + + + Invalid -proxy address: '%s' + Nevalid adreso -proxy: '%s' + + + + Unknown network specified in -onlynet: '%s' + Nekonata reto specifita en -onlynet: '%s' + + + + Unknown -socks proxy version requested: %i + Nekonata versio de -socks petita: %i + + + + Cannot resolve -bind address: '%s' + Ne eblas trovi la adreson -bind: '%s' + + + + Cannot resolve -externalip address: '%s' + Ne eblas trovi la adreson -externalip: '%s' + + + + Invalid amount for -paytxfee=<amount>: '%s' + Nevalida sumo por -paytxfee=<amount>: '%s' + + + + Error: could not start node + + + + + Sending... + + + + + Invalid amount + Nevalida sumo + + + + Insufficient funds + Nesufiĉa mono + + + + Loading block index... + Ŝarĝante blok-indekson... + + + + Add a node to connect to and attempt to keep the connection open + Aldoni nodon por alkonekti kaj provi daŭrigi la malferman konekton + + + + Unable to bind to %s on this computer. Arepacoin is probably already running. + + + + + Fee per KB to add to transactions you send + + + + + Invalid amount for -mininput=<amount>: '%s' + + + + + Loading wallet... + Ŝargado de monujo... + + + + Cannot downgrade wallet + Ne eblas malpromocii monujon + + + + Cannot initialize keypool + + + + + Cannot write default address + Ne eblas skribi defaŭltan adreson + + + + Rescanning... + Reskanado... + + + + Done loading + Ŝargado finiĝis + + + + To use the %s option + Por uzi la agordon %s + + + + Error + Eraro + + + + You must set rpcpassword=<password> in the configuration file: +%s +If the file does not exist, create it with owner-readable-only file permissions. + Vi devas agordi rpcpassword=<password> en la konfigura dosiero: +%s +Se la dosiero ne ekzistas, kreu ĝin kun permeso "nur posedanto rajtas legi". + + + \ No newline at end of file diff --git a/src/qt/locale/bitcoin_es.ts b/src/qt/locale/bitcoin_es.ts new file mode 100755 index 0000000..21c20fc --- /dev/null +++ b/src/qt/locale/bitcoin_es.ts @@ -0,0 +1,3350 @@ + + + AboutDialog + + + About Arepacoin + Acerca de Arepacoin + + + + <b>Arepacoin</b> version + <b>Arepacoin</b> versión + + + + Copyright © 2009-2014 The Bitcoin developers +Copyright © 2012-2014 The NovaCoin developers +Copyright © 2014 The Arepacoin developers + Copyright © 2009-2014 The Bitcoin developers +Copyright © 2012-2014 The NovaCoin developers +Copyright © 2014 The Arepacoin developers + + + + +This is experimental software. + +Distributed under the MIT/X11 software license, see the accompanying file COPYING or http://www.opensource.org/licenses/mit-license.php. + +This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit (http://www.openssl.org/) and cryptographic software written by Eric Young (eay@cryptsoft.com) and UPnP software written by Thomas Bernard. + +Este es un software experimental. + +Distribuido bajo la licencia MIT/X11, vea el archivo adjunto +COPYING o http://www.opensource.org/licenses/mit-license.php. + +Este producto incluye software desarrollado por OpenSSL Project para su uso en +el OpenSSL Toolkit (http://www.openssl.org/) y software criptográfico escrito por +Eric Young (eay@cryptsoft.com) y el software UPnP escrito por Thomas Bernard. + + + + AddressBookPage + + + Address Book + Libreta de Direcciones + + + + Double-click to edit address or label + Haga doble clic para editar una etiqueta o dirección + + + + Create a new address + Crear una nueva dirección + + + + Copy the currently selected address to the system clipboard + Copiar la dirección seleccionada al portapapeles del sistema + + + + &New Address + &Nueva Dirección + + + + These are your Arepacoin addresses for receiving payments. You may want to give a different one to each sender so you can keep track of who is paying you. + Estas son las direcciones de Arepacoin para recibir pagos. Es posible que desee dar una diferente a cada remitente para que pueda realizar un seguimiento de quien te está pagando. + + + + &Copy Address + &Copiar dirección + + + + Show &QR Code + Enseñar &QR Code + + + + Sign a message to prove you own a Arepacoin address + Firmar un mensaje para demostrar que es dueño de su dirección de Arepacoin + + + + Sign &Message + Firmar &Mensaje + + + + Delete the currently selected address from the list + Borrar de la lista la dirección seleccionada + + + + Verify a message to ensure it was signed with a specified Arepacoin address + Verifique el mensaje para asegurarse que fue firmado por una dirección específica de Arepacoin + + + + &Verify Message + &Verifique Mensaje + + + + &Delete + &Eliminar + + + + Copy &Label + Copiar &etiqueta + + + + &Edit + &Editar + + + + Export Address Book Data + Exportar Data de Libro de Direcciones + + + + Comma separated file (*.csv) + Archivos de columnas separadas por coma (*.csv) + + + + Error exporting + Error exportando + + + + Could not write to file %1. + No se pudo escribir en el archivo %1 + + + + AddressTableModel + + + Label + Etiqueta + + + + Address + Dirección + + + + (no label) + (sin etiqueta) + + + + AskPassphraseDialog + + + Passphrase Dialog + Diálogo de contraseña + + + + Enter passphrase + Introducir contraseña + + + + New passphrase + Nueva contraseña + + + + Repeat new passphrase + Repita la nueva contraseña + + + + Serves to disable the trivial sendmoney when OS account compromised. Provides no real security. + Sirve para desactivar SendMoney cuando la cuenta del Sistema Operativo está comprometida. No ofrece seguridad real. + + + + For staking only + Para "Staking" solamente + + + + Enter the new passphrase to the wallet.<br/>Please use a passphrase of <b>10 or more random characters</b>, or <b>eight or more words</b>. + Introduzca la nueva contraseña del monedero.<br/>Por favor elija una con <b>10 o más caracteres aleatorios</b>, u <b>ocho o más palabras</b>. + + + + Encrypt wallet + Cifrar el monedero + + + + This operation needs your wallet passphrase to unlock the wallet. + Esta operación requiere su contraseña para desbloquear el monedero. + + + + Unlock wallet + Desbloquear monedero + + + + This operation needs your wallet passphrase to decrypt the wallet. + Esta operación requiere su contraseña para descifrar el monedero. + + + + Decrypt wallet + Descifrar el monedero + + + + Change passphrase + Cambiar contraseña + + + + Enter the old and new passphrase to the wallet. + Introduzca la contraseña anterior del monedero y la nueva. + + + + Confirm wallet encryption + Confirmar cifrado del monedero + + + + Warning: If you encrypt your wallet and lose your passphrase, you will <b>LOSE ALL OF YOUR COINS</b>! + Advertencia: Si encripta su cartera y pierde su frase de contraseña, puede <b>PERDER TODAS SUS MONEDAS</ b>! + + + + Are you sure you wish to encrypt your wallet? + ¿Seguro que desea cifrar su monedero? + + + + IMPORTANT: Any previous backups you have made of your wallet file should be replaced with the newly generated, encrypted wallet file. For security reasons, previous backups of the unencrypted wallet file will become useless as soon as you start using the new, encrypted wallet. + IMPORTANTE: Cualquier copia de seguridad que haya realizado previamente de su archivo de monedero debe reemplazarse con el nuevo archivo de monedero cifrado. Por razones de seguridad, las copias de seguridad previas del archivo de monedero no cifradas serán inservibles en cuanto comience a usar el nuevo monedero cifrado. + + + + + Warning: The Caps Lock key is on! + Aviso: ¡La tecla de bloqueo de mayúsculas está activada! + + + + + Wallet encrypted + Monedero cifrado + + + + Arepacoin will close now to finish the encryption process. Remember that encrypting your wallet cannot fully protect your coins from being stolen by malware infecting your computer. + Arepacoin cerrará para terminar el proceso de encriptación. Recuerde que la encriptación de su monedero no puede proteger completamente que sus monedas sean robadas por malware infectando su computadora. + + + + + + + Wallet encryption failed + Ha fallado el cifrado del monedero + + + + Wallet encryption failed due to an internal error. Your wallet was not encrypted. + Ha fallado el cifrado del monedero debido a un error interno. El monedero no ha sido cifrado. + + + + + The supplied passphrases do not match. + Las contraseñas no coinciden. + + + + Wallet unlock failed + Ha fallado el desbloqueo del monedero + + + + + + The passphrase entered for the wallet decryption was incorrect. + La contraseña introducida para descifrar el monedero es incorrecta. + + + + Wallet decryption failed + Ha fallado el descifrado del monedero + + + + Wallet passphrase was successfully changed. + Se ha cambiado correctamente la contraseña del monedero. + + + + BitcoinGUI + + + Sign &message... + Firmar &mensaje... + + + + Synchronizing with network... + Sincronizando con la red… + + + + &Overview + &Vista general + + + + Show general overview of wallet + Mostrar vista general del monedero + + + + &Transactions + &Transacciones + + + + Browse transaction history + Examinar el historial de transacciones + + + + &Address Book + &Libreta de Direcciones + + + + Edit the list of stored addresses and labels + Editar la lista de direcciones y etiquetas almacenadas + + + + &Receive coins + &Recibir monedas + + + + Show the list of addresses for receiving payments + Mostrar la lista de direcciones para recibir pagos + + + + &Send coins + &Enviar monedas + + + + E&xit + &Salir + + + + Quit application + Salir de la aplicación + + + + Show information about Arepacoin + Mostrar información sobre Arepacoin + + + + About &Qt + Acerca de &Qt + + + + Show information about Qt + Mostrar información acerca de Qt + + + + &Options... + &Opciones... + + + + &Encrypt Wallet... + &Cifrar monedero… + + + + &Backup Wallet... + &Guardar copia de seguridad del monedero... + + + + &Change Passphrase... + &Cambiar la contraseña… + + + + ~%n block(s) remaining + ~%n bloque restante~%n bloques restantes + + + + Processed %1 of %2 (estimated) blocks of transaction history. + Procesado %1 de %2 (estimado) bloques de historial de transacciones. + + + + Processed %1 blocks of transaction history. + Procesado %1 bloques de historial de transacciones. + + + + &Export... + &Exportar... + + + + Send coins to a Arepacoin address + Enviar monedas a una dirección de Arepacoin + + + + Modify configuration options for Arepacoin + Modificar las opciones de configuración para Arepacoin + + + + Export the data in the current tab to a file + Exportar los datos en la ficha actual a un archivo + + + + Encrypt or decrypt wallet + Cifrar o descifrar el monedero + + + + Backup wallet to another location + Copia de seguridad del monedero en otra ubicación + + + + Change the passphrase used for wallet encryption + Cambiar la contraseña utilizada para el cifrado del monedero + + + + &Debug window + Ventana de &depuración + + + + Open debugging and diagnostic console + Abrir la consola de depuración y diagnóstico + + + + &Verify message... + &Verificar mensaje... + + + + Arepacoin + Arepacoin + + + + Wallet + Monedero + + + + &About Arepacoin + Acerca de Arepacoin + + + + &Show / Hide + &Mostrar / Ocultar + + + + Unlock wallet + Desbloquear el monedero + + + + &Lock Wallet + &Bloquear monedero + + + + Lock wallet + Bloquear monedero + + + + &File + &Archivo + + + + &Settings + &Configuración + + + + &Help + A&yuda + + + + Tabs toolbar + Barra de pestañas + + + + Actions toolbar + Barra de herramientas de acciones + + + + + [testnet] + [testnet] + + + + + Arepacoin client + Cliente Arepacoin + + + + %n active connection(s) to Arepacoin network + %n conexión activa a la red Arepacoin%n conexiones activas a la red Arepacoin + + + + Staking.<br>Your weight is %1<br>Network weight is %2<br>Expected time to earn reward is %3 + Staking.<br>Su contribución es %1<br>Contribución de la red es %2<br>Tiempo esperado para ganar la recompensa es %3 + + + + Not staking because wallet is locked + No esta "Staking" porque monedera está bloqueada + + + + Not staking because wallet is offline + No esta "Staking" porque monedera está desconectada + + + + Not staking because wallet is syncing + No esta "Staking" porque monedera está sincronizando + + + + Not staking because you don't have mature coins + No esta "Staking" ya que no tiene monedas maduras + + + + %n second(s) ago + hace %n segundohace %n segundos + + + + &Unlock Wallet... + &Desbloquear Monedero... + + + + %n minute(s) ago + hace %n minutohace %n minutos + + + + %n hour(s) ago + hace %n horahace %n horas + + + + %n day(s) ago + hace %n diahace %n dias + + + + Up to date + Actualizado + + + + Catching up... + Actualizando... + + + + Last received block was generated %1. + Último bloque recibido se generó en %1. + + + + This transaction is over the size limit. You can still send it for a fee of %1, which goes to the nodes that process your transaction and helps to support the network. Do you want to pay the fee? + Esta transacción se encuentra sobre el límite de tamaño. Usted todavía puede enviarlo a un costo de %1, lo que va a los nodos que procesan sus transacciones y ayuda a apoyar la red. ¿Quieres pagar la cuota? + + + + Confirm transaction fee + Confirme tarifa de transacción + + + + Sent transaction + Transacción enviada + + + + Incoming transaction + Transacción entrante + + + + Date: %1 +Amount: %2 +Type: %3 +Address: %4 + + Fecha: %1 +Cantidad: %2 +Tipo: %3 +Dirección: %4 + + + + + + URI handling + Manejar URI + + + + + URI can not be parsed! This can be caused by an invalid Arepacoin address or malformed URI parameters. + URI no se puede analizar! Esto puede ser causado por una dirección de Arepacoin no válida o parámetros de URI malformados. + + + + Wallet is <b>encrypted</b> and currently <b>unlocked</b> + El monedero está <b>cifrado</b> y actualmente <b>desbloqueado</b> + + + + Wallet is <b>encrypted</b> and currently <b>locked</b> + El monedero está <b>cifrado</b> y actualmente <b>bloqueado</b> + + + + Backup Wallet + Copia de Seguridad de Monedero + + + + Wallet Data (*.dat) + Data de Monedero (*.dat) + + + + Backup Failed + Copia de Seguridad a fracasado + + + + There was an error trying to save the wallet data to the new location. + Hubo un error al tratar de salvar los datos de su monedero a la nueva ubicación. + + + + %n second(s) + %n segundo%n segundos + + + + %n minute(s) + %n minuto%n minutos + + + + %n hour(s) + %n hora%n horas + + + + %n day(s) + %n día%n días + + + + %n week(s) + %n semana%n semanas + + + + %n year(s) + %n año%n años + + + + %1 behind + %1 detrás + + + + %1 and %2 + %1 y %2 + + + + Not staking + No estás "Staking" + + + + A fatal error occurred. Arepacoin can no longer continue safely and will quit. + Se ha producido un error fatal. Arepacoin ya no puede continuar de forma segura y cerrará. + + + + ClientModel + + + Network Alert + Alerta de red + + + + CoinControlDialog + + + Coin Control + Control de Moneda + + + + Quantity: + Cantidad: + + + + Bytes: + Bytes: + + + + Amount: + Cantidad: + + + + Priority: + Prioridad: + + + + Fee: + Tasa: + + + + Low Output: + Envío pequeño: + + + + no + no + + + + After Fee: + Después de tasas: + + + + Change: + Cambio: + + + + (un)select all + (des)marcar todos + + + + Tree mode + Modo árbol + + + + List mode + Modo lista + + + + Amount + Cuantía + + + + Label + Etiqueta + + + + Address + Dirección + + + + Date + Fecha + + + + Confirmations + Confirmaciones + + + + Confirmed + Confirmado + + + + Priority + Prioridad + + + + Copy address + Copiar dirección + + + + Copy label + Copiar etiqueta + + + + + Copy amount + Copiar cuantía + + + + Copy transaction ID + Copiar identificador de transacción + + + + Copy quantity + Copiar cantidad + + + + Copy fee + Copiar donación + + + + Copy after fee + Copiar después de aplicar donación + + + + Copy bytes + Copiar bytes + + + + Copy priority + Copiar prioridad + + + + Copy low output + Copiar envío pequeño + + + + Copy change + Copiar cambio + + + + highest + lo más alto + + + + high + alto + + + + medium-high + medio-alto + + + + medium + medio + + + + low-medium + bajo-medio + + + + low + bajo + + + + lowest + lo más bajo + + + + DUST + DUST + + + + yes + si + + + + This label turns red, if the transaction size is bigger than 10000 bytes. + + This means a fee of at least %1 per kb is required. + + Can vary +/- 1 Byte per input. + Esta etiqueta se convierte en rojo, si el tamaño de la transacción es mayor que 10000 bytes. + +Esto significa que se requiere una cuota de al menos el %1 por kb. + +Puede variar + / - 1 Byte por entrada. + + + + Transactions with higher priority get more likely into a block. + +This label turns red, if the priority is smaller than "medium". + + This means a fee of at least %1 per kb is required. + Las transacciones con mayor prioridad son más probables en entrar hacia un bloque. + +Esta etiqueta se convierte en rojo, si la prioridad es menor que "medium". + +Esto significa que se requiere una cuota de al menos el %1 por kb. + + + + This label turns red, if any recipient receives an amount smaller than %1. + + This means a fee of at least %2 is required. + + Amounts below 0.546 times the minimum relay fee are shown as DUST. + Esta etiqueta se convierte en rojo, si cualquier recipiente recibe una cantidad menor que %1. + +Esto significa que se requiere una cuota de al menos %2. + +Las cantidades inferiores a 0.546 veces la cuota mínima del relé se muestran en forma de DUST. + + + + This label turns red, if the change is smaller than %1. + + This means a fee of at least %2 is required. + Esta etiqueta se convierte en rojo, si el cambio es menor que %1. + +Esto significa que se requiere una cuota de al menos %2. + + + + + (no label) + (sin etiqueta) + + + + change from %1 (%2) + Enviar desde %1 (%2) + + + + (change) + (cambio) + + + + EditAddressDialog + + + Edit Address + Editar Dirección + + + + &Label + &Etiqueta + + + + The label associated with this address book entry + La etiqueta asociada con esta entrada de la libreta de direcciones + + + + &Address + &Dirección + + + + The address associated with this address book entry. This can only be modified for sending addresses. + La dirección asociada con esta entrada de la libreta de direcciones. Esto sólo puede ser modificada para direcciones de envío. + + + + New receiving address + Nueva dirección de recepción + + + + New sending address + Nueva dirección de envío + + + + Edit receiving address + Editar dirección de recepción + + + + Edit sending address + Editar dirección de envío + + + + The entered address "%1" is already in the address book. + La dirección introducida "%1" ya está presente en la libreta de direcciones. + + + + The entered address "%1" is not a valid Arepacoin address. + La dirección introducida "%1" no es una dirección válida de Arepacoin. + + + + Could not unlock wallet. + No se pudo desbloquear el monedero. + + + + New key generation failed. + Ha fallado la generación de la nueva clave. + + + + GUIUtil::HelpMessageBox + + + + Arepacoin-Qt + Arepacoin-Qt + + + + version + Versión + + + + Usage: + Uso: + + + + command-line options + opciones de líneas de comandos + + + + UI options + opciones del interfaz de usuario + + + + Set language, for example "de_DE" (default: system locale) + Defina el idioma, por ejemplo "de_DE" (predeterminado: región del sistema) + + + + Start minimized + Iniciar minimizado + + + + Show splash screen on startup (default: 1) + Mostrar pantalla de bienvenida al iniciar (predeterminado: 1) + + + + OptionsDialog + + + Options + Opciones + + + + &Main + &Principal + + + + Optional transaction fee per kB that helps make sure your transactions are processed quickly. Most transactions are 1 kB. Fee 0.01 recommended. + Tarifa de transacción opcional por kB que ayuda a asegurarse de que sus transacciones se procesan rápidamente. La mayoría de las transacciones son 1 kB. Cuota de 0.01 recomendada. + + + + Pay transaction &fee + Comisión de &transacciones + + + + Reserved amount does not participate in staking and is therefore spendable at any time. + Cantidad reservada no participa en el "Staking" y por lo tanto se puede gastar en cualquier momento. + + + + Reserve + Reserva + + + + Automatically start Arepacoin after logging in to the system. + Iniciar Arepacoin automáticamente después de entrar en el sistema. + + + + &Start Arepacoin on system login + &Iniciar Arepacoin al inicio del sistema + + + + Detach block and address databases at shutdown. This means they can be moved to another data directory, but it slows down shutdown. The wallet is always detached. + Separe el bloque y las bases de datos de direcciones al apagar el equipo. Esto significa que se puede mover a otro directorio de datos, pero desacelera el apagado. El monedero siempre está separado. + + + + &Detach databases at shutdown + &Separe la bases de datos al apagar el equipo + + + + &Network + &Red + + + + Automatically open the Arepacoin client port on the router. This only works when your router supports UPnP and it is enabled. + Abrir automáticamente el puerto de cliente Arepacoin en el router. Esto sólo funciona cuando el router es compatible con UPnP y está habilitado. + + + + Map port using &UPnP + Mapear el puerto usando &UPnP + + + + Connect to the Arepacoin network through a SOCKS proxy (e.g. when connecting through Tor). + Conéctese a la red de Arepacoin a través de un SOCKS proxy (e.g. cuando se conecta a través de Tor) + + + + &Connect through SOCKS proxy: + &Conéctese a través de un SOCKS proxy + + + + Proxy &IP: + Dirección &IP del proxy: + + + + IP address of the proxy (e.g. 127.0.0.1) + Dirección IP del proxy (e.g. 127.0.0.1) + + + + &Port: + &Puerto: + + + + Port of the proxy (e.g. 9050) + Puerto del servidor proxy (ej. 9050) + + + + SOCKS &Version: + &Versión SOCKS: + + + + SOCKS version of the proxy (e.g. 5) + Versión SOCKS del proxy (ej. 5) + + + + &Window + &Ventana + + + + Show only a tray icon after minimizing the window. + Minimizar la ventana a la bandeja de iconos del sistema. + + + + &Minimize to the tray instead of the taskbar + &Minimizar a la bandeja en vez de a la barra de tareas + + + + Minimize instead of exit the application when the window is closed. When this option is enabled, the application will be closed only after selecting Quit in the menu. + Minimizar en lugar de salir de la aplicación al cerrar la ventana. Cuando esta opción está activa, la aplicación solo se puede cerrar seleccionando Salir desde el menú. + + + + M&inimize on close + M&inimizar al cerrar + + + + &Display + &Interfaz + + + + User Interface &language: + I&dioma de la interfaz de usuario + + + + The user interface language can be set here. This setting will take effect after restarting Arepacoin. + El idioma del interfaz de usuario se puede configurar aquí. Esta configuración se aplicará después de reiniciar Arepacoin. + + + + &Unit to show amounts in: + Mostrar las cantidades en la &unidad: + + + + Choose the default subdivision unit to show in the interface and when sending coins. + Elegir la subdivisión predeterminada para mostrar cantidades en la interfaz y cuando se envían bitcoins. + + + + Whether to show Arepacoin addresses in the transaction list or not. + Tanto para mostrar direcciones de Arepacoin en la lista de transacciones o no. + + + + &Display addresses in transaction list + &Mostrar las direcciones en la lista de transacciones + + + + Whether to show coin control features or not. + Mostrar o no funcionalidad de Coin Control + + + + Display coin &control features (experts only!) + Mostrar moneda y Coin Control (expertos solamente!) + + + + &OK + &Aceptar + + + + &Cancel + &Cancelar + + + + &Apply + &Aplicar + + + + default + predeterminado + + + + + Warning + Advertencia + + + + + This setting will take effect after restarting Arepacoin. + Esta configuración se aplicará después de reiniciar Arepacoin. + + + + The supplied proxy address is invalid. + La dirección proxy indicada es inválida. + + + + OverviewPage + + + Form + Desde + + + + + The displayed information may be out of date. Your wallet automatically synchronizes with the Arepacoin network after a connection is established, but this process has not completed yet. + La información mostrada puede estar fuera de fecha. Su monedera se sincroniza automáticamente con la red Arepacoin después de que se establece una conexión, pero este proceso no se ha completado todavía. + + + + Stake: + Stake: + + + + Unconfirmed: + Sin confirmar: + + + + Wallet + Monedero + + + + Spendable: + Disponible: + + + + Your current spendable balance + Su actual balance disponible + + + + Immature: + No disponible: + + + + Mined balance that has not yet matured + Saldo recién minado que aún no está disponible. + + + + Total: + Total: + + + + Your current total balance + Su balance actual total + + + + <b>Recent transactions</b> + <b>Movimientos recientes</b> + + + + Total of transactions that have yet to be confirmed, and do not yet count toward the current balance + Total de transacciones que aún no se han confirmado, y aún no cuentan para el balance actual + + + + Total of coins that was staked, and do not yet count toward the current balance + Total de las monedas que fueron "Staked", y aún no cuentan para el balance actual + + + + + out of sync + desincronizado + + + + QRCodeDialog + + + QR Code Dialog + Código Diálogo QR + + + + Request Payment + Solicitar Pago + + + + Amount: + Cantidad: + + + + Label: + Etiqueta: + + + + Message: + Mensaje: + + + + &Save As... + &Guardar como.... + + + + Error encoding URI into QR Code. + Error codificando URI en código QR​​. + + + + The entered amount is invalid, please check. + La cantidad introducida es inválida, compruebe por favor. + + + + Resulting URI too long, try to reduce the text for label / message. + La URI es demasiado larga, pruebe a acortar el texto para la etiqueta / mensaje + + + + Save QR Code + Guardar código QR + + + + PNG Images (*.png) + Imagenes PNG (*.png) + + + + RPCConsole + + + Client name + Nombre del cliente + + + + + + + + + + + + + N/A + N/D + + + + Client version + Versión del cliente + + + + &Information + &Información + + + + Using OpenSSL version + Utilizando la versión OpenSSL + + + + Startup time + Hora de inicio + + + + Network + Red + + + + Number of connections + Número de conexiones + + + + On testnet + En testnet + + + + Block chain + Cadena de bloques + + + + Current number of blocks + Número actual de bloques + + + + Estimated total blocks + Bloques totales estimados + + + + Last block time + Hora del último bloque + + + + &Open + &Abrir + + + + Command-line options + Opciones de línea de comandos + + + + Show the Arepacoin-Qt help message to get a list with possible Arepacoin command-line options. + Mostrar el mensaje de ayuda de Arepacoin-Qt para obtener una lista con las posibles opciones de línea de comandos para Arepacoin. + + + + &Show + &Mostrar + + + + &Console + &Consola + + + + Build date + Fecha de compilación + + + + Arepacoin - Debug window + Arepacoin - Ventana de depuración + + + + Arepacoin Core + Núcleo Arepacoin + + + + Debug log file + Archivo de registro de depuración + + + + Open the Arepacoin debug log file from the current data directory. This can take a few seconds for large log files. + Abre el archivo de registro de Arepacoin del directorio de datos actual. Esto puede tardar algunos segundos para archivos grandes. + + + + Clear console + Borrar consola + + + + Welcome to the Arepacoin RPC console. + Bienvenido a la consola RPC de Arepacoin + + + + Use up and down arrows to navigate history, and <b>Ctrl-L</b> to clear screen. + Use las flechas arriba y abajo para navegar por el historial y <b>Control+L</b> para vaciar la pantalla. + + + + Type <b>help</b> for an overview of available commands. + Escriba <b>help</b> para ver un resumen de los comandos disponibles. + + + + SendCoinsDialog + + + + + + + + + + Send Coins + Enviar bitcoins + + + + Coin Control Features + Características de Coin Control + + + + Inputs... + Entradas... + + + + automatically selected + Seleccionado automáticamente + + + + Insufficient funds! + Fondos insuficientes! + + + + Quantity: + Cantidad: + + + + + 0 + 0 + + + + Bytes: + Bytes: + + + + Amount: + Cuantía: + + + + + + + 0.00 BC + 123.456 BC {0.00 ?} + + + + Priority: + Prioridad: + + + + medium + medio + + + + Fee: + Tasa: + + + + Low Output: + Envío pequeño: + + + + no + no + + + + After Fee: + Después de tasas: + + + + Change + Cambio + + + + custom change address + dirección de cambio personalizada + + + + Send to multiple recipients at once + Enviar a múltiples destinatarios de una vez + + + + Add &Recipient + Añadir &destinatario + + + + Remove all transaction fields + Elimina todos los campos de transacciones + + + + Clear &All + Vaciar &todo + + + + Balance: + Saldo: + + + + 123.456 BC + 123.456 BC + + + + Confirm the send action + Confirmar el envío + + + + S&end + &Enviar + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + Introduce una dirección Arepacoin (p.ej. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + Copy quantity + Copiar cantidad + + + + Copy amount + Copiar cuantía + + + + Copy fee + Copiar donación + + + + Copy after fee + Copiar después de aplicar donación + + + + Copy bytes + Copiar bytes + + + + Copy priority + Copiar prioridad + + + + Copy low output + Copiar envío pequeño + + + + Copy change + Copiar Cambio + + + + <b>%1</b> to %2 (%3) + <b>%1</b> para %2 (%3) + + + + Confirm send coins + Confirmar el envío de bitcoins + + + + Are you sure you want to send %1? + Estás seguro que quieres enviar %1? + + + + and + y + + + + The recipient address is not valid, please recheck. + La dirección de recepción no es válida, compruébela de nuevo. + + + + The amount to pay must be larger than 0. + La cantidad por pagar tiene que ser mayor de 0. + + + + The amount exceeds your balance. + La cantidad sobrepasa su saldo. + + + + The total exceeds your balance when the %1 transaction fee is included. + El total sobrepasa su saldo cuando se incluye la tasa de envío de %1 + + + + Duplicate address found, can only send to each address once per send operation. + Se ha encontrado una dirección duplicada. Solo se puede enviar a cada dirección una vez por operación de envío. + + + + Error: Transaction creation failed. + Error: Falla al crear la transacción. + + + + 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. + Error: La transacción ha sido rechazada. Esto puede ocurrir si algunas de sus monedas en el monedero ya se gastaron, por ejemplo, si se usa una copia del wallet.dat y se gastaron las monedas de la copia pero no se han marcado como gastadas aquí. + + + + WARNING: Invalid Arepacoin address + ADVERTENCIA: Dirección Arepacoin inválida + + + + (no label) + (sin etiqueta) + + + + WARNING: unknown change address + ADVERTENCIA: dirección de cambio desconocida + + + + SendCoinsEntry + + + Form + Formulario + + + + A&mount: + Ca&ntidad: + + + + Pay &To: + &Pagar a: + + + + + Enter a label for this address to add it to your address book + Etiquete esta dirección para añadirla a la libreta + + + + &Label: + &Etiqueta: + + + + The address to send the payment to (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + La dirección a la que se quiere enviar el pago (p.ej. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + Choose address from address book + Elije dirección de la libreta de direcciones + + + + Alt+A + Alt+A + + + + Paste address from clipboard + Pegar dirección desde portapapeles + + + + Alt+P + Alt+P + + + + Remove this recipient + Elimina este beneficiario + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + Introduce una dirección Arepacoin (p.ej. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + SignVerifyMessageDialog + + + Signatures - Sign / Verify a Message + Firmas - Firmar / verificar un mensaje + + + + + &Sign Message + &Firmar mensaje + + + + You can sign messages with your addresses to prove you own them. Be careful not to sign anything vague, as phishing attacks may try to trick you into signing your identity over to them. Only sign fully-detailed statements you agree to. + Puede firmar mensajes con sus direcciones para demostrar que las posee. Tenga cuidado de no firmar cualquier cosa vaga, ya que los ataques de phishing pueden tratar de engañarle para suplantar su identidad. Firme solo declaraciones totalmente detalladas con las que usted esté de acuerdo. + + + + The address to sign the message with (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + La dirección a firmar con un mensaje (p.ej. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Choose an address from the address book + Elije una dirección de la libreta de direcciones + + + + + Alt+A + Alt+A + + + + Paste address from clipboard + Pegar dirección desde portapapeles + + + + Alt+P + Alt+P + + + + Enter the message you want to sign here + Introduzca el mensaje que desea firmar aquí + + + + Copy the current signature to the system clipboard + Copiar la firma actual al portapapeles del sistema + + + + Sign the message to prove you own this Arepacoin address + Firma el mensaje para demostrar que posees esta dirección Arepacoin. + + + + Reset all sign message fields + Vaciar todos los campos de la firma de mensaje + + + + + Clear &All + Vaciar &todo + + + + + &Verify Message + &Verificar mensaje + + + + Enter the signing address, message (ensure you copy line breaks, spaces, tabs, etc. exactly) and signature below to verify the message. Be careful not to read more into the signature than what is in the signed message itself, to avoid being tricked by a man-in-the-middle attack. + Introduzca la dirección para la firma, el mensaje (asegurándose de copiar tal cual los saltos de línea, espacios, tabulaciones, etc.) y la firma a continuación para verificar el mensaje. Tenga cuidado de no asumir más información de lo que dice el propio mensaje firmado para evitar fraudes basados en ataques de tipo man-in-the-middle. + + + + The address the message was signed with (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + La dirección firmada con un mensaje (p.ej. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + Verify the message to ensure it was signed with the specified Arepacoin address + Verifique el mensaje para asegurarse de que se firmó con la dirección Arepacoin especificada. + + + + Reset all verify message fields + Vaciar todos los campos de la verificación de mensaje + + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + Introduce una dirección Arepacoin (p.ej AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + Click "Sign Message" to generate signature + Haga clic en "Firmar mensaje" para generar la firma + + + + Enter Arepacoin signature + Introduce la firma Arepacoin + + + + + The entered address is invalid. + La dirección introducida es inválida. + + + + + + + Please check the address and try again. + Verifique la dirección e inténtelo de nuevo. + + + + + The entered address does not refer to a key. + La dirección introducida no corresponde a una clave. + + + + Wallet unlock was cancelled. + Se ha cancelado el desbloqueo del monedero. + + + + Private key for the entered address is not available. + No se dispone de la clave privada para la dirección introducida. + + + + Message signing failed. + Ha fallado la firma del mensaje. + + + + Message signed. + Mensaje firmado. + + + + The signature could not be decoded. + No se puede decodificar la firma. + + + + + Please check the signature and try again. + Compruebe la firma e inténtelo de nuevo. + + + + The signature did not match the message digest. + La firma no coincide con el resumen del mensaje. + + + + Message verification failed. + La verificación del mensaje ha fallado. + + + + Message verified. + Mensaje verificado. + + + + TransactionDesc + + + Open until %1 + Abierto hasta %1 + + + + Open for %n block(s) + Abierto para %n bloqueAbierto para %n bloques + + + + conflicted + en conflicto + + + + %1/offline + %1/fuera de línea + + + + %1/unconfirmed + %1/no confirmado + + + + %1 confirmations + %1 confirmaciones + + + + Status + Estado + + + + , broadcast through %n node(s) + , transmitir a través de %n nodo, transmitir a través de %n nodos + + + + Date + Fecha + + + + Source + Fuente + + + + Generated + Generado + + + + + From + De + + + + + + To + Para + + + + + own address + dirección propia + + + + label + etiqueta + + + + + + + + Credit + Crédito + + + + matures in %n more block(s) + disponible en %n bloque másdisponible en %n bloques más + + + + not accepted + no aceptada + + + + + + + Debit + Débito + + + + Transaction fee + Comisión de transacción + + + + Net amount + Cantidad neta + + + + Message + Mensaje + + + + Comment + Comentario + + + + Transaction ID + Identificador de transacción + + + + Generated coins must mature 6 blocks before they can be spent. When you generated this block, it was broadcast to the network to be added to the block chain. If it fails to get into the chain, its state will change to "not accepted" and it won't be spendable. This may occasionally happen if another node generates a block within a few seconds of yours. + Las monedas generadas deben madurar 6 bloques antes de que puedan gastarse. Cuando generaste este bloque, este fue transmitido a la red para ser añadido a la cadena de bloques. Si falla al introducirse en la cadena, su estado cambiará a "no aceptado" y no se podrá gastar. Esto ocasionalmente puede ocurrir si otro nodo genera un bloque a unos segundos que el tuyo. + + + + Debug information + Información de depuración + + + + Transaction + Transacción + + + + Inputs + entradas + + + + Amount + Cantidad + + + + true + verdadero + + + + false + falso + + + + , has not been successfully broadcast yet + , todavía no se ha sido difundido satisfactoriamente + + + + unknown + desconocido + + + + TransactionDescDialog + + + Transaction details + Detalles de transacción + + + + This pane shows a detailed description of the transaction + Esta ventana muestra información detallada sobre la transacción + + + + TransactionTableModel + + + Date + Fecha + + + + Type + Tipo + + + + Address + Dirección + + + + Amount + Cantidad + + + + Open until %1 + Abierto hasta %1 + + + + Confirmed (%1 confirmations) + Confirmado (%1 confirmaciones) + + + + Open for %n more block(s) + Abrir para %n bloque másAbrir para %n bloques más + + + + Offline + Sin conexión + + + + Unconfirmed + Sin confirmar + + + + Confirming (%1 of %2 recommended confirmations) + Confirmando (%1 de %2 confirmaciones recomendadas) + + + + Conflicted + En conflicto + + + + Immature (%1 confirmations, will be available after %2) + No vencidos (%1 confirmaciones. Estarán disponibles al cabo de %2) + + + + This block was not received by any other nodes and will probably not be accepted! + Este bloque no ha sido recibido por otros nodos y probablemente no sea aceptado! + + + + Generated but not accepted + Generado pero no aceptado + + + + Received with + Recibido con + + + + Received from + Recibidos de + + + + Sent to + Enviado a + + + + Payment to yourself + Pago propio + + + + Mined + Minado + + + + (n/a) + (nd) + + + + Transaction status. Hover over this field to show number of confirmations. + Estado de transacción. Pasa el ratón sobre este campo para ver el número de confirmaciones. + + + + Date and time that the transaction was received. + Fecha y hora en que se recibió la transacción. + + + + Type of transaction. + Tipo de transacción. + + + + Destination address of transaction. + Dirección de destino de la transacción. + + + + Amount removed from or added to balance. + Cantidad retirada o añadida al saldo. + + + + TransactionView + + + + All + Todo + + + + Today + Hoy + + + + This week + Esta semana + + + + This month + Este mes + + + + Last month + Mes pasado + + + + This year + Este año + + + + Range... + Rango... + + + + Received with + Recibido con + + + + Sent to + Enviado a + + + + To yourself + A usted mismo + + + + Mined + Minado + + + + Other + Otra + + + + Enter address or label to search + Introduzca una dirección o etiqueta que buscar + + + + Min amount + Cantidad mínima + + + + Copy address + Copiar dirección + + + + Copy label + Copiar etiqueta + + + + Copy amount + Copiar cuantía + + + + Copy transaction ID + Copiar identificador de transacción + + + + Edit label + Editar etiqueta + + + + Show transaction details + Mostrar detalles de la transacción + + + + Export Transaction Data + Exportar datos de transacción + + + + Comma separated file (*.csv) + Archivos de columnas separadas por coma (*.csv) + + + + Confirmed + Confirmado + + + + Date + Fecha + + + + Type + Tipo + + + + Label + Etiqueta + + + + Address + Dirección + + + + Amount + Cantidad + + + + ID + ID + + + + Error exporting + Error al exportar + + + + Could not write to file %1. + No se puede escribir en el archivo %1. + + + + Range: + Rango: + + + + to + para + + + + WalletModel + + + Sending... + Enviando... + + + + bitcoin-core + + + Arepacoin version + versión Arepacoin + + + + Usage: + Uso: + + + + Send command to -server or arepacoind + Envía un comando a -server o arepacoind + + + + List commands + Muestra comandos + + + + + Get help for a command + Recibir ayuda para un comando + + + + + Options: + Opciones: + + + + + Specify configuration file (default: arepacoin.conf) + Especifica un archivo de configuración (por defecto: arepacoin.conf) + + + + Specify pid file (default: arepacoind.pid) + Especifica un archivo pid (por defecto: arepacoind.pid) + + + + Specify wallet file (within data directory) + Especificar archivo de monedero (dentro del directorio de datos) + + + + Specify data directory + Especificar directorio para los datos + + + + Set database cache size in megabytes (default: 25) + Establecer el tamaño de caché de la base de datos en megabytes (predeterminado: 25) + + + + Set database disk log size in megabytes (default: 100) + Ajusta el tamaño de la base de datos del registro en megabytes (por defecto: 100) + + + + Listen for connections on <port> (default: 9853 or testnet: 19853) + Escuchando conexiones en el puerto <port> (por defecto: 9853 o testnet: 19853) + + + + Maintain at most <n> connections to peers (default: 125) + Mantener como máximo <n> conexiones a pares (predeterminado: 125) + + + + Connect to a node to retrieve peer addresses, and disconnect + Conectar a un nodo para obtener direcciones de pares y desconectar + + + + Specify your own public address + Especifique su propia dirección pública + + + + Bind to given address. Use [host]:port notation for IPv6 + Enlazar a la dirección dada. Utilice la notación [host]:puerto para IPv6 + + + + Stake your coins to support network and gain reward (default: 1) + Pon tus monedas en participación "Stake" para dar soporte a la red y ganar alguna recompensa (por defecto: 1) + + + + Threshold for disconnecting misbehaving peers (default: 100) + Umbral para la desconexión de pares con mal comportamiento (predeterminado: 100) + + + + Number of seconds to keep misbehaving peers from reconnecting (default: 86400) + Número de segundos en que se evita la reconexión de pares con mal comportamiento (predeterminado: 86400) + + + + An error occurred while setting up the RPC port %u for listening on IPv4: %s + Ha ocurrido un error al configurar el puerto RPC %u para escucha en IPv4: %s + + + + Detach block and address databases. Increases shutdown time (default: 0) + Separa el bloque y la base de datos de direcciones. Aumenta el tiempo de apagado (por defecto: 0) + + + + 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. + Error: La transacción ha sido rechazada. Esto puede ocurrir si algunas de sus monedas en el monedero ya se gastaron, por ejemplo, si se usa una copia del wallet.dat y se gastaron las monedas de la copia pero no se han marcado como gastadas aquí. + + + + Error: This transaction requires a transaction fee of at least %s because of its amount, complexity, or use of recently received funds + Error: Esta transacción requiere de una comisión de transacción de al menos %s debido a su tamaño, complejidad, o uso de fondos recibidos recientemente. + + + + Listen for JSON-RPC connections on <port> (default: 9852 or testnet: 19852) + Escuchar conexiones JSON-RPC en <port> (predeterminado: 9852 o testnet: 19852) + + + + Accept command line and JSON-RPC commands + Aceptar comandos consola y JSON-RPC + + + + + Error: Transaction creation failed + Error: Fallo al crear la transacción. + + + + Error: Wallet locked, unable to create transaction + Error: Monedero bloqueado, no es posible crear una transacción + + + + Importing blockchain data file. + Importando el archivo de datos de la cadena de bloques. + + + + Importing bootstrap blockchain data file. + Importando el archivo de datos de arranque de la cadena de bloques. + + + + Run in the background as a daemon and accept commands + Ejecutar en segundo plano como daemon y aceptar comandos + + + + + Use the test network + Usar la red de pruebas + + + + + Accept connections from outside (default: 1 if no -proxy or -connect) + Aceptar conexiones desde el exterior (predeterminado: 1 si no -proxy o -connect) + + + + An error occurred while setting up the RPC port %u for listening on IPv6, falling back to IPv4: %s + Ha ocurrido un error al configurar el puerto RPC %u para escuchar mediante IPv6. Recurriendo a IPv4: %s + + + + Error initializing database environment %s! To recover, BACKUP THAT DIRECTORY, then remove everything from it except for wallet.dat. + Error al inicializar el entorno de base de datos %s! Para recuperar, HAGA UNA COPIA DE SEGURIDAD DEL DIRECTORIO, a continuación, elimine todo de ella excepto el archivo wallet.dat. + + + + Set maximum size of high-priority/low-fee transactions in bytes (default: 27000) + Establecer el tamaño máximo de las transacciones alta-prioridad/baja-comisión en bytes (por defecto: 27000) + + + + Warning: -paytxfee is set very high! This is the transaction fee you will pay if you send a transaction. + Aviso: ¡-paytxfee tiene un valor muy alto! Esta es la comisión que pagará si envía una transacción. + + + + Warning: Please check that your computer's date and time are correct! If your clock is wrong Arepacoin will not work properly. + Advertencia: Verifique que la fecha y hora del equipo sean correctas! Si su reloj es erróneo Arepacoin no funcionará correctamente. + + + + Warning: error reading wallet.dat! All keys read correctly, but transaction data or address book entries might be missing or incorrect. + Aviso: ¡Error al leer wallet.dat! Todas las claves se han leído correctamente, pero podrían faltar o ser incorrectos los datos de transacciones o las entradas de la libreta de direcciones. + + + + Warning: wallet.dat corrupt, data salvaged! Original wallet.dat saved as wallet.{timestamp}.bak in %s; if your balance or transactions are incorrect you should restore from a backup. + Aviso: ¡Recuperados datos de wallet.dat corrupto! El wallet.dat original se ha guardado como wallet.{timestamp}.bak en %s; si hubiera errores en su saldo o transacciones, deberá restaurar una copia de seguridad. + + + + Attempt to recover private keys from a corrupt wallet.dat + Intento de recuperar claves privadas de un wallet.dat corrupto + + + + Block creation options: + Opciones de creación de bloques: + + + + Connect only to the specified node(s) + Conectar sólo a los nodos (o nodo) especificados + + + + Discover own IP address (default: 1 when listening and no -externalip) + Descubrir dirección IP propia (predeterminado: 1 al escuchar sin -externalip) + + + + Failed to listen on any port. Use -listen=0 if you want this. + Ha fallado la escucha en todos los puertos. Use -listen=0 si desea esto. + + + + Find peers using DNS lookup (default: 1) + Encontrar pares usando la búsqueda de DNS (por defecto: 1) + + + + Sync checkpoints policy (default: strict) + Política de puntos de control de sincronización (por defecto: estricta) + + + + Invalid -tor address: '%s' + Dirección -tor inválida: '%s' + + + + Invalid amount for -reservebalance=<amount> + Cantidad no válida para -reservebalance=<amount> + + + + Maximum per-connection receive buffer, <n>*1000 bytes (default: 5000) + Búfer de recepción máximo por conexión, <n>*1000 bytes (predeterminado: 5000) + + + + Maximum per-connection send buffer, <n>*1000 bytes (default: 1000) + Búfer de recepción máximo por conexión, , <n>*1000 bytes (predeterminado: 1000) + + + + Only connect to nodes in network <net> (IPv4, IPv6 or Tor) + Conectarse solo a nodos de la red <net> (IPv4, IPv6 o Tor) + + + + Output extra debugging information. Implies all other -debug* options + Salida de información de depuración extra. Implica todas las opciones -debug* de depuración + + + + Output extra network debugging information + Salida extra de información de depuración de red + + + + Prepend debug output with timestamp + Prefijar salida de depuración con marca de tiempo + + + + SSL options: (see the Bitcoin Wiki for SSL setup instructions) + Opciones SSL: (ver la Bitcoin Wiki para instrucciones de configuración SSL) + + + + Select the version of socks proxy to use (4-5, default: 5) + Selecciona la versión de socks proxy a usar (4-5, por defecto: 5) + + + + Send trace/debug info to console instead of debug.log file + Enviar información de trazas/depuración a la consola en lugar de al archivo debug.log + + + + Send trace/debug info to debugger + Enviar información de rastreo / depurado al depurador + + + + Set maximum block size in bytes (default: 250000) + Establecer el tamaño máximo de bloque en bytes (por defecto: 250000) + + + + Set minimum block size in bytes (default: 0) + Establecer tamaño mínimo de bloque en bytes (predeterminado: 0) + + + + Shrink debug.log file on client startup (default: 1 when no -debug) + Reducir el archivo debug.log al iniciar el cliente (predeterminado: 1 sin -debug) + + + + Specify connection timeout in milliseconds (default: 5000) + Especificar el tiempo máximo de conexión en milisegundos (predeterminado: 5000) + + + + Unable to sign checkpoint, wrong checkpointkey? + + No es posible firmar el punto de control, clave de punto de control incorrecta?%s + + + + Use UPnP to map the listening port (default: 0) + Usar UPnP para asignar el puerto de escucha (predeterminado: 0) + + + + Use UPnP to map the listening port (default: 1 when listening) + Usar UPnP para asignar el puerto de escucha (predeterminado: 1 al escuchar) + + + + Use proxy to reach tor hidden services (default: same as -proxy) + Usar proxy para alcanzar a ver los servicios ocultos (por defecto: los mismos que -proxy) + + + + Username for JSON-RPC connections + Nombre de usuario para las conexiones JSON-RPC + + + + + Verifying database integrity... + Verificando la integridad de la base de datos... + + + + WARNING: syncronized checkpoint violation detected, but skipped! + ADVERTENCIA: violación de un punto de control sincronizado detectada, se saltara! + + + + Warning: Disk space is low! + Advertencia: Espacio en disco bajo! + + + + Warning: This version is obsolete, upgrade required! + Aviso: Esta versión es obsoleta, actualización necesaria! + + + + wallet.dat corrupt, salvage failed + wallet.dat corrupto. Ha fallado la recuperación. + + + + Password for JSON-RPC connections + Contraseña para las conexiones JSON-RPC + + + + + %s, you must set a rpcpassword in the configuration file: + %s +It is recommended you use the following random password: +rpcuser=arepacoinrpc +rpcpassword=%s +(you do not need to remember this password) +The username and password MUST NOT be the same. +If the file does not exist, create it with owner-readable-only file permissions. +It is also recommended to set alertnotify so you are notified of problems; +for example: alertnotify=echo %%s | mail -s "Arepacoin Alert" admin@foo.com + + %s, debe establecer un rpcpassword en el fichero de configuración: +%s +Se recomienda utilizar la siguiente contraseña aleatoria: +rpcuser=arepacoinrpc +rpcpassword=%s +(no necesita recordar este password) +El nombre de usuario y contraseña no debe ser el mismo. +Si no existe el archivo, créelo con permisos de sólo lectura para el dueño. +También se recomienda establecer alertnotify para ser notificado de los problemas; +por ejemplo: alertnotify=echo %%s | mail -s "Arepacoin Alert" admin@foo.com + + + + + Find peers using internet relay chat (default: 0) + Encontrar pares usando IRC (por defecto:1) {0)?} + + + + Sync time with other nodes. Disable if time on your system is precise e.g. syncing with NTP (default: 1) + Sincronizar el tiempo con otros nodos. Desactivar si el tiempo en su sistema es preciso, por ejemplo si usa sincronización con NTP (por defecto: 1) + + + + When creating transactions, ignore inputs with value less than this (default: 0.01) + Al crear transacciones, ignorar las entradas con valor inferior a esta (por defecto: 0.01) + + + + Allow JSON-RPC connections from specified IP address + Permitir conexiones JSON-RPC desde la dirección IP especificada + + + + + Send commands to node running on <ip> (default: 127.0.0.1) + Enviar comando al nodo situado en <ip> (predeterminado: 127.0.0.1) + + + + + Execute command when the best block changes (%s in cmd is replaced by block hash) + Ejecutar un comando cuando cambia el mejor bloque (%s en cmd se sustituye por el hash de bloque) + + + + Execute command when a wallet transaction changes (%s in cmd is replaced by TxID) + Ejecutar comando cuando una transacción del monedero cambia (%s en cmd se remplazará por TxID) + + + + Require a confirmations for change (default: 0) + Requerir confirmaciones para cambio (por defecto: 0) + + + + Enforce transaction scripts to use canonical PUSH operators (default: 1) + Exigir a los scripts de transacción que usen los operadores PUSH canónicos (por defecto: 1) + + + + Execute command when a relevant alert is received (%s in cmd is replaced by message) + Ejecutar comando cuando una alerta relevante sea recibida (%s en la linea de comandos es reemplazado por un mensaje) + + + + Upgrade wallet to latest format + Actualizar el monedero al último formato + + + + Set key pool size to <n> (default: 100) + Ajustar el número de claves en reserva <n> (predeterminado: 100) + + + + + Rescan the block chain for missing wallet transactions + Volver a examinar la cadena de bloques en busca de transacciones del monedero perdidas + + + + How many blocks to check at startup (default: 2500, 0 = all) + Cuantos bloques para comprobar al inicio (por defecto: 2500, 0 = todos) + + + + How thorough the block verification is (0-6, default: 1) + Cómo de minuciosa es la verificación del bloque (0-6, por defecto: 1) + + + + Imports blocks from external blk000?.dat file + Importar bloques desde el archivo externo blk000?.dat + + + + Use OpenSSL (https) for JSON-RPC connections + Usar OpenSSL (https) para las conexiones JSON-RPC + + + + + Server certificate file (default: server.cert) + Certificado del servidor (predeterminado: server.cert) + + + + + Server private key (default: server.pem) + Clave privada del servidor (predeterminado: server.pem) + + + + + Acceptable ciphers (default: TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH) + Cifras aceptables: (por defecto: TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH) + + + + Error: Wallet unlocked for staking only, unable to create transaction. + Error: Monedero desbloqueado sólo para hacer "stake", no es posible crear una transacción. + + + + WARNING: Invalid checkpoint found! Displayed transactions may not be correct! You may need to upgrade, or notify developers. + ADVERTENCIA: Punto de control no válido encontrado! Las transacciones que se muestran pueden no ser correctas! Puede que tenga que actualizar o notificar a los desarrolladores. + + + + This help message + Este mensaje de ayuda + + + + + Wallet %s resides outside data directory %s. + El monedero %s reside fuera del directorio de datos %s. + + + + Cannot obtain a lock on data directory %s. Arepacoin is probably already running. + No se puede obtener un bloqueo en el directorio de datos %s. Arepacoin probablemente ya esté en funcionamiento. + + + + Arepacoin + Arepacoin + + + + Unable to bind to %s on this computer (bind returned error %d, %s) + No es posible conectar con %s en este sistema (bind ha dado el error %d, %s) + + + + Connect through socks proxy + Conecte a través del socks proxy + + + + Allow DNS lookups for -addnode, -seednode and -connect + Permitir búsquedas DNS para -addnode, -seednode y -connect + + + + Loading addresses... + Cargando direcciones... + + + + Error loading blkindex.dat + Error al cargar blkindex.dat + + + + Error loading wallet.dat: Wallet corrupted + Error al cargar wallet.dat: el monedero está dañado + + + + Error loading wallet.dat: Wallet requires newer version of Arepacoin + Error cargando wallet.dat: El monedero requiere una nueva versión de Arepacoin + + + + Wallet needed to be rewritten: restart Arepacoin to complete + El monedero necesita ser reescrito: reinicie Arepacoin para completar + + + + Error loading wallet.dat + Error al cargar wallet.dat + + + + Invalid -proxy address: '%s' + Dirección -proxy inválida: '%s' + + + + Unknown network specified in -onlynet: '%s' + La red especificada en -onlynet '%s' es desconocida + + + + Unknown -socks proxy version requested: %i + Solicitada versión de proxy -socks desconocida: %i + + + + Cannot resolve -bind address: '%s' + No se puede resolver la dirección de -bind: '%s' + + + + Cannot resolve -externalip address: '%s' + No se puede resolver la dirección de -externalip: '%s' + + + + Invalid amount for -paytxfee=<amount>: '%s' + Cantidad inválida para -paytxfee=<amount>: '%s' + + + + Error: could not start node + Error: no se pudo iniciar el nodo + + + + Sending... + Enviando... + + + + Invalid amount + Cuantía no válida + + + + Insufficient funds + Fondos insuficientes + + + + Loading block index... + Cargando el índice de bloques... + + + + Add a node to connect to and attempt to keep the connection open + Añadir un nodo al que conectarse y tratar de mantener la conexión abierta + + + + Unable to bind to %s on this computer. Arepacoin is probably already running. + No se puede enlazar a %s en este equipo. Arepacoin probablemente ya esté en funcionamiento. + + + + Fee per KB to add to transactions you send + Comisión por KB a añadir a las transacciones que envía + + + + Invalid amount for -mininput=<amount>: '%s' + Cantidad no válida para -mininput=<amount>: '%s' + + + + Loading wallet... + Cargando monedero... + + + + Cannot downgrade wallet + No se puede rebajar el monedero + + + + Cannot initialize keypool + No se puede inicializar el keypool + + + + Cannot write default address + No se puede escribir la dirección predeterminada + + + + Rescanning... + Reexplorando... + + + + Done loading + Generado pero no aceptado + + + + To use the %s option + Para utilizar la opción %s + + + + Error + Error + + + + You must set rpcpassword=<password> in the configuration file: +%s +If the file does not exist, create it with owner-readable-only file permissions. + Tiene que establecer rpcpassword=<contraseña> en el fichero de configuración: ⏎ +%s ⏎ +Si el archivo no existe, créelo con permiso de lectura solamente del propietario. + + + \ No newline at end of file diff --git a/src/qt/locale/bitcoin_es_CL.ts b/src/qt/locale/bitcoin_es_CL.ts new file mode 100755 index 0000000..5605436 --- /dev/null +++ b/src/qt/locale/bitcoin_es_CL.ts @@ -0,0 +1,3325 @@ + + + AboutDialog + + + About Arepacoin + + + + + <b>Arepacoin</b> version + + + + + Copyright © 2009-2014 The Bitcoin developers +Copyright © 2012-2014 The NovaCoin developers +Copyright © 2014 The Arepacoin developers + + + + + +This is experimental software. + +Distributed under the MIT/X11 software license, see the accompanying file COPYING or http://www.opensource.org/licenses/mit-license.php. + +This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit (http://www.openssl.org/) and cryptographic software written by Eric Young (eay@cryptsoft.com) and UPnP software written by Thomas Bernard. + +Este es un software experimental. + +Distribuido bajo la licencia MIT/X11, vea el archivo adjunto +COPYING o http://www.opensource.org/licenses/mit-license.php. + +Este producto incluye software desarrollado por OpenSSL Project para su uso en +el OpenSSL Toolkit (http://www.openssl.org/), software criptográfico escrito por +Eric Young (eay@cryptsoft.com) y UPnP software escrito por Thomas Bernard. + + + + AddressBookPage + + + Address Book + + + + + Double-click to edit address or label + Haz doble clic para editar una dirección o etiqueta + + + + Create a new address + Crea una nueva dirección + + + + Copy the currently selected address to the system clipboard + Copia la dirección seleccionada al portapapeles + + + + &New Address + + + + + These are your Arepacoin addresses for receiving payments. You may want to give a different one to each sender so you can keep track of who is paying you. + + + + + &Copy Address + &Copia dirección + + + + Show &QR Code + + + + + Sign a message to prove you own a Arepacoin address + + + + + Sign &Message + + + + + Delete the currently selected address from the list + + + + + Verify a message to ensure it was signed with a specified Arepacoin address + + + + + &Verify Message + + + + + &Delete + &Borrar + + + + Copy &Label + Copia &etiqueta + + + + &Edit + &Editar + + + + Export Address Book Data + + + + + Comma separated file (*.csv) + Archivos separados por coma (*.csv) + + + + Error exporting + + + + + Could not write to file %1. + + + + + AddressTableModel + + + Label + Etiqueta + + + + Address + Dirección + + + + (no label) + (sin etiqueta) + + + + AskPassphraseDialog + + + Passphrase Dialog + + + + + Enter passphrase + Introduce contraseña actual + + + + New passphrase + Nueva contraseña + + + + Repeat new passphrase + Repite nueva contraseña + + + + Serves to disable the trivial sendmoney when OS account compromised. Provides no real security. + + + + + For staking only + + + + + Enter the new passphrase to the wallet.<br/>Please use a passphrase of <b>10 or more random characters</b>, or <b>eight or more words</b>. + Introduce la nueva contraseña para la billetera.<br/>Por favor utiliza un contraseña de<b>10 o más caracteres aleatorios</b>, u <b>ocho o más palabras</b>. + + + + Encrypt wallet + Codificar billetera + + + + This operation needs your wallet passphrase to unlock the wallet. + Esta operación necesita la contraseña para desbloquear la billetera. + + + + Unlock wallet + Desbloquea billetera + + + + This operation needs your wallet passphrase to decrypt the wallet. + Esta operación necesita la contraseña para decodificar la billetara. + + + + Decrypt wallet + Decodificar cartera + + + + Change passphrase + Cambia contraseña + + + + Enter the old and new passphrase to the wallet. + Introduce la contraseña anterior y la nueva de cartera + + + + Confirm wallet encryption + Confirma la codificación de cartera + + + + Warning: If you encrypt your wallet and lose your passphrase, you will <b>LOSE ALL OF YOUR COINS</b>! + + + + + Are you sure you wish to encrypt your wallet? + ¿Seguro que quieres seguir codificando la billetera? + + + + IMPORTANT: Any previous backups you have made of your wallet file should be replaced with the newly generated, encrypted wallet file. For security reasons, previous backups of the unencrypted wallet file will become useless as soon as you start using the new, encrypted wallet. + IMPORTANTE: Cualquier versión anterior que hayas realizado de tu archivo de billetera será reemplazada por el nuevo archivo de billetera encriptado. Por razones de seguridad, los respaldos anteriores de los archivos de billetera se volverán inútiles en tanto comiences a usar la nueva billetera encriptada. + + + + + Warning: The Caps Lock key is on! + Precaucion: Mayúsculas Activadas + + + + + Wallet encrypted + Billetera codificada + + + + Arepacoin will close now to finish the encryption process. Remember that encrypting your wallet cannot fully protect your coins from being stolen by malware infecting your computer. + + + + + + + + Wallet encryption failed + Falló la codificación de la billetera + + + + Wallet encryption failed due to an internal error. Your wallet was not encrypted. + La codificación de la billetera falló debido a un error interno. Tu billetera no ha sido codificada. + + + + + The supplied passphrases do not match. + Las contraseñas no coinciden. + + + + Wallet unlock failed + Ha fallado el desbloqueo de la billetera + + + + + + The passphrase entered for the wallet decryption was incorrect. + La contraseña introducida para decodificar la billetera es incorrecta. + + + + Wallet decryption failed + Ha fallado la decodificación de la billetera + + + + Wallet passphrase was successfully changed. + La contraseña de billetera ha sido cambiada con éxito. + + + + BitcoinGUI + + + Sign &message... + Firmar &Mensaje... + + + + Synchronizing with network... + Sincronizando con la red... + + + + &Overview + &Vista general + + + + Show general overview of wallet + Muestra una vista general de la billetera + + + + &Transactions + &Transacciones + + + + Browse transaction history + Explora el historial de transacciónes + + + + &Address Book + + + + + Edit the list of stored addresses and labels + + + + + &Receive coins + + + + + Show the list of addresses for receiving payments + + + + + &Send coins + + + + + E&xit + &Salir + + + + Quit application + Salir del programa + + + + Show information about Arepacoin + + + + + About &Qt + Acerca de + + + + Show information about Qt + Mostrar Información sobre QT + + + + &Options... + &Opciones + + + + &Encrypt Wallet... + &Codificar la billetera... + + + + &Backup Wallet... + &Respaldar billetera... + + + + &Change Passphrase... + &Cambiar la contraseña... + + + + ~%n block(s) remaining + + + + + Processed %1 of %2 (estimated) blocks of transaction history. + Procesado %1 de %2 (estimado) bloques de historial de transacciones. + + + + Processed %1 blocks of transaction history. + Procesado %1 bloques de historial de transacciones. + + + + &Export... + + + + + Send coins to a Arepacoin address + + + + + Modify configuration options for Arepacoin + + + + + Export the data in the current tab to a file + + + + + Encrypt or decrypt wallet + + + + + Backup wallet to another location + Respaldar billetera en otra ubicación + + + + Change the passphrase used for wallet encryption + Cambiar la contraseña utilizada para la codificación de la billetera + + + + &Debug window + Ventana &Debug + + + + Open debugging and diagnostic console + Abre consola de depuración y diagnóstico + + + + &Verify message... + + + + + Arepacoin + + + + + Wallet + Cartera + + + + &About Arepacoin + + + + + &Show / Hide + &Mostrar/Ocultar + + + + Unlock wallet + + + + + &Lock Wallet + + + + + Lock wallet + + + + + &File + &Archivo + + + + &Settings + &Configuración + + + + &Help + &Ayuda + + + + Tabs toolbar + Barra de pestañas + + + + Actions toolbar + + + + + + [testnet] + [red-de-pruebas] + + + + + Arepacoin client + + + + + %n active connection(s) to Arepacoin network + + + + + Staking.<br>Your weight is %1<br>Network weight is %2<br>Expected time to earn reward is %3 + + + + + Not staking because wallet is locked + + + + + Not staking because wallet is offline + + + + + Not staking because wallet is syncing + + + + + Not staking because you don't have mature coins + + + + + %n second(s) ago + + + + + &Unlock Wallet... + + + + + %n minute(s) ago + + + + + %n hour(s) ago + + + + + %n day(s) ago + + + + + Up to date + Actualizado + + + + Catching up... + Recuperando... + + + + Last received block was generated %1. + + + + + This transaction is over the size limit. You can still send it for a fee of %1, which goes to the nodes that process your transaction and helps to support the network. Do you want to pay the fee? + + + + + Confirm transaction fee + + + + + Sent transaction + Transacción enviada + + + + Incoming transaction + Transacción entrante + + + + Date: %1 +Amount: %2 +Type: %3 +Address: %4 + + Fecha: %1 +Cantidad: %2 +Tipo: %3 +Dirección: %4 + + + + + URI handling + + + + + + URI can not be parsed! This can be caused by an invalid Arepacoin address or malformed URI parameters. + + + + + Wallet is <b>encrypted</b> and currently <b>unlocked</b> + La billetera esta <b>codificada</b> y actualmente <b>desbloqueda</b> + + + + Wallet is <b>encrypted</b> and currently <b>locked</b> + La billetera esta <b>codificada</b> y actualmente <b>bloqueda</b> + + + + Backup Wallet + + + + + Wallet Data (*.dat) + + + + + Backup Failed + + + + + There was an error trying to save the wallet data to the new location. + + + + + %n second(s) + + + + + %n minute(s) + + + + + %n hour(s) + %n hora%n horas + + + + %n day(s) + %n día%n días + + + + %n week(s) + %n semana%n semanas + + + + %n year(s) + %n año%n años + + + + %1 behind + %1 detrás + + + + %1 and %2 + %1 y %2 + + + + Not staking + + + + + A fatal error occurred. Arepacoin can no longer continue safely and will quit. + + + + + ClientModel + + + Network Alert + Alerta de Red + + + + CoinControlDialog + + + Coin Control + + + + + Quantity: + + + + + Bytes: + + + + + Amount: + Cantidad: + + + + Priority: + + + + + Fee: + + + + + Low Output: + + + + + no + + + + + After Fee: + + + + + Change: + + + + + (un)select all + + + + + Tree mode + + + + + List mode + + + + + Amount + Cantidad + + + + Label + + + + + Address + Dirección + + + + Date + Fecha + + + + Confirmations + + + + + Confirmed + Confirmado + + + + Priority + + + + + Copy address + Copia dirección + + + + Copy label + Copia etiqueta + + + + + Copy amount + Copiar Cantidad + + + + Copy transaction ID + + + + + Copy quantity + + + + + Copy fee + + + + + Copy after fee + + + + + Copy bytes + + + + + Copy priority + + + + + Copy low output + + + + + Copy change + + + + + highest + + + + + high + + + + + medium-high + + + + + medium + + + + + low-medium + + + + + low + + + + + lowest + + + + + DUST + + + + + yes + + + + + This label turns red, if the transaction size is bigger than 10000 bytes. + + This means a fee of at least %1 per kb is required. + + Can vary +/- 1 Byte per input. + + + + + Transactions with higher priority get more likely into a block. + +This label turns red, if the priority is smaller than "medium". + + This means a fee of at least %1 per kb is required. + + + + + This label turns red, if any recipient receives an amount smaller than %1. + + This means a fee of at least %2 is required. + + Amounts below 0.546 times the minimum relay fee are shown as DUST. + + + + + This label turns red, if the change is smaller than %1. + + This means a fee of at least %2 is required. + + + + + + (no label) + (sin etiqueta) + + + + change from %1 (%2) + + + + + (change) + + + + + EditAddressDialog + + + Edit Address + Editar dirección + + + + &Label + &Etiqueta + + + + The label associated with this address book entry + + + + + &Address + &Dirección + + + + The address associated with this address book entry. This can only be modified for sending addresses. + + + + + New receiving address + Nueva dirección para recibir + + + + New sending address + Nueva dirección para enviar + + + + Edit receiving address + Editar dirección de recepción + + + + Edit sending address + Editar dirección de envio + + + + The entered address "%1" is already in the address book. + La dirección introducida "%1" ya esta guardada en la libreta de direcciones. + + + + The entered address "%1" is not a valid Arepacoin address. + + + + + Could not unlock wallet. + No se pudo desbloquear la billetera. + + + + New key generation failed. + La generación de nueva clave falló. + + + + GUIUtil::HelpMessageBox + + + + Arepacoin-Qt + + + + + version + + + + + Usage: + + + + + command-line options + + + + + UI options + + + + + Set language, for example "de_DE" (default: system locale) + + + + + Start minimized + + + + + Show splash screen on startup (default: 1) + + + + + OptionsDialog + + + Options + Opciones + + + + &Main + &Principal + + + + Optional transaction fee per kB that helps make sure your transactions are processed quickly. Most transactions are 1 kB. Fee 0.01 recommended. + + + + + Pay transaction &fee + Comisión de &transacciónes + + + + Reserved amount does not participate in staking and is therefore spendable at any time. + + + + + Reserve + + + + + Automatically start Arepacoin after logging in to the system. + + + + + &Start Arepacoin on system login + + + + + Detach block and address databases at shutdown. This means they can be moved to another data directory, but it slows down shutdown. The wallet is always detached. + + + + + &Detach databases at shutdown + + + + + &Network + &Red + + + + Automatically open the Arepacoin client port on the router. This only works when your router supports UPnP and it is enabled. + + + + + Map port using &UPnP + Direcciona el puerto usando &UPnP + + + + Connect to the Arepacoin network through a SOCKS proxy (e.g. when connecting through Tor). + + + + + &Connect through SOCKS proxy: + + + + + Proxy &IP: + &IP Proxy: + + + + IP address of the proxy (e.g. 127.0.0.1) + + + + + &Port: + &Puerto: + + + + Port of the proxy (e.g. 9050) + Puerto del servidor proxy (ej. 9050) + + + + SOCKS &Version: + + + + + SOCKS version of the proxy (e.g. 5) + + + + + &Window + + + + + Show only a tray icon after minimizing the window. + Muestra solo un ícono en la bandeja después de minimizar la ventana + + + + &Minimize to the tray instead of the taskbar + &Minimiza a la bandeja en vez de la barra de tareas + + + + Minimize instead of exit the application when the window is closed. When this option is enabled, the application will be closed only after selecting Quit in the menu. + Minimiza la ventana en lugar de salir del programa cuando la ventana se cierra. Cuando esta opción esta activa el programa solo se puede cerrar seleccionando Salir desde el menu. + + + + M&inimize on close + M&inimiza a la bandeja al cerrar + + + + &Display + &Mostrado + + + + User Interface &language: + + + + + The user interface language can be set here. This setting will take effect after restarting Arepacoin. + + + + + &Unit to show amounts in: + &Unidad en la que mostrar cantitades: + + + + Choose the default subdivision unit to show in the interface and when sending coins. + Elige la subdivisión por defecto para mostrar cantidaded en la interfaz cuando se envien monedas + + + + Whether to show Arepacoin addresses in the transaction list or not. + + + + + &Display addresses in transaction list + &Muestra direcciones en el listado de transaccioines + + + + Whether to show coin control features or not. + + + + + Display coin &control features (experts only!) + + + + + &OK + &OK + + + + &Cancel + &Cancela + + + + &Apply + + + + + default + predeterminado + + + + + Warning + + + + + + This setting will take effect after restarting Arepacoin. + + + + + The supplied proxy address is invalid. + + + + + OverviewPage + + + Form + Formulario + + + + + The displayed information may be out of date. Your wallet automatically synchronizes with the Arepacoin network after a connection is established, but this process has not completed yet. + + + + + Stake: + + + + + Unconfirmed: + No confirmados: + + + + Wallet + Cartera + + + + Spendable: + + + + + Your current spendable balance + + + + + Immature: + + + + + Mined balance that has not yet matured + + + + + Total: + Total: + + + + Your current total balance + + + + + <b>Recent transactions</b> + <b>Transacciones recientes</b> + + + + Total of transactions that have yet to be confirmed, and do not yet count toward the current balance + + + + + Total of coins that was staked, and do not yet count toward the current balance + + + + + + out of sync + desincronizado + + + + QRCodeDialog + + + QR Code Dialog + + + + + Request Payment + + + + + Amount: + + + + + Label: + + + + + Message: + + + + + &Save As... + + + + + Error encoding URI into QR Code. + + + + + The entered amount is invalid, please check. + + + + + Resulting URI too long, try to reduce the text for label / message. + + + + + Save QR Code + + + + + PNG Images (*.png) + + + + + RPCConsole + + + Client name + Nombre del cliente + + + + + + + + + + + + + N/A + N/A + + + + Client version + Versión del Cliente + + + + &Information + &Información + + + + Using OpenSSL version + + + + + Startup time + Tiempo de inicio + + + + Network + Red + + + + Number of connections + Número de conexiones + + + + On testnet + + + + + Block chain + Bloquea cadena + + + + Current number of blocks + + + + + Estimated total blocks + + + + + Last block time + + + + + &Open + &Abrir + + + + Command-line options + + + + + Show the Arepacoin-Qt help message to get a list with possible Arepacoin command-line options. + + + + + &Show + + + + + &Console + &Consola + + + + Build date + + + + + Arepacoin - Debug window + + + + + Arepacoin Core + + + + + Debug log file + + + + + Open the Arepacoin debug log file from the current data directory. This can take a few seconds for large log files. + + + + + Clear console + Limpiar Consola + + + + Welcome to the Arepacoin RPC console. + + + + + Use up and down arrows to navigate history, and <b>Ctrl-L</b> to clear screen. + + + + + Type <b>help</b> for an overview of available commands. + + + + + SendCoinsDialog + + + + + + + + + + Send Coins + Enviar monedas + + + + Coin Control Features + + + + + Inputs... + + + + + automatically selected + + + + + Insufficient funds! + + + + + Quantity: + + + + + + 0 + + + + + Bytes: + + + + + Amount: + Cantidad: + + + + + + + 0.00 BC + + + + + Priority: + + + + + medium + + + + + Fee: + + + + + Low Output: + + + + + no + + + + + After Fee: + + + + + Change + + + + + custom change address + + + + + Send to multiple recipients at once + Enviar a múltiples destinatarios + + + + Add &Recipient + &Agrega destinatario + + + + Remove all transaction fields + + + + + Clear &All + &Borra todos + + + + Balance: + Balance: + + + + 123.456 BC + + + + + Confirm the send action + Confirma el envio + + + + S&end + &Envía + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Copy quantity + + + + + Copy amount + Copiar Cantidad + + + + Copy fee + + + + + Copy after fee + + + + + Copy bytes + + + + + Copy priority + + + + + Copy low output + + + + + Copy change + + + + + <b>%1</b> to %2 (%3) + + + + + Confirm send coins + Confirmar el envio de monedas + + + + Are you sure you want to send %1? + + + + + and + + + + + The recipient address is not valid, please recheck. + La dirección de destinatarion no es valida, comprueba otra vez. + + + + The amount to pay must be larger than 0. + La cantidad por pagar tiene que ser mayor 0. + + + + The amount exceeds your balance. + La cantidad sobrepasa tu saldo. + + + + The total exceeds your balance when the %1 transaction fee is included. + El total sobrepasa tu saldo cuando se incluyen %1 como tasa de envio. + + + + Duplicate address found, can only send to each address once per send operation. + Tienes una dirección duplicada, solo puedes enviar a direcciónes individuales de una sola vez. + + + + Error: Transaction creation failed. + + + + + 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. + + + + + WARNING: Invalid Arepacoin address + + + + + (no label) + (sin etiqueta) + + + + WARNING: unknown change address + + + + + SendCoinsEntry + + + Form + + + + + A&mount: + Cantidad: + + + + Pay &To: + &Pagar a: + + + + + Enter a label for this address to add it to your address book + Introduce una etiqueta a esta dirección para añadirla a tu guia + + + + &Label: + &Etiqueta: + + + + The address to send the payment to (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Choose address from address book + + + + + Alt+A + Alt+A + + + + Paste address from clipboard + Pega dirección desde portapapeles + + + + Alt+P + Alt+P + + + + Remove this recipient + + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + SignVerifyMessageDialog + + + Signatures - Sign / Verify a Message + + + + + + &Sign Message + &Firmar Mensaje + + + + You can sign messages with your addresses to prove you own them. Be careful not to sign anything vague, as phishing attacks may try to trick you into signing your identity over to them. Only sign fully-detailed statements you agree to. + + + + + The address to sign the message with (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + + Choose an address from the address book + + + + + + Alt+A + Alt+A + + + + Paste address from clipboard + Pega dirección desde portapapeles + + + + Alt+P + Alt+P + + + + Enter the message you want to sign here + Escriba el mensaje que desea firmar + + + + Copy the current signature to the system clipboard + + + + + Sign the message to prove you own this Arepacoin address + + + + + Reset all sign message fields + + + + + + Clear &All + &Borra todos + + + + + &Verify Message + &Firmar Mensaje + + + + Enter the signing address, message (ensure you copy line breaks, spaces, tabs, etc. exactly) and signature below to verify the message. Be careful not to read more into the signature than what is in the signed message itself, to avoid being tricked by a man-in-the-middle attack. + + + + + The address the message was signed with (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Verify the message to ensure it was signed with the specified Arepacoin address + + + + + Reset all verify message fields + + + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Click "Sign Message" to generate signature + Click en "Firmar Mensage" para conseguir firma + + + + Enter Arepacoin signature + + + + + + The entered address is invalid. + La dirección introducida "%1" no es una dirección Bitcoin valida. + + + + + + + Please check the address and try again. + Por favor, revise la dirección Bitcoin e inténtelo denuevo + + + + + The entered address does not refer to a key. + + + + + Wallet unlock was cancelled. + Ha fallado el desbloqueo de la billetera + + + + Private key for the entered address is not available. + + + + + Message signing failed. + Firma fallida + + + + Message signed. + Mensaje firmado + + + + The signature could not be decoded. + + + + + + Please check the signature and try again. + + + + + The signature did not match the message digest. + + + + + Message verification failed. + + + + + Message verified. + Mensaje comprobado + + + + TransactionDesc + + + Open until %1 + Abierto hasta %1 + + + + Open for %n block(s) + + + + + conflicted + + + + + %1/offline + %1/fuera de linea + + + + %1/unconfirmed + %1/no confirmado + + + + %1 confirmations + %1 confirmaciónes + + + + Status + Estado + + + + , broadcast through %n node(s) + + + + + Date + Fecha + + + + Source + + + + + Generated + Generado + + + + + From + De + + + + + + To + A + + + + + own address + propia dirección + + + + label + etiqueta + + + + + + + + Credit + Credito + + + + matures in %n more block(s) + + + + + not accepted + no aceptada + + + + + + + Debit + Debito + + + + Transaction fee + Comisión transacción + + + + Net amount + Cantidad total + + + + Message + Mensaje + + + + Comment + Comentario + + + + Transaction ID + ID de Transacción + + + + Generated coins must mature 6 blocks before they can be spent. When you generated this block, it was broadcast to the network to be added to the block chain. If it fails to get into the chain, its state will change to "not accepted" and it won't be spendable. This may occasionally happen if another node generates a block within a few seconds of yours. + + + + + Debug information + + + + + Transaction + Transacción + + + + Inputs + + + + + Amount + Cantidad + + + + true + + + + + false + + + + + , has not been successfully broadcast yet + , no ha sido emitido satisfactoriamente todavía + + + + unknown + desconocido + + + + TransactionDescDialog + + + Transaction details + Detalles de transacción + + + + This pane shows a detailed description of the transaction + Esta ventana muestra información detallada sobre la transacción + + + + TransactionTableModel + + + Date + Fecha + + + + Type + Tipo + + + + Address + Dirección + + + + Amount + Cantidad + + + + Open until %1 + Abierto hasta %1 + + + + Confirmed (%1 confirmations) + Confirmado (%1 confirmaciones) + + + + Open for %n more block(s) + Abierto para &n bloque másAbierto para &n bloques más + + + + Offline + + + + + Unconfirmed + + + + + Confirming (%1 of %2 recommended confirmations) + + + + + Conflicted + + + + + Immature (%1 confirmations, will be available after %2) + + + + + This block was not received by any other nodes and will probably not be accepted! + Este bloque no ha sido recibido por otros nodos y probablemente no sea aceptado ! + + + + Generated but not accepted + Generado pero no acceptado + + + + Received with + Recibido con + + + + Received from + Recibido de + + + + Sent to + Enviado a + + + + Payment to yourself + Pagar a usted mismo + + + + Mined + Minado + + + + (n/a) + (n/a) + + + + Transaction status. Hover over this field to show number of confirmations. + Estado de transacción. Pasa el raton sobre este campo para ver el numero de confirmaciónes. + + + + Date and time that the transaction was received. + Fecha y hora cuando se recibió la transaccion + + + + Type of transaction. + Tipo de transacción. + + + + Destination address of transaction. + Dirección de destino para la transacción + + + + Amount removed from or added to balance. + Cantidad restada o añadida al balance + + + + TransactionView + + + + All + Todo + + + + Today + Hoy + + + + This week + Esta semana + + + + This month + Esta mes + + + + Last month + Mes pasado + + + + This year + Este año + + + + Range... + Rango... + + + + Received with + Recibido con + + + + Sent to + Enviado a + + + + To yourself + A ti mismo + + + + Mined + Minado + + + + Other + Otra + + + + Enter address or label to search + Introduce una dirección o etiqueta para buscar + + + + Min amount + Cantidad minima + + + + Copy address + Copia dirección + + + + Copy label + Copia etiqueta + + + + Copy amount + Copiar Cantidad + + + + Copy transaction ID + + + + + Edit label + Edita etiqueta + + + + Show transaction details + Mostrar detalles de la transacción + + + + Export Transaction Data + + + + + Comma separated file (*.csv) + Archivos separados por coma (*.csv) + + + + Confirmed + Confirmado + + + + Date + Fecha + + + + Type + Tipo + + + + Label + Etiqueta + + + + Address + Dirección + + + + Amount + Cantidad + + + + ID + ID + + + + Error exporting + + + + + Could not write to file %1. + + + + + Range: + Rango: + + + + to + para + + + + WalletModel + + + Sending... + + + + + bitcoin-core + + + Arepacoin version + + + + + Usage: + Uso: + + + + Send command to -server or arepacoind + + + + + List commands + Muestra comandos + + + + + Get help for a command + Recibir ayuda para un comando + + + + + Options: + Opciones: + + + + + Specify configuration file (default: arepacoin.conf) + + + + + Specify pid file (default: arepacoind.pid) + + + + + Specify wallet file (within data directory) + + + + + Specify data directory + Especifica directorio para los datos + + + + + Set database cache size in megabytes (default: 25) + Asigna el tamaño del caché de la base de datos en MB (25 predeterminado) + + + + Set database disk log size in megabytes (default: 100) + + + + + Listen for connections on <port> (default: 9853 or testnet: 19853) + + + + + Maintain at most <n> connections to peers (default: 125) + Mantener al menos <n> conecciones por cliente (por defecto: 125) + + + + Connect to a node to retrieve peer addresses, and disconnect + + + + + Specify your own public address + + + + + Bind to given address. Use [host]:port notation for IPv6 + + + + + Stake your coins to support network and gain reward (default: 1) + + + + + Threshold for disconnecting misbehaving peers (default: 100) + Umbral de desconección de clientes con mal comportamiento (por defecto: 100) + + + + Number of seconds to keep misbehaving peers from reconnecting (default: 86400) + + + + + An error occurred while setting up the RPC port %u for listening on IPv4: %s + + + + + Detach block and address databases. Increases shutdown time (default: 0) + + + + + 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. + + + + + Error: This transaction requires a transaction fee of at least %s because of its amount, complexity, or use of recently received funds + + + + + Listen for JSON-RPC connections on <port> (default: 9852 or testnet: 19852) + + + + + Accept command line and JSON-RPC commands + Aceptar comandos consola y JSON-RPC + + + + + Error: Transaction creation failed + + + + + Error: Wallet locked, unable to create transaction + + + + + Importing blockchain data file. + + + + + Importing bootstrap blockchain data file. + + + + + Run in the background as a daemon and accept commands + Correr como demonio y acepta comandos + + + + + Use the test network + Usa la red de pruebas + + + + + Accept connections from outside (default: 1 if no -proxy or -connect) + + + + + An error occurred while setting up the RPC port %u for listening on IPv6, falling back to IPv4: %s + + + + + Error initializing database environment %s! To recover, BACKUP THAT DIRECTORY, then remove everything from it except for wallet.dat. + + + + + Set maximum size of high-priority/low-fee transactions in bytes (default: 27000) + + + + + Warning: -paytxfee is set very high! This is the transaction fee you will pay if you send a transaction. + Precaución: -paytxfee es muy alta. Esta es la comisión que pagarás si envias una transacción. + + + + Warning: Please check that your computer's date and time are correct! If your clock is wrong Arepacoin will not work properly. + + + + + Warning: error reading wallet.dat! All keys read correctly, but transaction data or address book entries might be missing or incorrect. + + + + + Warning: wallet.dat corrupt, data salvaged! Original wallet.dat saved as wallet.{timestamp}.bak in %s; if your balance or transactions are incorrect you should restore from a backup. + + + + + Attempt to recover private keys from a corrupt wallet.dat + + + + + Block creation options: + + + + + Connect only to the specified node(s) + Conecta solo al nodo especificado + + + + + Discover own IP address (default: 1 when listening and no -externalip) + + + + + Failed to listen on any port. Use -listen=0 if you want this. + + + + + Find peers using DNS lookup (default: 1) + + + + + Sync checkpoints policy (default: strict) + + + + + Invalid -tor address: '%s' + + + + + Invalid amount for -reservebalance=<amount> + + + + + Maximum per-connection receive buffer, <n>*1000 bytes (default: 5000) + + + + + Maximum per-connection send buffer, <n>*1000 bytes (default: 1000) + + + + + Only connect to nodes in network <net> (IPv4, IPv6 or Tor) + + + + + Output extra debugging information. Implies all other -debug* options + + + + + Output extra network debugging information + + + + + Prepend debug output with timestamp + + + + + SSL options: (see the Bitcoin Wiki for SSL setup instructions) + Opciones SSL: (ver la Bitcoin Wiki para instrucciones de configuración SSL) + + + + Select the version of socks proxy to use (4-5, default: 5) + + + + + Send trace/debug info to console instead of debug.log file + Enviar informacion de seguimiento a la consola en vez del archivo debug.log + + + + Send trace/debug info to debugger + + + + + Set maximum block size in bytes (default: 250000) + + + + + Set minimum block size in bytes (default: 0) + Establezca el tamaño mínimo del bloque en bytes (por defecto: 0) + + + + Shrink debug.log file on client startup (default: 1 when no -debug) + + + + + Specify connection timeout in milliseconds (default: 5000) + Especifica tiempo de espera para conexion en milisegundos (predeterminado: 5000) + + + + Unable to sign checkpoint, wrong checkpointkey? + + + + + + Use UPnP to map the listening port (default: 0) + Intenta usar UPnP para mapear el puerto de escucha (default: 0) + + + + Use UPnP to map the listening port (default: 1 when listening) + Intenta usar UPnP para mapear el puerto de escucha (default: 1 when listening) + + + + Use proxy to reach tor hidden services (default: same as -proxy) + + + + + Username for JSON-RPC connections + Usuario para las conexiones JSON-RPC + + + + + Verifying database integrity... + + + + + WARNING: syncronized checkpoint violation detected, but skipped! + + + + + Warning: Disk space is low! + + + + + Warning: This version is obsolete, upgrade required! + Advertencia: Esta versión está obsoleta, se necesita actualizar! + + + + wallet.dat corrupt, salvage failed + wallet.dat corrompió, guardado fallido + + + + Password for JSON-RPC connections + Contraseña para las conexiones JSON-RPC + + + + + %s, you must set a rpcpassword in the configuration file: + %s +It is recommended you use the following random password: +rpcuser=arepacoinrpc +rpcpassword=%s +(you do not need to remember this password) +The username and password MUST NOT be the same. +If the file does not exist, create it with owner-readable-only file permissions. +It is also recommended to set alertnotify so you are notified of problems; +for example: alertnotify=echo %%s | mail -s "Arepacoin Alert" admin@foo.com + + + + + + Find peers using internet relay chat (default: 0) + + + + + Sync time with other nodes. Disable if time on your system is precise e.g. syncing with NTP (default: 1) + + + + + When creating transactions, ignore inputs with value less than this (default: 0.01) + + + + + Allow JSON-RPC connections from specified IP address + Permite conexiones JSON-RPC desde la dirección IP especificada + + + + + Send commands to node running on <ip> (default: 127.0.0.1) + Envia comando al nodo situado en <ip> (predeterminado: 127.0.0.1) + + + + + Execute command when the best block changes (%s in cmd is replaced by block hash) + + + + + Execute command when a wallet transaction changes (%s in cmd is replaced by TxID) + + + + + Require a confirmations for change (default: 0) + + + + + Enforce transaction scripts to use canonical PUSH operators (default: 1) + + + + + Execute command when a relevant alert is received (%s in cmd is replaced by message) + + + + + Upgrade wallet to latest format + Actualizar billetera al formato actual + + + + Set key pool size to <n> (default: 100) + Ajusta el numero de claves en reserva <n> (predeterminado: 100) + + + + + Rescan the block chain for missing wallet transactions + Rescanea la cadena de bloques para transacciones perdidas de la cartera + + + + + How many blocks to check at startup (default: 2500, 0 = all) + + + + + How thorough the block verification is (0-6, default: 1) + + + + + Imports blocks from external blk000?.dat file + + + + + Use OpenSSL (https) for JSON-RPC connections + Usa OpenSSL (https) para las conexiones JSON-RPC + + + + + Server certificate file (default: server.cert) + Certificado del servidor (Predeterminado: server.cert) + + + + + Server private key (default: server.pem) + Clave privada del servidor (Predeterminado: server.pem) + + + + + Acceptable ciphers (default: TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH) + + + + + Error: Wallet unlocked for staking only, unable to create transaction. + + + + + WARNING: Invalid checkpoint found! Displayed transactions may not be correct! You may need to upgrade, or notify developers. + + + + + This help message + Este mensaje de ayuda + + + + + Wallet %s resides outside data directory %s. + + + + + Cannot obtain a lock on data directory %s. Arepacoin is probably already running. + + + + + Arepacoin + + + + + Unable to bind to %s on this computer (bind returned error %d, %s) + No es posible escuchar en el %s en este ordenador (bind returned error %d, %s) + + + + Connect through socks proxy + + + + + Allow DNS lookups for -addnode, -seednode and -connect + Permite búsqueda DNS para addnode y connect + + + + + Loading addresses... + Cargando direcciónes... + + + + Error loading blkindex.dat + + + + + Error loading wallet.dat: Wallet corrupted + Error cargando wallet.dat: Billetera corrupta + + + + Error loading wallet.dat: Wallet requires newer version of Arepacoin + + + + + Wallet needed to be rewritten: restart Arepacoin to complete + + + + + Error loading wallet.dat + Error cargando wallet.dat + + + + Invalid -proxy address: '%s' + Dirección -proxy invalida: '%s' + + + + Unknown network specified in -onlynet: '%s' + + + + + Unknown -socks proxy version requested: %i + + + + + Cannot resolve -bind address: '%s' + + + + + Cannot resolve -externalip address: '%s' + + + + + Invalid amount for -paytxfee=<amount>: '%s' + Cantidad inválida para -paytxfee=<amount>: '%s' + + + + Error: could not start node + + + + + Sending... + + + + + Invalid amount + Cantidad inválida + + + + Insufficient funds + Fondos insuficientes + + + + Loading block index... + Cargando el index de bloques... + + + + Add a node to connect to and attempt to keep the connection open + Agrega un nodo para conectarse and attempt to keep the connection open + + + + Unable to bind to %s on this computer. Arepacoin is probably already running. + + + + + Fee per KB to add to transactions you send + + + + + Invalid amount for -mininput=<amount>: '%s' + + + + + Loading wallet... + Cargando cartera... + + + + Cannot downgrade wallet + + + + + Cannot initialize keypool + + + + + Cannot write default address + + + + + Rescanning... + Rescaneando... + + + + Done loading + Carga completa + + + + To use the %s option + Para utilizar la opción %s + + + + Error + Error + + + + You must set rpcpassword=<password> in the configuration file: +%s +If the file does not exist, create it with owner-readable-only file permissions. + + + + \ No newline at end of file diff --git a/src/qt/locale/bitcoin_es_DO.ts b/src/qt/locale/bitcoin_es_DO.ts new file mode 100755 index 0000000..ddc4d0f --- /dev/null +++ b/src/qt/locale/bitcoin_es_DO.ts @@ -0,0 +1,3324 @@ + + + AboutDialog + + + About Arepacoin + + + + + <b>Arepacoin</b> version + + + + + Copyright © 2009-2014 The Bitcoin developers +Copyright © 2012-2014 The NovaCoin developers +Copyright © 2014 The Arepacoin developers + + + + + +This is experimental software. + +Distributed under the MIT/X11 software license, see the accompanying file COPYING or http://www.opensource.org/licenses/mit-license.php. + +This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit (http://www.openssl.org/) and cryptographic software written by Eric Young (eay@cryptsoft.com) and UPnP software written by Thomas Bernard. + +Este es un software experimental. + +Distribuido bajo la licencia MIT/X11, vea el archivo adjunto +COPYING o http://www.opensource.org/licenses/mit-license.php. + +Este producto incluye software desarrollado por OpenSSL Project para su uso en +el OpenSSL Toolkit (http://www.openssl.org/) y software criptográfico escrito por +Eric Young (eay@cryptsoft.com) y el software UPnP escrito por Thomas Bernard. + + + + AddressBookPage + + + Address Book + + + + + Double-click to edit address or label + Haga doble clic para editar una dirección o etiqueta + + + + Create a new address + Crear una nueva dirección + + + + Copy the currently selected address to the system clipboard + Copiar la dirección seleccionada al portapapeles del sistema + + + + &New Address + + + + + These are your Arepacoin addresses for receiving payments. You may want to give a different one to each sender so you can keep track of who is paying you. + + + + + &Copy Address + &Copiar dirección + + + + Show &QR Code + + + + + Sign a message to prove you own a Arepacoin address + + + + + Sign &Message + + + + + Delete the currently selected address from the list + Borrar de la lista la dirección seleccionada + + + + Verify a message to ensure it was signed with a specified Arepacoin address + + + + + &Verify Message + + + + + &Delete + &Eliminar + + + + Copy &Label + Copiar &etiqueta + + + + &Edit + &Editar + + + + Export Address Book Data + + + + + Comma separated file (*.csv) + Archivos de columnas separadas por coma (*.csv) + + + + Error exporting + + + + + Could not write to file %1. + + + + + AddressTableModel + + + Label + Etiqueta + + + + Address + Dirección + + + + (no label) + (sin etiqueta) + + + + AskPassphraseDialog + + + Passphrase Dialog + Diálogo de contraseña + + + + Enter passphrase + Introducir contraseña + + + + New passphrase + Nueva contraseña + + + + Repeat new passphrase + Repita la nueva contraseña + + + + Serves to disable the trivial sendmoney when OS account compromised. Provides no real security. + + + + + For staking only + + + + + Enter the new passphrase to the wallet.<br/>Please use a passphrase of <b>10 or more random characters</b>, or <b>eight or more words</b>. + Introduzca la nueva contraseña de la cartera.<br/>Por favor elija una con <b>10 o más caracteres aleatorios</b>, u <b>ocho o más palabras</b>. + + + + Encrypt wallet + Cifrar la cartera + + + + This operation needs your wallet passphrase to unlock the wallet. + Esta operación requiere su contraseña para desbloquear la cartera + + + + Unlock wallet + Desbloquear cartera + + + + This operation needs your wallet passphrase to decrypt the wallet. + Esta operación requiere su contraseña para descifrar la cartera. + + + + Decrypt wallet + Descifrar la certare + + + + Change passphrase + Cambiar contraseña + + + + Enter the old and new passphrase to the wallet. + Introduzca la contraseña anterior de la cartera y la nueva. + + + + Confirm wallet encryption + Confirmar cifrado de la cartera + + + + Warning: If you encrypt your wallet and lose your passphrase, you will <b>LOSE ALL OF YOUR COINS</b>! + + + + + Are you sure you wish to encrypt your wallet? + ¿Seguro que desea cifrar su monedero? + + + + IMPORTANT: Any previous backups you have made of your wallet file should be replaced with the newly generated, encrypted wallet file. For security reasons, previous backups of the unencrypted wallet file will become useless as soon as you start using the new, encrypted wallet. + IMPORTANTE: Cualquier copia de seguridad que haya realizado previamente de su archivo de monedero debe reemplazarse con el nuevo archivo de monedero cifrado. Por razones de seguridad, las copias de seguridad previas del archivo de monedero no cifradas serán inservibles en cuanto comience a usar el nuevo monedero cifrado. + + + + + Warning: The Caps Lock key is on! + Aviso: ¡La tecla de bloqueo de mayúsculas está activada! + + + + + Wallet encrypted + Monedero cifrado + + + + Arepacoin will close now to finish the encryption process. Remember that encrypting your wallet cannot fully protect your coins from being stolen by malware infecting your computer. + + + + + + + + Wallet encryption failed + Ha fallado el cifrado del monedero + + + + Wallet encryption failed due to an internal error. Your wallet was not encrypted. + Ha fallado el cifrado del monedero debido a un error interno. El monedero no ha sido cifrado. + + + + + The supplied passphrases do not match. + Las contraseñas no coinciden. + + + + Wallet unlock failed + Ha fallado el desbloqueo del monedero + + + + + + The passphrase entered for the wallet decryption was incorrect. + La contraseña introducida para descifrar el monedero es incorrecta. + + + + Wallet decryption failed + Ha fallado el descifrado del monedero + + + + Wallet passphrase was successfully changed. + Se ha cambiado correctamente la contraseña del monedero. + + + + BitcoinGUI + + + Sign &message... + Firmar &mensaje... + + + + Synchronizing with network... + Sincronizando con la red… + + + + &Overview + &Vista general + + + + Show general overview of wallet + Mostrar vista general del monedero + + + + &Transactions + &Transacciones + + + + Browse transaction history + Examinar el historial de transacciones + + + + &Address Book + + + + + Edit the list of stored addresses and labels + + + + + &Receive coins + + + + + Show the list of addresses for receiving payments + + + + + &Send coins + + + + + E&xit + &Salir + + + + Quit application + Salir de la aplicación + + + + Show information about Arepacoin + + + + + About &Qt + Acerca de &Qt + + + + Show information about Qt + Mostrar información acerca de Qt + + + + &Options... + &Opciones... + + + + &Encrypt Wallet... + &Cifrar monedero… + + + + &Backup Wallet... + Copia de &respaldo del monedero... + + + + &Change Passphrase... + &Cambiar la contraseña… + + + + ~%n block(s) remaining + + + + + Processed %1 of %2 (estimated) blocks of transaction history. + Procesado %1 de %2 (estimado) bloques de historial de transacciones. + + + + Processed %1 blocks of transaction history. + Procesado %1 bloques de historial de transacciones. + + + + &Export... + + + + + Send coins to a Arepacoin address + + + + + Modify configuration options for Arepacoin + + + + + Export the data in the current tab to a file + + + + + Encrypt or decrypt wallet + + + + + Backup wallet to another location + Copia de seguridad del monedero en otra ubicación + + + + Change the passphrase used for wallet encryption + Cambiar la contraseña utilizada para el cifrado del monedero + + + + &Debug window + Ventana de &depuración + + + + Open debugging and diagnostic console + Abrir la consola de depuración y diagnóstico + + + + &Verify message... + &Verificar mensaje... + + + + Arepacoin + + + + + Wallet + Monedero + + + + &About Arepacoin + + + + + &Show / Hide + Mo&strar/ocultar + + + + Unlock wallet + + + + + &Lock Wallet + + + + + Lock wallet + + + + + &File + &Archivo + + + + &Settings + &Configuración + + + + &Help + A&yuda + + + + Tabs toolbar + Barra de pestañas + + + + Actions toolbar + + + + + + [testnet] + [testnet] + + + + + Arepacoin client + + + + + %n active connection(s) to Arepacoin network + + + + + Staking.<br>Your weight is %1<br>Network weight is %2<br>Expected time to earn reward is %3 + + + + + Not staking because wallet is locked + + + + + Not staking because wallet is offline + + + + + Not staking because wallet is syncing + + + + + Not staking because you don't have mature coins + + + + + %n second(s) ago + + + + + &Unlock Wallet... + + + + + %n minute(s) ago + + + + + %n hour(s) ago + + + + + %n day(s) ago + + + + + Up to date + Actualizado + + + + Catching up... + Actualizando... + + + + Last received block was generated %1. + + + + + This transaction is over the size limit. You can still send it for a fee of %1, which goes to the nodes that process your transaction and helps to support the network. Do you want to pay the fee? + + + + + Confirm transaction fee + + + + + Sent transaction + Transacción enviada + + + + Incoming transaction + Transacción entrante + + + + Date: %1 +Amount: %2 +Type: %3 +Address: %4 + + Fecha: %1 +Cantidad: %2 +Tipo: %3 +Dirección: %4 + + + + + + URI handling + + + + + + URI can not be parsed! This can be caused by an invalid Arepacoin address or malformed URI parameters. + + + + + Wallet is <b>encrypted</b> and currently <b>unlocked</b> + El monedero está <b>cifrado</b> y actualmente <b>desbloqueado</b> + + + + Wallet is <b>encrypted</b> and currently <b>locked</b> + El monedero está <b>cifrado</b> y actualmente <b>bloqueado</b> + + + + Backup Wallet + + + + + Wallet Data (*.dat) + + + + + Backup Failed + + + + + There was an error trying to save the wallet data to the new location. + + + + + %n second(s) + + + + + %n minute(s) + + + + + %n hour(s) + %n hora%n horas + + + + %n day(s) + %n día%n días + + + + %n week(s) + %n semana%n semanas + + + + %n year(s) + %n año%n años + + + + %1 behind + %1 detrás + + + + %1 and %2 + %1 y %2 + + + + Not staking + + + + + A fatal error occurred. Arepacoin can no longer continue safely and will quit. + + + + + ClientModel + + + Network Alert + Alerta de red + + + + CoinControlDialog + + + Coin Control + + + + + Quantity: + Cantidad: + + + + Bytes: + Bytes: + + + + Amount: + Cuantía: + + + + Priority: + Prioridad: + + + + Fee: + Tasa: + + + + Low Output: + Envío pequeño: + + + + no + no + + + + After Fee: + Después de tasas: + + + + Change: + Cambio: + + + + (un)select all + (des)selecciona todos + + + + Tree mode + Modo arbol + + + + List mode + Modo lista + + + + Amount + Cantidad + + + + Label + + + + + Address + Dirección + + + + Date + Fecha + + + + Confirmations + Confirmaciones + + + + Confirmed + Confirmado + + + + Priority + Prioridad + + + + Copy address + Copiar dirección + + + + Copy label + Copiar etiqueta + + + + + Copy amount + Copiar cantidad + + + + Copy transaction ID + Copiar identificador de transacción + + + + Copy quantity + Copiar cantidad + + + + Copy fee + Copiar donación + + + + Copy after fee + Copiar después de aplicar donación + + + + Copy bytes + Copiar bytes + + + + Copy priority + Copiar prioridad + + + + Copy low output + Copiar envío pequeño + + + + Copy change + Copiar cambio + + + + highest + lo más alto + + + + high + alto + + + + medium-high + medio-alto + + + + medium + medio + + + + low-medium + bajo-medio + + + + low + bajo + + + + lowest + lo más bajo + + + + DUST + + + + + yes + si + + + + This label turns red, if the transaction size is bigger than 10000 bytes. + + This means a fee of at least %1 per kb is required. + + Can vary +/- 1 Byte per input. + + + + + Transactions with higher priority get more likely into a block. + +This label turns red, if the priority is smaller than "medium". + + This means a fee of at least %1 per kb is required. + + + + + This label turns red, if any recipient receives an amount smaller than %1. + + This means a fee of at least %2 is required. + + Amounts below 0.546 times the minimum relay fee are shown as DUST. + + + + + This label turns red, if the change is smaller than %1. + + This means a fee of at least %2 is required. + + + + + + (no label) + (sin etiqueta) + + + + change from %1 (%2) + Enviar desde %1 (%2) + + + + (change) + (cambio) + + + + EditAddressDialog + + + Edit Address + Editar Dirección + + + + &Label + &Etiqueta + + + + The label associated with this address book entry + + + + + &Address + &Dirección + + + + The address associated with this address book entry. This can only be modified for sending addresses. + + + + + New receiving address + Nueva dirección de recepción + + + + New sending address + Nueva dirección de envío + + + + Edit receiving address + Editar dirección de recepción + + + + Edit sending address + Editar dirección de envío + + + + The entered address "%1" is already in the address book. + La dirección introducida "%1" ya está presente en la libreta de direcciones. + + + + The entered address "%1" is not a valid Arepacoin address. + + + + + Could not unlock wallet. + No se pudo desbloquear el monedero. + + + + New key generation failed. + Ha fallado la generación de la nueva clave. + + + + GUIUtil::HelpMessageBox + + + + Arepacoin-Qt + + + + + version + + + + + Usage: + + + + + command-line options + + + + + UI options + + + + + Set language, for example "de_DE" (default: system locale) + + + + + Start minimized + + + + + Show splash screen on startup (default: 1) + + + + + OptionsDialog + + + Options + Opciones + + + + &Main + &Principal + + + + Optional transaction fee per kB that helps make sure your transactions are processed quickly. Most transactions are 1 kB. Fee 0.01 recommended. + + + + + Pay transaction &fee + Comisión de &transacciones + + + + Reserved amount does not participate in staking and is therefore spendable at any time. + + + + + Reserve + + + + + Automatically start Arepacoin after logging in to the system. + + + + + &Start Arepacoin on system login + + + + + Detach block and address databases at shutdown. This means they can be moved to another data directory, but it slows down shutdown. The wallet is always detached. + + + + + &Detach databases at shutdown + + + + + &Network + &Red + + + + Automatically open the Arepacoin client port on the router. This only works when your router supports UPnP and it is enabled. + + + + + Map port using &UPnP + Mapear el puerto usando &UPnP + + + + Connect to the Arepacoin network through a SOCKS proxy (e.g. when connecting through Tor). + + + + + &Connect through SOCKS proxy: + + + + + Proxy &IP: + Dirección &IP del proxy: + + + + IP address of the proxy (e.g. 127.0.0.1) + + + + + &Port: + &Puerto: + + + + Port of the proxy (e.g. 9050) + Puerto del servidor proxy (ej. 9050) + + + + SOCKS &Version: + &Versión SOCKS: + + + + SOCKS version of the proxy (e.g. 5) + Versión del proxy SOCKS (ej. 5) + + + + &Window + &Ventana + + + + Show only a tray icon after minimizing the window. + Minimizar la ventana a la bandeja de iconos del sistema. + + + + &Minimize to the tray instead of the taskbar + &Minimizar a la bandeja en vez de a la barra de tareas + + + + Minimize instead of exit the application when the window is closed. When this option is enabled, the application will be closed only after selecting Quit in the menu. + Minimizar en lugar de salir de la aplicación al cerrar la ventana. Cuando esta opción está activa, la aplicación solo se puede cerrar seleccionando Salir desde el menú. + + + + M&inimize on close + M&inimizar al cerrar + + + + &Display + &Interfaz + + + + User Interface &language: + I&dioma de la interfaz de usuario + + + + The user interface language can be set here. This setting will take effect after restarting Arepacoin. + + + + + &Unit to show amounts in: + Mostrar las cantidades en la &unidad: + + + + Choose the default subdivision unit to show in the interface and when sending coins. + Elegir la subdivisión predeterminada para mostrar cantidades en la interfaz y cuando se envían monedas. + + + + Whether to show Arepacoin addresses in the transaction list or not. + + + + + &Display addresses in transaction list + &Mostrar las direcciones en la lista de transacciones + + + + Whether to show coin control features or not. + Mostrar o no características de control de moneda + + + + Display coin &control features (experts only!) + + + + + &OK + &Aceptar + + + + &Cancel + &Cancelar + + + + &Apply + + + + + default + predeterminado + + + + + Warning + + + + + + This setting will take effect after restarting Arepacoin. + + + + + The supplied proxy address is invalid. + La dirección proxy indicada es inválida. + + + + OverviewPage + + + Form + Desde + + + + + The displayed information may be out of date. Your wallet automatically synchronizes with the Arepacoin network after a connection is established, but this process has not completed yet. + + + + + Stake: + + + + + Unconfirmed: + No confirmado(s): + + + + Wallet + Monedero + + + + Spendable: + + + + + Your current spendable balance + Su balance actual gastable + + + + Immature: + No disponible: + + + + Mined balance that has not yet matured + Saldo recién minado que aún no está disponible. + + + + Total: + Total: + + + + Your current total balance + Su balance actual total + + + + <b>Recent transactions</b> + <b>Movimientos recientes</b> + + + + Total of transactions that have yet to be confirmed, and do not yet count toward the current balance + + + + + Total of coins that was staked, and do not yet count toward the current balance + + + + + + out of sync + desincronizado + + + + QRCodeDialog + + + QR Code Dialog + + + + + Request Payment + + + + + Amount: + + + + + Label: + + + + + Message: + + + + + &Save As... + + + + + Error encoding URI into QR Code. + + + + + The entered amount is invalid, please check. + + + + + Resulting URI too long, try to reduce the text for label / message. + + + + + Save QR Code + + + + + PNG Images (*.png) + + + + + RPCConsole + + + Client name + Nombre del cliente + + + + + + + + + + + + + N/A + N/D + + + + Client version + Versión del cliente + + + + &Information + &Información + + + + Using OpenSSL version + Utilizando la versión OpenSSL + + + + Startup time + Hora de inicio + + + + Network + Red + + + + Number of connections + Número de conexiones + + + + On testnet + + + + + Block chain + Cadena de bloques + + + + Current number of blocks + Número actual de bloques + + + + Estimated total blocks + Bloques totales estimados + + + + Last block time + Hora del último bloque + + + + &Open + &Abrir + + + + Command-line options + + + + + Show the Arepacoin-Qt help message to get a list with possible Arepacoin command-line options. + + + + + &Show + + + + + &Console + &Consola + + + + Build date + Fecha de compilación + + + + Arepacoin - Debug window + + + + + Arepacoin Core + + + + + Debug log file + Archivo de registro de depuración + + + + Open the Arepacoin debug log file from the current data directory. This can take a few seconds for large log files. + + + + + Clear console + Borrar consola + + + + Welcome to the Arepacoin RPC console. + + + + + Use up and down arrows to navigate history, and <b>Ctrl-L</b> to clear screen. + Use las flechas arriba y abajo para navegar por el historial y <b>Control+L</b> para limpiar la pantalla. + + + + Type <b>help</b> for an overview of available commands. + Escriba <b>help</b> para ver un resumen de los comandos disponibles. + + + + SendCoinsDialog + + + + + + + + + + Send Coins + Enviar monedas + + + + Coin Control Features + Características de control de la moneda + + + + Inputs... + Entradas... + + + + automatically selected + Seleccionado automaticamente + + + + Insufficient funds! + Fondos insuficientes! + + + + Quantity: + Cantidad: + + + + + 0 + + + + + Bytes: + Bytes: + + + + Amount: + Cuantía: + + + + + + + 0.00 BC + + + + + Priority: + Prioridad: + + + + medium + + + + + Fee: + Tasa: + + + + Low Output: + Envío pequeño: + + + + no + + + + + After Fee: + Después de tasas: + + + + Change + + + + + custom change address + + + + + Send to multiple recipients at once + Enviar a múltiples destinatarios de una vez + + + + Add &Recipient + Añadir &destinatario + + + + Remove all transaction fields + + + + + Clear &All + Limpiar &todo + + + + Balance: + Saldo: + + + + 123.456 BC + + + + + Confirm the send action + Confirmar el envío + + + + S&end + &Enviar + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Copy quantity + Copiar cantidad + + + + Copy amount + Copiar cuantía + + + + Copy fee + Copiar donación + + + + Copy after fee + Copiar después de aplicar donación + + + + Copy bytes + Copiar bytes + + + + Copy priority + Copiar prioridad + + + + Copy low output + Copiar envío pequeño + + + + Copy change + Copiar Cambio + + + + <b>%1</b> to %2 (%3) + + + + + Confirm send coins + Confirmar el envío de monedas + + + + Are you sure you want to send %1? + + + + + and + + + + + The recipient address is not valid, please recheck. + La dirección de recepción no es válida, compruébela de nuevo. + + + + The amount to pay must be larger than 0. + La cantidad por pagar tiene que ser mayor de 0. + + + + The amount exceeds your balance. + La cantidad sobrepasa su saldo. + + + + The total exceeds your balance when the %1 transaction fee is included. + El total sobrepasa su saldo cuando se incluye la tasa de envío de %1 + + + + Duplicate address found, can only send to each address once per send operation. + Se ha encontrado una dirección duplicada. Solo se puede enviar a cada dirección una vez por operación de envío. + + + + Error: Transaction creation failed. + + + + + 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. + + + + + WARNING: Invalid Arepacoin address + + + + + (no label) + (sin etiqueta) + + + + WARNING: unknown change address + + + + + SendCoinsEntry + + + Form + + + + + A&mount: + Ca&ntidad: + + + + Pay &To: + &Pagar a: + + + + + Enter a label for this address to add it to your address book + Etiquete esta dirección para añadirla a la libreta + + + + &Label: + &Etiqueta: + + + + The address to send the payment to (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Choose address from address book + + + + + Alt+A + Alt+A + + + + Paste address from clipboard + Pegar dirección desde portapapeles + + + + Alt+P + Alt+P + + + + Remove this recipient + + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + SignVerifyMessageDialog + + + Signatures - Sign / Verify a Message + Firmas - Firmar / verificar un mensaje + + + + + &Sign Message + &Firmar mensaje + + + + You can sign messages with your addresses to prove you own them. Be careful not to sign anything vague, as phishing attacks may try to trick you into signing your identity over to them. Only sign fully-detailed statements you agree to. + Puede firmar mensajes con sus direcciones para demostrar que las posee. Tenga cuidado de no firmar cualquier cosa vaga, ya que los ataques de phishing pueden tratar de engañarle para suplantar su identidad. Firme solo declaraciones totalmente detalladas con las que usted esté de acuerdo. + + + + The address to sign the message with (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + + Choose an address from the address book + + + + + + Alt+A + Alt+A + + + + Paste address from clipboard + Pegar dirección desde portapapeles + + + + Alt+P + Alt+P + + + + Enter the message you want to sign here + Introduzca el mensaje que desea firmar aquí + + + + Copy the current signature to the system clipboard + Copiar la firma actual al portapapeles del sistema + + + + Sign the message to prove you own this Arepacoin address + + + + + Reset all sign message fields + Limpiar todos los campos de la firma de mensaje + + + + + Clear &All + Limpiar &todo + + + + + &Verify Message + &Verificar mensaje + + + + Enter the signing address, message (ensure you copy line breaks, spaces, tabs, etc. exactly) and signature below to verify the message. Be careful not to read more into the signature than what is in the signed message itself, to avoid being tricked by a man-in-the-middle attack. + Introduzca la dirección para la firma, el mensaje (asegurándose de copiar tal cual los saltos de línea, espacios, tabulaciones, etc.) y la firma a continuación para verificar el mensaje. Tenga cuidado de no asumir más información de lo que dice el propio mensaje firmado para evitar fraudes basados en ataques de tipo man-in-the-middle. + + + + The address the message was signed with (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Verify the message to ensure it was signed with the specified Arepacoin address + + + + + Reset all verify message fields + Limpiar todos los campos de la verificación de mensaje + + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Click "Sign Message" to generate signature + Haga clic en "Firmar mensaje" para generar la firma + + + + Enter Arepacoin signature + + + + + + The entered address is invalid. + La dirección introducida es inválida. + + + + + + + Please check the address and try again. + Verifique la dirección e inténtelo de nuevo. + + + + + The entered address does not refer to a key. + La dirección introducida no corresponde a una clave. + + + + Wallet unlock was cancelled. + Se ha cancelado el desbloqueo del monedero. + + + + Private key for the entered address is not available. + No se dispone de la clave privada para la dirección introducida. + + + + Message signing failed. + Ha fallado la firma del mensaje. + + + + Message signed. + Mensaje firmado. + + + + The signature could not be decoded. + No se puede decodificar la firma. + + + + + Please check the signature and try again. + Compruebe la firma e inténtelo de nuevo. + + + + The signature did not match the message digest. + La firma no coincide con el resumen del mensaje. + + + + Message verification failed. + La verificación del mensaje ha fallado. + + + + Message verified. + Mensaje verificado. + + + + TransactionDesc + + + Open until %1 + Abierto hasta %1 + + + + Open for %n block(s) + + + + + conflicted + + + + + %1/offline + %1/fuera de línea + + + + %1/unconfirmed + %1/no confirmado + + + + %1 confirmations + %1 confirmaciones + + + + Status + Estado + + + + , broadcast through %n node(s) + , transmitir a través de %n nodo, transmitir a través de %n nodos + + + + Date + Fecha + + + + Source + Fuente + + + + Generated + Generado + + + + + From + De + + + + + + To + Para + + + + + own address + dirección propia + + + + label + etiqueta + + + + + + + + Credit + Crédito + + + + matures in %n more block(s) + disponible en %n bloque másdisponible en %n bloques más + + + + not accepted + no aceptada + + + + + + + Debit + Débito + + + + Transaction fee + Comisión de transacción + + + + Net amount + Cantidad neta + + + + Message + Mensaje + + + + Comment + Comentario + + + + Transaction ID + Identificador de transacción + + + + Generated coins must mature 6 blocks before they can be spent. When you generated this block, it was broadcast to the network to be added to the block chain. If it fails to get into the chain, its state will change to "not accepted" and it won't be spendable. This may occasionally happen if another node generates a block within a few seconds of yours. + + + + + Debug information + Información de depuración + + + + Transaction + Transacción + + + + Inputs + entradas + + + + Amount + Cantidad + + + + true + verdadero + + + + false + falso + + + + , has not been successfully broadcast yet + , todavía no se ha sido difundido satisfactoriamente + + + + unknown + desconocido + + + + TransactionDescDialog + + + Transaction details + Detalles de transacción + + + + This pane shows a detailed description of the transaction + Esta ventana muestra información detallada sobre la transacción + + + + TransactionTableModel + + + Date + Fecha + + + + Type + Tipo + + + + Address + Dirección + + + + Amount + Cantidad + + + + Open until %1 + Abierto hasta %1 + + + + Confirmed (%1 confirmations) + Confirmado (%1 confirmaciones) + + + + Open for %n more block(s) + Abrir para %n bloque másAbrir para %n bloques más + + + + Offline + + + + + Unconfirmed + + + + + Confirming (%1 of %2 recommended confirmations) + + + + + Conflicted + + + + + Immature (%1 confirmations, will be available after %2) + + + + + This block was not received by any other nodes and will probably not be accepted! + Este bloque no ha sido recibido por otros nodos y probablemente no sea aceptado! + + + + Generated but not accepted + Generado pero no aceptado + + + + Received with + Recibido con + + + + Received from + Recibidos de + + + + Sent to + Enviado a + + + + Payment to yourself + Pago propio + + + + Mined + Minado + + + + (n/a) + (nd) + + + + Transaction status. Hover over this field to show number of confirmations. + Estado de transacción. Pasa el ratón sobre este campo para ver el número de confirmaciones. + + + + Date and time that the transaction was received. + Fecha y hora en que se recibió la transacción. + + + + Type of transaction. + Tipo de transacción. + + + + Destination address of transaction. + Dirección de destino de la transacción. + + + + Amount removed from or added to balance. + Cantidad retirada o añadida al saldo. + + + + TransactionView + + + + All + Todo + + + + Today + Hoy + + + + This week + Esta semana + + + + This month + Este mes + + + + Last month + Mes pasado + + + + This year + Este año + + + + Range... + Rango... + + + + Received with + Recibido con + + + + Sent to + Enviado a + + + + To yourself + A usted mismo + + + + Mined + Minado + + + + Other + Otra + + + + Enter address or label to search + Introduzca una dirección o etiqueta que buscar + + + + Min amount + Cantidad mínima + + + + Copy address + Copiar dirección + + + + Copy label + Copiar etiqueta + + + + Copy amount + Copiar cuantía + + + + Copy transaction ID + Copiar identificador de transacción + + + + Edit label + Editar etiqueta + + + + Show transaction details + Mostrar detalles de la transacción + + + + Export Transaction Data + + + + + Comma separated file (*.csv) + Archivos de columnas separadas por coma (*.csv) + + + + Confirmed + Confirmado + + + + Date + Fecha + + + + Type + Tipo + + + + Label + Etiqueta + + + + Address + Dirección + + + + Amount + Cantidad + + + + ID + ID + + + + Error exporting + + + + + Could not write to file %1. + + + + + Range: + Rango: + + + + to + para + + + + WalletModel + + + Sending... + + + + + bitcoin-core + + + Arepacoin version + + + + + Usage: + Uso: + + + + Send command to -server or arepacoind + + + + + List commands + Muestra comandos + + + + + Get help for a command + Recibir ayuda para un comando + + + + + Options: + Opciones: + + + + + Specify configuration file (default: arepacoin.conf) + + + + + Specify pid file (default: arepacoind.pid) + + + + + Specify wallet file (within data directory) + Especificar archivo de monedero (dentro del directorio de datos) + + + + Specify data directory + Especificar directorio para los datos + + + + Set database cache size in megabytes (default: 25) + Establecer el tamaño de caché de la base de datos en megabytes (predeterminado: 25) + + + + Set database disk log size in megabytes (default: 100) + + + + + Listen for connections on <port> (default: 9853 or testnet: 19853) + + + + + Maintain at most <n> connections to peers (default: 125) + Mantener como máximo <n> conexiones a pares (predeterminado: 125) + + + + Connect to a node to retrieve peer addresses, and disconnect + Conectar a un nodo para obtener direcciones de pares y desconectar + + + + Specify your own public address + Especifique su propia dirección pública + + + + Bind to given address. Use [host]:port notation for IPv6 + + + + + Stake your coins to support network and gain reward (default: 1) + + + + + Threshold for disconnecting misbehaving peers (default: 100) + Umbral para la desconexión de pares con mal comportamiento (predeterminado: 100) + + + + Number of seconds to keep misbehaving peers from reconnecting (default: 86400) + Número de segundos en que se evita la reconexión de pares con mal comportamiento (predeterminado: 86400) + + + + An error occurred while setting up the RPC port %u for listening on IPv4: %s + Ha ocurrido un error al configurar el puerto RPC %u para escucha en IPv4: %s + + + + Detach block and address databases. Increases shutdown time (default: 0) + + + + + 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. + + + + + Error: This transaction requires a transaction fee of at least %s because of its amount, complexity, or use of recently received funds + + + + + Listen for JSON-RPC connections on <port> (default: 9852 or testnet: 19852) + + + + + Accept command line and JSON-RPC commands + Aceptar comandos consola y JSON-RPC + + + + + Error: Transaction creation failed + + + + + Error: Wallet locked, unable to create transaction + + + + + Importing blockchain data file. + + + + + Importing bootstrap blockchain data file. + + + + + Run in the background as a daemon and accept commands + Ejecutar en segundo plano como daemon y aceptar comandos + + + + + Use the test network + Usar la red de pruebas + + + + + Accept connections from outside (default: 1 if no -proxy or -connect) + Aceptar conexiones desde el exterior (predeterminado: 1 si no -proxy o -connect) + + + + An error occurred while setting up the RPC port %u for listening on IPv6, falling back to IPv4: %s + Ha ocurrido un error al configurar el puerto RPC %u para escuchar mediante IPv6. Recurriendo a IPv4: %s + + + + Error initializing database environment %s! To recover, BACKUP THAT DIRECTORY, then remove everything from it except for wallet.dat. + + + + + Set maximum size of high-priority/low-fee transactions in bytes (default: 27000) + + + + + Warning: -paytxfee is set very high! This is the transaction fee you will pay if you send a transaction. + Aviso: ¡-paytxfee tiene un valor muy alto! Esta es la comisión que pagará si envía una transacción. + + + + Warning: Please check that your computer's date and time are correct! If your clock is wrong Arepacoin will not work properly. + + + + + Warning: error reading wallet.dat! All keys read correctly, but transaction data or address book entries might be missing or incorrect. + Aviso: ¡Error al leer wallet.dat! Todas las claves se han leído correctamente, pero podrían faltar o ser incorrectos los datos de transacciones o las entradas de la libreta de direcciones. + + + + Warning: wallet.dat corrupt, data salvaged! Original wallet.dat saved as wallet.{timestamp}.bak in %s; if your balance or transactions are incorrect you should restore from a backup. + Aviso: ¡Recuperados datos de wallet.dat corrupto! El wallet.dat original se ha guardado como wallet.{timestamp}.bak en %s; si hubiera errores en su saldo o transacciones, deberá restaurar una copia de seguridad. + + + + Attempt to recover private keys from a corrupt wallet.dat + Intento de recuperar claves privadas de un wallet.dat corrupto + + + + Block creation options: + Opciones de creación de bloques: + + + + Connect only to the specified node(s) + Conectar sólo a los nodos (o nodo) especificados + + + + Discover own IP address (default: 1 when listening and no -externalip) + Descubrir dirección IP propia (predeterminado: 1 al escuchar sin -externalip) + + + + Failed to listen on any port. Use -listen=0 if you want this. + Ha fallado la escucha en todos los puertos. Use -listen=0 si desea esto. + + + + Find peers using DNS lookup (default: 1) + + + + + Sync checkpoints policy (default: strict) + + + + + Invalid -tor address: '%s' + + + + + Invalid amount for -reservebalance=<amount> + + + + + Maximum per-connection receive buffer, <n>*1000 bytes (default: 5000) + Búfer de recepción máximo por conexión, <n>*1000 bytes (predeterminado: 5000) + + + + Maximum per-connection send buffer, <n>*1000 bytes (default: 1000) + Búfer de recepción máximo por conexión, , <n>*1000 bytes (predeterminado: 1000) + + + + Only connect to nodes in network <net> (IPv4, IPv6 or Tor) + Conectarse solo a nodos de la red <net> (IPv4, IPv6 o Tor) + + + + Output extra debugging information. Implies all other -debug* options + + + + + Output extra network debugging information + + + + + Prepend debug output with timestamp + + + + + SSL options: (see the Bitcoin Wiki for SSL setup instructions) + Opciones SSL: (ver la Bitcoin Wiki para instrucciones de configuración SSL) + + + + Select the version of socks proxy to use (4-5, default: 5) + + + + + Send trace/debug info to console instead of debug.log file + Enviar información de trazas/depuración a la consola en lugar de al archivo debug.log + + + + Send trace/debug info to debugger + + + + + Set maximum block size in bytes (default: 250000) + + + + + Set minimum block size in bytes (default: 0) + Establecer tamaño mínimo de bloque en bytes (predeterminado: 0) + + + + Shrink debug.log file on client startup (default: 1 when no -debug) + Reducir el archivo debug.log al iniciar el cliente (predeterminado: 1 sin -debug) + + + + Specify connection timeout in milliseconds (default: 5000) + Especificar el tiempo máximo de conexión en milisegundos (predeterminado: 5000) + + + + Unable to sign checkpoint, wrong checkpointkey? + + + + + + Use UPnP to map the listening port (default: 0) + Usar UPnP para asignar el puerto de escucha (predeterminado: 0) + + + + Use UPnP to map the listening port (default: 1 when listening) + Usar UPnP para asignar el puerto de escucha (predeterminado: 1 al escuchar) + + + + Use proxy to reach tor hidden services (default: same as -proxy) + + + + + Username for JSON-RPC connections + Nombre de usuario para las conexiones JSON-RPC + + + + + Verifying database integrity... + + + + + WARNING: syncronized checkpoint violation detected, but skipped! + + + + + Warning: Disk space is low! + + + + + Warning: This version is obsolete, upgrade required! + Aviso: Esta versión es obsoleta, actualización necesaria! + + + + wallet.dat corrupt, salvage failed + wallet.dat corrupto. Ha fallado la recuperación. + + + + Password for JSON-RPC connections + Contraseña para las conexiones JSON-RPC + + + + + %s, you must set a rpcpassword in the configuration file: + %s +It is recommended you use the following random password: +rpcuser=arepacoinrpc +rpcpassword=%s +(you do not need to remember this password) +The username and password MUST NOT be the same. +If the file does not exist, create it with owner-readable-only file permissions. +It is also recommended to set alertnotify so you are notified of problems; +for example: alertnotify=echo %%s | mail -s "Arepacoin Alert" admin@foo.com + + + + + + Find peers using internet relay chat (default: 0) + + + + + Sync time with other nodes. Disable if time on your system is precise e.g. syncing with NTP (default: 1) + + + + + When creating transactions, ignore inputs with value less than this (default: 0.01) + + + + + Allow JSON-RPC connections from specified IP address + Permitir conexiones JSON-RPC desde la dirección IP especificada + + + + + Send commands to node running on <ip> (default: 127.0.0.1) + Enviar comando al nodo situado en <ip> (predeterminado: 127.0.0.1) + + + + + Execute command when the best block changes (%s in cmd is replaced by block hash) + Ejecutar un comando cuando cambia el mejor bloque (%s en cmd se sustituye por el hash de bloque) + + + + Execute command when a wallet transaction changes (%s in cmd is replaced by TxID) + Ejecutar comando cuando una transacción del monedero cambia (%s en cmd se remplazará por TxID) + + + + Require a confirmations for change (default: 0) + + + + + Enforce transaction scripts to use canonical PUSH operators (default: 1) + + + + + Execute command when a relevant alert is received (%s in cmd is replaced by message) + + + + + Upgrade wallet to latest format + Actualizar el monedero al último formato + + + + Set key pool size to <n> (default: 100) + Ajustar el número de claves en reserva <n> (predeterminado: 100) + + + + + Rescan the block chain for missing wallet transactions + Volver a examinar la cadena de bloques en busca de transacciones del monedero perdidas + + + + How many blocks to check at startup (default: 2500, 0 = all) + + + + + How thorough the block verification is (0-6, default: 1) + + + + + Imports blocks from external blk000?.dat file + + + + + Use OpenSSL (https) for JSON-RPC connections + Usar OpenSSL (https) para las conexiones JSON-RPC + + + + + Server certificate file (default: server.cert) + Certificado del servidor (predeterminado: server.cert) + + + + + Server private key (default: server.pem) + Clave privada del servidor (predeterminado: server.pem) + + + + + Acceptable ciphers (default: TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH) + + + + + Error: Wallet unlocked for staking only, unable to create transaction. + + + + + WARNING: Invalid checkpoint found! Displayed transactions may not be correct! You may need to upgrade, or notify developers. + + + + + This help message + Este mensaje de ayuda + + + + + Wallet %s resides outside data directory %s. + + + + + Cannot obtain a lock on data directory %s. Arepacoin is probably already running. + + + + + Arepacoin + + + + + Unable to bind to %s on this computer (bind returned error %d, %s) + No es posible conectar con %s en este sistema (bind ha dado el error %d, %s) + + + + Connect through socks proxy + + + + + Allow DNS lookups for -addnode, -seednode and -connect + Permitir búsquedas DNS para -addnode, -seednode y -connect + + + + Loading addresses... + Cargando direcciones... + + + + Error loading blkindex.dat + + + + + Error loading wallet.dat: Wallet corrupted + Error al cargar wallet.dat: el monedero está dañado + + + + Error loading wallet.dat: Wallet requires newer version of Arepacoin + + + + + Wallet needed to be rewritten: restart Arepacoin to complete + + + + + Error loading wallet.dat + Error al cargar wallet.dat + + + + Invalid -proxy address: '%s' + Dirección -proxy inválida: '%s' + + + + Unknown network specified in -onlynet: '%s' + La red especificada en -onlynet '%s' es desconocida + + + + Unknown -socks proxy version requested: %i + Solicitada versión de proxy -socks desconocida: %i + + + + Cannot resolve -bind address: '%s' + No se puede resolver la dirección de -bind: '%s' + + + + Cannot resolve -externalip address: '%s' + No se puede resolver la dirección de -externalip: '%s' + + + + Invalid amount for -paytxfee=<amount>: '%s' + Cantidad inválida para -paytxfee=<amount>: '%s' + + + + Error: could not start node + + + + + Sending... + + + + + Invalid amount + Cuantía no válida + + + + Insufficient funds + Fondos insuficientes + + + + Loading block index... + Cargando el índice de bloques... + + + + Add a node to connect to and attempt to keep the connection open + Añadir un nodo al que conectarse y tratar de mantener la conexión abierta + + + + Unable to bind to %s on this computer. Arepacoin is probably already running. + + + + + Fee per KB to add to transactions you send + + + + + Invalid amount for -mininput=<amount>: '%s' + + + + + Loading wallet... + Cargando monedero... + + + + Cannot downgrade wallet + No se puede rebajar el monedero + + + + Cannot initialize keypool + + + + + Cannot write default address + No se puede escribir la dirección predeterminada + + + + Rescanning... + Reexplorando... + + + + Done loading + Generado pero no aceptado + + + + To use the %s option + Para utilizar la opción %s + + + + Error + Error + + + + You must set rpcpassword=<password> in the configuration file: +%s +If the file does not exist, create it with owner-readable-only file permissions. + Tiene que establecer rpcpassword=<contraseña> en el fichero de configuración: ⏎ +%s ⏎ +Si el archivo no existe, créelo con permiso de lectura solamente del propietario. + + + \ No newline at end of file diff --git a/src/qt/locale/bitcoin_es_MX.ts b/src/qt/locale/bitcoin_es_MX.ts new file mode 100755 index 0000000..361a034 --- /dev/null +++ b/src/qt/locale/bitcoin_es_MX.ts @@ -0,0 +1,3297 @@ + + + AboutDialog + + + About Arepacoin + + + + + <b>Arepacoin</b> version + + + + + Copyright © 2009-2014 The Bitcoin developers +Copyright © 2012-2014 The NovaCoin developers +Copyright © 2014 The Arepacoin developers + + + + + +This is experimental software. + +Distributed under the MIT/X11 software license, see the accompanying file COPYING or http://www.opensource.org/licenses/mit-license.php. + +This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit (http://www.openssl.org/) and cryptographic software written by Eric Young (eay@cryptsoft.com) and UPnP software written by Thomas Bernard. + + + + + AddressBookPage + + + Address Book + + + + + Double-click to edit address or label + Haga doble clic para editar el domicilio o la etiqueta + + + + Create a new address + Crear una dirección nueva + + + + Copy the currently selected address to the system clipboard + Copiar el domicilio seleccionado al portapapeles del sistema + + + + &New Address + + + + + These are your Arepacoin addresses for receiving payments. You may want to give a different one to each sender so you can keep track of who is paying you. + + + + + &Copy Address + + + + + Show &QR Code + + + + + Sign a message to prove you own a Arepacoin address + + + + + Sign &Message + + + + + Delete the currently selected address from the list + + + + + Verify a message to ensure it was signed with a specified Arepacoin address + + + + + &Verify Message + + + + + &Delete + &Borrar + + + + Copy &Label + + + + + &Edit + + + + + Export Address Book Data + + + + + Comma separated file (*.csv) + Archivo separado por comas (*.CSV) + + + + Error exporting + + + + + Could not write to file %1. + + + + + AddressTableModel + + + Label + Etiqueta + + + + Address + Domicilio + + + + (no label) + (sin etiqueta) + + + + AskPassphraseDialog + + + Passphrase Dialog + + + + + Enter passphrase + Ingrese la contraseña + + + + New passphrase + Nueva contraseña + + + + Repeat new passphrase + Repita la nueva contraseña + + + + Serves to disable the trivial sendmoney when OS account compromised. Provides no real security. + + + + + For staking only + + + + + Enter the new passphrase to the wallet.<br/>Please use a passphrase of <b>10 or more random characters</b>, or <b>eight or more words</b>. + Ingrese la nueva contraseña a la cartera<br/>Por favor use una contraseña de<b>10 o más caracteres aleatorios</b> o <b>ocho o más palabras</b>. + + + + Encrypt wallet + Cartera encriptada. + + + + This operation needs your wallet passphrase to unlock the wallet. + Esta operación necesita la contraseña de su cartera para desbloquear su cartera. + + + + Unlock wallet + Desbloquear cartera. + + + + This operation needs your wallet passphrase to decrypt the wallet. + Esta operación necesita la contraseña de su cartera para desencriptar su cartera. + + + + Decrypt wallet + Desencriptar la cartera + + + + Change passphrase + Cambiar contraseña + + + + Enter the old and new passphrase to the wallet. + Ingrese la antugüa y nueva contraseña de la cartera + + + + Confirm wallet encryption + Confirmar la encriptación de cartera + + + + Warning: If you encrypt your wallet and lose your passphrase, you will <b>LOSE ALL OF YOUR COINS</b>! + + + + + Are you sure you wish to encrypt your wallet? + + + + + IMPORTANT: Any previous backups you have made of your wallet file should be replaced with the newly generated, encrypted wallet file. For security reasons, previous backups of the unencrypted wallet file will become useless as soon as you start using the new, encrypted wallet. + + + + + + Warning: The Caps Lock key is on! + + + + + + Wallet encrypted + Cartera encriptada + + + + Arepacoin will close now to finish the encryption process. Remember that encrypting your wallet cannot fully protect your coins from being stolen by malware infecting your computer. + + + + + + + + Wallet encryption failed + La encriptación de la cartera falló + + + + Wallet encryption failed due to an internal error. Your wallet was not encrypted. + La encriptación de la cartera falló debido a un error interno. Su cartera no fue encriptada. + + + + + The supplied passphrases do not match. + Las contraseñas dadas no coinciden + + + + Wallet unlock failed + El desbloqueo de la cartera Fallo + + + + + + The passphrase entered for the wallet decryption was incorrect. + La contraseña ingresada para la des encriptación de la cartera es incorrecto + + + + Wallet decryption failed + La desencriptación de la cartera fallo + + + + Wallet passphrase was successfully changed. + + + + + BitcoinGUI + + + Sign &message... + + + + + Synchronizing with network... + Sincronizando con la red... + + + + &Overview + &Vista previa + + + + Show general overview of wallet + Mostrar la vista previa general de la cartera + + + + &Transactions + &Transacciones + + + + Browse transaction history + Explorar el historial de transacciones + + + + &Address Book + + + + + Edit the list of stored addresses and labels + + + + + &Receive coins + + + + + Show the list of addresses for receiving payments + + + + + &Send coins + + + + + E&xit + S&alir + + + + Quit application + Salir de la aplicación + + + + Show information about Arepacoin + + + + + About &Qt + + + + + Show information about Qt + + + + + &Options... + &Opciones + + + + &Encrypt Wallet... + + + + + &Backup Wallet... + + + + + &Change Passphrase... + + + + + ~%n block(s) remaining + + + + + Processed %1 of %2 (estimated) blocks of transaction history. + Procesado %1 de %2 (estimado) bloques de historial de transacciones. + + + + Processed %1 blocks of transaction history. + Procesado %1 bloques de historial de transacciones. + + + + &Export... + + + + + Send coins to a Arepacoin address + + + + + Modify configuration options for Arepacoin + + + + + Export the data in the current tab to a file + + + + + Encrypt or decrypt wallet + + + + + Backup wallet to another location + + + + + Change the passphrase used for wallet encryption + Cambiar la contraseña usada para la encriptación de la cartera + + + + &Debug window + + + + + Open debugging and diagnostic console + + + + + &Verify message... + + + + + Arepacoin + + + + + Wallet + + + + + &About Arepacoin + + + + + &Show / Hide + + + + + Unlock wallet + + + + + &Lock Wallet + + + + + Lock wallet + + + + + &File + &Archivo + + + + &Settings + &Configuraciones + + + + &Help + &Ayuda + + + + Tabs toolbar + Pestañas + + + + Actions toolbar + + + + + + [testnet] + + + + + + Arepacoin client + + + + + %n active connection(s) to Arepacoin network + + + + + + + Staking.<br>Your weight is %1<br>Network weight is %2<br>Expected time to earn reward is %3 + + + + + Not staking because wallet is locked + + + + + Not staking because wallet is offline + + + + + Not staking because wallet is syncing + + + + + Not staking because you don't have mature coins + + + + + %n second(s) ago + + + + + &Unlock Wallet... + + + + + %n minute(s) ago + + + + + %n hour(s) ago + + + + + %n day(s) ago + + + + + Up to date + Actualizado al dia + + + + Catching up... + Resiviendo... + + + + Last received block was generated %1. + + + + + This transaction is over the size limit. You can still send it for a fee of %1, which goes to the nodes that process your transaction and helps to support the network. Do you want to pay the fee? + + + + + Confirm transaction fee + + + + + Sent transaction + Enviar Transacción + + + + Incoming transaction + Transacción entrante + + + + Date: %1 +Amount: %2 +Type: %3 +Address: %4 + + + + + + + URI handling + + + + + + URI can not be parsed! This can be caused by an invalid Arepacoin address or malformed URI parameters. + + + + + Wallet is <b>encrypted</b> and currently <b>unlocked</b> + La cartera esta <b>encriptada</b> y <b>desbloqueada</b> actualmente + + + + Wallet is <b>encrypted</b> and currently <b>locked</b> + La cartera esta <b>encriptada</b> y <b>bloqueada</b> actualmente + + + + Backup Wallet + + + + + Wallet Data (*.dat) + + + + + Backup Failed + + + + + There was an error trying to save the wallet data to the new location. + + + + + %n second(s) + + + + + %n minute(s) + + + + + %n hour(s) + + + + + %n day(s) + + + + + %n week(s) + %n semana%n semanas + + + + %n year(s) + %n año%n años + + + + %1 behind + %1 detrás + + + + %1 and %2 + %1 y %2 + + + + Not staking + + + + + A fatal error occurred. Arepacoin can no longer continue safely and will quit. + + + + + ClientModel + + + Network Alert + + + + + CoinControlDialog + + + Coin Control + + + + + Quantity: + + + + + Bytes: + Bytes: + + + + Amount: + Monto: + + + + Priority: + Prioridad: + + + + Fee: + Cuota: + + + + Low Output: + + + + + no + + + + + After Fee: + + + + + Change: + + + + + (un)select all + + + + + Tree mode + + + + + List mode + + + + + Amount + Monto + + + + Label + + + + + Address + Domicilio + + + + Date + Fecha + + + + Confirmations + + + + + Confirmed + Confirmado + + + + Priority + + + + + Copy address + Copiar dirección + + + + Copy label + Copiar capa + + + + + Copy amount + copiar monto + + + + Copy transaction ID + + + + + Copy quantity + copiar cantidad + + + + Copy fee + copiar cuota + + + + Copy after fee + copiar despues de cuota + + + + Copy bytes + copiar bytes + + + + Copy priority + copiar prioridad + + + + Copy low output + + + + + Copy change + copiar cambio + + + + highest + + + + + high + + + + + medium-high + + + + + medium + + + + + low-medium + + + + + low + + + + + lowest + + + + + DUST + + + + + yes + + + + + This label turns red, if the transaction size is bigger than 10000 bytes. + + This means a fee of at least %1 per kb is required. + + Can vary +/- 1 Byte per input. + + + + + Transactions with higher priority get more likely into a block. + +This label turns red, if the priority is smaller than "medium". + + This means a fee of at least %1 per kb is required. + + + + + This label turns red, if any recipient receives an amount smaller than %1. + + This means a fee of at least %2 is required. + + Amounts below 0.546 times the minimum relay fee are shown as DUST. + + + + + This label turns red, if the change is smaller than %1. + + This means a fee of at least %2 is required. + + + + + + (no label) + (sin etiqueta) + + + + change from %1 (%2) + + + + + (change) + + + + + EditAddressDialog + + + Edit Address + Editar dirección + + + + &Label + &Etiqueta + + + + The label associated with this address book entry + + + + + &Address + &Dirección + + + + The address associated with this address book entry. This can only be modified for sending addresses. + + + + + New receiving address + Nueva dirección de entregas + + + + New sending address + Nueva dirección de entregas + + + + Edit receiving address + Editar dirección de entregas + + + + Edit sending address + Editar dirección de envios + + + + The entered address "%1" is already in the address book. + El domicilio ingresado "%1" ya existe en la libreta de direcciones + + + + The entered address "%1" is not a valid Arepacoin address. + + + + + Could not unlock wallet. + No se puede desbloquear la cartera + + + + New key generation failed. + La generación de la nueva clave fallo + + + + GUIUtil::HelpMessageBox + + + + Arepacoin-Qt + + + + + version + + + + + Usage: + + + + + command-line options + + + + + UI options + + + + + Set language, for example "de_DE" (default: system locale) + + + + + Start minimized + + + + + Show splash screen on startup (default: 1) + + + + + OptionsDialog + + + Options + Opciones + + + + &Main + + + + + Optional transaction fee per kB that helps make sure your transactions are processed quickly. Most transactions are 1 kB. Fee 0.01 recommended. + + + + + Pay transaction &fee + + + + + Reserved amount does not participate in staking and is therefore spendable at any time. + + + + + Reserve + + + + + Automatically start Arepacoin after logging in to the system. + + + + + &Start Arepacoin on system login + + + + + Detach block and address databases at shutdown. This means they can be moved to another data directory, but it slows down shutdown. The wallet is always detached. + + + + + &Detach databases at shutdown + + + + + &Network + + + + + Automatically open the Arepacoin client port on the router. This only works when your router supports UPnP and it is enabled. + + + + + Map port using &UPnP + + + + + Connect to the Arepacoin network through a SOCKS proxy (e.g. when connecting through Tor). + + + + + &Connect through SOCKS proxy: + + + + + Proxy &IP: + + + + + IP address of the proxy (e.g. 127.0.0.1) + + + + + &Port: + + + + + Port of the proxy (e.g. 9050) + + + + + SOCKS &Version: + + + + + SOCKS version of the proxy (e.g. 5) + + + + + &Window + + + + + Show only a tray icon after minimizing the window. + + + + + &Minimize to the tray instead of the taskbar + + + + + Minimize instead of exit the application when the window is closed. When this option is enabled, the application will be closed only after selecting Quit in the menu. + + + + + M&inimize on close + + + + + &Display + + + + + User Interface &language: + + + + + The user interface language can be set here. This setting will take effect after restarting Arepacoin. + + + + + &Unit to show amounts in: + + + + + Choose the default subdivision unit to show in the interface and when sending coins. + + + + + Whether to show Arepacoin addresses in the transaction list or not. + + + + + &Display addresses in transaction list + + + + + Whether to show coin control features or not. + + + + + Display coin &control features (experts only!) + + + + + &OK + + + + + &Cancel + + + + + &Apply + + + + + default + + + + + + Warning + + + + + + This setting will take effect after restarting Arepacoin. + + + + + The supplied proxy address is invalid. + + + + + OverviewPage + + + Form + Formulario + + + + + The displayed information may be out of date. Your wallet automatically synchronizes with the Arepacoin network after a connection is established, but this process has not completed yet. + + + + + Stake: + + + + + Unconfirmed: + + + + + Wallet + + + + + Spendable: + + + + + Your current spendable balance + + + + + Immature: + + + + + Mined balance that has not yet matured + + + + + Total: + + + + + Your current total balance + + + + + <b>Recent transactions</b> + <b>Transacciones recientes</b> + + + + Total of transactions that have yet to be confirmed, and do not yet count toward the current balance + + + + + Total of coins that was staked, and do not yet count toward the current balance + + + + + + out of sync + + + + + QRCodeDialog + + + QR Code Dialog + + + + + Request Payment + + + + + Amount: + + + + + Label: + + + + + Message: + + + + + &Save As... + + + + + Error encoding URI into QR Code. + + + + + The entered amount is invalid, please check. + + + + + Resulting URI too long, try to reduce the text for label / message. + + + + + Save QR Code + + + + + PNG Images (*.png) + + + + + RPCConsole + + + Client name + + + + + + + + + + + + + + N/A + + + + + Client version + + + + + &Information + + + + + Using OpenSSL version + + + + + Startup time + + + + + Network + + + + + Number of connections + + + + + On testnet + + + + + Block chain + + + + + Current number of blocks + + + + + Estimated total blocks + + + + + Last block time + + + + + &Open + + + + + Command-line options + + + + + Show the Arepacoin-Qt help message to get a list with possible Arepacoin command-line options. + + + + + &Show + + + + + &Console + + + + + Build date + + + + + Arepacoin - Debug window + + + + + Arepacoin Core + + + + + Debug log file + + + + + Open the Arepacoin debug log file from the current data directory. This can take a few seconds for large log files. + + + + + Clear console + + + + + Welcome to the Arepacoin RPC console. + + + + + Use up and down arrows to navigate history, and <b>Ctrl-L</b> to clear screen. + + + + + Type <b>help</b> for an overview of available commands. + + + + + SendCoinsDialog + + + + + + + + + + Send Coins + Mandar monedas + + + + Coin Control Features + + + + + Inputs... + + + + + automatically selected + + + + + Insufficient funds! + + + + + Quantity: + + + + + + 0 + + + + + Bytes: + Bytes: + + + + Amount: + Monto: + + + + + + + 0.00 BC + + + + + Priority: + Prioridad: + + + + medium + + + + + Fee: + Cuota: + + + + Low Output: + + + + + no + + + + + After Fee: + + + + + Change + + + + + custom change address + + + + + Send to multiple recipients at once + Enviar a múltiples receptores a la vez + + + + Add &Recipient + + + + + Remove all transaction fields + + + + + Clear &All + + + + + Balance: + Saldo: + + + + 123.456 BC + + + + + Confirm the send action + Confirme la acción de enviar + + + + S&end + + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Copy quantity + copiar cantidad + + + + Copy amount + copiar monto + + + + Copy fee + copiar cuota + + + + Copy after fee + copiar despues de cuota + + + + Copy bytes + copiar bytes + + + + Copy priority + copiar prioridad + + + + Copy low output + + + + + Copy change + copiar cambio + + + + <b>%1</b> to %2 (%3) + + + + + Confirm send coins + Confirme para mandar monedas + + + + Are you sure you want to send %1? + + + + + and + + + + + The recipient address is not valid, please recheck. + + + + + The amount to pay must be larger than 0. + El monto a pagar debe ser mayor a 0 + + + + The amount exceeds your balance. + + + + + The total exceeds your balance when the %1 transaction fee is included. + + + + + Duplicate address found, can only send to each address once per send operation. + + + + + Error: Transaction creation failed. + + + + + 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. + + + + + WARNING: Invalid Arepacoin address + + + + + (no label) + (sin etiqueta) + + + + WARNING: unknown change address + + + + + SendCoinsEntry + + + Form + + + + + A&mount: + M&onto + + + + Pay &To: + Pagar &a: + + + + + Enter a label for this address to add it to your address book + Ingrese una etiqueta para esta dirección para agregarlo en su libreta de direcciones. + + + + &Label: + &Etiqueta + + + + The address to send the payment to (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Choose address from address book + + + + + Alt+A + Alt+A + + + + Paste address from clipboard + Pegar dirección del portapapeles + + + + Alt+P + Alt+P + + + + Remove this recipient + + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + SignVerifyMessageDialog + + + Signatures - Sign / Verify a Message + + + + + + &Sign Message + + + + + You can sign messages with your addresses to prove you own them. Be careful not to sign anything vague, as phishing attacks may try to trick you into signing your identity over to them. Only sign fully-detailed statements you agree to. + + + + + The address to sign the message with (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + + Choose an address from the address book + + + + + + Alt+A + Alt+A + + + + Paste address from clipboard + Pegar dirección del portapapeles + + + + Alt+P + Alt+P + + + + Enter the message you want to sign here + + + + + Copy the current signature to the system clipboard + + + + + Sign the message to prove you own this Arepacoin address + + + + + Reset all sign message fields + + + + + + Clear &All + + + + + + &Verify Message + + + + + Enter the signing address, message (ensure you copy line breaks, spaces, tabs, etc. exactly) and signature below to verify the message. Be careful not to read more into the signature than what is in the signed message itself, to avoid being tricked by a man-in-the-middle attack. + + + + + The address the message was signed with (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Verify the message to ensure it was signed with the specified Arepacoin address + + + + + Reset all verify message fields + + + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Click "Sign Message" to generate signature + + + + + Enter Arepacoin signature + + + + + + The entered address is invalid. + + + + + + + + Please check the address and try again. + + + + + + The entered address does not refer to a key. + + + + + Wallet unlock was cancelled. + + + + + Private key for the entered address is not available. + + + + + Message signing failed. + + + + + Message signed. + + + + + The signature could not be decoded. + + + + + + Please check the signature and try again. + + + + + The signature did not match the message digest. + + + + + Message verification failed. + + + + + Message verified. + + + + + TransactionDesc + + + Open until %1 + Abrir hasta %1 + + + + Open for %n block(s) + + + + + conflicted + + + + + %1/offline + + + + + %1/unconfirmed + %1/No confirmado + + + + %1 confirmations + %1 confirmaciones + + + + Status + + + + + , broadcast through %n node(s) + + + + + Date + Fecha + + + + Source + + + + + Generated + + + + + + From + + + + + + + To + + + + + + own address + + + + + label + + + + + + + + + Credit + + + + + matures in %n more block(s) + + + + + not accepted + + + + + + + + Debit + + + + + Transaction fee + + + + + Net amount + + + + + Message + + + + + Comment + + + + + Transaction ID + + + + + Generated coins must mature 6 blocks before they can be spent. When you generated this block, it was broadcast to the network to be added to the block chain. If it fails to get into the chain, its state will change to "not accepted" and it won't be spendable. This may occasionally happen if another node generates a block within a few seconds of yours. + + + + + Debug information + + + + + Transaction + + + + + Inputs + + + + + Amount + Monto + + + + true + + + + + false + + + + + , has not been successfully broadcast yet + , no ha sido transmitido aun + + + + unknown + desconocido + + + + TransactionDescDialog + + + Transaction details + Detalles de la transacción + + + + This pane shows a detailed description of the transaction + Este panel muestras una descripción detallada de la transacción + + + + TransactionTableModel + + + Date + Fecha + + + + Type + Tipo + + + + Address + Domicilio + + + + Amount + Monto + + + + Open until %1 + Abrir hasta %1 + + + + Confirmed (%1 confirmations) + Confimado (%1 confirmaciones) + + + + Open for %n more block(s) + + + + + Offline + + + + + Unconfirmed + + + + + Confirming (%1 of %2 recommended confirmations) + + + + + Conflicted + + + + + Immature (%1 confirmations, will be available after %2) + + + + + This block was not received by any other nodes and will probably not be accepted! + Este bloque no fue recibido por ningun nodo y probablemente no fue aceptado ! + + + + Generated but not accepted + Generado pero no aprovado + + + + Received with + Recivido con + + + + Received from + + + + + Sent to + Enviar a + + + + Payment to yourself + Pagar a si mismo + + + + Mined + Minado + + + + (n/a) + (n/a) + + + + Transaction status. Hover over this field to show number of confirmations. + + + + + Date and time that the transaction was received. + Fecha y hora en que la transacción fue recibida + + + + Type of transaction. + Escriba una transacción + + + + Destination address of transaction. + Direccion del destinatario de la transacción + + + + Amount removed from or added to balance. + Cantidad removida del saldo o agregada + + + + TransactionView + + + + All + Todo + + + + Today + Hoy + + + + This week + Esta semana + + + + This month + Este mes + + + + Last month + El mes pasado + + + + This year + Este año + + + + Range... + + + + + Received with + Recivido con + + + + Sent to + Enviar a + + + + To yourself + Para ti mismo + + + + Mined + Minado + + + + Other + Otro + + + + Enter address or label to search + Ingrese dirección o capa a buscar + + + + Min amount + Monto minimo + + + + Copy address + Copiar dirección + + + + Copy label + Copiar capa + + + + Copy amount + copiar monto + + + + Copy transaction ID + + + + + Edit label + Editar capa + + + + Show transaction details + + + + + Export Transaction Data + + + + + Comma separated file (*.csv) + Arhchivo separado por comas (*.CSV) + + + + Confirmed + Confirmado + + + + Date + Fecha + + + + Type + Tipo + + + + Label + Etiqueta + + + + Address + Domicilio + + + + Amount + Monto + + + + ID + ID + + + + Error exporting + + + + + Could not write to file %1. + + + + + Range: + + + + + to + Para + + + + WalletModel + + + Sending... + + + + + bitcoin-core + + + Arepacoin version + + + + + Usage: + Uso: + + + + Send command to -server or arepacoind + + + + + List commands + Lista de comandos + + + + Get help for a command + + + + + Options: + + + + + Specify configuration file (default: arepacoin.conf) + + + + + Specify pid file (default: arepacoind.pid) + + + + + Specify wallet file (within data directory) + + + + + Specify data directory + + + + + Set database cache size in megabytes (default: 25) + + + + + Set database disk log size in megabytes (default: 100) + + + + + Listen for connections on <port> (default: 9853 or testnet: 19853) + + + + + Maintain at most <n> connections to peers (default: 125) + + + + + Connect to a node to retrieve peer addresses, and disconnect + + + + + Specify your own public address + + + + + Bind to given address. Use [host]:port notation for IPv6 + + + + + Stake your coins to support network and gain reward (default: 1) + + + + + Threshold for disconnecting misbehaving peers (default: 100) + + + + + Number of seconds to keep misbehaving peers from reconnecting (default: 86400) + + + + + An error occurred while setting up the RPC port %u for listening on IPv4: %s + + + + + Detach block and address databases. Increases shutdown time (default: 0) + + + + + 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. + + + + + Error: This transaction requires a transaction fee of at least %s because of its amount, complexity, or use of recently received funds + + + + + Listen for JSON-RPC connections on <port> (default: 9852 or testnet: 19852) + + + + + Accept command line and JSON-RPC commands + + + + + Error: Transaction creation failed + + + + + Error: Wallet locked, unable to create transaction + + + + + Importing blockchain data file. + + + + + Importing bootstrap blockchain data file. + + + + + Run in the background as a daemon and accept commands + + + + + Use the test network + + + + + Accept connections from outside (default: 1 if no -proxy or -connect) + + + + + An error occurred while setting up the RPC port %u for listening on IPv6, falling back to IPv4: %s + + + + + Error initializing database environment %s! To recover, BACKUP THAT DIRECTORY, then remove everything from it except for wallet.dat. + + + + + Set maximum size of high-priority/low-fee transactions in bytes (default: 27000) + + + + + Warning: -paytxfee is set very high! This is the transaction fee you will pay if you send a transaction. + + + + + Warning: Please check that your computer's date and time are correct! If your clock is wrong Arepacoin will not work properly. + + + + + Warning: error reading wallet.dat! All keys read correctly, but transaction data or address book entries might be missing or incorrect. + + + + + Warning: wallet.dat corrupt, data salvaged! Original wallet.dat saved as wallet.{timestamp}.bak in %s; if your balance or transactions are incorrect you should restore from a backup. + + + + + Attempt to recover private keys from a corrupt wallet.dat + + + + + Block creation options: + + + + + Connect only to the specified node(s) + + + + + Discover own IP address (default: 1 when listening and no -externalip) + + + + + Failed to listen on any port. Use -listen=0 if you want this. + + + + + Find peers using DNS lookup (default: 1) + + + + + Sync checkpoints policy (default: strict) + + + + + Invalid -tor address: '%s' + + + + + Invalid amount for -reservebalance=<amount> + + + + + Maximum per-connection receive buffer, <n>*1000 bytes (default: 5000) + + + + + Maximum per-connection send buffer, <n>*1000 bytes (default: 1000) + + + + + Only connect to nodes in network <net> (IPv4, IPv6 or Tor) + + + + + Output extra debugging information. Implies all other -debug* options + + + + + Output extra network debugging information + + + + + Prepend debug output with timestamp + + + + + SSL options: (see the Bitcoin Wiki for SSL setup instructions) + + + + + Select the version of socks proxy to use (4-5, default: 5) + + + + + Send trace/debug info to console instead of debug.log file + + + + + Send trace/debug info to debugger + + + + + Set maximum block size in bytes (default: 250000) + + + + + Set minimum block size in bytes (default: 0) + + + + + Shrink debug.log file on client startup (default: 1 when no -debug) + + + + + Specify connection timeout in milliseconds (default: 5000) + + + + + Unable to sign checkpoint, wrong checkpointkey? + + + + + + Use UPnP to map the listening port (default: 0) + + + + + Use UPnP to map the listening port (default: 1 when listening) + + + + + Use proxy to reach tor hidden services (default: same as -proxy) + + + + + Username for JSON-RPC connections + + + + + Verifying database integrity... + + + + + WARNING: syncronized checkpoint violation detected, but skipped! + + + + + Warning: Disk space is low! + + + + + Warning: This version is obsolete, upgrade required! + + + + + wallet.dat corrupt, salvage failed + + + + + Password for JSON-RPC connections + + + + + %s, you must set a rpcpassword in the configuration file: + %s +It is recommended you use the following random password: +rpcuser=arepacoinrpc +rpcpassword=%s +(you do not need to remember this password) +The username and password MUST NOT be the same. +If the file does not exist, create it with owner-readable-only file permissions. +It is also recommended to set alertnotify so you are notified of problems; +for example: alertnotify=echo %%s | mail -s "Arepacoin Alert" admin@foo.com + + + + + + Find peers using internet relay chat (default: 0) + + + + + Sync time with other nodes. Disable if time on your system is precise e.g. syncing with NTP (default: 1) + + + + + When creating transactions, ignore inputs with value less than this (default: 0.01) + + + + + Allow JSON-RPC connections from specified IP address + + + + + Send commands to node running on <ip> (default: 127.0.0.1) + + + + + Execute command when the best block changes (%s in cmd is replaced by block hash) + + + + + Execute command when a wallet transaction changes (%s in cmd is replaced by TxID) + + + + + Require a confirmations for change (default: 0) + + + + + Enforce transaction scripts to use canonical PUSH operators (default: 1) + + + + + Execute command when a relevant alert is received (%s in cmd is replaced by message) + + + + + Upgrade wallet to latest format + + + + + Set key pool size to <n> (default: 100) + + + + + Rescan the block chain for missing wallet transactions + + + + + How many blocks to check at startup (default: 2500, 0 = all) + + + + + How thorough the block verification is (0-6, default: 1) + + + + + Imports blocks from external blk000?.dat file + + + + + Use OpenSSL (https) for JSON-RPC connections + + + + + Server certificate file (default: server.cert) + + + + + Server private key (default: server.pem) + + + + + Acceptable ciphers (default: TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH) + + + + + Error: Wallet unlocked for staking only, unable to create transaction. + + + + + WARNING: Invalid checkpoint found! Displayed transactions may not be correct! You may need to upgrade, or notify developers. + + + + + This help message + + + + + Wallet %s resides outside data directory %s. + + + + + Cannot obtain a lock on data directory %s. Arepacoin is probably already running. + + + + + Arepacoin + + + + + Unable to bind to %s on this computer (bind returned error %d, %s) + + + + + Connect through socks proxy + + + + + Allow DNS lookups for -addnode, -seednode and -connect + + + + + Loading addresses... + Cargando direcciones... + + + + Error loading blkindex.dat + + + + + Error loading wallet.dat: Wallet corrupted + + + + + Error loading wallet.dat: Wallet requires newer version of Arepacoin + + + + + Wallet needed to be rewritten: restart Arepacoin to complete + + + + + Error loading wallet.dat + + + + + Invalid -proxy address: '%s' + + + + + Unknown network specified in -onlynet: '%s' + + + + + Unknown -socks proxy version requested: %i + + + + + Cannot resolve -bind address: '%s' + + + + + Cannot resolve -externalip address: '%s' + + + + + Invalid amount for -paytxfee=<amount>: '%s' + + + + + Error: could not start node + + + + + Sending... + + + + + Invalid amount + + + + + Insufficient funds + + + + + Loading block index... + Cargando indice de bloques... + + + + Add a node to connect to and attempt to keep the connection open + + + + + Unable to bind to %s on this computer. Arepacoin is probably already running. + + + + + Fee per KB to add to transactions you send + + + + + Invalid amount for -mininput=<amount>: '%s' + + + + + Loading wallet... + Cargando billetera... + + + + Cannot downgrade wallet + + + + + Cannot initialize keypool + + + + + Cannot write default address + + + + + Rescanning... + + + + + Done loading + Carga completa + + + + To use the %s option + + + + + Error + + + + + You must set rpcpassword=<password> in the configuration file: +%s +If the file does not exist, create it with owner-readable-only file permissions. + + + + \ No newline at end of file diff --git a/src/qt/locale/bitcoin_es_UY.ts b/src/qt/locale/bitcoin_es_UY.ts new file mode 100755 index 0000000..05cbbab --- /dev/null +++ b/src/qt/locale/bitcoin_es_UY.ts @@ -0,0 +1,3295 @@ + + + AboutDialog + + + About Arepacoin + + + + + <b>Arepacoin</b> version + + + + + Copyright © 2009-2014 The Bitcoin developers +Copyright © 2012-2014 The NovaCoin developers +Copyright © 2014 The Arepacoin developers + + + + + +This is experimental software. + +Distributed under the MIT/X11 software license, see the accompanying file COPYING or http://www.opensource.org/licenses/mit-license.php. + +This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit (http://www.openssl.org/) and cryptographic software written by Eric Young (eay@cryptsoft.com) and UPnP software written by Thomas Bernard. + + + + + AddressBookPage + + + Address Book + + + + + Double-click to edit address or label + Doble clic para editar etiqueta o dirección + + + + Create a new address + Crear una nueva dirección + + + + Copy the currently selected address to the system clipboard + Copia la dirección seleccionada al portapapeles del sistema + + + + &New Address + + + + + These are your Arepacoin addresses for receiving payments. You may want to give a different one to each sender so you can keep track of who is paying you. + + + + + &Copy Address + + + + + Show &QR Code + + + + + Sign a message to prove you own a Arepacoin address + + + + + Sign &Message + + + + + Delete the currently selected address from the list + + + + + Verify a message to ensure it was signed with a specified Arepacoin address + + + + + &Verify Message + + + + + &Delete + &Borrar + + + + Copy &Label + + + + + &Edit + + + + + Export Address Book Data + + + + + Comma separated file (*.csv) + Archivos separados por coma (*.csv) + + + + Error exporting + + + + + Could not write to file %1. + + + + + AddressTableModel + + + Label + Etiqueta + + + + Address + Direccion + + + + (no label) + (Sin etiqueta) + + + + AskPassphraseDialog + + + Passphrase Dialog + + + + + Enter passphrase + Escriba la contraseña + + + + New passphrase + Nueva contraseña + + + + Repeat new passphrase + Repetir nueva contraseña + + + + Serves to disable the trivial sendmoney when OS account compromised. Provides no real security. + + + + + For staking only + + + + + Enter the new passphrase to the wallet.<br/>Please use a passphrase of <b>10 or more random characters</b>, or <b>eight or more words</b>. + Introduzca la nueva contraseña para el monedero. <br/> Utilice una contraseña de <b> 10 o más caracteres al azar </ b>, o <b> ocho o más palabras </ b>. + + + + Encrypt wallet + Monedero cifrado + + + + This operation needs your wallet passphrase to unlock the wallet. + Esta operacion necesita la contraseña del monedero para desbloquear el mismo + + + + Unlock wallet + Monedero destrabado + + + + This operation needs your wallet passphrase to decrypt the wallet. + Esta operacion necesita la contraseña del monedero para descifrar el mismo + + + + Decrypt wallet + Monedero descifrado + + + + Change passphrase + Cambiar contraseña + + + + Enter the old and new passphrase to the wallet. + Ingrese la contraseña anterior y la nueva de acceso a el monedero + + + + Confirm wallet encryption + Confirme el cifrado del monedero + + + + Warning: If you encrypt your wallet and lose your passphrase, you will <b>LOSE ALL OF YOUR COINS</b>! + + + + + Are you sure you wish to encrypt your wallet? + + + + + IMPORTANT: Any previous backups you have made of your wallet file should be replaced with the newly generated, encrypted wallet file. For security reasons, previous backups of the unencrypted wallet file will become useless as soon as you start using the new, encrypted wallet. + + + + + + Warning: The Caps Lock key is on! + + + + + + Wallet encrypted + Monedero cifrado + + + + Arepacoin will close now to finish the encryption process. Remember that encrypting your wallet cannot fully protect your coins from being stolen by malware infecting your computer. + + + + + + + + Wallet encryption failed + Fallo en el cifrado del monedero + + + + Wallet encryption failed due to an internal error. Your wallet was not encrypted. + Fallo en el cifrado del monedero a causa de un error interno. Su monedero no esta cifrado + + + + + The supplied passphrases do not match. + Las contraseñas suministradas no coinciden. + + + + Wallet unlock failed + Fallo en el desbloqueo del mondero + + + + + + The passphrase entered for the wallet decryption was incorrect. + La contraseña introducida para el descifrado del monedero es incorrecta. + + + + Wallet decryption failed + Fallo en el descifrado del monedero + + + + Wallet passphrase was successfully changed. + + + + + BitcoinGUI + + + Sign &message... + + + + + Synchronizing with network... + Sincronizando con la red... + + + + &Overview + &Vista previa + + + + Show general overview of wallet + Mostrar descripción general del monedero + + + + &Transactions + &transaciones + + + + Browse transaction history + Buscar en el historial de transacciones + + + + &Address Book + + + + + Edit the list of stored addresses and labels + + + + + &Receive coins + + + + + Show the list of addresses for receiving payments + + + + + &Send coins + + + + + E&xit + + + + + Quit application + Salir de la aplicacion + + + + Show information about Arepacoin + + + + + About &Qt + + + + + Show information about Qt + + + + + &Options... + &Opciones... + + + + &Encrypt Wallet... + + + + + &Backup Wallet... + + + + + &Change Passphrase... + + + + + ~%n block(s) remaining + + + + + Processed %1 of %2 (estimated) blocks of transaction history. + Procesado %1 de %2 (estimado) bloques de historial de transacciones. + + + + Processed %1 blocks of transaction history. + Procesado %1 bloques de historial de transacciones. + + + + &Export... + + + + + Send coins to a Arepacoin address + + + + + Modify configuration options for Arepacoin + + + + + Export the data in the current tab to a file + + + + + Encrypt or decrypt wallet + + + + + Backup wallet to another location + + + + + Change the passphrase used for wallet encryption + Cambie la clave utilizada para el cifrado del monedero + + + + &Debug window + + + + + Open debugging and diagnostic console + + + + + &Verify message... + + + + + Arepacoin + + + + + Wallet + + + + + &About Arepacoin + + + + + &Show / Hide + + + + + Unlock wallet + + + + + &Lock Wallet + + + + + Lock wallet + + + + + &File + &Archivo + + + + &Settings + &Configuracion + + + + &Help + &Ayuda + + + + Tabs toolbar + Barra de herramientas + + + + Actions toolbar + + + + + + [testnet] + [prueba_de_red] + + + + + Arepacoin client + + + + + %n active connection(s) to Arepacoin network + + + + + Staking.<br>Your weight is %1<br>Network weight is %2<br>Expected time to earn reward is %3 + + + + + Not staking because wallet is locked + + + + + Not staking because wallet is offline + + + + + Not staking because wallet is syncing + + + + + Not staking because you don't have mature coins + + + + + %n second(s) ago + + + + + &Unlock Wallet... + + + + + %n minute(s) ago + + + + + %n hour(s) ago + + + + + %n day(s) ago + + + + + Up to date + A la fecha + + + + Catching up... + Ponerse al dia... + + + + Last received block was generated %1. + + + + + This transaction is over the size limit. You can still send it for a fee of %1, which goes to the nodes that process your transaction and helps to support the network. Do you want to pay the fee? + + + + + Confirm transaction fee + + + + + Sent transaction + Transaccion enviada + + + + Incoming transaction + Transacción entrante + + + + Date: %1 +Amount: %2 +Type: %3 +Address: %4 + + + + + + + URI handling + + + + + + URI can not be parsed! This can be caused by an invalid Arepacoin address or malformed URI parameters. + + + + + Wallet is <b>encrypted</b> and currently <b>unlocked</b> + El Monedero esta <b>cifrado</b> y actualmente <b>desbloqueado</b> + + + + Wallet is <b>encrypted</b> and currently <b>locked</b> + El Monedero esta <b>cifrado</b> y actualmente <b>bloqueado</b> + + + + Backup Wallet + + + + + Wallet Data (*.dat) + + + + + Backup Failed + + + + + There was an error trying to save the wallet data to the new location. + + + + + %n second(s) + + + + + %n minute(s) + + + + + %n hour(s) + + + + + %n day(s) + + + + + %n week(s) + %n semana%n semanas + + + + %n year(s) + %n año%n años + + + + %1 behind + %1 detrás + + + + %1 and %2 + %1 y %2 + + + + Not staking + + + + + A fatal error occurred. Arepacoin can no longer continue safely and will quit. + + + + + ClientModel + + + Network Alert + + + + + CoinControlDialog + + + Coin Control + + + + + Quantity: + + + + + Bytes: + + + + + Amount: + + + + + Priority: + + + + + Fee: + + + + + Low Output: + + + + + no + + + + + After Fee: + + + + + Change: + + + + + (un)select all + + + + + Tree mode + + + + + List mode + + + + + Amount + + + + + Label + + + + + Address + Direccion + + + + Date + Fecha + + + + Confirmations + + + + + Confirmed + + + + + Priority + + + + + Copy address + + + + + Copy label + + + + + + Copy amount + + + + + Copy transaction ID + + + + + Copy quantity + + + + + Copy fee + + + + + Copy after fee + + + + + Copy bytes + + + + + Copy priority + + + + + Copy low output + + + + + Copy change + + + + + highest + + + + + high + + + + + medium-high + + + + + medium + + + + + low-medium + + + + + low + + + + + lowest + + + + + DUST + + + + + yes + + + + + This label turns red, if the transaction size is bigger than 10000 bytes. + + This means a fee of at least %1 per kb is required. + + Can vary +/- 1 Byte per input. + + + + + Transactions with higher priority get more likely into a block. + +This label turns red, if the priority is smaller than "medium". + + This means a fee of at least %1 per kb is required. + + + + + This label turns red, if any recipient receives an amount smaller than %1. + + This means a fee of at least %2 is required. + + Amounts below 0.546 times the minimum relay fee are shown as DUST. + + + + + This label turns red, if the change is smaller than %1. + + This means a fee of at least %2 is required. + + + + + + (no label) + (Sin etiqueta) + + + + change from %1 (%2) + + + + + (change) + + + + + EditAddressDialog + + + Edit Address + Editar dirección + + + + &Label + &Etiqueta + + + + The label associated with this address book entry + + + + + &Address + &Direccion + + + + The address associated with this address book entry. This can only be modified for sending addresses. + + + + + New receiving address + Nueva dirección de recepción + + + + New sending address + Nueva dirección de envío + + + + Edit receiving address + Editar dirección de recepcion + + + + Edit sending address + Editar dirección de envío + + + + The entered address "%1" is already in the address book. + La dirección introducida "% 1" ya está en la libreta de direcciones. + + + + The entered address "%1" is not a valid Arepacoin address. + + + + + Could not unlock wallet. + No se puede abrir el monedero. + + + + New key generation failed. + Fallo en la nueva clave generada. + + + + GUIUtil::HelpMessageBox + + + + Arepacoin-Qt + + + + + version + + + + + Usage: + + + + + command-line options + + + + + UI options + + + + + Set language, for example "de_DE" (default: system locale) + + + + + Start minimized + + + + + Show splash screen on startup (default: 1) + + + + + OptionsDialog + + + Options + Opciones + + + + &Main + + + + + Optional transaction fee per kB that helps make sure your transactions are processed quickly. Most transactions are 1 kB. Fee 0.01 recommended. + + + + + Pay transaction &fee + + + + + Reserved amount does not participate in staking and is therefore spendable at any time. + + + + + Reserve + + + + + Automatically start Arepacoin after logging in to the system. + + + + + &Start Arepacoin on system login + + + + + Detach block and address databases at shutdown. This means they can be moved to another data directory, but it slows down shutdown. The wallet is always detached. + + + + + &Detach databases at shutdown + + + + + &Network + + + + + Automatically open the Arepacoin client port on the router. This only works when your router supports UPnP and it is enabled. + + + + + Map port using &UPnP + + + + + Connect to the Arepacoin network through a SOCKS proxy (e.g. when connecting through Tor). + + + + + &Connect through SOCKS proxy: + + + + + Proxy &IP: + + + + + IP address of the proxy (e.g. 127.0.0.1) + + + + + &Port: + + + + + Port of the proxy (e.g. 9050) + + + + + SOCKS &Version: + + + + + SOCKS version of the proxy (e.g. 5) + + + + + &Window + + + + + Show only a tray icon after minimizing the window. + + + + + &Minimize to the tray instead of the taskbar + + + + + Minimize instead of exit the application when the window is closed. When this option is enabled, the application will be closed only after selecting Quit in the menu. + + + + + M&inimize on close + + + + + &Display + + + + + User Interface &language: + + + + + The user interface language can be set here. This setting will take effect after restarting Arepacoin. + + + + + &Unit to show amounts in: + + + + + Choose the default subdivision unit to show in the interface and when sending coins. + + + + + Whether to show Arepacoin addresses in the transaction list or not. + + + + + &Display addresses in transaction list + + + + + Whether to show coin control features or not. + + + + + Display coin &control features (experts only!) + + + + + &OK + + + + + &Cancel + + + + + &Apply + + + + + default + + + + + + Warning + + + + + + This setting will take effect after restarting Arepacoin. + + + + + The supplied proxy address is invalid. + + + + + OverviewPage + + + Form + Formulario + + + + + The displayed information may be out of date. Your wallet automatically synchronizes with the Arepacoin network after a connection is established, but this process has not completed yet. + + + + + Stake: + + + + + Unconfirmed: + + + + + Wallet + + + + + Spendable: + + + + + Your current spendable balance + + + + + Immature: + + + + + Mined balance that has not yet matured + + + + + Total: + + + + + Your current total balance + + + + + <b>Recent transactions</b> + <b>Transacciones recientes</b> + + + + Total of transactions that have yet to be confirmed, and do not yet count toward the current balance + + + + + Total of coins that was staked, and do not yet count toward the current balance + + + + + + out of sync + + + + + QRCodeDialog + + + QR Code Dialog + + + + + Request Payment + + + + + Amount: + + + + + Label: + + + + + Message: + + + + + &Save As... + + + + + Error encoding URI into QR Code. + + + + + The entered amount is invalid, please check. + + + + + Resulting URI too long, try to reduce the text for label / message. + + + + + Save QR Code + + + + + PNG Images (*.png) + + + + + RPCConsole + + + Client name + + + + + + + + + + + + + + N/A + + + + + Client version + + + + + &Information + + + + + Using OpenSSL version + + + + + Startup time + + + + + Network + + + + + Number of connections + + + + + On testnet + + + + + Block chain + + + + + Current number of blocks + + + + + Estimated total blocks + + + + + Last block time + + + + + &Open + + + + + Command-line options + + + + + Show the Arepacoin-Qt help message to get a list with possible Arepacoin command-line options. + + + + + &Show + + + + + &Console + + + + + Build date + + + + + Arepacoin - Debug window + + + + + Arepacoin Core + + + + + Debug log file + + + + + Open the Arepacoin debug log file from the current data directory. This can take a few seconds for large log files. + + + + + Clear console + + + + + Welcome to the Arepacoin RPC console. + + + + + Use up and down arrows to navigate history, and <b>Ctrl-L</b> to clear screen. + + + + + Type <b>help</b> for an overview of available commands. + + + + + SendCoinsDialog + + + + + + + + + + Send Coins + Enviar monedas + + + + Coin Control Features + + + + + Inputs... + + + + + automatically selected + + + + + Insufficient funds! + + + + + Quantity: + + + + + + 0 + + + + + Bytes: + + + + + Amount: + + + + + + + + 0.00 BC + + + + + Priority: + + + + + medium + + + + + Fee: + + + + + Low Output: + + + + + no + + + + + After Fee: + + + + + Change + + + + + custom change address + + + + + Send to multiple recipients at once + Enviar a varios destinatarios a la vez + + + + Add &Recipient + + + + + Remove all transaction fields + + + + + Clear &All + + + + + Balance: + Balance: + + + + 123.456 BC + + + + + Confirm the send action + Confirmar el envío + + + + S&end + + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Copy quantity + + + + + Copy amount + + + + + Copy fee + + + + + Copy after fee + + + + + Copy bytes + + + + + Copy priority + + + + + Copy low output + + + + + Copy change + + + + + <b>%1</b> to %2 (%3) + + + + + Confirm send coins + Confirmar el envio de monedas + + + + Are you sure you want to send %1? + + + + + and + + + + + The recipient address is not valid, please recheck. + + + + + The amount to pay must be larger than 0. + La cantidad a pagar debe ser mayor que 0. + + + + The amount exceeds your balance. + + + + + The total exceeds your balance when the %1 transaction fee is included. + + + + + Duplicate address found, can only send to each address once per send operation. + + + + + Error: Transaction creation failed. + + + + + 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. + + + + + WARNING: Invalid Arepacoin address + + + + + (no label) + (Sin etiqueta) + + + + WARNING: unknown change address + + + + + SendCoinsEntry + + + Form + + + + + A&mount: + A&Monto: + + + + Pay &To: + Pagar &A: + + + + + Enter a label for this address to add it to your address book + Introduzca una etiqueta para esta dirección para añadirla a su libreta de direcciones + + + + &Label: + &Etiqueta: + + + + The address to send the payment to (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Choose address from address book + + + + + Alt+A + Alt+A + + + + Paste address from clipboard + Pegar la dirección desde el portapapeles + + + + Alt+P + Alt+P + + + + Remove this recipient + + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + SignVerifyMessageDialog + + + Signatures - Sign / Verify a Message + + + + + + &Sign Message + + + + + You can sign messages with your addresses to prove you own them. Be careful not to sign anything vague, as phishing attacks may try to trick you into signing your identity over to them. Only sign fully-detailed statements you agree to. + + + + + The address to sign the message with (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + + Choose an address from the address book + + + + + + Alt+A + Alt+A + + + + Paste address from clipboard + Pegar la dirección desde el portapapeles + + + + Alt+P + Alt+P + + + + Enter the message you want to sign here + + + + + Copy the current signature to the system clipboard + + + + + Sign the message to prove you own this Arepacoin address + + + + + Reset all sign message fields + + + + + + Clear &All + + + + + + &Verify Message + + + + + Enter the signing address, message (ensure you copy line breaks, spaces, tabs, etc. exactly) and signature below to verify the message. Be careful not to read more into the signature than what is in the signed message itself, to avoid being tricked by a man-in-the-middle attack. + + + + + The address the message was signed with (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Verify the message to ensure it was signed with the specified Arepacoin address + + + + + Reset all verify message fields + + + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Click "Sign Message" to generate signature + + + + + Enter Arepacoin signature + + + + + + The entered address is invalid. + + + + + + + + Please check the address and try again. + + + + + + The entered address does not refer to a key. + + + + + Wallet unlock was cancelled. + + + + + Private key for the entered address is not available. + + + + + Message signing failed. + + + + + Message signed. + + + + + The signature could not be decoded. + + + + + + Please check the signature and try again. + + + + + The signature did not match the message digest. + + + + + Message verification failed. + + + + + Message verified. + + + + + TransactionDesc + + + Open until %1 + Abrir hasta %1 + + + + Open for %n block(s) + + + + + conflicted + + + + + %1/offline + + + + + %1/unconfirmed + + + + + %1 confirmations + + + + + Status + + + + + , broadcast through %n node(s) + + + + + Date + Fecha + + + + Source + + + + + Generated + + + + + + From + + + + + + + To + + + + + + own address + + + + + label + + + + + + + + + Credit + + + + + matures in %n more block(s) + + + + + not accepted + + + + + + + + Debit + + + + + Transaction fee + + + + + Net amount + + + + + Message + + + + + Comment + + + + + Transaction ID + + + + + Generated coins must mature 6 blocks before they can be spent. When you generated this block, it was broadcast to the network to be added to the block chain. If it fails to get into the chain, its state will change to "not accepted" and it won't be spendable. This may occasionally happen if another node generates a block within a few seconds of yours. + + + + + Debug information + + + + + Transaction + + + + + Inputs + + + + + Amount + + + + + true + + + + + false + + + + + , has not been successfully broadcast yet + + + + + unknown + desconocido + + + + TransactionDescDialog + + + Transaction details + + + + + This pane shows a detailed description of the transaction + + + + + TransactionTableModel + + + Date + Fecha + + + + Type + + + + + Address + Direccion + + + + Amount + + + + + Open until %1 + Abrir hasta %1 + + + + Confirmed (%1 confirmations) + + + + + Open for %n more block(s) + + + + + Offline + + + + + Unconfirmed + + + + + Confirming (%1 of %2 recommended confirmations) + + + + + Conflicted + + + + + Immature (%1 confirmations, will be available after %2) + + + + + This block was not received by any other nodes and will probably not be accepted! + + + + + Generated but not accepted + + + + + Received with + + + + + Received from + + + + + Sent to + + + + + Payment to yourself + + + + + Mined + + + + + (n/a) + + + + + Transaction status. Hover over this field to show number of confirmations. + + + + + Date and time that the transaction was received. + + + + + Type of transaction. + + + + + Destination address of transaction. + + + + + Amount removed from or added to balance. + + + + + TransactionView + + + + All + + + + + Today + + + + + This week + + + + + This month + + + + + Last month + + + + + This year + + + + + Range... + + + + + Received with + + + + + Sent to + + + + + To yourself + + + + + Mined + + + + + Other + + + + + Enter address or label to search + + + + + Min amount + + + + + Copy address + + + + + Copy label + + + + + Copy amount + + + + + Copy transaction ID + + + + + Edit label + + + + + Show transaction details + + + + + Export Transaction Data + + + + + Comma separated file (*.csv) + Archivos separados por coma (*.csv) + + + + Confirmed + + + + + Date + Fecha + + + + Type + + + + + Label + Etiqueta + + + + Address + Direccion + + + + Amount + + + + + ID + + + + + Error exporting + + + + + Could not write to file %1. + + + + + Range: + + + + + to + + + + + WalletModel + + + Sending... + + + + + bitcoin-core + + + Arepacoin version + + + + + Usage: + + + + + Send command to -server or arepacoind + + + + + List commands + + + + + Get help for a command + + + + + Options: + + + + + Specify configuration file (default: arepacoin.conf) + + + + + Specify pid file (default: arepacoind.pid) + + + + + Specify wallet file (within data directory) + + + + + Specify data directory + + + + + Set database cache size in megabytes (default: 25) + + + + + Set database disk log size in megabytes (default: 100) + + + + + Listen for connections on <port> (default: 9853 or testnet: 19853) + + + + + Maintain at most <n> connections to peers (default: 125) + + + + + Connect to a node to retrieve peer addresses, and disconnect + + + + + Specify your own public address + + + + + Bind to given address. Use [host]:port notation for IPv6 + + + + + Stake your coins to support network and gain reward (default: 1) + + + + + Threshold for disconnecting misbehaving peers (default: 100) + + + + + Number of seconds to keep misbehaving peers from reconnecting (default: 86400) + + + + + An error occurred while setting up the RPC port %u for listening on IPv4: %s + + + + + Detach block and address databases. Increases shutdown time (default: 0) + + + + + 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. + + + + + Error: This transaction requires a transaction fee of at least %s because of its amount, complexity, or use of recently received funds + + + + + Listen for JSON-RPC connections on <port> (default: 9852 or testnet: 19852) + + + + + Accept command line and JSON-RPC commands + + + + + Error: Transaction creation failed + + + + + Error: Wallet locked, unable to create transaction + + + + + Importing blockchain data file. + + + + + Importing bootstrap blockchain data file. + + + + + Run in the background as a daemon and accept commands + + + + + Use the test network + + + + + Accept connections from outside (default: 1 if no -proxy or -connect) + + + + + An error occurred while setting up the RPC port %u for listening on IPv6, falling back to IPv4: %s + + + + + Error initializing database environment %s! To recover, BACKUP THAT DIRECTORY, then remove everything from it except for wallet.dat. + + + + + Set maximum size of high-priority/low-fee transactions in bytes (default: 27000) + + + + + Warning: -paytxfee is set very high! This is the transaction fee you will pay if you send a transaction. + + + + + Warning: Please check that your computer's date and time are correct! If your clock is wrong Arepacoin will not work properly. + + + + + Warning: error reading wallet.dat! All keys read correctly, but transaction data or address book entries might be missing or incorrect. + + + + + Warning: wallet.dat corrupt, data salvaged! Original wallet.dat saved as wallet.{timestamp}.bak in %s; if your balance or transactions are incorrect you should restore from a backup. + + + + + Attempt to recover private keys from a corrupt wallet.dat + + + + + Block creation options: + + + + + Connect only to the specified node(s) + + + + + Discover own IP address (default: 1 when listening and no -externalip) + + + + + Failed to listen on any port. Use -listen=0 if you want this. + + + + + Find peers using DNS lookup (default: 1) + + + + + Sync checkpoints policy (default: strict) + + + + + Invalid -tor address: '%s' + + + + + Invalid amount for -reservebalance=<amount> + + + + + Maximum per-connection receive buffer, <n>*1000 bytes (default: 5000) + + + + + Maximum per-connection send buffer, <n>*1000 bytes (default: 1000) + + + + + Only connect to nodes in network <net> (IPv4, IPv6 or Tor) + + + + + Output extra debugging information. Implies all other -debug* options + + + + + Output extra network debugging information + + + + + Prepend debug output with timestamp + + + + + SSL options: (see the Bitcoin Wiki for SSL setup instructions) + + + + + Select the version of socks proxy to use (4-5, default: 5) + + + + + Send trace/debug info to console instead of debug.log file + + + + + Send trace/debug info to debugger + + + + + Set maximum block size in bytes (default: 250000) + + + + + Set minimum block size in bytes (default: 0) + + + + + Shrink debug.log file on client startup (default: 1 when no -debug) + + + + + Specify connection timeout in milliseconds (default: 5000) + + + + + Unable to sign checkpoint, wrong checkpointkey? + + + + + + Use UPnP to map the listening port (default: 0) + + + + + Use UPnP to map the listening port (default: 1 when listening) + + + + + Use proxy to reach tor hidden services (default: same as -proxy) + + + + + Username for JSON-RPC connections + + + + + Verifying database integrity... + + + + + WARNING: syncronized checkpoint violation detected, but skipped! + + + + + Warning: Disk space is low! + + + + + Warning: This version is obsolete, upgrade required! + + + + + wallet.dat corrupt, salvage failed + + + + + Password for JSON-RPC connections + + + + + %s, you must set a rpcpassword in the configuration file: + %s +It is recommended you use the following random password: +rpcuser=arepacoinrpc +rpcpassword=%s +(you do not need to remember this password) +The username and password MUST NOT be the same. +If the file does not exist, create it with owner-readable-only file permissions. +It is also recommended to set alertnotify so you are notified of problems; +for example: alertnotify=echo %%s | mail -s "Arepacoin Alert" admin@foo.com + + + + + + Find peers using internet relay chat (default: 0) + + + + + Sync time with other nodes. Disable if time on your system is precise e.g. syncing with NTP (default: 1) + + + + + When creating transactions, ignore inputs with value less than this (default: 0.01) + + + + + Allow JSON-RPC connections from specified IP address + + + + + Send commands to node running on <ip> (default: 127.0.0.1) + + + + + Execute command when the best block changes (%s in cmd is replaced by block hash) + + + + + Execute command when a wallet transaction changes (%s in cmd is replaced by TxID) + + + + + Require a confirmations for change (default: 0) + + + + + Enforce transaction scripts to use canonical PUSH operators (default: 1) + + + + + Execute command when a relevant alert is received (%s in cmd is replaced by message) + + + + + Upgrade wallet to latest format + + + + + Set key pool size to <n> (default: 100) + + + + + Rescan the block chain for missing wallet transactions + + + + + How many blocks to check at startup (default: 2500, 0 = all) + + + + + How thorough the block verification is (0-6, default: 1) + + + + + Imports blocks from external blk000?.dat file + + + + + Use OpenSSL (https) for JSON-RPC connections + + + + + Server certificate file (default: server.cert) + + + + + Server private key (default: server.pem) + + + + + Acceptable ciphers (default: TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH) + + + + + Error: Wallet unlocked for staking only, unable to create transaction. + + + + + WARNING: Invalid checkpoint found! Displayed transactions may not be correct! You may need to upgrade, or notify developers. + + + + + This help message + + + + + Wallet %s resides outside data directory %s. + + + + + Cannot obtain a lock on data directory %s. Arepacoin is probably already running. + + + + + Arepacoin + + + + + Unable to bind to %s on this computer (bind returned error %d, %s) + + + + + Connect through socks proxy + + + + + Allow DNS lookups for -addnode, -seednode and -connect + + + + + Loading addresses... + + + + + Error loading blkindex.dat + + + + + Error loading wallet.dat: Wallet corrupted + + + + + Error loading wallet.dat: Wallet requires newer version of Arepacoin + + + + + Wallet needed to be rewritten: restart Arepacoin to complete + + + + + Error loading wallet.dat + + + + + Invalid -proxy address: '%s' + + + + + Unknown network specified in -onlynet: '%s' + + + + + Unknown -socks proxy version requested: %i + + + + + Cannot resolve -bind address: '%s' + + + + + Cannot resolve -externalip address: '%s' + + + + + Invalid amount for -paytxfee=<amount>: '%s' + + + + + Error: could not start node + + + + + Sending... + + + + + Invalid amount + + + + + Insufficient funds + + + + + Loading block index... + + + + + Add a node to connect to and attempt to keep the connection open + + + + + Unable to bind to %s on this computer. Arepacoin is probably already running. + + + + + Fee per KB to add to transactions you send + + + + + Invalid amount for -mininput=<amount>: '%s' + + + + + Loading wallet... + + + + + Cannot downgrade wallet + + + + + Cannot initialize keypool + + + + + Cannot write default address + + + + + Rescanning... + + + + + Done loading + + + + + To use the %s option + + + + + Error + + + + + You must set rpcpassword=<password> in the configuration file: +%s +If the file does not exist, create it with owner-readable-only file permissions. + + + + \ No newline at end of file diff --git a/src/qt/locale/bitcoin_et.ts b/src/qt/locale/bitcoin_et.ts new file mode 100755 index 0000000..9792009 --- /dev/null +++ b/src/qt/locale/bitcoin_et.ts @@ -0,0 +1,3285 @@ + + + AboutDialog + + + About Arepacoin + Info Arepacoin'i kohta + + + + <b>Arepacoin</b> version + <b>Arepacoin</b>'i versioon + + + + Copyright © 2009-2014 The Bitcoin developers +Copyright © 2012-2014 The NovaCoin developers +Copyright © 2014 The Arepacoin developers + + + + + +This is experimental software. + +Distributed under the MIT/X11 software license, see the accompanying file COPYING or http://www.opensource.org/licenses/mit-license.php. + +This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit (http://www.openssl.org/) and cryptographic software written by Eric Young (eay@cryptsoft.com) and UPnP software written by Thomas Bernard. + ⏎ +See on eksperimentaalne tarkvara.⏎ +⏎ +Levitatud MIT/X11 tarkvara litsentsi all, vaata kaasasolevat faili COPYING või http://www.opensource.org/licenses/mit-license.php⏎ +⏎ +Toode sisaldab OpenSSL Projekti all toodetud tarkvara, mis on kasutamiseks OpenSSL Toolkitis (http://www.openssl.org/) ja Eric Young'i poolt loodud krüptograafilist tarkvara (eay@cryptsoft.com) ning Thomas Bernard'i loodud UPnP tarkvara. + + + + AddressBookPage + + + Address Book + Aadressiraamat + + + + Double-click to edit address or label + Tee topeltklõps aadressi või märgise muutmiseks + + + + Create a new address + Loo uus aadress + + + + Copy the currently selected address to the system clipboard + Kopeeri valitud aadress vahemällu + + + + &New Address + + + + + These are your Arepacoin addresses for receiving payments. You may want to give a different one to each sender so you can keep track of who is paying you. + Need on Sinu Arepacoin'i aadressid maksete vastuvõtmiseks. Soovi korral saad anda igale saatjale eraldi aadressi, et hõlpsamini omada ülevaadet, et kellelt mündid laekuvad. + + + + &Copy Address + &Aadressi kopeerimine + + + + Show &QR Code + Näita &QR koodi. + + + + Sign a message to prove you own a Arepacoin address + Allkirjasta sõnum Arepacoin'i aadressi omamise tõestamiseks. + + + + Sign &Message + + + + + Delete the currently selected address from the list + Kustuta märgistatud aadress loetelust + + + + Verify a message to ensure it was signed with a specified Arepacoin address + + + + + &Verify Message + + + + + &Delete + &Kustuta + + + + Copy &Label + &Märgise kopeerimine + + + + &Edit + &Muuda + + + + Export Address Book Data + + + + + Comma separated file (*.csv) + Komaeraldatud fail (*.csv) + + + + Error exporting + + + + + Could not write to file %1. + + + + + AddressTableModel + + + Label + Silt + + + + Address + Aadress + + + + (no label) + (silti pole) + + + + AskPassphraseDialog + + + Passphrase Dialog + Salafraasi dialoog + + + + Enter passphrase + Sisesta salasõna + + + + New passphrase + Uus salasõna + + + + Repeat new passphrase + Korda salafraasi + + + + Serves to disable the trivial sendmoney when OS account compromised. Provides no real security. + + + + + For staking only + + + + + Enter the new passphrase to the wallet.<br/>Please use a passphrase of <b>10 or more random characters</b>, or <b>eight or more words</b>. + Sisesta rahakotile uus salafraas.<br/>Palun kasuta salafraasina <b>vähemalt 10 tähte/numbrit/sümbolit</b>, või <b>vähemalt 8 sõna</b>. + + + + Encrypt wallet + Krüpteeri rahakott + + + + This operation needs your wallet passphrase to unlock the wallet. + See toiming nõuab sinu rahakoti salafraasi. + + + + Unlock wallet + Tee rahakott lukust lahti. + + + + This operation needs your wallet passphrase to decrypt the wallet. + See toiming nõuab sinu rahakoti salafraasi. + + + + Decrypt wallet + Dekrüpteeri rahakott. + + + + Change passphrase + Muuda salafraasi + + + + Enter the old and new passphrase to the wallet. + Sisesta rahakoti vana ning uus salafraas. + + + + Confirm wallet encryption + Kinnita rahakoti krüpteering + + + + Warning: If you encrypt your wallet and lose your passphrase, you will <b>LOSE ALL OF YOUR COINS</b>! + + + + + Are you sure you wish to encrypt your wallet? + Kas soovid oma rahakoti krüpteerida? + + + + IMPORTANT: Any previous backups you have made of your wallet file should be replaced with the newly generated, encrypted wallet file. For security reasons, previous backups of the unencrypted wallet file will become useless as soon as you start using the new, encrypted wallet. + TÄHTIS: Kõik varasemad rahakoti varundfailid tuleks üle kirjutada äsja loodud krüpteeritud rahakoti failiga. Turvakaalutlustel tühistatakse krüpteerimata rahakoti failid alates uue, krüpteeritud rahakoti, kasutusele võtust. + + + + + Warning: The Caps Lock key is on! + Hoiatus: Caps Lock on sisse lülitatud! + + + + + Wallet encrypted + Rahakott krüpteeritud + + + + Arepacoin will close now to finish the encryption process. Remember that encrypting your wallet cannot fully protect your coins from being stolen by malware infecting your computer. + + + + + + + + Wallet encryption failed + Tõrge rahakoti krüpteerimisel + + + + Wallet encryption failed due to an internal error. Your wallet was not encrypted. + Rahakoti krüpteering ebaõnnestus tõrke tõttu. Sinu rahakotti ei krüpteeritud. + + + + + The supplied passphrases do not match. + Salafraasid ei kattu. + + + + Wallet unlock failed + Rahakoti avamine ebaõnnestus + + + + + + The passphrase entered for the wallet decryption was incorrect. + Rahakoti salafraas ei ole õige. + + + + Wallet decryption failed + Rahakoti dekrüpteerimine ei õnnestunud + + + + Wallet passphrase was successfully changed. + Rahakoti salafraasi muutmine õnnestus. + + + + BitcoinGUI + + + Sign &message... + Signeeri &sõnum + + + + Synchronizing with network... + Võrgusünkimine... + + + + &Overview + &Ülevaade + + + + Show general overview of wallet + Kuva rahakoti üld-ülevaade + + + + &Transactions + &Tehingud + + + + Browse transaction history + Sirvi tehingute ajalugu + + + + &Address Book + + + + + Edit the list of stored addresses and labels + + + + + &Receive coins + + + + + Show the list of addresses for receiving payments + + + + + &Send coins + + + + + E&xit + V&älju + + + + Quit application + Väljumine + + + + Show information about Arepacoin + + + + + About &Qt + Teave &Qt kohta + + + + Show information about Qt + Kuva Qt kohta käiv info + + + + &Options... + &Valikud... + + + + &Encrypt Wallet... + &Krüpteeri Rahakott + + + + &Backup Wallet... + &Varunda Rahakott + + + + &Change Passphrase... + &Salafraasi muutmine + + + + ~%n block(s) remaining + + + + + Downloaded %1 of %2 blocks of transaction history (%3% done). + + + + + &Export... + + + + + Send coins to a Arepacoin address + + + + + Modify configuration options for Arepacoin + + + + + Export the data in the current tab to a file + + + + + Encrypt or decrypt wallet + + + + + Backup wallet to another location + Varunda rahakott teise asukohta + + + + Change the passphrase used for wallet encryption + Rahakoti krüpteerimise salafraasi muutmine + + + + &Debug window + &Debugimise aken + + + + Open debugging and diagnostic console + Ava debugimise ja diagnostika konsool + + + + &Verify message... + &Kontrolli sõnumit... + + + + Arepacoin + + + + + Wallet + Rahakott + + + + &About Arepacoin + + + + + &Show / Hide + &Näita / Peida + + + + Unlock wallet + + + + + &Lock Wallet + + + + + Lock wallet + + + + + &File + &Fail + + + + &Settings + &Seaded + + + + &Help + &Abi + + + + Tabs toolbar + Vahelehe tööriistariba + + + + Actions toolbar + + + + + + [testnet] + [testnet] + + + + + Arepacoin client + + + + + %n active connection(s) to Arepacoin network + + + + + Downloaded %1 blocks of transaction history. + + + + + Staking.<br>Your weight is %1<br>Network weight is %2<br>Expected time to earn reward is %3 + + + + + Not staking because wallet is locked + + + + + Not staking because wallet is offline + + + + + Not staking because wallet is syncing + + + + + Not staking because you don't have mature coins + + + + + %n second(s) ago + + + + + &Unlock Wallet... + + + + + %n minute(s) ago + + + + + %n hour(s) ago + + + + + %n day(s) ago + + + + + Up to date + Ajakohane + + + + Catching up... + Jõuan... + + + + Last received block was generated %1. + + + + + This transaction is over the size limit. You can still send it for a fee of %1, which goes to the nodes that process your transaction and helps to support the network. Do you want to pay the fee? + + + + + Confirm transaction fee + + + + + Sent transaction + Saadetud tehing + + + + Incoming transaction + Sisenev tehing + + + + Date: %1 +Amount: %2 +Type: %3 +Address: %4 + + Kuupäev: %1⏎ +Summa: %2⏎ +Tüüp: %3⏎ +Aadress: %4⏎ + + + + + URI handling + + + + + + URI can not be parsed! This can be caused by an invalid Arepacoin address or malformed URI parameters. + + + + + Wallet is <b>encrypted</b> and currently <b>unlocked</b> + Rahakott on <b>krüpteeritud</b> ning hetkel <b>avatud</b> + + + + Wallet is <b>encrypted</b> and currently <b>locked</b> + Rahakott on <b>krüpteeritud</b> ning hetkel <b>suletud</b> + + + + Backup Wallet + + + + + Wallet Data (*.dat) + + + + + Backup Failed + + + + + There was an error trying to save the wallet data to the new location. + + + + + %n second(s) + + + + + %n minute(s) + + + + + %n hour(s) + %n tund%n tundi + + + + %n day(s) + %n päev%n päeva + + + + Not staking + + + + + A fatal error occurred. Arepacoin can no longer continue safely and will quit. + + + + + ClientModel + + + Network Alert + Võrgu Häire + + + + CoinControlDialog + + + Coin Control + + + + + Quantity: + + + + + Bytes: + + + + + Amount: + Summa: + + + + Priority: + + + + + Fee: + + + + + Low Output: + + + + + no + + + + + After Fee: + + + + + Change: + + + + + (un)select all + + + + + Tree mode + + + + + List mode + + + + + Amount + Kogus + + + + Label + + + + + Address + Aadress + + + + Date + Kuupäev + + + + Confirmations + + + + + Confirmed + Kinnitatud + + + + Priority + + + + + Copy address + Aadressi kopeerimine + + + + Copy label + Märgise kopeerimine + + + + + Copy amount + Kopeeri summa + + + + Copy transaction ID + Kopeeri tehingu ID + + + + Copy quantity + + + + + Copy fee + + + + + Copy after fee + + + + + Copy bytes + + + + + Copy priority + + + + + Copy low output + + + + + Copy change + + + + + highest + + + + + high + + + + + medium-high + + + + + medium + + + + + low-medium + + + + + low + + + + + lowest + + + + + DUST + + + + + yes + + + + + This label turns red, if the transaction size is bigger than 10000 bytes. + + This means a fee of at least %1 per kb is required. + + Can vary +/- 1 Byte per input. + + + + + Transactions with higher priority get more likely into a block. + +This label turns red, if the priority is smaller than "medium". + + This means a fee of at least %1 per kb is required. + + + + + This label turns red, if any recipient receives an amount smaller than %1. + + This means a fee of at least %2 is required. + + Amounts below 0.546 times the minimum relay fee are shown as DUST. + + + + + This label turns red, if the change is smaller than %1. + + This means a fee of at least %2 is required. + + + + + + (no label) + (silti pole) + + + + change from %1 (%2) + + + + + (change) + + + + + EditAddressDialog + + + Edit Address + Muuda aadressi + + + + &Label + &Märgis + + + + The label associated with this address book entry + + + + + &Address + &Aadress + + + + The address associated with this address book entry. This can only be modified for sending addresses. + + + + + New receiving address + Uus sissetulev aadress + + + + New sending address + Uus väljaminev aadress + + + + Edit receiving address + Sissetulevate aadresside muutmine + + + + Edit sending address + Väljaminevate aadresside muutmine + + + + The entered address "%1" is already in the address book. + Selline aadress on juba olemas: "%1" + + + + The entered address "%1" is not a valid Arepacoin address. + + + + + Could not unlock wallet. + Rahakotti ei avatud + + + + New key generation failed. + Tõrge uue võtme loomisel. + + + + GUIUtil::HelpMessageBox + + + + Arepacoin-Qt + + + + + version + + + + + Usage: + + + + + command-line options + + + + + UI options + + + + + Set language, for example "de_DE" (default: system locale) + + + + + Start minimized + + + + + Show splash screen on startup (default: 1) + + + + + OptionsDialog + + + Options + Valikud + + + + &Main + %Peamine + + + + Optional transaction fee per kB that helps make sure your transactions are processed quickly. Most transactions are 1 kB. Fee 0.01 recommended. + + + + + Pay transaction &fee + Tasu tehingu &fee + + + + Reserved amount does not participate in staking and is therefore spendable at any time. + + + + + Reserve + + + + + Automatically start Arepacoin after logging in to the system. + + + + + &Start Arepacoin on system login + + + + + Detach block and address databases at shutdown. This means they can be moved to another data directory, but it slows down shutdown. The wallet is always detached. + + + + + &Detach databases at shutdown + + + + + &Network + &Võrk + + + + Automatically open the Arepacoin client port on the router. This only works when your router supports UPnP and it is enabled. + + + + + Map port using &UPnP + Suuna port &UPnP kaudu + + + + Connect to the Arepacoin network through a SOCKS proxy (e.g. when connecting through Tor). + + + + + &Connect through SOCKS proxy: + + + + + Proxy &IP: + Proxi &IP: + + + + IP address of the proxy (e.g. 127.0.0.1) + + + + + &Port: + &Port: + + + + Port of the proxy (e.g. 9050) + Proxi port (nt 9050) + + + + SOCKS &Version: + Turva proxi SOCKS &Version: + + + + SOCKS version of the proxy (e.g. 5) + Turva proxi SOCKS versioon (nt 5) + + + + &Window + &Aken + + + + Show only a tray icon after minimizing the window. + Minimeeri systray alale. + + + + &Minimize to the tray instead of the taskbar + &Minimeeri systray alale + + + + Minimize instead of exit the application when the window is closed. When this option is enabled, the application will be closed only after selecting Quit in the menu. + Sulgemise asemel minimeeri aken. Selle valiku tegemisel suletakse programm Menüüst "Välju" käsuga. + + + + M&inimize on close + M&inimeeri sulgemisel + + + + &Display + &Kuva + + + + User Interface &language: + Kasutajaliidese &keel: + + + + The user interface language can be set here. This setting will take effect after restarting Arepacoin. + + + + + &Unit to show amounts in: + Summade kuvamise &Unit: + + + + Choose the default subdivision unit to show in the interface and when sending coins. + Vali liideses ning müntide saatmisel kuvatav vaikimisi alajaotus. + + + + Whether to show Arepacoin addresses in the transaction list or not. + + + + + &Display addresses in transaction list + Tehingute loetelu &Display aadress + + + + Whether to show coin control features or not. + + + + + Display coin &control features (experts only!) + + + + + &OK + &OK + + + + &Cancel + &Katkesta + + + + &Apply + + + + + default + vaikeväärtus + + + + + Warning + + + + + + This setting will take effect after restarting Arepacoin. + + + + + The supplied proxy address is invalid. + Sisestatud kehtetu proxy aadress. + + + + OverviewPage + + + Form + Vorm + + + + + The displayed information may be out of date. Your wallet automatically synchronizes with the Arepacoin network after a connection is established, but this process has not completed yet. + + + + + Stake: + + + + + Unconfirmed: + + + + + Wallet + Rahakott + + + + Spendable: + + + + + Your current spendable balance + + + + + Immature: + Ebaküps: + + + + Mined balance that has not yet matured + Mitte aegunud mine'itud jääk + + + + Total: + + + + + Your current total balance + + + + + <b>Recent transactions</b> + <b>Uuesti saadetud tehingud</b> + + + + Total of transactions that have yet to be confirmed, and do not yet count toward the current balance + + + + + Total of coins that was staked, and do not yet count toward the current balance + + + + + + out of sync + sünkimata + + + + QRCodeDialog + + + QR Code Dialog + + + + + Request Payment + + + + + Amount: + + + + + Label: + + + + + Message: + + + + + &Save As... + + + + + Error encoding URI into QR Code. + + + + + The entered amount is invalid, please check. + + + + + Resulting URI too long, try to reduce the text for label / message. + + + + + Save QR Code + + + + + PNG Images (*.png) + + + + + RPCConsole + + + Client name + Kliendi nimi + + + + + + + + + + + + + N/A + N/A + + + + Client version + Kliendi versioon + + + + &Information + &Informatsioon + + + + Using OpenSSL version + Kasutan OpenSSL versiooni + + + + Startup time + Käivitamise hetk + + + + Network + Võrgustik + + + + Number of connections + Ühenduste arv + + + + On testnet + + + + + Block chain + Ploki jada + + + + Current number of blocks + Plokkide hetkearv + + + + Estimated total blocks + Ligikaudne plokkide kogus + + + + Last block time + Viimane ploki aeg + + + + &Open + &Ava + + + + Command-line options + + + + + Show the Arepacoin-Qt help message to get a list with possible Arepacoin command-line options. + + + + + &Show + + + + + &Console + &Konsool + + + + Build date + Valmistusaeg + + + + Arepacoin - Debug window + + + + + Arepacoin Core + + + + + Debug log file + Debugimise logifail + + + + Open the Arepacoin debug log file from the current data directory. This can take a few seconds for large log files. + + + + + Clear console + Puhasta konsool + + + + Welcome to the Arepacoin RPC console. + + + + + Use up and down arrows to navigate history, and <b>Ctrl-L</b> to clear screen. + Ajaloo sirvimiseks kasuta üles ja alla nooli, ekraani puhastamiseks <b>Ctrl-L</b>. + + + + Type <b>help</b> for an overview of available commands. + Ülevaateks võimalikest käsklustest trüki <b>help</b>. + + + + SendCoinsDialog + + + + + + + + + + Send Coins + Müntide saatmine + + + + Coin Control Features + + + + + Inputs... + + + + + automatically selected + + + + + Insufficient funds! + + + + + Quantity: + + + + + + 0 + + + + + Bytes: + + + + + Amount: + Summa: + + + + + + + 0.00 BC + + + + + Priority: + + + + + medium + + + + + Fee: + + + + + Low Output: + + + + + no + + + + + After Fee: + + + + + Change + + + + + custom change address + + + + + Send to multiple recipients at once + Saatmine mitmele korraga + + + + Add &Recipient + Lisa &Saaja + + + + Remove all transaction fields + + + + + Clear &All + Puhasta &Kõik + + + + Balance: + Jääk: + + + + 123.456 BC + + + + + Confirm the send action + Saatmise kinnitamine + + + + S&end + S&aada + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Copy quantity + + + + + Copy amount + Kopeeri summa + + + + Copy fee + + + + + Copy after fee + + + + + Copy bytes + + + + + Copy priority + + + + + Copy low output + + + + + Copy change + + + + + <b>%1</b> to %2 (%3) + + + + + Confirm send coins + Müntide saatmise kinnitamine + + + + Are you sure you want to send %1? + + + + + and + + + + + The recipient address is not valid, please recheck. + Saaja aadress ei ole kehtiv, palun kontrolli. + + + + The amount to pay must be larger than 0. + Makstav summa peab olema suurem kui 0. + + + + The amount exceeds your balance. + Summa ületab jäägi. + + + + The total exceeds your balance when the %1 transaction fee is included. + Summa koos tehingu tasuga %1 ületab sinu jääki. + + + + Duplicate address found, can only send to each address once per send operation. + Ühe saatmisega topelt-adressaati olla ei tohi. + + + + Error: Transaction creation failed. + + + + + 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. + + + + + WARNING: Invalid Arepacoin address + + + + + (no label) + (silti pole) + + + + WARNING: unknown change address + + + + + SendCoinsEntry + + + Form + + + + + A&mount: + S&umma: + + + + Pay &To: + Maksa &: + + + + + Enter a label for this address to add it to your address book + Aadressiraamatusse sisestamiseks märgista aadress + + + + &Label: + &Märgis + + + + The address to send the payment to (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Choose address from address book + + + + + Alt+A + Alt+A + + + + Paste address from clipboard + Kleebi aadress vahemälust + + + + Alt+P + Alt+P + + + + Remove this recipient + + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + SignVerifyMessageDialog + + + Signatures - Sign / Verify a Message + Signatuurid - Allkirjasta / Kinnita Sõnum + + + + + &Sign Message + &Allkirjastamise teade + + + + You can sign messages with your addresses to prove you own them. Be careful not to sign anything vague, as phishing attacks may try to trick you into signing your identity over to them. Only sign fully-detailed statements you agree to. + Omandiõigsuse tõestamiseks saad sõnumeid allkirjastada oma aadressiga. Ettevaatust petturitega, kes üritavad saada sinu allkirja endale saada. Allkirjasta ainult korralikult täidetud avaldusi, millega nõustud. + + + + The address to sign the message with (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + + Choose an address from the address book + + + + + + Alt+A + Alt+A + + + + Paste address from clipboard + Kleebi aadress vahemälust + + + + Alt+P + Alt+P + + + + Enter the message you want to sign here + Sisesta siia allkirjastamise sõnum + + + + Copy the current signature to the system clipboard + Kopeeri praegune signatuur vahemällu + + + + Sign the message to prove you own this Arepacoin address + + + + + Reset all sign message fields + Tühjenda kõik sõnumi allkirjastamise väljad + + + + + Clear &All + Puhasta &Kõik + + + + + &Verify Message + &Kinnita Sõnum + + + + Enter the signing address, message (ensure you copy line breaks, spaces, tabs, etc. exactly) and signature below to verify the message. Be careful not to read more into the signature than what is in the signed message itself, to avoid being tricked by a man-in-the-middle attack. + Kinnitamiseks sisesta allkirjastamise aadress, sõnum (kindlasti kopeeri täpselt ka reavahetused, tühikud, tabulaatorid jms) ning allolev signatuur. + + + + The address the message was signed with (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Verify the message to ensure it was signed with the specified Arepacoin address + + + + + Reset all verify message fields + Tühjenda kõik sõnumi kinnitamise väljad + + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Click "Sign Message" to generate signature + Signatuuri genereerimiseks vajuta "Allkirjasta Sõnum" + + + + Enter Arepacoin signature + + + + + + The entered address is invalid. + Sisestatud aadress ei kehti. + + + + + + + Please check the address and try again. + Palun kontrolli aadressi ning proovi uuesti. + + + + + The entered address does not refer to a key. + Sisestatud aadress ei viita võtmele. + + + + Wallet unlock was cancelled. + Rahakoti avamine katkestati. + + + + Private key for the entered address is not available. + Sisestatud aadressi privaatvõti ei ole saadaval. + + + + Message signing failed. + Sõnumi signeerimine ebaõnnestus. + + + + Message signed. + Sõnum signeeritud. + + + + The signature could not be decoded. + Signatuuri ei õnnestunud dekodeerida. + + + + + Please check the signature and try again. + Palun kontrolli signatuuri ning proovi uuesti. + + + + The signature did not match the message digest. + Signatuur ei kattunud sõnumi kokkuvõttega. + + + + Message verification failed. + Sõnumi kontroll ebaõnnestus. + + + + Message verified. + Sõnum kontrollitud. + + + + TransactionDesc + + + Open until %1 + Avatud kuni %1 + + + + Open for %n block(s) + + + + + conflicted + + + + + %1/offline + %/1offline'is + + + + %1/unconfirmed + %1/kinnitamata + + + + %1 confirmations + %1 kinnitust + + + + Status + Staatus + + + + , broadcast through %n node(s) + , levita läbi %n node'i, levita läbi %n node'i + + + + Date + Kuupäev + + + + Source + Allikas + + + + Generated + Genereeritud + + + + + From + Saatja + + + + + + To + Saaja + + + + + own address + oma aadress + + + + label + märgis + + + + + + + + Credit + Krediit + + + + matures in %n more block(s) + aegub %n bloki pärastaegub %n bloki pärast + + + + not accepted + mitte aktsepteeritud + + + + + + + Debit + Deebet + + + + Transaction fee + Tehingu tasu + + + + Net amount + Neto summa + + + + Message + Sõnum + + + + Comment + Kommentaar + + + + Transaction ID + Tehingu ID + + + + Generated coins must mature 6 blocks before they can be spent. When you generated this block, it was broadcast to the network to be added to the block chain. If it fails to get into the chain, its state will change to "not accepted" and it won't be spendable. This may occasionally happen if another node generates a block within a few seconds of yours. + + + + + Debug information + Debug'imise info + + + + Transaction + Tehing + + + + Inputs + Sisendid + + + + Amount + Kogus + + + + true + õige + + + + false + vale + + + + , has not been successfully broadcast yet + , veel esitlemata + + + + unknown + tundmatu + + + + TransactionDescDialog + + + Transaction details + Tehingu üksikasjad + + + + This pane shows a detailed description of the transaction + Paan kuvab tehingu detailid + + + + TransactionTableModel + + + Date + Kuupäev + + + + Type + Tüüp + + + + Address + Aadress + + + + Amount + Kogus + + + + Open until %1 + Avatud kuni %1 + + + + Confirmed (%1 confirmations) + Kinnitatud (%1 kinnitust) + + + + Open for %n more block(s) + Avaneb %n bloki pärastAvaneb %n bloki pärast + + + + Offline + + + + + Unconfirmed + + + + + Confirming (%1 of %2 recommended confirmations) + + + + + Conflicted + + + + + Immature (%1 confirmations, will be available after %2) + + + + + This block was not received by any other nodes and will probably not be accepted! + Antud klotsi pole saanud ükski osapool ning tõenäoliselt seda ei aktsepteerita! + + + + Generated but not accepted + Loodud, kuid aktsepteerimata + + + + Received with + Saadud koos + + + + Received from + Kellelt saadud + + + + Sent to + Saadetud + + + + Payment to yourself + Makse iseendale + + + + Mined + Mine'itud + + + + (n/a) + (n/a) + + + + Transaction status. Hover over this field to show number of confirmations. + Tehingu staatus. Kinnituste arvu kuvamiseks liigu hiire noolega selle peale. + + + + Date and time that the transaction was received. + Tehingu saamise kuupäev ning kellaaeg. + + + + Type of transaction. + Tehingu tüüp. + + + + Destination address of transaction. + Tehingu saaja aadress. + + + + Amount removed from or added to balance. + Jäägile lisatud või eemaldatud summa. + + + + TransactionView + + + + All + Kõik + + + + Today + Täna + + + + This week + Jooksev nädal + + + + This month + Jooksev kuu + + + + Last month + Eelmine kuu + + + + This year + Jooksev aasta + + + + Range... + Ulatus... + + + + Received with + Saadud koos + + + + Sent to + Saadetud + + + + To yourself + Iseendale + + + + Mined + Mine'itud + + + + Other + Muu + + + + Enter address or label to search + Otsimiseks sisesta märgis või aadress + + + + Min amount + Vähim summa + + + + Copy address + Aadressi kopeerimine + + + + Copy label + Märgise kopeerimine + + + + Copy amount + Kopeeri summa + + + + Copy transaction ID + Kopeeri tehingu ID + + + + Edit label + Märgise muutmine + + + + Show transaction details + Kuva tehingu detailid + + + + Export Transaction Data + + + + + Comma separated file (*.csv) + Komaeraldatud fail (*.csv) + + + + Confirmed + Kinnitatud + + + + Date + Kuupäev + + + + Type + Tüüp + + + + Label + Silt + + + + Address + Aadress + + + + Amount + Kogus + + + + ID + ID + + + + Error exporting + + + + + Could not write to file %1. + + + + + Range: + Ulatus: + + + + to + saaja + + + + WalletModel + + + Sending... + + + + + bitcoin-core + + + Arepacoin version + + + + + Usage: + Kasutus: + + + + Send command to -server or arepacoind + + + + + List commands + Käskluste loetelu + + + + Get help for a command + Käskluste abiinfo + + + + Options: + Valikud: + + + + Specify configuration file (default: arepacoin.conf) + + + + + Specify pid file (default: arepacoind.pid) + + + + + Specify wallet file (within data directory) + + + + + Specify data directory + Täpsusta andmekataloog + + + + Set database cache size in megabytes (default: 25) + Sea andmebaasi vahemälu suurus MB (vaikeväärtus: 25) + + + + Set database disk log size in megabytes (default: 100) + + + + + Listen for connections on <port> (default: 9853 or testnet: 19853) + + + + + Maintain at most <n> connections to peers (default: 125) + Säilita vähemalt <n> ühendust peeridega (vaikeväärtus: 125) + + + + Connect to a node to retrieve peer addresses, and disconnect + Peeri aadressi saamiseks ühendu korraks node'iga + + + + Specify your own public address + Täpsusta enda avalik aadress + + + + Bind to given address. Use [host]:port notation for IPv6 + + + + + Stake your coins to support network and gain reward (default: 1) + + + + + Threshold for disconnecting misbehaving peers (default: 100) + Ulakate peeride valulävi (vaikeväärtus: 100) + + + + Number of seconds to keep misbehaving peers from reconnecting (default: 86400) + Mitme sekundi pärast ulakad peerid tagasi võivad tulla (vaikeväärtus: 86400) + + + + An error occurred while setting up the RPC port %u for listening on IPv4: %s + RPC pordi %u kuulamiseks seadistamisel ilmnes viga IPv4'l: %s + + + + Detach block and address databases. Increases shutdown time (default: 0) + + + + + 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. + + + + + Error: This transaction requires a transaction fee of at least %s because of its amount, complexity, or use of recently received funds + + + + + Listen for JSON-RPC connections on <port> (default: 9852 or testnet: 19852) + + + + + Accept command line and JSON-RPC commands + Luba käsurea ning JSON-RPC käsklusi + + + + Error: Transaction creation failed + + + + + Error: Wallet locked, unable to create transaction + + + + + Importing blockchain data file. + + + + + Importing bootstrap blockchain data file. + + + + + Run in the background as a daemon and accept commands + Tööta taustal ning aktsepteeri käsklusi + + + + Use the test network + Testvõrgu kasutamine + + + + Accept connections from outside (default: 1 if no -proxy or -connect) + Luba välisühendusi (vaikeväärtus: 1 kui puudub -proxy või -connect) + + + + An error occurred while setting up the RPC port %u for listening on IPv6, falling back to IPv4: %s + RPC pordi %u kuulamiseks seadistamisel ilmnes viga IPv6'l, lülitumine tagasi IPv4'le : %s + + + + Error initializing database environment %s! To recover, BACKUP THAT DIRECTORY, then remove everything from it except for wallet.dat. + + + + + Set maximum size of high-priority/low-fee transactions in bytes (default: 27000) + + + + + Warning: -paytxfee is set very high! This is the transaction fee you will pay if you send a transaction. + Hoiatus: -paytxfee on seatud väga kõrgeks! See on sinu poolt makstav tehingu lisatasu. + + + + Warning: Please check that your computer's date and time are correct! If your clock is wrong Arepacoin will not work properly. + + + + + Warning: error reading wallet.dat! All keys read correctly, but transaction data or address book entries might be missing or incorrect. + Hoiatus: ilmnes tõrge wallet.dat faili lugemisel! Võtmed on terved, kuid tehingu andmed või aadressiraamatu kirjed võivad olla kadunud või vigased. + + + + Warning: wallet.dat corrupt, data salvaged! Original wallet.dat saved as wallet.{timestamp}.bak in %s; if your balance or transactions are incorrect you should restore from a backup. + Hoiatus: toimus wallet.dat faili andmete päästmine! Originaal wallet.dat nimetati kaustas %s ümber wallet.{ajatempel}.bak'iks, jäägi või tehingute ebakõlade puhul tuleks teha backup'ist taastamine. + + + + Attempt to recover private keys from a corrupt wallet.dat + Püüa vigasest wallet.dat failist taastada turvavõtmed + + + + Block creation options: + Blokeeri loomise valikud: + + + + Connect only to the specified node(s) + Ühendu ainult määratud node'i(de)ga + + + + Discover own IP address (default: 1 when listening and no -externalip) + Leia oma IP aadress (vaikeväärtus: 1, kui kuulatakse ning puudub -externalip) + + + + Failed to listen on any port. Use -listen=0 if you want this. + Pordi kuulamine nurjus. Soovikorral kasuta -listen=0. + + + + Find peers using DNS lookup (default: 1) + + + + + Sync checkpoints policy (default: strict) + + + + + Invalid -tor address: '%s' + + + + + Invalid amount for -reservebalance=<amount> + + + + + Maximum per-connection receive buffer, <n>*1000 bytes (default: 5000) + Maksimaalne saamise puhver -connection kohta , <n>*1000 baiti (vaikeväärtus: 5000) + + + + Maximum per-connection send buffer, <n>*1000 bytes (default: 1000) + Maksimaalne saatmise puhver -connection kohta , <n>*1000 baiti (vaikeväärtus: 1000) + + + + Only connect to nodes in network <net> (IPv4, IPv6 or Tor) + Ühenda ainult node'idega <net> võrgus (IPv4, IPv6 või Tor) + + + + Output extra debugging information. Implies all other -debug* options + + + + + Output extra network debugging information + + + + + Prepend debug output with timestamp + + + + + SSL options: (see the Bitcoin Wiki for SSL setup instructions) + SSL valikud: (vaata Bitcoini Wikist või SSL sätete juhendist) + + + + Select the version of socks proxy to use (4-5, default: 5) + + + + + Send trace/debug info to console instead of debug.log file + Saada jälitus/debug, debug.log faili asemel, konsooli + + + + Send trace/debug info to debugger + + + + + Set maximum block size in bytes (default: 250000) + + + + + Set minimum block size in bytes (default: 0) + Sea minimaalne bloki suurus baitides (vaikeväärtus: 0) + + + + Shrink debug.log file on client startup (default: 1 when no -debug) + Kahanda programmi käivitamisel debug.log faili (vaikeväärtus: 1, kui ei ole -debug) + + + + Specify connection timeout in milliseconds (default: 5000) + Sea ühenduse timeout millisekundites (vaikeväärtus: 5000) + + + + Unable to sign checkpoint, wrong checkpointkey? + + + + + + Use UPnP to map the listening port (default: 0) + Kasuta kuulatava pordi määramiseks UPnP ühendust (vaikeväärtus: 0) + + + + Use UPnP to map the listening port (default: 1 when listening) + Kasuta kuulatava pordi määramiseks UPnP ühendust (vaikeväärtus: 1, kui kuulatakse) + + + + Use proxy to reach tor hidden services (default: same as -proxy) + + + + + Username for JSON-RPC connections + JSON-RPC ühenduste kasutajatunnus + + + + Verifying database integrity... + + + + + WARNING: syncronized checkpoint violation detected, but skipped! + + + + + Warning: Disk space is low! + + + + + Warning: This version is obsolete, upgrade required! + Hoiatus: versioon on aegunud, uuendus on nõutav! + + + + wallet.dat corrupt, salvage failed + wallet.dat fail on katki, päästmine ebaõnnestus + + + + Password for JSON-RPC connections + JSON-RPC ühenduste salasõna + + + + %s, you must set a rpcpassword in the configuration file: + %s +It is recommended you use the following random password: +rpcuser=arepacoinrpc +rpcpassword=%s +(you do not need to remember this password) +The username and password MUST NOT be the same. +If the file does not exist, create it with owner-readable-only file permissions. +It is also recommended to set alertnotify so you are notified of problems; +for example: alertnotify=echo %%s | mail -s "Arepacoin Alert" admin@foo.com + + + + + + Find peers using internet relay chat (default: 0) + + + + + Sync time with other nodes. Disable if time on your system is precise e.g. syncing with NTP (default: 1) + + + + + When creating transactions, ignore inputs with value less than this (default: 0.01) + + + + + Allow JSON-RPC connections from specified IP address + JSON-RPC ühenduste lubamine kindla IP pealt + + + + Send commands to node running on <ip> (default: 127.0.0.1) + Saada käsklusi node'ile IP'ga <ip> (vaikeväärtus: 127.0.0.1) + + + + Execute command when the best block changes (%s in cmd is replaced by block hash) + Käivita käsklus, kui parim plokk muutub (käskluse %s asendatakse ploki hash'iga) + + + + Execute command when a wallet transaction changes (%s in cmd is replaced by TxID) + Käivita käsklus, kui rahakoti tehing muutub (%s cmd's muudetakse TxID'ks) + + + + Require a confirmations for change (default: 0) + + + + + Enforce transaction scripts to use canonical PUSH operators (default: 1) + + + + + Execute command when a relevant alert is received (%s in cmd is replaced by message) + + + + + Upgrade wallet to latest format + Uuenda rahakott uusimasse vormingusse + + + + Set key pool size to <n> (default: 100) + Sea võtmete hulgaks <n> (vaikeväärtus: 100) + + + + Rescan the block chain for missing wallet transactions + Otsi ploki jadast rahakoti kadunud tehinguid + + + + How many blocks to check at startup (default: 2500, 0 = all) + + + + + How thorough the block verification is (0-6, default: 1) + + + + + Imports blocks from external blk000?.dat file + + + + + Use OpenSSL (https) for JSON-RPC connections + Kasuta JSON-RPC ühenduste jaoks OpenSSL'i (https) + + + + Server certificate file (default: server.cert) + Serveri sertifikaadifail (vaikeväärtus: server.cert) + + + + Server private key (default: server.pem) + Serveri privaatvõti (vaikeväärtus: server.pem) + + + + Acceptable ciphers (default: TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH) + + + + + Error: Wallet unlocked for staking only, unable to create transaction. + + + + + WARNING: Invalid checkpoint found! Displayed transactions may not be correct! You may need to upgrade, or notify developers. + + + + + This help message + Käesolev abitekst + + + + Wallet %s resides outside data directory %s. + Rahakott %s paikenb väljaspool kataloogi %s. + + + + Cannot obtain a lock on data directory %s. Arepacoin is probably already running. + + + + + Arepacoin + Arepacoin + + + + Unable to bind to %s on this computer (bind returned error %d, %s) + Selle arvutiga ei ole võimalik siduda %s külge (katse nurjus %d, %s tõttu) + + + + Connect through socks proxy + + + + + Allow DNS lookups for -addnode, -seednode and -connect + -addnode, -seednode ja -connect tohivad kasutada DNS lookup'i + + + + Loading addresses... + Aadresside laadimine... + + + + Error loading blkindex.dat + Viga faili blkindex.dat laadimisel + + + + Error loading wallet.dat: Wallet corrupted + Viga wallet.dat käivitamisel. Vigane rahakkott + + + + Error loading wallet.dat: Wallet requires newer version of Arepacoin + Viga faili wallet.dat laadimisel: rahakott vajab Arepacoin'i uuemat versiooni. + + + + Wallet needed to be rewritten: restart Arepacoin to complete + Rahakott on vaja üle kirjutada: käivita Arepacoin uuesti toimingu lõpetamiseks + + + + Error loading wallet.dat + Viga wallet.dat käivitamisel + + + + Invalid -proxy address: '%s' + Vigane -proxi aadress: '%s' + + + + Unknown network specified in -onlynet: '%s' + Kirjeldatud tundmatu võrgustik -onlynet'is: '%s' + + + + Unknown -socks proxy version requested: %i + Küsitud tundmatu -socks proxi versioon: %i + + + + Cannot resolve -bind address: '%s' + Tundmatu -bind aadress: '%s' + + + + Cannot resolve -externalip address: '%s' + Tundmatu -externalip aadress: '%s' + + + + Invalid amount for -paytxfee=<amount>: '%s' + -paytxfee=<amount> jaoks vigane kogus: '%s' + + + + Error: could not start node + + + + + Sending... + Saatmine... + + + + Invalid amount + Kehtetu summa + + + + Insufficient funds + Liiga suur summa + + + + Loading block index... + Klotside indeksi laadimine... + + + + Add a node to connect to and attempt to keep the connection open + Lisa node ning hoia ühendus avatud + + + + Unable to bind to %s on this computer. Arepacoin is probably already running. + + + + + Fee per KB to add to transactions you send + + + + + Invalid amount for -mininput=<amount>: '%s' + + + + + Loading wallet... + Rahakoti laadimine... + + + + Cannot downgrade wallet + Rahakoti vanandamine ebaõnnestus + + + + Cannot initialize keypool + + + + + Cannot write default address + Tõrge vaikimisi aadressi kirjutamisel + + + + Rescanning... + Üleskaneerimine... + + + + Done loading + Laetud + + + + To use the %s option + %s valiku kasutamine + + + + Error + Tõrge + + + + You must set rpcpassword=<password> in the configuration file: +%s +If the file does not exist, create it with owner-readable-only file permissions. + rpcpassword=<password> peab sätete failis olema seadistatud:⏎ +%s⏎ +Kui seda faili ei ole, loo see ainult-omanikule-lugemiseks faili õigustes. + + + \ No newline at end of file diff --git a/src/qt/locale/bitcoin_eu_ES.ts b/src/qt/locale/bitcoin_eu_ES.ts new file mode 100755 index 0000000..defc349 --- /dev/null +++ b/src/qt/locale/bitcoin_eu_ES.ts @@ -0,0 +1,3275 @@ + + + AboutDialog + + + About Arepacoin + + + + + <b>Arepacoin</b> version + + + + + Copyright © 2009-2014 The Bitcoin developers +Copyright © 2012-2014 The NovaCoin developers +Copyright © 2014 The Arepacoin developers + + + + + +This is experimental software. + +Distributed under the MIT/X11 software license, see the accompanying file COPYING or http://www.opensource.org/licenses/mit-license.php. + +This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit (http://www.openssl.org/) and cryptographic software written by Eric Young (eay@cryptsoft.com) and UPnP software written by Thomas Bernard. + + + + + AddressBookPage + + + Address Book + + + + + Double-click to edit address or label + Klik bikoitza helbidea edo etiketa editatzeko + + + + Create a new address + Sortu helbide berria + + + + Copy the currently selected address to the system clipboard + Kopiatu hautatutako helbidea sistemaren arbelera + + + + &New Address + + + + + These are your Arepacoin addresses for receiving payments. You may want to give a different one to each sender so you can keep track of who is paying you. + + + + + &Copy Address + + + + + Show &QR Code + + + + + Sign a message to prove you own a Arepacoin address + + + + + Sign &Message + + + + + Delete the currently selected address from the list + + + + + Verify a message to ensure it was signed with a specified Arepacoin address + + + + + &Verify Message + + + + + &Delete + &Ezabatu + + + + Copy &Label + + + + + &Edit + + + + + Export Address Book Data + + + + + Comma separated file (*.csv) + Komaz bereizitako artxiboa (*.csv) + + + + Error exporting + + + + + Could not write to file %1. + + + + + AddressTableModel + + + Label + Etiketa + + + + Address + Helbidea + + + + (no label) + (etiketarik ez) + + + + AskPassphraseDialog + + + Passphrase Dialog + + + + + Enter passphrase + Sartu pasahitza + + + + New passphrase + Pasahitz berria + + + + Repeat new passphrase + Errepikatu pasahitz berria + + + + Serves to disable the trivial sendmoney when OS account compromised. Provides no real security. + + + + + For staking only + + + + + Enter the new passphrase to the wallet.<br/>Please use a passphrase of <b>10 or more random characters</b>, or <b>eight or more words</b>. + Sartu zorrorako pasahitz berria.<br/> Mesedez erabili <b>gutxienez ausazko 10 karaktere</b>, edo <b>gutxienez zortzi hitz</b> pasahitza osatzeko. + + + + Encrypt wallet + Enkriptatu zorroa + + + + This operation needs your wallet passphrase to unlock the wallet. + Eragiketa honek zorroaren pasahitza behar du zorroa desblokeatzeko. + + + + Unlock wallet + Desblokeatu zorroa + + + + This operation needs your wallet passphrase to decrypt the wallet. + Eragiketa honek zure zorroaren pasahitza behar du, zorroa desenkriptatzeko. + + + + Decrypt wallet + Desenkriptatu zorroa + + + + Change passphrase + Aldatu pasahitza + + + + Enter the old and new passphrase to the wallet. + Sartu zorroaren pasahitz zaharra eta berria. + + + + Confirm wallet encryption + Berretsi zorroaren enkriptazioa + + + + Warning: If you encrypt your wallet and lose your passphrase, you will <b>LOSE ALL OF YOUR COINS</b>! + + + + + Are you sure you wish to encrypt your wallet? + + + + + IMPORTANT: Any previous backups you have made of your wallet file should be replaced with the newly generated, encrypted wallet file. For security reasons, previous backups of the unencrypted wallet file will become useless as soon as you start using the new, encrypted wallet. + + + + + + Warning: The Caps Lock key is on! + + + + + + Wallet encrypted + Zorroa enkriptatuta + + + + Arepacoin will close now to finish the encryption process. Remember that encrypting your wallet cannot fully protect your coins from being stolen by malware infecting your computer. + + + + + + + + Wallet encryption failed + Zorroaren enkriptazioak huts egin du + + + + Wallet encryption failed due to an internal error. Your wallet was not encrypted. + Zorroaren enkriptazioak huts egin du barne-errore baten ondorioz. Zure zorroa ez da enkriptatu. + + + + + The supplied passphrases do not match. + Eman dituzun pasahitzak ez datoz bat. + + + + Wallet unlock failed + Zorroaren desblokeoak huts egin du + + + + + + The passphrase entered for the wallet decryption was incorrect. + Zorroa desenkriptatzeko sartutako pasahitza okerra da. + + + + Wallet decryption failed + Zorroaren desenkriptazioak huts egin du + + + + Wallet passphrase was successfully changed. + + + + + BitcoinGUI + + + Sign &message... + + + + + Synchronizing with network... + Sarearekin sinkronizatzen... + + + + &Overview + &Gainbegiratu + + + + Show general overview of wallet + Ikusi zorroaren begirada orokorra + + + + &Transactions + &Transakzioak + + + + Browse transaction history + Ikusi transakzioen historia + + + + &Address Book + + + + + Edit the list of stored addresses and labels + + + + + &Receive coins + + + + + Show the list of addresses for receiving payments + + + + + &Send coins + + + + + E&xit + Irten + + + + Quit application + Irten aplikaziotik + + + + Show information about Arepacoin + + + + + About &Qt + &Qt-ari buruz + + + + Show information about Qt + Erakutsi Bitcoin-i buruzko informazioa + + + + &Options... + &Aukerak... + + + + &Encrypt Wallet... + + + + + &Backup Wallet... + + + + + &Change Passphrase... + + + + + ~%n block(s) remaining + + + + + Downloaded %1 of %2 blocks of transaction history (%3% done). + + + + + &Export... + + + + + Send coins to a Arepacoin address + + + + + Modify configuration options for Arepacoin + + + + + Export the data in the current tab to a file + + + + + Encrypt or decrypt wallet + + + + + Backup wallet to another location + + + + + Change the passphrase used for wallet encryption + Aldatu zorroa enkriptatzeko erabilitako pasahitza + + + + &Debug window + + + + + Open debugging and diagnostic console + + + + + &Verify message... + + + + + Arepacoin + + + + + Wallet + + + + + &About Arepacoin + + + + + &Show / Hide + + + + + Unlock wallet + + + + + &Lock Wallet + + + + + Lock wallet + + + + + &File + &Artxiboa + + + + &Settings + &Ezarpenak + + + + &Help + &Laguntza + + + + Tabs toolbar + Fitxen tresna-barra + + + + Actions toolbar + + + + + + [testnet] + [testnet] + + + + + Arepacoin client + + + + + %n active connection(s) to Arepacoin network + + + + + Downloaded %1 blocks of transaction history. + + + + + Staking.<br>Your weight is %1<br>Network weight is %2<br>Expected time to earn reward is %3 + + + + + Not staking because wallet is locked + + + + + Not staking because wallet is offline + + + + + Not staking because wallet is syncing + + + + + Not staking because you don't have mature coins + + + + + %n second(s) ago + + + + + &Unlock Wallet... + + + + + %n minute(s) ago + + + + + %n hour(s) ago + + + + + %n day(s) ago + + + + + Up to date + Egunean + + + + Catching up... + Eguneratzen... + + + + Last received block was generated %1. + + + + + This transaction is over the size limit. You can still send it for a fee of %1, which goes to the nodes that process your transaction and helps to support the network. Do you want to pay the fee? + + + + + Confirm transaction fee + + + + + Sent transaction + Bidalitako transakzioa + + + + Incoming transaction + Sarrerako transakzioa + + + + Date: %1 +Amount: %2 +Type: %3 +Address: %4 + + + + + + + URI handling + + + + + + URI can not be parsed! This can be caused by an invalid Arepacoin address or malformed URI parameters. + + + + + Wallet is <b>encrypted</b> and currently <b>unlocked</b> + Zorroa <b>enkriptatuta</b> eta <b>desblokeatuta</b> dago une honetan + + + + Wallet is <b>encrypted</b> and currently <b>locked</b> + Zorroa <b>enkriptatuta</b> eta <b>blokeatuta</b> dago une honetan + + + + Backup Wallet + + + + + Wallet Data (*.dat) + + + + + Backup Failed + + + + + There was an error trying to save the wallet data to the new location. + + + + + %n second(s) + + + + + %n minute(s) + + + + + %n hour(s) + + + + + %n day(s) + + + + + Not staking + + + + + A fatal error occurred. Arepacoin can no longer continue safely and will quit. + + + + + ClientModel + + + Network Alert + + + + + CoinControlDialog + + + Coin Control + + + + + Quantity: + + + + + Bytes: + + + + + Amount: + Kopurua + + + + Priority: + + + + + Fee: + + + + + Low Output: + + + + + no + + + + + After Fee: + + + + + Change: + + + + + (un)select all + + + + + Tree mode + + + + + List mode + + + + + Amount + Kopurua + + + + Label + + + + + Address + Helbidea + + + + Date + Data + + + + Confirmations + + + + + Confirmed + + + + + Priority + + + + + Copy address + Kopiatu helbidea + + + + Copy label + Kopiatu etiketa + + + + + Copy amount + + + + + Copy transaction ID + + + + + Copy quantity + + + + + Copy fee + + + + + Copy after fee + + + + + Copy bytes + + + + + Copy priority + + + + + Copy low output + + + + + Copy change + + + + + highest + + + + + high + + + + + medium-high + + + + + medium + + + + + low-medium + + + + + low + + + + + lowest + + + + + DUST + + + + + yes + + + + + This label turns red, if the transaction size is bigger than 10000 bytes. + + This means a fee of at least %1 per kb is required. + + Can vary +/- 1 Byte per input. + + + + + Transactions with higher priority get more likely into a block. + +This label turns red, if the priority is smaller than "medium". + + This means a fee of at least %1 per kb is required. + + + + + This label turns red, if any recipient receives an amount smaller than %1. + + This means a fee of at least %2 is required. + + Amounts below 0.546 times the minimum relay fee are shown as DUST. + + + + + This label turns red, if the change is smaller than %1. + + This means a fee of at least %2 is required. + + + + + + (no label) + (etiketarik ez) + + + + change from %1 (%2) + + + + + (change) + + + + + EditAddressDialog + + + Edit Address + Editatu helbidea + + + + &Label + &Etiketa + + + + The label associated with this address book entry + + + + + &Address + &Helbidea + + + + The address associated with this address book entry. This can only be modified for sending addresses. + + + + + New receiving address + Jasotzeko helbide berria + + + + New sending address + Bidaltzeko helbide berria + + + + Edit receiving address + Editatu jasotzeko helbidea + + + + Edit sending address + Editatu bidaltzeko helbidea + + + + The entered address "%1" is already in the address book. + Sartu berri den helbidea, "%1", helbide-liburuan dago jadanik. + + + + The entered address "%1" is not a valid Arepacoin address. + + + + + Could not unlock wallet. + Ezin desblokeatu zorroa. + + + + New key generation failed. + Gako berriaren sorrerak huts egin du. + + + + GUIUtil::HelpMessageBox + + + + Arepacoin-Qt + + + + + version + + + + + Usage: + + + + + command-line options + + + + + UI options + + + + + Set language, for example "de_DE" (default: system locale) + + + + + Start minimized + + + + + Show splash screen on startup (default: 1) + + + + + OptionsDialog + + + Options + Aukerak + + + + &Main + + + + + Optional transaction fee per kB that helps make sure your transactions are processed quickly. Most transactions are 1 kB. Fee 0.01 recommended. + + + + + Pay transaction &fee + + + + + Reserved amount does not participate in staking and is therefore spendable at any time. + + + + + Reserve + + + + + Automatically start Arepacoin after logging in to the system. + + + + + &Start Arepacoin on system login + + + + + Detach block and address databases at shutdown. This means they can be moved to another data directory, but it slows down shutdown. The wallet is always detached. + + + + + &Detach databases at shutdown + + + + + &Network + + + + + Automatically open the Arepacoin client port on the router. This only works when your router supports UPnP and it is enabled. + + + + + Map port using &UPnP + + + + + Connect to the Arepacoin network through a SOCKS proxy (e.g. when connecting through Tor). + + + + + &Connect through SOCKS proxy: + + + + + Proxy &IP: + + + + + IP address of the proxy (e.g. 127.0.0.1) + + + + + &Port: + + + + + Port of the proxy (e.g. 9050) + + + + + SOCKS &Version: + + + + + SOCKS version of the proxy (e.g. 5) + + + + + &Window + + + + + Show only a tray icon after minimizing the window. + + + + + &Minimize to the tray instead of the taskbar + + + + + Minimize instead of exit the application when the window is closed. When this option is enabled, the application will be closed only after selecting Quit in the menu. + + + + + M&inimize on close + + + + + &Display + + + + + User Interface &language: + + + + + The user interface language can be set here. This setting will take effect after restarting Arepacoin. + + + + + &Unit to show amounts in: + + + + + Choose the default subdivision unit to show in the interface and when sending coins. + + + + + Whether to show Arepacoin addresses in the transaction list or not. + + + + + &Display addresses in transaction list + + + + + Whether to show coin control features or not. + + + + + Display coin &control features (experts only!) + + + + + &OK + + + + + &Cancel + + + + + &Apply + + + + + default + + + + + + Warning + + + + + + This setting will take effect after restarting Arepacoin. + + + + + The supplied proxy address is invalid. + + + + + OverviewPage + + + Form + Inprimakia + + + + + The displayed information may be out of date. Your wallet automatically synchronizes with the Arepacoin network after a connection is established, but this process has not completed yet. + + + + + Stake: + + + + + Unconfirmed: + + + + + Wallet + + + + + Spendable: + + + + + Your current spendable balance + + + + + Immature: + + + + + Mined balance that has not yet matured + + + + + Total: + + + + + Your current total balance + + + + + <b>Recent transactions</b> + <b>Azken transakzioak</b> + + + + Total of transactions that have yet to be confirmed, and do not yet count toward the current balance + + + + + Total of coins that was staked, and do not yet count toward the current balance + + + + + + out of sync + + + + + QRCodeDialog + + + QR Code Dialog + + + + + Request Payment + + + + + Amount: + + + + + Label: + + + + + Message: + + + + + &Save As... + + + + + Error encoding URI into QR Code. + + + + + The entered amount is invalid, please check. + + + + + Resulting URI too long, try to reduce the text for label / message. + + + + + Save QR Code + + + + + PNG Images (*.png) + + + + + RPCConsole + + + Client name + + + + + + + + + + + + + + N/A + + + + + Client version + + + + + &Information + + + + + Using OpenSSL version + + + + + Startup time + + + + + Network + + + + + Number of connections + + + + + On testnet + + + + + Block chain + + + + + Current number of blocks + + + + + Estimated total blocks + + + + + Last block time + + + + + &Open + + + + + Command-line options + + + + + Show the Arepacoin-Qt help message to get a list with possible Arepacoin command-line options. + + + + + &Show + + + + + &Console + + + + + Build date + + + + + Arepacoin - Debug window + + + + + Arepacoin Core + + + + + Debug log file + + + + + Open the Arepacoin debug log file from the current data directory. This can take a few seconds for large log files. + + + + + Clear console + + + + + Welcome to the Arepacoin RPC console. + + + + + Use up and down arrows to navigate history, and <b>Ctrl-L</b> to clear screen. + + + + + Type <b>help</b> for an overview of available commands. + + + + + SendCoinsDialog + + + + + + + + + + Send Coins + Bidali txanponak + + + + Coin Control Features + + + + + Inputs... + + + + + automatically selected + + + + + Insufficient funds! + + + + + Quantity: + + + + + + 0 + + + + + Bytes: + + + + + Amount: + Kopurua + + + + + + + 0.00 BC + + + + + Priority: + + + + + medium + + + + + Fee: + + + + + Low Output: + + + + + no + + + + + After Fee: + + + + + Change + + + + + custom change address + + + + + Send to multiple recipients at once + Bidali hainbat jasotzaileri batera + + + + Add &Recipient + + + + + Remove all transaction fields + + + + + Clear &All + + + + + Balance: + Saldoa: + + + + 123.456 BC + + + + + Confirm the send action + Berretsi bidaltzeko ekintza + + + + S&end + + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Copy quantity + + + + + Copy amount + + + + + Copy fee + + + + + Copy after fee + + + + + Copy bytes + + + + + Copy priority + + + + + Copy low output + + + + + Copy change + + + + + <b>%1</b> to %2 (%3) + + + + + Confirm send coins + Berretsi txanponak bidaltzea + + + + Are you sure you want to send %1? + + + + + and + + + + + The recipient address is not valid, please recheck. + + + + + The amount to pay must be larger than 0. + Ordaintzeko kopurua 0 baino handiagoa izan behar du. + + + + The amount exceeds your balance. + + + + + The total exceeds your balance when the %1 transaction fee is included. + + + + + Duplicate address found, can only send to each address once per send operation. + + + + + Error: Transaction creation failed. + + + + + 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. + + + + + WARNING: Invalid Arepacoin address + + + + + (no label) + (etiketarik ez) + + + + WARNING: unknown change address + + + + + SendCoinsEntry + + + Form + + + + + A&mount: + K&opurua: + + + + Pay &To: + Ordaindu &honi: + + + + + Enter a label for this address to add it to your address book + Sartu etiketa bat helbide honetarako, eta gehitu zure helbide-liburuan + + + + &Label: + &Etiketa: + + + + The address to send the payment to (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Choose address from address book + + + + + Alt+A + Alt+A + + + + Paste address from clipboard + Itsatsi helbidea arbeletik + + + + Alt+P + Alt+P + + + + Remove this recipient + + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + SignVerifyMessageDialog + + + Signatures - Sign / Verify a Message + + + + + + &Sign Message + + + + + You can sign messages with your addresses to prove you own them. Be careful not to sign anything vague, as phishing attacks may try to trick you into signing your identity over to them. Only sign fully-detailed statements you agree to. + + + + + The address to sign the message with (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + + Choose an address from the address book + + + + + + Alt+A + Alt+A + + + + Paste address from clipboard + Itsatsi helbidea arbeletik + + + + Alt+P + Alt+P + + + + Enter the message you want to sign here + + + + + Copy the current signature to the system clipboard + + + + + Sign the message to prove you own this Arepacoin address + + + + + Reset all sign message fields + + + + + + Clear &All + + + + + + &Verify Message + + + + + Enter the signing address, message (ensure you copy line breaks, spaces, tabs, etc. exactly) and signature below to verify the message. Be careful not to read more into the signature than what is in the signed message itself, to avoid being tricked by a man-in-the-middle attack. + + + + + The address the message was signed with (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Verify the message to ensure it was signed with the specified Arepacoin address + + + + + Reset all verify message fields + + + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Click "Sign Message" to generate signature + + + + + Enter Arepacoin signature + + + + + + The entered address is invalid. + + + + + + + + Please check the address and try again. + + + + + + The entered address does not refer to a key. + + + + + Wallet unlock was cancelled. + + + + + Private key for the entered address is not available. + + + + + Message signing failed. + + + + + Message signed. + + + + + The signature could not be decoded. + + + + + + Please check the signature and try again. + + + + + The signature did not match the message digest. + + + + + Message verification failed. + + + + + Message verified. + + + + + TransactionDesc + + + Open until %1 + Zabalik %1 arte + + + + Open for %n block(s) + + + + + conflicted + + + + + %1/offline + + + + + %1/unconfirmed + %1/konfirmatu gabe + + + + %1 confirmations + %1 konfirmazioak + + + + Status + + + + + , broadcast through %n node(s) + + + + + Date + Data + + + + Source + + + + + Generated + + + + + + From + + + + + + + To + + + + + + own address + + + + + label + + + + + + + + + Credit + + + + + matures in %n more block(s) + + + + + not accepted + + + + + + + + Debit + + + + + Transaction fee + + + + + Net amount + + + + + Message + + + + + Comment + + + + + Transaction ID + + + + + Generated coins must mature 6 blocks before they can be spent. When you generated this block, it was broadcast to the network to be added to the block chain. If it fails to get into the chain, its state will change to "not accepted" and it won't be spendable. This may occasionally happen if another node generates a block within a few seconds of yours. + + + + + Debug information + + + + + Transaction + + + + + Inputs + + + + + Amount + Kopurua + + + + true + + + + + false + + + + + , has not been successfully broadcast yet + , ez da arrakastaz emititu oraindik + + + + unknown + ezezaguna + + + + TransactionDescDialog + + + Transaction details + Transakzioaren xehetasunak + + + + This pane shows a detailed description of the transaction + Panel honek transakzioaren deskribapen xehea erakusten du + + + + TransactionTableModel + + + Date + Data + + + + Type + Mota + + + + Address + Helbidea + + + + Amount + Kopurua + + + + Open until %1 + Zabalik %1 arte + + + + Confirmed (%1 confirmations) + Konfirmatuta (%1 konfirmazio) + + + + Open for %n more block(s) + + + + + Offline + + + + + Unconfirmed + + + + + Confirming (%1 of %2 recommended confirmations) + + + + + Conflicted + + + + + Immature (%1 confirmations, will be available after %2) + + + + + This block was not received by any other nodes and will probably not be accepted! + Bloke hau ez du beste inongo nodorik jaso, eta seguruenik ez da onartuko! + + + + Generated but not accepted + Sortua, baina ez onartua + + + + Received with + Jasoa honekin: + + + + Received from + + + + + Sent to + Honi bidalia: + + + + Payment to yourself + Ordainketa zeure buruari + + + + Mined + Bildua + + + + (n/a) + (n/a) + + + + Transaction status. Hover over this field to show number of confirmations. + Transakzioaren egoera. Pasatu sagua gainetik konfirmazio kopurua ikusteko. + + + + Date and time that the transaction was received. + Transakzioa jasotako data eta ordua. + + + + Type of transaction. + Transakzio mota. + + + + Destination address of transaction. + Transakzioaren xede-helbidea. + + + + Amount removed from or added to balance. + Saldoan kendu edo gehitutako kopurua. + + + + TransactionView + + + + All + Denak + + + + Today + Gaur + + + + This week + Aste honetan + + + + This month + Hil honetan + + + + Last month + Azken hilean + + + + This year + Aurten + + + + Range... + Muga... + + + + Received with + Jasota honekin: + + + + Sent to + Hona bidalia: + + + + To yourself + Zeure buruari + + + + Mined + Bildua + + + + Other + Beste + + + + Enter address or label to search + Sartu bilatzeko helbide edo etiketa + + + + Min amount + Kopuru minimoa + + + + Copy address + Kopiatu helbidea + + + + Copy label + Kopiatu etiketa + + + + Copy amount + + + + + Copy transaction ID + + + + + Edit label + + + + + Show transaction details + + + + + Export Transaction Data + + + + + Comma separated file (*.csv) + Komaz bereizitako artxiboa (*.csv) + + + + Confirmed + + + + + Date + Data + + + + Type + Mota + + + + Label + Etiketa + + + + Address + Helbidea + + + + Amount + Kopurua + + + + ID + + + + + Error exporting + + + + + Could not write to file %1. + + + + + Range: + + + + + to + + + + + WalletModel + + + Sending... + + + + + bitcoin-core + + + Arepacoin version + + + + + Usage: + + + + + Send command to -server or arepacoind + + + + + List commands + Komandoen lista + + + + Get help for a command + Laguntza komando batean + + + + Options: + Aukerak + + + + Specify configuration file (default: arepacoin.conf) + + + + + Specify pid file (default: arepacoind.pid) + + + + + Specify wallet file (within data directory) + + + + + Specify data directory + + + + + Set database cache size in megabytes (default: 25) + + + + + Set database disk log size in megabytes (default: 100) + + + + + Listen for connections on <port> (default: 9853 or testnet: 19853) + + + + + Maintain at most <n> connections to peers (default: 125) + + + + + Connect to a node to retrieve peer addresses, and disconnect + + + + + Specify your own public address + + + + + Bind to given address. Use [host]:port notation for IPv6 + + + + + Stake your coins to support network and gain reward (default: 1) + + + + + Threshold for disconnecting misbehaving peers (default: 100) + + + + + Number of seconds to keep misbehaving peers from reconnecting (default: 86400) + + + + + An error occurred while setting up the RPC port %u for listening on IPv4: %s + + + + + Detach block and address databases. Increases shutdown time (default: 0) + + + + + 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. + + + + + Error: This transaction requires a transaction fee of at least %s because of its amount, complexity, or use of recently received funds + + + + + Listen for JSON-RPC connections on <port> (default: 9852 or testnet: 19852) + + + + + Accept command line and JSON-RPC commands + + + + + Error: Transaction creation failed + + + + + Error: Wallet locked, unable to create transaction + + + + + Importing blockchain data file. + + + + + Importing bootstrap blockchain data file. + + + + + Run in the background as a daemon and accept commands + + + + + Use the test network + + + + + Accept connections from outside (default: 1 if no -proxy or -connect) + + + + + An error occurred while setting up the RPC port %u for listening on IPv6, falling back to IPv4: %s + + + + + Error initializing database environment %s! To recover, BACKUP THAT DIRECTORY, then remove everything from it except for wallet.dat. + + + + + Set maximum size of high-priority/low-fee transactions in bytes (default: 27000) + + + + + Warning: -paytxfee is set very high! This is the transaction fee you will pay if you send a transaction. + + + + + Warning: Please check that your computer's date and time are correct! If your clock is wrong Arepacoin will not work properly. + + + + + Warning: error reading wallet.dat! All keys read correctly, but transaction data or address book entries might be missing or incorrect. + + + + + Warning: wallet.dat corrupt, data salvaged! Original wallet.dat saved as wallet.{timestamp}.bak in %s; if your balance or transactions are incorrect you should restore from a backup. + + + + + Attempt to recover private keys from a corrupt wallet.dat + + + + + Block creation options: + + + + + Connect only to the specified node(s) + + + + + Discover own IP address (default: 1 when listening and no -externalip) + + + + + Failed to listen on any port. Use -listen=0 if you want this. + + + + + Find peers using DNS lookup (default: 1) + + + + + Sync checkpoints policy (default: strict) + + + + + Invalid -tor address: '%s' + + + + + Invalid amount for -reservebalance=<amount> + + + + + Maximum per-connection receive buffer, <n>*1000 bytes (default: 5000) + + + + + Maximum per-connection send buffer, <n>*1000 bytes (default: 1000) + + + + + Only connect to nodes in network <net> (IPv4, IPv6 or Tor) + + + + + Output extra debugging information. Implies all other -debug* options + + + + + Output extra network debugging information + + + + + Prepend debug output with timestamp + + + + + SSL options: (see the Bitcoin Wiki for SSL setup instructions) + + + + + Select the version of socks proxy to use (4-5, default: 5) + + + + + Send trace/debug info to console instead of debug.log file + + + + + Send trace/debug info to debugger + + + + + Set maximum block size in bytes (default: 250000) + + + + + Set minimum block size in bytes (default: 0) + + + + + Shrink debug.log file on client startup (default: 1 when no -debug) + + + + + Specify connection timeout in milliseconds (default: 5000) + + + + + Unable to sign checkpoint, wrong checkpointkey? + + + + + + Use UPnP to map the listening port (default: 0) + + + + + Use UPnP to map the listening port (default: 1 when listening) + + + + + Use proxy to reach tor hidden services (default: same as -proxy) + + + + + Username for JSON-RPC connections + + + + + Verifying database integrity... + + + + + WARNING: syncronized checkpoint violation detected, but skipped! + + + + + Warning: Disk space is low! + + + + + Warning: This version is obsolete, upgrade required! + + + + + wallet.dat corrupt, salvage failed + + + + + Password for JSON-RPC connections + + + + + %s, you must set a rpcpassword in the configuration file: + %s +It is recommended you use the following random password: +rpcuser=arepacoinrpc +rpcpassword=%s +(you do not need to remember this password) +The username and password MUST NOT be the same. +If the file does not exist, create it with owner-readable-only file permissions. +It is also recommended to set alertnotify so you are notified of problems; +for example: alertnotify=echo %%s | mail -s "Arepacoin Alert" admin@foo.com + + + + + + Find peers using internet relay chat (default: 0) + + + + + Sync time with other nodes. Disable if time on your system is precise e.g. syncing with NTP (default: 1) + + + + + When creating transactions, ignore inputs with value less than this (default: 0.01) + + + + + Allow JSON-RPC connections from specified IP address + + + + + Send commands to node running on <ip> (default: 127.0.0.1) + + + + + Execute command when the best block changes (%s in cmd is replaced by block hash) + + + + + Execute command when a wallet transaction changes (%s in cmd is replaced by TxID) + + + + + Require a confirmations for change (default: 0) + + + + + Enforce transaction scripts to use canonical PUSH operators (default: 1) + + + + + Execute command when a relevant alert is received (%s in cmd is replaced by message) + + + + + Upgrade wallet to latest format + + + + + Set key pool size to <n> (default: 100) + + + + + Rescan the block chain for missing wallet transactions + + + + + How many blocks to check at startup (default: 2500, 0 = all) + + + + + How thorough the block verification is (0-6, default: 1) + + + + + Imports blocks from external blk000?.dat file + + + + + Use OpenSSL (https) for JSON-RPC connections + + + + + Server certificate file (default: server.cert) + + + + + Server private key (default: server.pem) + + + + + Acceptable ciphers (default: TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH) + + + + + Error: Wallet unlocked for staking only, unable to create transaction. + + + + + WARNING: Invalid checkpoint found! Displayed transactions may not be correct! You may need to upgrade, or notify developers. + + + + + This help message + Laguntza mezu hau + + + + Wallet %s resides outside data directory %s. + + + + + Cannot obtain a lock on data directory %s. Arepacoin is probably already running. + + + + + Arepacoin + + + + + Unable to bind to %s on this computer (bind returned error %d, %s) + + + + + Connect through socks proxy + + + + + Allow DNS lookups for -addnode, -seednode and -connect + + + + + Loading addresses... + + + + + Error loading blkindex.dat + + + + + Error loading wallet.dat: Wallet corrupted + + + + + Error loading wallet.dat: Wallet requires newer version of Arepacoin + + + + + Wallet needed to be rewritten: restart Arepacoin to complete + + + + + Error loading wallet.dat + + + + + Invalid -proxy address: '%s' + + + + + Unknown network specified in -onlynet: '%s' + + + + + Unknown -socks proxy version requested: %i + + + + + Cannot resolve -bind address: '%s' + + + + + Cannot resolve -externalip address: '%s' + + + + + Invalid amount for -paytxfee=<amount>: '%s' + + + + + Error: could not start node + + + + + Sending... + + + + + Invalid amount + + + + + Insufficient funds + + + + + Loading block index... + + + + + Add a node to connect to and attempt to keep the connection open + + + + + Unable to bind to %s on this computer. Arepacoin is probably already running. + + + + + Fee per KB to add to transactions you send + + + + + Invalid amount for -mininput=<amount>: '%s' + + + + + Loading wallet... + + + + + Cannot downgrade wallet + + + + + Cannot initialize keypool + + + + + Cannot write default address + + + + + Rescanning... + Birbilatzen... + + + + Done loading + Zamaketa amaitua + + + + To use the %s option + + + + + Error + + + + + You must set rpcpassword=<password> in the configuration file: +%s +If the file does not exist, create it with owner-readable-only file permissions. + + + + \ No newline at end of file diff --git a/src/qt/locale/bitcoin_fa.ts b/src/qt/locale/bitcoin_fa.ts new file mode 100755 index 0000000..34514df --- /dev/null +++ b/src/qt/locale/bitcoin_fa.ts @@ -0,0 +1,3280 @@ + + + AboutDialog + + + About Arepacoin + + + + + <b>Arepacoin</b> version + + + + + Copyright © 2009-2014 The Bitcoin developers +Copyright © 2012-2014 The NovaCoin developers +Copyright © 2014 The Arepacoin developers + + + + + +This is experimental software. + +Distributed under the MIT/X11 software license, see the accompanying file COPYING or http://www.opensource.org/licenses/mit-license.php. + +This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit (http://www.openssl.org/) and cryptographic software written by Eric Young (eay@cryptsoft.com) and UPnP software written by Thomas Bernard. + ⏎ ⏎ این یک نرم‌افزار آزمایشی است⏎ ⏎ نرم افزار تحت مجوز MIT/X11 منتشر شده است. پروندهٔ COPYING یا نشانی http://www.opensource.org/licenses/mit-license.php. را ببینید⏎ ⏎ این محصول شامل نرم‌افزار توسعه داده‌شده در پروژهٔ OpenSSL است. در این نرم‌افزار از OpenSSL Toolkit (http://www.openssl.org/) و نرم‌افزار رمزنگاری نوشته شده توسط اریک یانگ (eay@cryptsoft.com) و UPnP توسط توماس برنارد استفاده شده است. + + + + AddressBookPage + + + Address Book + + + + + Double-click to edit address or label + برای ویرایش نشانی یا برچسب دوبار کلیک کنید + + + + Create a new address + ایجاد نشانی جدید + + + + Copy the currently selected address to the system clipboard + نشانی انتخاب شده را در حافظهٔ سیستم کپی کن! + + + + &New Address + + + + + These are your Arepacoin addresses for receiving payments. You may want to give a different one to each sender so you can keep track of who is paying you. + + + + + &Copy Address + &کپی نشانی + + + + Show &QR Code + + + + + Sign a message to prove you own a Arepacoin address + + + + + Sign &Message + + + + + Delete the currently selected address from the list + حذف نشانی انتخاب‌شده از لیست + + + + Verify a message to ensure it was signed with a specified Arepacoin address + + + + + &Verify Message + + + + + &Delete + &حذف + + + + Copy &Label + کپی و برچسب‌&گذاری + + + + &Edit + &ویرایش + + + + Export Address Book Data + + + + + Comma separated file (*.csv) + پروندهٔ نوع CSV جداشونده با کاما (*.csv) + + + + Error exporting + + + + + Could not write to file %1. + + + + + AddressTableModel + + + Label + برچسب + + + + Address + نشانی + + + + (no label) + (بدون برچسب) + + + + AskPassphraseDialog + + + Passphrase Dialog + پنجرهٔ گذرواژه + + + + Enter passphrase + گذرواژه را وارد کنید + + + + New passphrase + گذرواژهٔ جدید + + + + Repeat new passphrase + تکرار گذرواژهٔ جدید + + + + Serves to disable the trivial sendmoney when OS account compromised. Provides no real security. + + + + + For staking only + + + + + Enter the new passphrase to the wallet.<br/>Please use a passphrase of <b>10 or more random characters</b>, or <b>eight or more words</b>. + گذرواژهٔ جدید کیف پول خود را وارد کنید.<br/>لطفاً از گذرواژه‌ای با <b>حداقل ۱۰ حرف تصادفی</b>، یا <b>حداقل هشت کلمه</b> انتخاب کنید. + + + + Encrypt wallet + رمزنگاری کیف پول + + + + This operation needs your wallet passphrase to unlock the wallet. + انجام این عملیات نیازمند گذرواژهٔ کیف پول شما برای باز کردن قفل آن است. + + + + Unlock wallet + باز کردن قفل کیف پول + + + + This operation needs your wallet passphrase to decrypt the wallet. + انجام این عملیات نیازمند گذرواژهٔ کیف پول شما برای رمزگشایی کردن آن است. + + + + Decrypt wallet + رمزگشایی کیف پول + + + + Change passphrase + تغییر گذرواژه + + + + Enter the old and new passphrase to the wallet. + گذرواژهٔ قدیمی و جدید کیف پول را وارد کنید. + + + + Confirm wallet encryption + تأیید رمزنگاری کیف پول + + + + Warning: If you encrypt your wallet and lose your passphrase, you will <b>LOSE ALL OF YOUR COINS</b>! + + + + + Are you sure you wish to encrypt your wallet? + آیا مطمئن هستید که می‌خواهید کیف پول خود را رمزنگاری کنید؟ + + + + IMPORTANT: Any previous backups you have made of your wallet file should be replaced with the newly generated, encrypted wallet file. For security reasons, previous backups of the unencrypted wallet file will become useless as soon as you start using the new, encrypted wallet. + مهم: هر نسخهٔ پشتیبانی که تا کنون از کیف پول خود تهیه کرده‌اید، باید با کیف پول رمزنگاری شدهٔ جدید جایگزین شود. به دلایل امنیتی، پروندهٔ قدیمی کیف پول بدون رمزنگاری، تا زمانی که از کیف پول رمزنگاری‌شدهٔ جدید استفاده نکنید، غیرقابل استفاده خواهد بود. + + + + + Warning: The Caps Lock key is on! + هشدار: کلید Caps Lock روشن است! + + + + + Wallet encrypted + کیف پول رمزنگاری شد + + + + Arepacoin will close now to finish the encryption process. Remember that encrypting your wallet cannot fully protect your coins from being stolen by malware infecting your computer. + + + + + + + + Wallet encryption failed + رمزنگاری کیف پول با خطا مواجه شد + + + + Wallet encryption failed due to an internal error. Your wallet was not encrypted. + رمزنگاری کیف پول بنا به یک خطای داخلی با شکست مواجه شد. کیف پول شما رمزنگاری نشد. + + + + + The supplied passphrases do not match. + گذرواژه‌های داده شده با هم تطابق ندارند. + + + + Wallet unlock failed + بازگشایی قفل کیف‌پول با شکست مواجه شد + + + + + + The passphrase entered for the wallet decryption was incorrect. + گذرواژهٔ وارد شده برای رمزگشایی کیف پول نادرست بود. + + + + Wallet decryption failed + رمزگشایی ناموفق کیف پول + + + + Wallet passphrase was successfully changed. + گذرواژهٔ کیف پول با موفقیت عوض شد. + + + + BitcoinGUI + + + Sign &message... + &امضای پیام... + + + + Synchronizing with network... + همگام‌سازی با شبکه... + + + + &Overview + &بررسی اجمالی + + + + Show general overview of wallet + نمایش بررسی اجمالی کیف پول + + + + &Transactions + &تراکنش‌ها + + + + Browse transaction history + مرور تاریخچهٔ تراکنش‌ها + + + + &Address Book + + + + + Edit the list of stored addresses and labels + + + + + &Receive coins + + + + + Show the list of addresses for receiving payments + + + + + &Send coins + + + + + E&xit + &خروج + + + + Quit application + خروج از برنامه + + + + Show information about Arepacoin + + + + + About &Qt + دربارهٔ &کیوت + + + + Show information about Qt + نمایش اطلاعات دربارهٔ کیوت + + + + &Options... + &تنظیمات... + + + + &Encrypt Wallet... + &رمزنگاری کیف پول... + + + + &Backup Wallet... + &پیشتیبان‌گیری از کیف پول... + + + + &Change Passphrase... + &تغییر گذرواژه... + + + + ~%n block(s) remaining + + + + + Downloaded %1 of %2 blocks of transaction history (%3% done). + + + + + &Export... + + + + + Send coins to a Arepacoin address + + + + + Modify configuration options for Arepacoin + + + + + Export the data in the current tab to a file + + + + + Encrypt or decrypt wallet + + + + + Backup wallet to another location + تهیهٔ پشتیبان از کیف پول در یک مکان دیگر + + + + Change the passphrase used for wallet encryption + تغییر گذرواژهٔ مورد استفاده در رمزنگاری کیف پول + + + + &Debug window + پنجرهٔ ا&شکال‌زدایی + + + + Open debugging and diagnostic console + باز کردن کنسول خطایابی و اشکال‌زدایی + + + + &Verify message... + با&زبینی پیام... + + + + Arepacoin + + + + + Wallet + کیف پول + + + + &About Arepacoin + + + + + &Show / Hide + &نمایش/ عدم نمایش + + + + Unlock wallet + + + + + &Lock Wallet + + + + + Lock wallet + + + + + &File + &پرونده + + + + &Settings + &تنظیمات + + + + &Help + &کمک‌رسانی + + + + Tabs toolbar + نوارابزار برگه‌ها + + + + Actions toolbar + + + + + + [testnet] + [شبکهٔ آزمایش] + + + + + Arepacoin client + + + + + %n active connection(s) to Arepacoin network + + + + + Downloaded %1 blocks of transaction history. + + + + + Staking.<br>Your weight is %1<br>Network weight is %2<br>Expected time to earn reward is %3 + + + + + Not staking because wallet is locked + + + + + Not staking because wallet is offline + + + + + Not staking because wallet is syncing + + + + + Not staking because you don't have mature coins + + + + + %n second(s) ago + + + + + &Unlock Wallet... + + + + + %n minute(s) ago + + + + + %n hour(s) ago + + + + + %n day(s) ago + + + + + Up to date + وضعیت به‌روز + + + + Catching up... + به‌روز رسانی... + + + + Last received block was generated %1. + + + + + This transaction is over the size limit. You can still send it for a fee of %1, which goes to the nodes that process your transaction and helps to support the network. Do you want to pay the fee? + + + + + Confirm transaction fee + + + + + Sent transaction + تراکنش ارسال شد + + + + Incoming transaction + تراکنش دریافت شد + + + + Date: %1 +Amount: %2 +Type: %3 +Address: %4 + + تاریخ: %1 +مبلغ: %2 +نوع: %3 +نشانی: %4 + + + + + + URI handling + + + + + + URI can not be parsed! This can be caused by an invalid Arepacoin address or malformed URI parameters. + + + + + Wallet is <b>encrypted</b> and currently <b>unlocked</b> + کیف پول <b>رمزنگاری شده</b> است و هم‌اکنون <b>باز</b> است + + + + Wallet is <b>encrypted</b> and currently <b>locked</b> + کیف پول <b>رمزنگاری شده</b> است و هم‌اکنون <b>قفل</b> است + + + + Backup Wallet + + + + + Wallet Data (*.dat) + + + + + Backup Failed + + + + + There was an error trying to save the wallet data to the new location. + + + + + %n second(s) + + + + + %n minute(s) + + + + + %n hour(s) + %n ساعت + + + + %n day(s) + %n روز + + + + Not staking + + + + + A fatal error occurred. Arepacoin can no longer continue safely and will quit. + + + + + ClientModel + + + Network Alert + پیام شبکه + + + + CoinControlDialog + + + Coin Control + + + + + Quantity: + + + + + Bytes: + + + + + Amount: + مبلغ: + + + + Priority: + + + + + Fee: + + + + + Low Output: + + + + + no + + + + + After Fee: + + + + + Change: + + + + + (un)select all + + + + + Tree mode + + + + + List mode + + + + + Amount + مبلغ + + + + Label + + + + + Address + نشانی + + + + Date + تاریخ + + + + Confirmations + + + + + Confirmed + تأیید شده + + + + Priority + + + + + Copy address + کپی نشانی + + + + Copy label + کپی برچسب + + + + + Copy amount + کپی مقدار + + + + Copy transaction ID + کپی شناسهٔ تراکنش + + + + Copy quantity + + + + + Copy fee + + + + + Copy after fee + + + + + Copy bytes + + + + + Copy priority + + + + + Copy low output + + + + + Copy change + + + + + highest + + + + + high + + + + + medium-high + + + + + medium + + + + + low-medium + + + + + low + + + + + lowest + + + + + DUST + + + + + yes + + + + + This label turns red, if the transaction size is bigger than 10000 bytes. + + This means a fee of at least %1 per kb is required. + + Can vary +/- 1 Byte per input. + + + + + Transactions with higher priority get more likely into a block. + +This label turns red, if the priority is smaller than "medium". + + This means a fee of at least %1 per kb is required. + + + + + This label turns red, if any recipient receives an amount smaller than %1. + + This means a fee of at least %2 is required. + + Amounts below 0.546 times the minimum relay fee are shown as DUST. + + + + + This label turns red, if the change is smaller than %1. + + This means a fee of at least %2 is required. + + + + + + (no label) + (بدون برچسب) + + + + change from %1 (%2) + + + + + (change) + + + + + EditAddressDialog + + + Edit Address + ویرایش نشانی + + + + &Label + &برچسب + + + + The label associated with this address book entry + + + + + &Address + &نشانی + + + + The address associated with this address book entry. This can only be modified for sending addresses. + + + + + New receiving address + نشانی دریافتی جدید + + + + New sending address + نشانی ارسالی جدید + + + + Edit receiving address + ویرایش نشانی دریافتی + + + + Edit sending address + ویرایش نشانی ارسالی + + + + The entered address "%1" is already in the address book. + نشانی وارد شده «%1» در حال حاضر در دفترچه وجود دارد. + + + + The entered address "%1" is not a valid Arepacoin address. + + + + + Could not unlock wallet. + نمی‌توان کیف پول را رمزگشایی کرد. + + + + New key generation failed. + ایجاد کلید جدید با شکست مواجه شد. + + + + GUIUtil::HelpMessageBox + + + + Arepacoin-Qt + + + + + version + + + + + Usage: + + + + + command-line options + + + + + UI options + + + + + Set language, for example "de_DE" (default: system locale) + + + + + Start minimized + + + + + Show splash screen on startup (default: 1) + + + + + OptionsDialog + + + Options + گزینه‌ها + + + + &Main + &عمومی + + + + Optional transaction fee per kB that helps make sure your transactions are processed quickly. Most transactions are 1 kB. Fee 0.01 recommended. + + + + + Pay transaction &fee + پرداخت &کارمزد تراکنش + + + + Reserved amount does not participate in staking and is therefore spendable at any time. + + + + + Reserve + + + + + Automatically start Arepacoin after logging in to the system. + + + + + &Start Arepacoin on system login + + + + + Detach block and address databases at shutdown. This means they can be moved to another data directory, but it slows down shutdown. The wallet is always detached. + + + + + &Detach databases at shutdown + + + + + &Network + &شبکه + + + + Automatically open the Arepacoin client port on the router. This only works when your router supports UPnP and it is enabled. + + + + + Map port using &UPnP + نگاشت درگاه شبکه با استفاده از پروتکل &UPnP + + + + Connect to the Arepacoin network through a SOCKS proxy (e.g. when connecting through Tor). + + + + + &Connect through SOCKS proxy: + + + + + Proxy &IP: + آ&ی‌پی پراکسی: + + + + IP address of the proxy (e.g. 127.0.0.1) + + + + + &Port: + &درگاه: + + + + Port of the proxy (e.g. 9050) + درگاه پراکسی (مثال 9050) + + + + SOCKS &Version: + &نسخهٔ SOCKS: + + + + SOCKS version of the proxy (e.g. 5) + نسخهٔ پراکسی SOCKS (مثلاً 5) + + + + &Window + &پنجره + + + + Show only a tray icon after minimizing the window. + تنها بعد از کوچک کردن پنجره، tray icon را نشان بده. + + + + &Minimize to the tray instead of the taskbar + &کوچک کردن به سینی به‌جای نوار وظیفه + + + + Minimize instead of exit the application when the window is closed. When this option is enabled, the application will be closed only after selecting Quit in the menu. + مخفی کردن در نوار کناری به‌جای خروج هنگام بستن پنجره. زمانی که این گزینه فعال است، برنامه فقط با استفاده از گزینهٔ خروج در منو قابل بسته شدن است. + + + + M&inimize on close + کوچک کردن &در زمان بسته شدن + + + + &Display + &نمایش + + + + User Interface &language: + زبان &رابط کاربری: + + + + The user interface language can be set here. This setting will take effect after restarting Arepacoin. + + + + + &Unit to show amounts in: + &واحد نمایش مبالغ: + + + + Choose the default subdivision unit to show in the interface and when sending coins. + انتخاب واحد پول مورد استفاده برای نمایش در پنجره‌ها و برای ارسال سکه. + + + + Whether to show Arepacoin addresses in the transaction list or not. + + + + + &Display addresses in transaction list + نمایش ن&شانی‌ها در فهرست تراکنش‌ها + + + + Whether to show coin control features or not. + + + + + Display coin &control features (experts only!) + + + + + &OK + &تأیید + + + + &Cancel + &لغو + + + + &Apply + + + + + default + پیش‌فرض + + + + + Warning + + + + + + This setting will take effect after restarting Arepacoin. + + + + + The supplied proxy address is invalid. + آدرس پراکسی داده شده صحیح نیست. + + + + OverviewPage + + + Form + فرم + + + + + The displayed information may be out of date. Your wallet automatically synchronizes with the Arepacoin network after a connection is established, but this process has not completed yet. + + + + + Stake: + + + + + Unconfirmed: + + + + + Wallet + کیف پول + + + + Spendable: + + + + + Your current spendable balance + تراز علی‌الحساب شما + + + + Immature: + نارسیده: + + + + Mined balance that has not yet matured + تراز استخراج شده از معدن که هنوز بالغ نشده است + + + + Total: + جمع کل: + + + + Your current total balance + تراز کل فعلی شما + + + + <b>Recent transactions</b> + <b>تراکنش‌های اخیر</b> + + + + Total of transactions that have yet to be confirmed, and do not yet count toward the current balance + + + + + Total of coins that was staked, and do not yet count toward the current balance + + + + + + out of sync + ناهمگام + + + + QRCodeDialog + + + QR Code Dialog + + + + + Request Payment + + + + + Amount: + + + + + Label: + + + + + Message: + + + + + &Save As... + + + + + Error encoding URI into QR Code. + + + + + The entered amount is invalid, please check. + + + + + Resulting URI too long, try to reduce the text for label / message. + + + + + Save QR Code + + + + + PNG Images (*.png) + + + + + RPCConsole + + + Client name + نام کلاینت + + + + + + + + + + + + + N/A + ناموجود + + + + Client version + نسخهٔ کلاینت + + + + &Information + &اطلاعات + + + + Using OpenSSL version + نسخهٔ OpenSSL استفاده شده + + + + Startup time + زمان آغاز به کار + + + + Network + شبکه + + + + Number of connections + تعداد ارتباطات + + + + On testnet + + + + + Block chain + زنجیرهٔ بلوک‌ها + + + + Current number of blocks + تعداد فعلی بلوک‌ها + + + + Estimated total blocks + تعداد تخمینی بلوک‌ها + + + + Last block time + زمان آخرین بلوک + + + + &Open + با&ز کردن + + + + Command-line options + + + + + Show the Arepacoin-Qt help message to get a list with possible Arepacoin command-line options. + + + + + &Show + + + + + &Console + &کنسول + + + + Build date + ساخت تاریخ + + + + Arepacoin - Debug window + + + + + Arepacoin Core + + + + + Debug log file + فایلِ لاگِ اشکال زدایی + + + + Open the Arepacoin debug log file from the current data directory. This can take a few seconds for large log files. + + + + + Clear console + پاکسازی کنسول + + + + Welcome to the Arepacoin RPC console. + + + + + Use up and down arrows to navigate history, and <b>Ctrl-L</b> to clear screen. + دکمه‌های بالا و پایین برای پیمایش تاریخچه و <b>Ctrl-L</b> برای پاک کردن صفحه. + + + + Type <b>help</b> for an overview of available commands. + برای نمایش یک مرور کلی از دستورات ممکن، عبارت <b>help</b> را بنویسید. + + + + SendCoinsDialog + + + + + + + + + + Send Coins + ارسال سکه + + + + Coin Control Features + + + + + Inputs... + + + + + automatically selected + + + + + Insufficient funds! + + + + + Quantity: + + + + + + 0 + + + + + Bytes: + + + + + Amount: + مبلغ: + + + + + + + 0.00 BC + + + + + Priority: + + + + + medium + + + + + Fee: + + + + + Low Output: + + + + + no + + + + + After Fee: + + + + + Change + + + + + custom change address + + + + + Send to multiple recipients at once + ارسال به چند دریافت‌کنندهٔ به‌طور همزمان + + + + Add &Recipient + &دریافت‌کنندهٔ جدید + + + + Remove all transaction fields + + + + + Clear &All + پاکسازی &همه + + + + Balance: + تزار: + + + + 123.456 BC + + + + + Confirm the send action + عملیات ارسال را تأیید کنید + + + + S&end + &ارسال + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Copy quantity + + + + + Copy amount + کپی مقدار + + + + Copy fee + + + + + Copy after fee + + + + + Copy bytes + + + + + Copy priority + + + + + Copy low output + + + + + Copy change + + + + + <b>%1</b> to %2 (%3) + + + + + Confirm send coins + ارسال سکه را تأیید کنید + + + + Are you sure you want to send %1? + + + + + and + + + + + The recipient address is not valid, please recheck. + نشانی گیرنده معتبر نیست؛ لطفا دوباره بررسی کنید. + + + + The amount to pay must be larger than 0. + مبلغ پرداخت باید بیشتر از ۰ باشد. + + + + The amount exceeds your balance. + میزان پرداخت از تراز شما بیشتر است. + + + + The total exceeds your balance when the %1 transaction fee is included. + با احتساب هزینهٔ %1 برای هر تراکنش، مجموع میزان پرداختی از مبلغ تراز شما بیشتر می‌شود. + + + + Duplicate address found, can only send to each address once per send operation. + یک نشانی تکراری پیدا شد. در هر عملیات ارسال، به هر نشانی فقط مبلغ می‌توان ارسال کرد. + + + + Error: Transaction creation failed. + + + + + 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. + + + + + WARNING: Invalid Arepacoin address + + + + + (no label) + (بدون برچسب) + + + + WARNING: unknown change address + + + + + SendCoinsEntry + + + Form + + + + + A&mount: + A&مبلغ : + + + + Pay &To: + پرداخ&ت به: + + + + + Enter a label for this address to add it to your address book + برای این نشانی یک برچسب وارد کنید تا در دفترچهٔ آدرس ذخیره شود + + + + &Label: + &برچسب: + + + + The address to send the payment to (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Choose address from address book + + + + + Alt+A + Alt+A + + + + Paste address from clipboard + چسباندن نشانی از حافظهٔ سیستم + + + + Alt+P + Alt+P + + + + Remove this recipient + + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + SignVerifyMessageDialog + + + Signatures - Sign / Verify a Message + امضاها - امضا / تأیید یک پیام + + + + + &Sign Message + ا&مضای پیام + + + + You can sign messages with your addresses to prove you own them. Be careful not to sign anything vague, as phishing attacks may try to trick you into signing your identity over to them. Only sign fully-detailed statements you agree to. + برای احراز اینکه پیام‌ها از جانب شما هستند، می‌توانید آن‌ها را با نشانی خودتان امضا کنید. مراقب باشید چیزی که بدان اطمینان ندارید را امضا نکنید زیرا حملات فیشینگ ممکن است بخواهند از.پیامی با امضای شما سوءاستفاده کنند. تنها مواردی را که حاوی اطلاعات دقیق و قابل قبول برای شما هستند امضا کنید. + + + + The address to sign the message with (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + + Choose an address from the address book + + + + + + Alt+A + Alt+A + + + + Paste address from clipboard + چسباندن نشانی از حافظهٔ سیستم + + + + Alt+P + Alt+P + + + + Enter the message you want to sign here + پیامی را که می‌خواهید امضا کنید در اینجا وارد کنید + + + + Copy the current signature to the system clipboard + امضای فعلی را به حافظهٔ سیستم کپی کن + + + + Sign the message to prove you own this Arepacoin address + + + + + Reset all sign message fields + بازنشانی تمام فیلدهای پیام + + + + + Clear &All + پاک &کردن همه + + + + + &Verify Message + &شناسایی پیام + + + + Enter the signing address, message (ensure you copy line breaks, spaces, tabs, etc. exactly) and signature below to verify the message. Be careful not to read more into the signature than what is in the signed message itself, to avoid being tricked by a man-in-the-middle attack. + برای شناسایی پیام، نشانیِ امضا کننده و متن پیام را وارد کنید. (مطمئن شوید که فاصله‌ها، تب‌ها و خطوط را عیناً کپی می‌کنید.) مراقب باشید در امضا چیزی بیشتر از آنچه در پیام می‌بینید وجود نداشته باشد تا فریب دزدان اینترنتی و حملات از نوع MITM را نخورید. + + + + The address the message was signed with (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Verify the message to ensure it was signed with the specified Arepacoin address + + + + + Reset all verify message fields + بازنشانی تمام فیلدهای پیام + + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Click "Sign Message" to generate signature + برای ایجاد یک امضای جدید روی «امضای پیام» کلیک کنید + + + + Enter Arepacoin signature + + + + + + The entered address is invalid. + نشانی وارد شده نامعتبر است. + + + + + + + Please check the address and try again. + لطفاً نشانی را بررسی کنید و دوباره تلاش کنید. + + + + + The entered address does not refer to a key. + نشانی وارد شده به هیچ کلیدی اشاره نمی‌کند. + + + + Wallet unlock was cancelled. + عملیات باز کرن قفل کیف پول لغو شد. + + + + Private key for the entered address is not available. + کلید خصوصی برای نشانی وارد شده در دسترس نیست. + + + + Message signing failed. + امضای پیام با شکست مواجه شد. + + + + Message signed. + پیام امضا شد. + + + + The signature could not be decoded. + امضا نمی‌تواند کدگشایی شود. + + + + + Please check the signature and try again. + لطفاً امضا را بررسی نموده و دوباره تلاش کنید. + + + + The signature did not match the message digest. + امضا با خلاصهٔ پیام مطابقت ندارد. + + + + Message verification failed. + شناسایی پیام با شکست مواجه شد. + + + + Message verified. + پیام شناسایی شد. + + + + TransactionDesc + + + Open until %1 + باز تا %1 + + + + Open for %n block(s) + + + + + conflicted + + + + + %1/offline + %1/آفلاین + + + + %1/unconfirmed + %1/تأیید نشده + + + + %1 confirmations + %1 تأییدیه + + + + Status + وضعیت + + + + , broadcast through %n node(s) + ، پخش از طریق %n گره + + + + Date + تاریخ + + + + Source + منبع + + + + Generated + تولید شده + + + + + From + فرستنده + + + + + + To + گیرنده + + + + + own address + آدرس شما + + + + label + برچسب + + + + + + + + Credit + بدهی + + + + matures in %n more block(s) + بلوغ در %n بلوک دیگر + + + + not accepted + پذیرفته نشد + + + + + + + Debit + اعتبار + + + + Transaction fee + هزینهٔ تراکنش + + + + Net amount + مبلغ خالص + + + + Message + پیام + + + + Comment + نظر + + + + Transaction ID + شناسهٔ تراکنش + + + + Generated coins must mature 6 blocks before they can be spent. When you generated this block, it was broadcast to the network to be added to the block chain. If it fails to get into the chain, its state will change to "not accepted" and it won't be spendable. This may occasionally happen if another node generates a block within a few seconds of yours. + + + + + Debug information + اطلاعات اشکال‌زدایی + + + + Transaction + تراکنش + + + + Inputs + ورودی‌ها + + + + Amount + مبلغ + + + + true + درست + + + + false + نادرست + + + + , has not been successfully broadcast yet + ، هنوز با موفقیت ارسال نشده + + + + unknown + ناشناس + + + + TransactionDescDialog + + + Transaction details + جزئیات تراکنش + + + + This pane shows a detailed description of the transaction + این پانل شامل توصیف کاملی از جزئیات تراکنش است + + + + TransactionTableModel + + + Date + تاریخ + + + + Type + نوع + + + + Address + نشانی + + + + Amount + مبلغ + + + + Open until %1 + باز شده تا %1 + + + + Confirmed (%1 confirmations) + تأیید شده (%1 تأییدیه) + + + + Open for %n more block(s) + باز برای %n بلوک دیگر + + + + Offline + + + + + Unconfirmed + + + + + Confirming (%1 of %2 recommended confirmations) + + + + + Conflicted + + + + + Immature (%1 confirmations, will be available after %2) + + + + + This block was not received by any other nodes and will probably not be accepted! + این بلوک از هیچ همتای دیگری دریافت نشده است و احتمال می‌رود پذیرفته نشود! + + + + Generated but not accepted + تولید شده ولی قبول نشده + + + + Received with + دریافت‌شده با + + + + Received from + دریافت‌شده از + + + + Sent to + ارسال‌شده به + + + + Payment to yourself + پر داخت به خودتان + + + + Mined + استخراج‌شده + + + + (n/a) + (ناموجود) + + + + Transaction status. Hover over this field to show number of confirmations. + وضعیت تراکنش. نشانگر را روی این فیلد نگه دارید تا تعداد تأییدیه‌ها نشان داده شود. + + + + Date and time that the transaction was received. + تاریخ و ساعت دریافت تراکنش. + + + + Type of transaction. + نوع تراکنش. + + + + Destination address of transaction. + نشانی مقصد تراکنش. + + + + Amount removed from or added to balance. + مبلغ کسر شده و یا اضافه شده به تراز. + + + + TransactionView + + + + All + همه + + + + Today + امروز + + + + This week + این هفته + + + + This month + این ماه + + + + Last month + ماه گذشته + + + + This year + امسال + + + + Range... + محدوده... + + + + Received with + دریافت‌شده با + + + + Sent to + ارسال به + + + + To yourself + به خودتان + + + + Mined + استخراج‌شده + + + + Other + دیگر + + + + Enter address or label to search + برای جست‌‌وجو نشانی یا برچسب را وارد کنید + + + + Min amount + مبلغ حداقل + + + + Copy address + کپی نشانی + + + + Copy label + کپی برچسب + + + + Copy amount + کپی مقدار + + + + Copy transaction ID + کپی شناسهٔ تراکنش + + + + Edit label + ویرایش برچسب + + + + Show transaction details + نمایش جزئیات تراکنش + + + + Export Transaction Data + + + + + Comma separated file (*.csv) + پروندهٔ نوع CSV جداشونده با کاما (*.csv) + + + + Confirmed + تأیید شده + + + + Date + تاریخ + + + + Type + نوع + + + + Label + برچسب + + + + Address + نشانی + + + + Amount + مبلغ + + + + ID + شناسه + + + + Error exporting + + + + + Could not write to file %1. + + + + + Range: + محدوده: + + + + to + به + + + + WalletModel + + + Sending... + + + + + bitcoin-core + + + Arepacoin version + + + + + Usage: + استفاده: + + + + Send command to -server or arepacoind + + + + + List commands + نمایش لیست فرمان‌ها + + + + Get help for a command + راهنمایی در مورد یک دستور + + + + Options: + گزینه‌ها: + + + + Specify configuration file (default: arepacoin.conf) + + + + + Specify pid file (default: arepacoind.pid) + + + + + Specify wallet file (within data directory) + + + + + Specify data directory + مشخص کردن دایرکتوری داده‌ها + + + + Set database cache size in megabytes (default: 25) + تنظیم اندازهٔ کَش پایگاه‌داده برحسب مگابایت (پیش‌فرض: ۲۵) + + + + Set database disk log size in megabytes (default: 100) + + + + + Listen for connections on <port> (default: 9853 or testnet: 19853) + + + + + Maintain at most <n> connections to peers (default: 125) + حداکثر <n> اتصال با همتایان برقرار شود (پیش‌فرض: ۱۲۵) + + + + Connect to a node to retrieve peer addresses, and disconnect + اتصال به یک گره برای دریافت آدرس‌های همتا و قطع اتصال پس از اتمام عملیات + + + + Specify your own public address + آدرس عمومی خود را مشخص کنید + + + + Bind to given address. Use [host]:port notation for IPv6 + + + + + Stake your coins to support network and gain reward (default: 1) + + + + + Threshold for disconnecting misbehaving peers (default: 100) + حد آستانه برای قطع ارتباط با همتایان بدرفتار (پیش‌فرض: ۱۰۰) + + + + Number of seconds to keep misbehaving peers from reconnecting (default: 86400) + مدت زمان جلوگیری از اتصال مجدد همتایان بدرفتار، به ثانیه (پیش‌فرض: ۸۴۶۰۰) + + + + An error occurred while setting up the RPC port %u for listening on IPv4: %s + هنگام تنظیم پورت RPC %u برای گوش دادن روی IPv4 خطایی رخ داده است: %s + + + + Detach block and address databases. Increases shutdown time (default: 0) + + + + + 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. + + + + + Error: This transaction requires a transaction fee of at least %s because of its amount, complexity, or use of recently received funds + + + + + Listen for JSON-RPC connections on <port> (default: 9852 or testnet: 19852) + + + + + Accept command line and JSON-RPC commands + پذیرش دستورات خط فرمان و دستورات JSON-RPC + + + + Error: Transaction creation failed + + + + + Error: Wallet locked, unable to create transaction + + + + + Importing blockchain data file. + + + + + Importing bootstrap blockchain data file. + + + + + Run in the background as a daemon and accept commands + اجرا در پشت زمینه به‌صورت یک سرویس و پذیرش دستورات + + + + Use the test network + استفاده از شبکهٔ آزمایش + + + + Accept connections from outside (default: 1 if no -proxy or -connect) + پذیرش اتصالات از بیرون (پیش فرض:1 بدون پراکسی یا اتصال) + + + + An error occurred while setting up the RPC port %u for listening on IPv6, falling back to IPv4: %s + + + + + Error initializing database environment %s! To recover, BACKUP THAT DIRECTORY, then remove everything from it except for wallet.dat. + + + + + Set maximum size of high-priority/low-fee transactions in bytes (default: 27000) + + + + + Warning: -paytxfee is set very high! This is the transaction fee you will pay if you send a transaction. + هشدار: مبلغ paytxfee بسیار بالایی تنظیم شده است! این مبلغ هزینه‌ای است که شما برای تراکنش‌ها پرداخت می‌کنید. + + + + Warning: Please check that your computer's date and time are correct! If your clock is wrong Arepacoin will not work properly. + + + + + Warning: error reading wallet.dat! All keys read correctly, but transaction data or address book entries might be missing or incorrect. + + + + + Warning: wallet.dat corrupt, data salvaged! Original wallet.dat saved as wallet.{timestamp}.bak in %s; if your balance or transactions are incorrect you should restore from a backup. + + + + + Attempt to recover private keys from a corrupt wallet.dat + + + + + Block creation options: + بستن گزینه ایجاد + + + + Connect only to the specified node(s) + تنها در گره (های) مشخص شده متصل شوید + + + + Discover own IP address (default: 1 when listening and no -externalip) + آدرس آی.پی. خود را شناسایی کنید (پیش فرض:1 در زمان when listening وno -externalip) + + + + Failed to listen on any port. Use -listen=0 if you want this. + شنیدن هر گونه درگاه انجام پذیر نیست. ازlisten=0 برای اینکار استفاده کیند. + + + + Find peers using DNS lookup (default: 1) + + + + + Sync checkpoints policy (default: strict) + + + + + Invalid -tor address: '%s' + + + + + Invalid amount for -reservebalance=<amount> + + + + + Maximum per-connection receive buffer, <n>*1000 bytes (default: 5000) + حداکثر بافر دریافت شده بر اساس اتصال <n>* 1000 بایت (پیش فرض:5000) + + + + Maximum per-connection send buffer, <n>*1000 bytes (default: 1000) + حداکثر بافر دریافت شده بر اساس اتصال <n>* 1000 بایت (پیش فرض:1000) + + + + Only connect to nodes in network <net> (IPv4, IPv6 or Tor) + تنها =به گره ها در شبکه متصا شوید <net> (IPv4, IPv6 or Tor) + + + + Output extra debugging information. Implies all other -debug* options + + + + + Output extra network debugging information + + + + + Prepend debug output with timestamp + + + + + SSL options: (see the Bitcoin Wiki for SSL setup instructions) + گزینه ssl (به ویکیbitcoin برای راهنمای راه اندازی ssl مراجعه شود) + + + + Select the version of socks proxy to use (4-5, default: 5) + + + + + Send trace/debug info to console instead of debug.log file + اطلاعات ردگیری/اشکال‌زدایی را به جای فایل لاگ اشکال‌زدایی به کنسول بفرستید + + + + Send trace/debug info to debugger + + + + + Set maximum block size in bytes (default: 250000) + + + + + Set minimum block size in bytes (default: 0) + حداقل سایز بلاک بر اساس بایت تنظیم شود (پیش فرض: 0) + + + + Shrink debug.log file on client startup (default: 1 when no -debug) + فایل debug.log را در startup مشتری کوچک کن (پیش فرض:1 اگر اشکال زدایی روی نداد) + + + + Specify connection timeout in milliseconds (default: 5000) + (میلی ثانیه )فاصله ارتباط خاص + + + + Unable to sign checkpoint, wrong checkpointkey? + + + + + + Use UPnP to map the listening port (default: 0) + از UPnP برای شناسایی درگاه شنیداری استفاده کنید (پیش فرض:0) + + + + Use UPnP to map the listening port (default: 1 when listening) + از UPnP برای شناسایی درگاه شنیداری استفاده کنید (پیش فرض:1 در زمان شنیدن) + + + + Use proxy to reach tor hidden services (default: same as -proxy) + + + + + Username for JSON-RPC connections + JSON-RPC شناسه برای ارتباطات + + + + Verifying database integrity... + + + + + WARNING: syncronized checkpoint violation detected, but skipped! + + + + + Warning: Disk space is low! + + + + + Warning: This version is obsolete, upgrade required! + هشدار: این نسخه قدیمی است، روزآمدسازی مورد نیاز است + + + + wallet.dat corrupt, salvage failed + + + + + Password for JSON-RPC connections + JSON-RPC عبارت عبور برای ارتباطات + + + + %s, you must set a rpcpassword in the configuration file: + %s +It is recommended you use the following random password: +rpcuser=arepacoinrpc +rpcpassword=%s +(you do not need to remember this password) +The username and password MUST NOT be the same. +If the file does not exist, create it with owner-readable-only file permissions. +It is also recommended to set alertnotify so you are notified of problems; +for example: alertnotify=echo %%s | mail -s "Arepacoin Alert" admin@foo.com + + + + + + Find peers using internet relay chat (default: 0) + + + + + Sync time with other nodes. Disable if time on your system is precise e.g. syncing with NTP (default: 1) + + + + + When creating transactions, ignore inputs with value less than this (default: 0.01) + + + + + Allow JSON-RPC connections from specified IP address + از آدرس آی پی خاص JSON-RPC قبول ارتباطات + + + + Send commands to node running on <ip> (default: 127.0.0.1) + (127.0.0.1پیش فرض: ) &lt;ip&gt; دادن فرمانها برای استفاده گره ها روی + + + + Execute command when the best block changes (%s in cmd is replaced by block hash) + زمانی که بهترین بلاک تغییر کرد، دستور را اجرا کن (%s در cmd با block hash جایگزین شده است) + + + + Execute command when a wallet transaction changes (%s in cmd is replaced by TxID) + هنگامی که یک تراکنش در کیف پولی رخ می دهد، دستور را اجرا کن(%s در دستورات بوسیله ی TxID جایگزین می شود) + + + + Require a confirmations for change (default: 0) + + + + + Enforce transaction scripts to use canonical PUSH operators (default: 1) + + + + + Execute command when a relevant alert is received (%s in cmd is replaced by message) + + + + + Upgrade wallet to latest format + wallet را به جدیدترین فرمت روزآمد کنید + + + + Set key pool size to <n> (default: 100) + (100پیش فرض:)&lt;n&gt; گذاشتن اندازه کلید روی + + + + Rescan the block chain for missing wallet transactions + اسکان مجدد زنجیر بلوکها برای گم والت معامله + + + + How many blocks to check at startup (default: 2500, 0 = all) + + + + + How thorough the block verification is (0-6, default: 1) + + + + + Imports blocks from external blk000?.dat file + + + + + Use OpenSSL (https) for JSON-RPC connections + JSON-RPCبرای ارتباطات استفاده کنید OpenSSL (https) + + + + Server certificate file (default: server.cert) + (server.certپیش فرض: )گواهی نامه سرور + + + + Server private key (default: server.pem) + (server.pemپیش فرض: ) کلید خصوصی سرور + + + + Acceptable ciphers (default: TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH) + + + + + Error: Wallet unlocked for staking only, unable to create transaction. + + + + + WARNING: Invalid checkpoint found! Displayed transactions may not be correct! You may need to upgrade, or notify developers. + + + + + This help message + پیام کمکی + + + + Wallet %s resides outside data directory %s. + + + + + Cannot obtain a lock on data directory %s. Arepacoin is probably already running. + + + + + Arepacoin + + + + + Unable to bind to %s on this computer (bind returned error %d, %s) + امکان اتصال به %s از این رایانه وجود ندارد ( bind returned error %d, %s) + + + + Connect through socks proxy + + + + + Allow DNS lookups for -addnode, -seednode and -connect + به DNS اجازه بده تا برای addnode ، seednode و اتصال جستجو کند + + + + Loading addresses... + بار گیری آدرس ها + + + + Error loading blkindex.dat + + + + + Error loading wallet.dat: Wallet corrupted + خطا در بارگیری wallet.dat: کیف پول خراب شده است + + + + Error loading wallet.dat: Wallet requires newer version of Arepacoin + + + + + Wallet needed to be rewritten: restart Arepacoin to complete + + + + + Error loading wallet.dat + خطا در بارگیری wallet.dat + + + + Invalid -proxy address: '%s' + آدرس پراکسی اشتباه %s + + + + Unknown network specified in -onlynet: '%s' + شبکه مشخص شده غیرقابل شناسایی در onlynet: '%s' + + + + Unknown -socks proxy version requested: %i + نسخه پراکسی ساکس غیرقابل شناسایی درخواست شده است: %i + + + + Cannot resolve -bind address: '%s' + آدرس قابل اتصال- شناسایی نیست %s + + + + Cannot resolve -externalip address: '%s' + آدرس خارجی قابل اتصال- شناسایی نیست %s + + + + Invalid amount for -paytxfee=<amount>: '%s' + میزان وجه اشتباه برای paytxfee=<میزان وجه>: %s + + + + Error: could not start node + + + + + Sending... + + + + + Invalid amount + میزان وجه اشتباه + + + + Insufficient funds + بود جه نا کافی + + + + Loading block index... + بار گیری شاخص بلوک + + + + Add a node to connect to and attempt to keep the connection open + به اتصال یک گره اضافه کنید و اتصال را باز نگاه دارید + + + + Unable to bind to %s on this computer. Arepacoin is probably already running. + + + + + Fee per KB to add to transactions you send + + + + + Invalid amount for -mininput=<amount>: '%s' + + + + + Loading wallet... + بار گیری والت + + + + Cannot downgrade wallet + امکان تنزل نسخه در wallet وجود ندارد + + + + Cannot initialize keypool + + + + + Cannot write default address + آدرس پیش فرض قابل ذخیره نیست + + + + Rescanning... + اسکان مجدد + + + + Done loading + بار گیری انجام شده است + + + + To use the %s option + برای استفاده از %s از انتخابات + + + + Error + خطا + + + + You must set rpcpassword=<password> in the configuration file: +%s +If the file does not exist, create it with owner-readable-only file permissions. + %s، شما باید یک rpcpassword را در فایل پیکربندی تنظیم کنید :⏎%s⏎ اگر فایل ایجاد نشد، یک فایل فقط متنی ایجاد کنید. + + + + \ No newline at end of file diff --git a/src/qt/locale/bitcoin_fa_IR.ts b/src/qt/locale/bitcoin_fa_IR.ts new file mode 100755 index 0000000..40b3e1e --- /dev/null +++ b/src/qt/locale/bitcoin_fa_IR.ts @@ -0,0 +1,3278 @@ + + + AboutDialog + + + About Arepacoin + + + + + <b>Arepacoin</b> version + + + + + Copyright © 2009-2014 The Bitcoin developers +Copyright © 2012-2014 The NovaCoin developers +Copyright © 2014 The Arepacoin developers + + + + + +This is experimental software. + +Distributed under the MIT/X11 software license, see the accompanying file COPYING or http://www.opensource.org/licenses/mit-license.php. + +This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit (http://www.openssl.org/) and cryptographic software written by Eric Young (eay@cryptsoft.com) and UPnP software written by Thomas Bernard. + + + + + AddressBookPage + + + Address Book + + + + + Double-click to edit address or label + برای ویرایش حساب و یا برچسب دوبار کلیک نمایید + + + + Create a new address + گشایش حسابی جدید + + + + Copy the currently selected address to the system clipboard + کپی کردن حساب انتخاب شده به حافظه سیستم - کلیپ بورد + + + + &New Address + + + + + These are your Arepacoin addresses for receiving payments. You may want to give a different one to each sender so you can keep track of who is paying you. + + + + + &Copy Address + و کپی آدرس + + + + Show &QR Code + + + + + Sign a message to prove you own a Arepacoin address + + + + + Sign &Message + + + + + Delete the currently selected address from the list + + + + + Verify a message to ensure it was signed with a specified Arepacoin address + + + + + &Verify Message + + + + + &Delete + و حذف + + + + Copy &Label + کپی و برچسب + + + + &Edit + و ویرایش + + + + Export Address Book Data + + + + + Comma separated file (*.csv) + سی.اس.وی. (فایل جداگانه دستوری) + + + + Error exporting + + + + + Could not write to file %1. + + + + + AddressTableModel + + + Label + برچسب + + + + Address + حساب + + + + (no label) + (برچسب ندارد) + + + + AskPassphraseDialog + + + Passphrase Dialog + + + + + Enter passphrase + رمز/پَس فرِیز را وارد کنید + + + + New passphrase + رمز/پَس فرِیز جدید را وارد کنید + + + + Repeat new passphrase + رمز/پَس فرِیز را دوباره وارد کنید + + + + Serves to disable the trivial sendmoney when OS account compromised. Provides no real security. + + + + + For staking only + + + + + Enter the new passphrase to the wallet.<br/>Please use a passphrase of <b>10 or more random characters</b>, or <b>eight or more words</b>. + رمز/پَس فرِیز جدید را در wallet وارد کنید. برای انتخاب رمز/پَس فرِیز از 10 کاراکتر تصادفی یا بیشتر و یا هشت کلمه یا بیشتر استفاده کنید. + + + + Encrypt wallet + wallet را رمزگذاری کنید + + + + This operation needs your wallet passphrase to unlock the wallet. + برای انجام این عملکرد به رمز/پَس فرِیزِwallet نیاز است تا آن را از حالت قفل درآورد. + + + + Unlock wallet + باز کردن قفل wallet + + + + This operation needs your wallet passphrase to decrypt the wallet. + برای کشف رمز wallet، به رمز/پَس فرِیزِwallet نیاز است. + + + + Decrypt wallet + کشف رمز wallet + + + + Change passphrase + تغییر رمز/پَس فرِیز + + + + Enter the old and new passphrase to the wallet. + رمز/پَس فرِیزِ قدیم و جدید را در wallet وارد کنید + + + + Confirm wallet encryption + رمزگذاری wallet را تایید کنید + + + + Warning: If you encrypt your wallet and lose your passphrase, you will <b>LOSE ALL OF YOUR COINS</b>! + + + + + Are you sure you wish to encrypt your wallet? + + + + + IMPORTANT: Any previous backups you have made of your wallet file should be replaced with the newly generated, encrypted wallet file. For security reasons, previous backups of the unencrypted wallet file will become useless as soon as you start using the new, encrypted wallet. + + + + + + Warning: The Caps Lock key is on! + + + + + + Wallet encrypted + تایید رمزگذاری + + + + Arepacoin will close now to finish the encryption process. Remember that encrypting your wallet cannot fully protect your coins from being stolen by malware infecting your computer. + + + + + + + + Wallet encryption failed + رمزگذاری تایید نشد + + + + Wallet encryption failed due to an internal error. Your wallet was not encrypted. + رمزگذاری به علت خطای داخلی تایید نشد. wallet شما رمزگذاری نشد + + + + + The supplied passphrases do not match. + رمزهای/پَس فرِیزهایِ وارد شده با هم تطابق ندارند + + + + Wallet unlock failed + قفل wallet باز نشد + + + + + + The passphrase entered for the wallet decryption was incorrect. + رمزهای/پَس فرِیزهایِ وارد شده wallet برای کشف رمز اشتباه است. + + + + Wallet decryption failed + کشف رمز wallet انجام نشد + + + + Wallet passphrase was successfully changed. + + + + + BitcoinGUI + + + Sign &message... + امضا و پیام + + + + Synchronizing with network... + به روز رسانی با شبکه... + + + + &Overview + و بازبینی + + + + Show general overview of wallet + نمای کلی از wallet را نشان بده + + + + &Transactions + و تراکنش + + + + Browse transaction history + تاریخچه تراکنش را باز کن + + + + &Address Book + + + + + Edit the list of stored addresses and labels + + + + + &Receive coins + + + + + Show the list of addresses for receiving payments + + + + + &Send coins + + + + + E&xit + خروج + + + + Quit application + از "درخواست نامه"/ application خارج شو + + + + Show information about Arepacoin + + + + + About &Qt + درباره و QT + + + + Show information about Qt + نمایش اطلاعات درباره QT + + + + &Options... + و انتخابها + + + + &Encrypt Wallet... + و رمزگذاری wallet + + + + &Backup Wallet... + و گرفتن نسخه پیشتیبان از wallet + + + + &Change Passphrase... + تغییر رمز/پَس فرِیز + + + + ~%n block(s) remaining + + + + + Downloaded %1 of %2 blocks of transaction history (%3% done). + + + + + &Export... + + + + + Send coins to a Arepacoin address + + + + + Modify configuration options for Arepacoin + + + + + Export the data in the current tab to a file + + + + + Encrypt or decrypt wallet + + + + + Backup wallet to another location + گرفتن نسخه پیشتیبان در آدرسی دیگر + + + + Change the passphrase used for wallet encryption + رمز مربوط به رمزگذاریِ wallet را تغییر دهید + + + + &Debug window + + + + + Open debugging and diagnostic console + + + + + &Verify message... + + + + + Arepacoin + + + + + Wallet + کیف پول + + + + &About Arepacoin + + + + + &Show / Hide + &نمایش/ عدم نمایش و + + + + Unlock wallet + + + + + &Lock Wallet + + + + + Lock wallet + + + + + &File + و فایل + + + + &Settings + و تنظیمات + + + + &Help + و راهنما + + + + Tabs toolbar + نوار ابزار + + + + Actions toolbar + + + + + + [testnet] + [testnet] + + + + + Arepacoin client + + + + + %n active connection(s) to Arepacoin network + + + + + Downloaded %1 blocks of transaction history. + + + + + Staking.<br>Your weight is %1<br>Network weight is %2<br>Expected time to earn reward is %3 + + + + + Not staking because wallet is locked + + + + + Not staking because wallet is offline + + + + + Not staking because wallet is syncing + + + + + Not staking because you don't have mature coins + + + + + %n second(s) ago + + + + + &Unlock Wallet... + + + + + %n minute(s) ago + + + + + %n hour(s) ago + + + + + %n day(s) ago + + + + + Up to date + روزآمد + + + + Catching up... + در حال روزآمد سازی.. + + + + Last received block was generated %1. + + + + + This transaction is over the size limit. You can still send it for a fee of %1, which goes to the nodes that process your transaction and helps to support the network. Do you want to pay the fee? + + + + + Confirm transaction fee + + + + + Sent transaction + ارسال تراکنش + + + + Incoming transaction + تراکنش دریافتی + + + + Date: %1 +Amount: %2 +Type: %3 +Address: %4 + + تاریخ: %1⏎ میزان وجه : %2⏎ نوع: %3⏎ آدرس: %4⏎ + + + + + + URI handling + + + + + + URI can not be parsed! This can be caused by an invalid Arepacoin address or malformed URI parameters. + + + + + Wallet is <b>encrypted</b> and currently <b>unlocked</b> + wallet رمزگذاری شد و در حال حاضر از حالت قفل در آمده است + + + + Wallet is <b>encrypted</b> and currently <b>locked</b> + wallet رمزگذاری شد و در حال حاضر قفل است + + + + Backup Wallet + + + + + Wallet Data (*.dat) + + + + + Backup Failed + + + + + There was an error trying to save the wallet data to the new location. + + + + + %n second(s) + + + + + %n minute(s) + + + + + %n hour(s) + + + + + %n day(s) + + + + + Not staking + + + + + A fatal error occurred. Arepacoin can no longer continue safely and will quit. + + + + + ClientModel + + + Network Alert + هشدار شبکه + + + + CoinControlDialog + + + Coin Control + + + + + Quantity: + + + + + Bytes: + + + + + Amount: + میزان وجه: + + + + Priority: + + + + + Fee: + + + + + Low Output: + + + + + no + + + + + After Fee: + + + + + Change: + + + + + (un)select all + + + + + Tree mode + + + + + List mode + + + + + Amount + میزان + + + + Label + + + + + Address + حساب + + + + Date + تاریخ + + + + Confirmations + + + + + Confirmed + تایید شده + + + + Priority + + + + + Copy address + آدرس را کپی کنید + + + + Copy label + برچسب را کپی کنید + + + + + Copy amount + میزان وجه کپی شود + + + + Copy transaction ID + + + + + Copy quantity + + + + + Copy fee + + + + + Copy after fee + + + + + Copy bytes + + + + + Copy priority + + + + + Copy low output + + + + + Copy change + + + + + highest + + + + + high + + + + + medium-high + + + + + medium + + + + + low-medium + + + + + low + + + + + lowest + + + + + DUST + + + + + yes + + + + + This label turns red, if the transaction size is bigger than 10000 bytes. + + This means a fee of at least %1 per kb is required. + + Can vary +/- 1 Byte per input. + + + + + Transactions with higher priority get more likely into a block. + +This label turns red, if the priority is smaller than "medium". + + This means a fee of at least %1 per kb is required. + + + + + This label turns red, if any recipient receives an amount smaller than %1. + + This means a fee of at least %2 is required. + + Amounts below 0.546 times the minimum relay fee are shown as DUST. + + + + + This label turns red, if the change is smaller than %1. + + This means a fee of at least %2 is required. + + + + + + (no label) + (برچسب ندارد) + + + + change from %1 (%2) + + + + + (change) + + + + + EditAddressDialog + + + Edit Address + ویرایش حساب + + + + &Label + و برچسب + + + + The label associated with this address book entry + + + + + &Address + حساب& + + + + The address associated with this address book entry. This can only be modified for sending addresses. + + + + + New receiving address + حساب دریافت کننده جدید + + + + + New sending address + حساب ارسال کننده جدید + + + + Edit receiving address + ویرایش حساب دریافت کننده + + + + Edit sending address + ویرایش حساب ارسال کننده + + + + The entered address "%1" is already in the address book. + حساب وارد شده «1%» از پیش در دفترچه حساب ها موجود است. + + + + The entered address "%1" is not a valid Arepacoin address. + + + + + Could not unlock wallet. + عدم توانیی برای قفل گشایی wallet + + + + New key generation failed. + عدم توانیی در ایجاد کلید جدید + + + + GUIUtil::HelpMessageBox + + + + Arepacoin-Qt + + + + + version + + + + + Usage: + + + + + command-line options + + + + + UI options + + + + + Set language, for example "de_DE" (default: system locale) + + + + + Start minimized + + + + + Show splash screen on startup (default: 1) + + + + + OptionsDialog + + + Options + انتخاب/آپشن + + + + &Main + + + + + Optional transaction fee per kB that helps make sure your transactions are processed quickly. Most transactions are 1 kB. Fee 0.01 recommended. + + + + + Pay transaction &fee + + + + + Reserved amount does not participate in staking and is therefore spendable at any time. + + + + + Reserve + + + + + Automatically start Arepacoin after logging in to the system. + + + + + &Start Arepacoin on system login + + + + + Detach block and address databases at shutdown. This means they can be moved to another data directory, but it slows down shutdown. The wallet is always detached. + + + + + &Detach databases at shutdown + + + + + &Network + + + + + Automatically open the Arepacoin client port on the router. This only works when your router supports UPnP and it is enabled. + + + + + Map port using &UPnP + + + + + Connect to the Arepacoin network through a SOCKS proxy (e.g. when connecting through Tor). + + + + + &Connect through SOCKS proxy: + + + + + Proxy &IP: + + + + + IP address of the proxy (e.g. 127.0.0.1) + + + + + &Port: + + + + + Port of the proxy (e.g. 9050) + + + + + SOCKS &Version: + + + + + SOCKS version of the proxy (e.g. 5) + + + + + &Window + + + + + Show only a tray icon after minimizing the window. + + + + + &Minimize to the tray instead of the taskbar + + + + + Minimize instead of exit the application when the window is closed. When this option is enabled, the application will be closed only after selecting Quit in the menu. + + + + + M&inimize on close + + + + + &Display + + + + + User Interface &language: + + + + + The user interface language can be set here. This setting will take effect after restarting Arepacoin. + + + + + &Unit to show amounts in: + + + + + Choose the default subdivision unit to show in the interface and when sending coins. + + + + + Whether to show Arepacoin addresses in the transaction list or not. + + + + + &Display addresses in transaction list + و نمایش آدرسها در فهرست تراکنش + + + + Whether to show coin control features or not. + + + + + Display coin &control features (experts only!) + + + + + &OK + و تایید + + + + &Cancel + و رد + + + + &Apply + + + + + default + پیش فرض + + + + + Warning + + + + + + This setting will take effect after restarting Arepacoin. + + + + + The supplied proxy address is invalid. + + + + + OverviewPage + + + Form + فرم + + + + + The displayed information may be out of date. Your wallet automatically synchronizes with the Arepacoin network after a connection is established, but this process has not completed yet. + + + + + Stake: + + + + + Unconfirmed: + + + + + Wallet + کیف پول + + + + Spendable: + + + + + Your current spendable balance + + + + + Immature: + + + + + Mined balance that has not yet matured + + + + + Total: + + + + + Your current total balance + + + + + <b>Recent transactions</b> + تراکنشهای اخیر + + + + Total of transactions that have yet to be confirmed, and do not yet count toward the current balance + + + + + Total of coins that was staked, and do not yet count toward the current balance + + + + + + out of sync + خارج از روزآمد سازی + + + + QRCodeDialog + + + QR Code Dialog + + + + + Request Payment + + + + + Amount: + + + + + Label: + + + + + Message: + + + + + &Save As... + + + + + Error encoding URI into QR Code. + + + + + The entered amount is invalid, please check. + + + + + Resulting URI too long, try to reduce the text for label / message. + + + + + Save QR Code + + + + + PNG Images (*.png) + + + + + RPCConsole + + + Client name + نام کنسول RPC + + + + + + + + + + + + + N/A + + + + + Client version + ویرایش کنسول RPC + + + + &Information + + + + + Using OpenSSL version + + + + + Startup time + + + + + Network + شبکه + + + + Number of connections + تعداد اتصال + + + + On testnet + + + + + Block chain + زنجیره مجموعه تراکنش ها + + + + Current number of blocks + تعداد زنجیره های حاضر + + + + Estimated total blocks + + + + + Last block time + + + + + &Open + + + + + Command-line options + + + + + Show the Arepacoin-Qt help message to get a list with possible Arepacoin command-line options. + + + + + &Show + + + + + &Console + + + + + Build date + + + + + Arepacoin - Debug window + + + + + Arepacoin Core + + + + + Debug log file + + + + + Open the Arepacoin debug log file from the current data directory. This can take a few seconds for large log files. + + + + + Clear console + + + + + Welcome to the Arepacoin RPC console. + + + + + Use up and down arrows to navigate history, and <b>Ctrl-L</b> to clear screen. + + + + + Type <b>help</b> for an overview of available commands. + + + + + SendCoinsDialog + + + + + + + + + + Send Coins + سکه های ارسالی + + + + Coin Control Features + + + + + Inputs... + + + + + automatically selected + + + + + Insufficient funds! + + + + + Quantity: + + + + + + 0 + + + + + Bytes: + + + + + Amount: + میزان وجه: + + + + + + + 0.00 BC + + + + + Priority: + + + + + medium + + + + + Fee: + + + + + Low Output: + + + + + no + + + + + After Fee: + + + + + Change + + + + + custom change address + + + + + Send to multiple recipients at once + ارسال همزمان به گیرنده های متعدد + + + + Add &Recipient + + + + + Remove all transaction fields + + + + + Clear &All + + + + + Balance: + مانده حساب: + + + + 123.456 BC + + + + + Confirm the send action + تایید عملیات ارسال + + + + S&end + و ارسال + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Copy quantity + + + + + Copy amount + میزان وجه کپی شود + + + + Copy fee + + + + + Copy after fee + + + + + Copy bytes + + + + + Copy priority + + + + + Copy low output + + + + + Copy change + + + + + <b>%1</b> to %2 (%3) + + + + + Confirm send coins + تایید ارسال بیت کوین ها + + + + Are you sure you want to send %1? + + + + + and + + + + + The recipient address is not valid, please recheck. + + + + + The amount to pay must be larger than 0. + میزان پرداخت باید بیشتر از 0 باشد + + + + The amount exceeds your balance. + مقدار مورد نظر از مانده حساب بیشتر است. + + + + The total exceeds your balance when the %1 transaction fee is included. + + + + + Duplicate address found, can only send to each address once per send operation. + + + + + Error: Transaction creation failed. + + + + + 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. + + + + + WARNING: Invalid Arepacoin address + + + + + (no label) + (برچسب ندارد) + + + + WARNING: unknown change address + + + + + SendCoinsEntry + + + Form + + + + + A&mount: + و میزان وجه + + + + Pay &To: + پرداخت و به چه کسی + + + + + Enter a label for this address to add it to your address book + یک برچسب برای این آدرس بنویسید تا به دفترچه آدرسهای شما اضافه شود + + + + &Label: + و برچسب + + + + The address to send the payment to (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Choose address from address book + + + + + Alt+A + Alt و A + + + + Paste address from clipboard + آدرس را بر کلیپ بورد کپی کنید + + + + Alt+P + Alt و P + + + + Remove this recipient + + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + SignVerifyMessageDialog + + + Signatures - Sign / Verify a Message + + + + + + &Sign Message + و امضای پیام + + + + You can sign messages with your addresses to prove you own them. Be careful not to sign anything vague, as phishing attacks may try to trick you into signing your identity over to them. Only sign fully-detailed statements you agree to. + + + + + The address to sign the message with (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + + Choose an address from the address book + + + + + + Alt+A + Alt و A + + + + Paste address from clipboard + آدرس را بر کلیپ بورد کپی کنید + + + + Alt+P + Alt و P + + + + Enter the message you want to sign here + + + + + Copy the current signature to the system clipboard + + + + + Sign the message to prove you own this Arepacoin address + + + + + Reset all sign message fields + + + + + + Clear &All + + + + + + &Verify Message + + + + + Enter the signing address, message (ensure you copy line breaks, spaces, tabs, etc. exactly) and signature below to verify the message. Be careful not to read more into the signature than what is in the signed message itself, to avoid being tricked by a man-in-the-middle attack. + + + + + The address the message was signed with (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Verify the message to ensure it was signed with the specified Arepacoin address + + + + + Reset all verify message fields + + + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Click "Sign Message" to generate signature + + + + + Enter Arepacoin signature + + + + + + The entered address is invalid. + + + + + + + + Please check the address and try again. + + + + + + The entered address does not refer to a key. + + + + + Wallet unlock was cancelled. + + + + + Private key for the entered address is not available. + + + + + Message signing failed. + + + + + Message signed. + + + + + The signature could not be decoded. + + + + + + Please check the signature and try again. + + + + + The signature did not match the message digest. + + + + + Message verification failed. + + + + + Message verified. + + + + + TransactionDesc + + + Open until %1 + باز کن تا %1 + + + + Open for %n block(s) + + + + + conflicted + + + + + %1/offline + + + + + %1/unconfirmed + %1 / تایید نشده + + + + %1 confirmations + %1 تایید + + + + Status + + + + + , broadcast through %n node(s) + + + + + Date + تاریخ + + + + Source + + + + + Generated + + + + + + From + + + + + + + To + + + + + + own address + + + + + label + برچسب + + + + + + + + Credit + + + + + matures in %n more block(s) + + + + + not accepted + + + + + + + + Debit + + + + + Transaction fee + + + + + Net amount + + + + + Message + پیام + + + + Comment + + + + + Transaction ID + + + + + Generated coins must mature 6 blocks before they can be spent. When you generated this block, it was broadcast to the network to be added to the block chain. If it fails to get into the chain, its state will change to "not accepted" and it won't be spendable. This may occasionally happen if another node generates a block within a few seconds of yours. + + + + + Debug information + + + + + Transaction + + + + + Inputs + + + + + Amount + میزان + + + + true + + + + + false + + + + + , has not been successfully broadcast yet + ، هنوز با موفقیت ارسال نگردیده است + + + + unknown + ناشناس + + + + TransactionDescDialog + + + Transaction details + جزئیات تراکنش + + + + This pane shows a detailed description of the transaction + این بخش جزئیات تراکنش را نشان می دهد + + + + TransactionTableModel + + + Date + تاریخ + + + + Type + گونه + + + + Address + آدرس + + + + Amount + میزان وجه + + + + Open until %1 + باز کن تا %1 + + + + Confirmed (%1 confirmations) + تایید شده (%1 تاییدها) + + + + Open for %n more block(s) + + + + + Offline + + + + + Unconfirmed + + + + + Confirming (%1 of %2 recommended confirmations) + + + + + Conflicted + + + + + Immature (%1 confirmations, will be available after %2) + + + + + This block was not received by any other nodes and will probably not be accepted! + این block توسط گره های دیگری دریافت نشده است و ممکن است قبول نشود + + + + Generated but not accepted + تولید شده اما قبول نشده است + + + + Received with + قبول با + + + + Received from + دریافت شده از + + + + Sent to + ارسال به + + + + Payment to yourself + وجه برای شما + + + + Mined + استخراج شده + + + + (n/a) + خالی + + + + Transaction status. Hover over this field to show number of confirmations. + وضعیت تراکنش. با اشاره به این بخش تعداد تاییدها نمایش داده می شود + + + + Date and time that the transaction was received. + زمان و تاریخی که تراکنش دریافت شده است + + + + Type of transaction. + نوع تراکنش + + + + Destination address of transaction. + آدرس مقصد در تراکنش + + + + Amount removed from or added to balance. + میزان وجه کم شده یا اضافه شده به حساب + + + + TransactionView + + + + All + همه + + + + Today + امروز + + + + This week + این هفته + + + + This month + این ماه + + + + Last month + ماه گذشته + + + + This year + این سال + + + + Range... + حدود.. + + + + Received with + دریافت با + + + + Sent to + ارسال به + + + + To yourself + به شما + + + + Mined + استخراج شده + + + + Other + دیگر + + + + Enter address or label to search + آدرس یا برچسب را برای جستجو وارد کنید + + + + Min amount + حداقل میزان وجه + + + + Copy address + آدرس را کپی کنید + + + + Copy label + برچسب را کپی کنید + + + + Copy amount + میزان وجه کپی شود + + + + Copy transaction ID + + + + + Edit label + برچسب را ویرایش کنید + + + + Show transaction details + + + + + Export Transaction Data + + + + + Comma separated file (*.csv) + Comma separated file (*.csv) فایل جداگانه دستوری + + + + Confirmed + تایید شده + + + + Date + تاریخ + + + + Type + نوع + + + + Label + برچسب + + + + Address + آدرس + + + + Amount + میزان + + + + ID + شناسه کاربری + + + + Error exporting + + + + + Could not write to file %1. + + + + + Range: + دامنه: + + + + to + به + + + + WalletModel + + + Sending... + + + + + bitcoin-core + + + Arepacoin version + + + + + Usage: + میزان استفاده: + + + + Send command to -server or arepacoind + + + + + List commands + فهرست دستورها + + + + Get help for a command + درخواست کمک برای یک دستور + + + + Options: + انتخابها: + + + + Specify configuration file (default: arepacoin.conf) + + + + + Specify pid file (default: arepacoind.pid) + + + + + Specify wallet file (within data directory) + + + + + Specify data directory + دایرکتوری داده را مشخص کن + + + + Set database cache size in megabytes (default: 25) + حافظه بانک داده را به مگابایت تنظیم کنید (پیش فرض: 25) + + + + Set database disk log size in megabytes (default: 100) + + + + + Listen for connections on <port> (default: 9853 or testnet: 19853) + + + + + Maintain at most <n> connections to peers (default: 125) + نگهداری <N> ارتباطات برای قرینه سازی (پیش فرض:125) + + + + Connect to a node to retrieve peer addresses, and disconnect + + + + + Specify your own public address + + + + + Bind to given address. Use [host]:port notation for IPv6 + + + + + Stake your coins to support network and gain reward (default: 1) + + + + + Threshold for disconnecting misbehaving peers (default: 100) + آستانه قطع برای قرینه سازی اشتباه (پیش فرض:100) + + + + Number of seconds to keep misbehaving peers from reconnecting (default: 86400) + تعداد ثانیه ها برای اتصال دوباره قرینه های اشتباه (پیش فرض:86400) + + + + An error occurred while setting up the RPC port %u for listening on IPv4: %s + + + + + Detach block and address databases. Increases shutdown time (default: 0) + + + + + 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. + + + + + Error: This transaction requires a transaction fee of at least %s because of its amount, complexity, or use of recently received funds + + + + + Listen for JSON-RPC connections on <port> (default: 9852 or testnet: 19852) + + + + + Accept command line and JSON-RPC commands + command line و JSON-RPC commands را قبول کنید + + + + Error: Transaction creation failed + + + + + Error: Wallet locked, unable to create transaction + + + + + Importing blockchain data file. + + + + + Importing bootstrap blockchain data file. + + + + + Run in the background as a daemon and accept commands + به عنوان daemon بک گراند را اجرا کنید و دستورات را قبول نمایید + + + + Use the test network + از تستِ شبکه استفاده نمایید + + + + Accept connections from outside (default: 1 if no -proxy or -connect) + + + + + An error occurred while setting up the RPC port %u for listening on IPv6, falling back to IPv4: %s + + + + + Error initializing database environment %s! To recover, BACKUP THAT DIRECTORY, then remove everything from it except for wallet.dat. + + + + + Set maximum size of high-priority/low-fee transactions in bytes (default: 27000) + + + + + Warning: -paytxfee is set very high! This is the transaction fee you will pay if you send a transaction. + + + + + Warning: Please check that your computer's date and time are correct! If your clock is wrong Arepacoin will not work properly. + + + + + Warning: error reading wallet.dat! All keys read correctly, but transaction data or address book entries might be missing or incorrect. + + + + + Warning: wallet.dat corrupt, data salvaged! Original wallet.dat saved as wallet.{timestamp}.bak in %s; if your balance or transactions are incorrect you should restore from a backup. + + + + + Attempt to recover private keys from a corrupt wallet.dat + + + + + Block creation options: + + + + + Connect only to the specified node(s) + + + + + Discover own IP address (default: 1 when listening and no -externalip) + + + + + Failed to listen on any port. Use -listen=0 if you want this. + + + + + Find peers using DNS lookup (default: 1) + + + + + Sync checkpoints policy (default: strict) + + + + + Invalid -tor address: '%s' + + + + + Invalid amount for -reservebalance=<amount> + + + + + Maximum per-connection receive buffer, <n>*1000 bytes (default: 5000) + + + + + Maximum per-connection send buffer, <n>*1000 bytes (default: 1000) + + + + + Only connect to nodes in network <net> (IPv4, IPv6 or Tor) + + + + + Output extra debugging information. Implies all other -debug* options + + + + + Output extra network debugging information + + + + + Prepend debug output with timestamp + + + + + SSL options: (see the Bitcoin Wiki for SSL setup instructions) + + + + + Select the version of socks proxy to use (4-5, default: 5) + + + + + Send trace/debug info to console instead of debug.log file + ارسال اطلاعات پیگیری/خطایابی به کنسول به جای ارسال به فایل debug.log + + + + Send trace/debug info to debugger + + + + + Set maximum block size in bytes (default: 250000) + + + + + Set minimum block size in bytes (default: 0) + + + + + Shrink debug.log file on client startup (default: 1 when no -debug) + + + + + Specify connection timeout in milliseconds (default: 5000) + تعیین مدت زمان وقفه (time out) به هزارم ثانیه + + + + Unable to sign checkpoint, wrong checkpointkey? + + + + + + Use UPnP to map the listening port (default: 0) + + + + + Use UPnP to map the listening port (default: 1 when listening) + + + + + Use proxy to reach tor hidden services (default: same as -proxy) + + + + + Username for JSON-RPC connections + شناسه کاربری برای ارتباطاتِ JSON-RPC + + + + Verifying database integrity... + + + + + WARNING: syncronized checkpoint violation detected, but skipped! + + + + + Warning: Disk space is low! + + + + + Warning: This version is obsolete, upgrade required! + + + + + wallet.dat corrupt, salvage failed + + + + + Password for JSON-RPC connections + رمز برای ارتباطاتِ JSON-RPC + + + + %s, you must set a rpcpassword in the configuration file: + %s +It is recommended you use the following random password: +rpcuser=arepacoinrpc +rpcpassword=%s +(you do not need to remember this password) +The username and password MUST NOT be the same. +If the file does not exist, create it with owner-readable-only file permissions. +It is also recommended to set alertnotify so you are notified of problems; +for example: alertnotify=echo %%s | mail -s "Arepacoin Alert" admin@foo.com + + + + + + Find peers using internet relay chat (default: 0) + + + + + Sync time with other nodes. Disable if time on your system is precise e.g. syncing with NTP (default: 1) + + + + + When creating transactions, ignore inputs with value less than this (default: 0.01) + + + + + Allow JSON-RPC connections from specified IP address + ارتباطاتِ JSON-RPC را از آدرس آی.پی. مشخصی برقرار کنید. + + + + Send commands to node running on <ip> (default: 127.0.0.1) + دستورات را به گره اجرا شده در<ip> ارسال کنید (پیش فرض:127.0.0.1) + + + + Execute command when the best block changes (%s in cmd is replaced by block hash) + دستور را وقتی بهترین بلاک تغییر کرد اجرا کن (%s در دستور توسط block hash جایگزین شده است) + + + + Execute command when a wallet transaction changes (%s in cmd is replaced by TxID) + + + + + Require a confirmations for change (default: 0) + + + + + Enforce transaction scripts to use canonical PUSH operators (default: 1) + + + + + Execute command when a relevant alert is received (%s in cmd is replaced by message) + + + + + Upgrade wallet to latest format + wallet را به جدیدترین نسخه روزآمد کنید + + + + Set key pool size to <n> (default: 100) + حجم key pool را به اندازه <n> تنظیم کنید (پیش فرض:100) + + + + Rescan the block chain for missing wallet transactions + زنجیره بلاک را برای تراکنش جا افتاده در WALLET دوباره اسکن کنید + + + + How many blocks to check at startup (default: 2500, 0 = all) + + + + + How thorough the block verification is (0-6, default: 1) + + + + + Imports blocks from external blk000?.dat file + + + + + Use OpenSSL (https) for JSON-RPC connections + برای ارتباطاتِ JSON-RPC از OpenSSL (https) استفاده کنید + + + + Server certificate file (default: server.cert) + فایل certificate سرور (پیش فرض server.cert) + + + + Server private key (default: server.pem) + رمز اختصاصی سرور (پیش فرض: server.pem) + + + + Acceptable ciphers (default: TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH) + + + + + Error: Wallet unlocked for staking only, unable to create transaction. + + + + + WARNING: Invalid checkpoint found! Displayed transactions may not be correct! You may need to upgrade, or notify developers. + + + + + This help message + این پیام راهنما + + + + Wallet %s resides outside data directory %s. + + + + + Cannot obtain a lock on data directory %s. Arepacoin is probably already running. + + + + + Arepacoin + + + + + Unable to bind to %s on this computer (bind returned error %d, %s) + + + + + Connect through socks proxy + + + + + Allow DNS lookups for -addnode, -seednode and -connect + + + + + Loading addresses... + لود شدن آدرسها.. + + + + Error loading blkindex.dat + + + + + Error loading wallet.dat: Wallet corrupted + خطا در هنگام لود شدن wallet.dat: Wallet corrupted + + + + Error loading wallet.dat: Wallet requires newer version of Arepacoin + + + + + Wallet needed to be rewritten: restart Arepacoin to complete + + + + + Error loading wallet.dat + خطا در هنگام لود شدن wallet.dat + + + + Invalid -proxy address: '%s' + + + + + Unknown network specified in -onlynet: '%s' + + + + + Unknown -socks proxy version requested: %i + + + + + Cannot resolve -bind address: '%s' + + + + + Cannot resolve -externalip address: '%s' + + + + + Invalid amount for -paytxfee=<amount>: '%s' + میزان اشتباه است for -paytxfee=<amount>: '%s' + + + + Error: could not start node + + + + + Sending... + + + + + Invalid amount + میزان اشتباه است + + + + Insufficient funds + وجوه ناکافی + + + + Loading block index... + لود شدن نمایه بلاکها.. + + + + Add a node to connect to and attempt to keep the connection open + یک گره برای اتصال اضافه کنید و تلاش کنید تا اتصال را باز نگاه دارید + + + + Unable to bind to %s on this computer. Arepacoin is probably already running. + + + + + Fee per KB to add to transactions you send + + + + + Invalid amount for -mininput=<amount>: '%s' + + + + + Loading wallet... + wallet در حال لود شدن است... + + + + Cannot downgrade wallet + قابلیت برگشت به نسخه قبلی برای wallet امکان پذیر نیست + + + + Cannot initialize keypool + + + + + Cannot write default address + آدرس پیش فرض قابل ذخیره نیست + + + + Rescanning... + اسکنِ دوباره... + + + + Done loading + اتمام لود شدن + + + + To use the %s option + برای استفاده از %s از اختیارات + + + + Error + خطا + + + + You must set rpcpassword=<password> in the configuration file: +%s +If the file does not exist, create it with owner-readable-only file permissions. + شما باید یک رمز rpcpassword=<password> را در فایل تنظیمات ایجاد کنید⏎ %s ⏎ اگر فایل ایجاد نشده است، آن را با یک فایل "فقط متنی" ایجاد کنید. + + + + \ No newline at end of file diff --git a/src/qt/locale/bitcoin_fi.ts b/src/qt/locale/bitcoin_fi.ts new file mode 100755 index 0000000..4c51265 --- /dev/null +++ b/src/qt/locale/bitcoin_fi.ts @@ -0,0 +1,3310 @@ + + + AboutDialog + + + About Arepacoin + Tietoa Arepacoinista + + + + <b>Arepacoin</b> version + <b>Arepacoin</b> versio + + + + Copyright © 2009-2014 The Bitcoin developers +Copyright © 2012-2014 The NovaCoin developers +Copyright © 2014 The Arepacoin developers + + + + + +This is experimental software. + +Distributed under the MIT/X11 software license, see the accompanying file COPYING or http://www.opensource.org/licenses/mit-license.php. + +This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit (http://www.openssl.org/) and cryptographic software written by Eric Young (eay@cryptsoft.com) and UPnP software written by Thomas Bernard. + +Tämä on kokeellista ohjelmistoa. + +Levitetään MIT/X11 ohjelmistolisenssin alaisuudessa. Tarkemmat tiedot löytyvät tiedostosta COPYING tai osoitteesta http://www.opensource.org/licenses/mit-license.php. + +Tämä tuote sisältää OpenSSL-projektin kehittämää ohjelmistoa OpenSSL-työkalupakettia varten (http://www.openssl.org/), Eric Youngin (eay@cryptsoft.com) kehittämän salausohjelmiston sekä Thomas Bernardin UPnP-ohjelmiston. + + + + + AddressBookPage + + + Address Book + Osoitekirja + + + + Double-click to edit address or label + Kaksoisnapauta muokataksesi osoitetta tai nimikettä + + + + Create a new address + Luo uusi osoite + + + + Copy the currently selected address to the system clipboard + Kopioi valittu osoite järjestelmän leikepöydälle + + + + &New Address + &Uusi osoite + + + + These are your Arepacoin addresses for receiving payments. You may want to give a different one to each sender so you can keep track of who is paying you. + Nämä ovat Arepacoin-osoitteesi rahansiirtojen vastaanottoa varten. Jos haluat, voit antaa jokaiselle lähettäjälle oman osoitteen jotta voit pitää kirjaa sinulle rahaa siirtäneistä henkilöistä. + + + + &Copy Address + &Kopioi osoite + + + + Show &QR Code + Näytä &QR-koodi + + + + Sign a message to prove you own a Arepacoin address + Allekirjoita viesti osoittaaksesi Arepacoin-osoitteesi omistajuus + + + + Sign &Message + Allekirjoita &Viesti + + + + Delete the currently selected address from the list + Poista valittu osoite listalta + + + + Verify a message to ensure it was signed with a specified Arepacoin address + Vahvista viesti varmistaaksesi että kyseinen Arepacoin-osoitteesi on allekirjoittanut sen + + + + &Verify Message + &Varmista viesti + + + + &Delete + &Poista + + + + Copy &Label + Kopioi &nimi + + + + &Edit + &Muokkaa + + + + Export Address Book Data + Vie osoitekirjasta tietoja + + + + Comma separated file (*.csv) + Pilkuilla eroteltu tiedosto (*.csv) + + + + Error exporting + Virhe vietäessä + + + + Could not write to file %1. + Ei voida kirjoittaa tiedostoon %1. + + + + AddressTableModel + + + Label + Nimi + + + + Address + Osoite + + + + (no label) + (ei nimeä) + + + + AskPassphraseDialog + + + Passphrase Dialog + Tunnuslauseen Dialogi + + + + Enter passphrase + Syötä tunnuslause + + + + New passphrase + Uusi tunnuslause + + + + Repeat new passphrase + Toista uusi tunnuslause uudelleen + + + + Serves to disable the trivial sendmoney when OS account compromised. Provides no real security. + Sallii estettäväksi yksinkertaiset rahansiirrot kun käyttöjärjestelmän käyttäjätunnuksen turvallisuutta on rikottu. Tämä ei takaa oikeasti turvallisuutta. + + + + For staking only + Vain osakkuutta varten + + + + Enter the new passphrase to the wallet.<br/>Please use a passphrase of <b>10 or more random characters</b>, or <b>eight or more words</b>. + Anna lompakolle uusi tunnuslause.<br/>Käytä tunnuslausetta, jossa on ainakin <b>10 satunnaista merkkiä</b> tai <b>kahdeksan sanaa</b>. + + + + Encrypt wallet + Salaa lompakko + + + + This operation needs your wallet passphrase to unlock the wallet. + Tätä toimintoa varten sinun täytyy antaa lompakon tunnuslause sen avaamiseksi. + + + + Unlock wallet + Avaa lompakko lukituksestaan + + + + This operation needs your wallet passphrase to decrypt the wallet. + Tätä toimintoa varten sinun täytyy antaa lompakon tunnuslause salauksen purkuun. + + + + Decrypt wallet + Pura lompakon salaus + + + + Change passphrase + Vaihda tunnuslause + + + + Enter the old and new passphrase to the wallet. + Anna vanha ja uusi tunnuslause. + + + + Confirm wallet encryption + Vahvista lompakon salaus + + + + Warning: If you encrypt your wallet and lose your passphrase, you will <b>LOSE ALL OF YOUR COINS</b>! + Varoitus: Jos salaat lompakkosi ja hukkaat salasanasi, <b>MENETÄT KAIKKI KOLIKKOSI</b>! + + + + Are you sure you wish to encrypt your wallet? + Haluatko varmasti salata lompakkosi? + + + + IMPORTANT: Any previous backups you have made of your wallet file should be replaced with the newly generated, encrypted wallet file. For security reasons, previous backups of the unencrypted wallet file will become useless as soon as you start using the new, encrypted wallet. + TÄRKEÄÄ: Kaikki vanhat lompakon varmuuskopiot tulisi korvata uusilla suojatuilla varmuuskopioilla. Turvallisuussyistä edelliset varmuuskopiot muuttuvat käyttökelvottomiksi, kun aloitat uuden salatun lompakon käytön. + + + + + Warning: The Caps Lock key is on! + Varoitus: Caps Lock-näppäin on käytössä! + + + + + Wallet encrypted + Lompakko salattu + + + + Arepacoin will close now to finish the encryption process. Remember that encrypting your wallet cannot fully protect your coins from being stolen by malware infecting your computer. + Arepacoin-ohjelma sulkee itsensä päättääkseen salauksen luonnin. Muista, että lompakon salaaminen ei täysin turvaa kolikoitasi haittaohjelmien aiheuttamien varkauksien uhalta. + + + + + + + Wallet encryption failed + Lompakon salaus epäonnistui + + + + Wallet encryption failed due to an internal error. Your wallet was not encrypted. + Lompakon salaaminen epäonnistui sisäisen virheen vuoksi. Lompakkoasi ei salattu. + + + + + The supplied passphrases do not match. + Annetut tunnuslauseet eivät täsmää. + + + + Wallet unlock failed + Lompakon avaaminen epäonnistui. + + + + + + The passphrase entered for the wallet decryption was incorrect. + Annettu tunnuslause oli väärä. + + + + Wallet decryption failed + Lompakon salauksen purku epäonnistui. + + + + Wallet passphrase was successfully changed. + Lompakon tunnuslause vaihdettiin onnistuneesti. + + + + BitcoinGUI + + + Sign &message... + Allekirjoita &viesti... + + + + Synchronizing with network... + Synkronoidaan verkon kanssa... + + + + &Overview + &Yleisnäkymä + + + + Show general overview of wallet + Lompakon tilanteen yleiskatsaus + + + + &Transactions + &Rahansiirrot + + + + Browse transaction history + Selaa rahansiirtohistoriaa + + + + &Address Book + %Osoitekirja + + + + Edit the list of stored addresses and labels + Muokkaa tallennettujen osoitteiden ja nimien listaa + + + + &Receive coins + &Vastaanota kolikoita + + + + Show the list of addresses for receiving payments + Näytä osoitelista vastaanottaaksesi maksuja + + + + &Send coins + &Lähetä kolikoita + + + + E&xit + L&opeta + + + + Quit application + Sulje ohjelma + + + + Show information about Arepacoin + Näytä tietoja Arepacoinista + + + + About &Qt + Tietoja &Qt + + + + Show information about Qt + Näytä tietoja Qt:sta + + + + &Options... + &Asetukset... + + + + &Encrypt Wallet... + &Salaa lompakko... + + + + &Backup Wallet... + &Varmuuskopioi lompakko... + + + + &Change Passphrase... + &Vaihda tunnuslause... + + + + ~%n block(s) remaining + ~%n lohko jäljellä~%n lohkoa jäljellä + + + + Downloaded %1 of %2 blocks of transaction history (%3% done). + Ladattu %1 lohkoa %2 lohkosta rahansiirtohistoriassa (%3% ladattu). + + + + &Export... + Vie... + + + + Send coins to a Arepacoin address + Lähetä kolikkoja Arepacoin osoitteeseen + + + + Modify configuration options for Arepacoin + Mukauta Arepacoinin konfigurointiasetuksia + + + + Export the data in the current tab to a file + Vie data tämänhetkisestä välilehdestä tiedostoon + + + + Encrypt or decrypt wallet + Salaa tai pura salaus lompakosta + + + + Backup wallet to another location + Varmuuskopioi lompakko toiseen sijaintiin + + + + Change the passphrase used for wallet encryption + Vaihda lompakon salaukseen käytettävä tunnuslause + + + + &Debug window + &Testausikkuna + + + + Open debugging and diagnostic console + Avaa debuggaus- ja diagnostiikkakonsoli + + + + &Verify message... + &Vahvista viesti... + + + + Arepacoin + Arepacoin + + + + Wallet + Lompakko + + + + &About Arepacoin + &Tietoa Arepacoinista + + + + &Show / Hide + &Näytä / Piilota + + + + Unlock wallet + Avaa Lompakko + + + + &Lock Wallet + &Lukitse Lompakko + + + + Lock wallet + Lukitse lompakko + + + + &File + &Tiedosto + + + + &Settings + &Asetukset + + + + &Help + &Apua + + + + Tabs toolbar + Välilehtipalkki + + + + Actions toolbar + Toimintopalkki + + + + + [testnet] + [testnet] + + + + + Arepacoin client + Arepacoin-asiakas + + + + %n active connection(s) to Arepacoin network + %n aktiivinen yhteys Arepacoin-verkkoon%n aktiivista yhteyttä Arepacoin-verkkoon + + + + Downloaded %1 blocks of transaction history. + Ladattu %1 lohkoa rahansiirtohistoriasta. + + + + Staking.<br>Your weight is %1<br>Network weight is %2<br>Expected time to earn reward is %3 + Osakkaana.<br>Osuutesi on %1<br>Verkon osuus on %2<br>Odotettu aika palkkion ansaitsemiselle on %3 + + + + Not staking because wallet is locked + Ei osakkaana koska lompakko on lukittu + + + + Not staking because wallet is offline + Ei osakkaana koska lompakko on offline-tilassa + + + + Not staking because wallet is syncing + Ei osakkaana koska lompakko synkronoituu + + + + Not staking because you don't have mature coins + Ei osakkaana koska sinulle ei ole erääntynyt kolikoita + + + + %n second(s) ago + %n sekunti sitten%n sekuntia sitten + + + + &Unlock Wallet... + &Aukaise lompakko + + + + %n minute(s) ago + %n minuutti sitten%n minuuttia sitten + + + + %n hour(s) ago + %n tunti sitten%n tuntia sitten + + + + %n day(s) ago + %n päivä sitten%n päivää sitten + + + + Up to date + Rahansiirtohistoria on ajan tasalla + + + + Catching up... + Saavutetaan verkkoa... + + + + Last received block was generated %1. + Viimeinen vastaanotettu lohko generoitu %1. + + + + This transaction is over the size limit. You can still send it for a fee of %1, which goes to the nodes that process your transaction and helps to support the network. Do you want to pay the fee? + Tämä rahansiirto ylittää siirtorajan. Voit silti lähettää sen %1 rahansiirtopalkkiota vastaan, joka siirretään rahansiirtoasi käsitteleville solmuille jotta se auttaisi ja tukisi verkkoa. Haluatko maksaa rahansiirtopalkkion? + + + + Confirm transaction fee + Hyväksy rahansiirtopalkkio + + + + Sent transaction + Lähetetyt rahansiirrot + + + + Incoming transaction + Saapuva rahansiirto + + + + Date: %1 +Amount: %2 +Type: %3 +Address: %4 + + Päivä: %1 +Määrä: %2 +Tyyppi: %3 +Osoite: %4 + + + + + URI handling + URI-merkkijonojen käsittely + + + + + URI can not be parsed! This can be caused by an invalid Arepacoin address or malformed URI parameters. + URI-merkkijonoa ei voida jäsentää! Tämä voi johtua väärästä Arepacoin-osoitteesta tai väärässä muodossa olevista URI-parametreistä. + + + + Wallet is <b>encrypted</b> and currently <b>unlocked</b> + Lompakko on <b>salattu</b> ja tällä hetkellä <b>avoinna</b> + + + + Wallet is <b>encrypted</b> and currently <b>locked</b> + Lompakko on <b>salattu</b> ja tällä hetkellä <b>lukittuna</b> + + + + Backup Wallet + Varmuuskopioi lompakkosi + + + + Wallet Data (*.dat) + Lompakkodata (*.dat) + + + + Backup Failed + Varmuuskopion luonti epäonnistui + + + + There was an error trying to save the wallet data to the new location. + Virhe tallentaessa lompakkotiedostoa uuteen sijaintiinsa. + + + + %n second(s) + %n sekunti%n sekuntia + + + + %n minute(s) + %n minuutti%n minuuttia + + + + %n hour(s) + %n tunti%n tuntia + + + + %n day(s) + %n päivä%n päivää + + + + Not staking + Ei osakkaana + + + + A fatal error occurred. Arepacoin can no longer continue safely and will quit. + Vakava virhe kohdattu. Arepacoin-ohjelma ei voi enää jatkaa turvallisesti ja sulkee itsensä. + + + + ClientModel + + + Network Alert + Verkkohälytys + + + + CoinControlDialog + + + Coin Control + Rahan hallinta + + + + Quantity: + Määrä: + + + + Bytes: + Tavua: + + + + Amount: + Määrä: + + + + Priority: + Prioriteetti: + + + + Fee: + Kulu: + + + + Low Output: + Heikko ulosanti: + + + + no + ei + + + + After Fee: + Kulujen jälkeen: + + + + Change: + Vaihdos: + + + + (un)select all + (tai ei)Valitse kaikki + + + + Tree mode + Puunäkymä + + + + List mode + Listanäkymä + + + + Amount + Määrä + + + + Label + Nimike + + + + Address + Osoite + + + + Date + Päivämäärä + + + + Confirmations + Vahvistukset + + + + Confirmed + Vahvistettu + + + + Priority + Prioriteetti + + + + Copy address + Kopioi osoite + + + + Copy label + Kopioi nimi + + + + + Copy amount + Kopioi määrä + + + + Copy transaction ID + Kopioi siirtotunnus + + + + Copy quantity + Kopioi määrä + + + + Copy fee + Kopioi kulu + + + + Copy after fee + Kopioi kulun jälkeen + + + + Copy bytes + Kopioi tavuja + + + + Copy priority + Kopioi prioriteetti + + + + Copy low output + Kopioi heikko ulosanti + + + + Copy change + Kopioi vaihdos + + + + highest + korkein + + + + high + korkea + + + + medium-high + keskikorkea + + + + medium + keski + + + + low-medium + keskimatala + + + + low + matala + + + + lowest + matalin + + + + DUST + pölyä + + + + yes + kyllä + + + + This label turns red, if the transaction size is bigger than 10000 bytes. + + This means a fee of at least %1 per kb is required. + + Can vary +/- 1 Byte per input. + Tämä nimike muuttuu punaiseksi, jos rahansiirron koko on suurempi kuin 10000 tavua. + +Tämä tarkoittaa, että ainakin %1 rahansiirtopalkkio per kilotavu tarvitaan. + +Voi vaihdella välillä +/- 1 Tavu per syöte. + + + + Transactions with higher priority get more likely into a block. + +This label turns red, if the priority is smaller than "medium". + + This means a fee of at least %1 per kb is required. + Suuremman prioriteetin rahansiirrot pääsevät suuremmalla todennäköisyydellä lohkoketjuun. + +Tämä nimike muuttuu punaiseksi, jos prioriteetti on pienempi kuin "keskikokoinen". + +Tämä tarkoittaa, että ainakin %1 rahansiirtopalkkio per kilotavu tarvitaan. + + + + This label turns red, if any recipient receives an amount smaller than %1. + + This means a fee of at least %2 is required. + + Amounts below 0.546 times the minimum relay fee are shown as DUST. + Tämä nimike muuttuu punaiseksi, jos jokin asiakas saa pienemmän määrän kuin %1. + +Tämä tarkoittaa, että ainakin %2 rahansiirtopalkkio tarvitaan. + +Määrät alle 0.546 kertaa pienimmän rahansiirtokulun verran näytetään pölynä. + + + + This label turns red, if the change is smaller than %1. + + This means a fee of at least %2 is required. + Tämä nimike muuttuu punaiseksi, jos vaihdos on pienempi kuin %1. + +Tämä tarkoittaa, että ainakin %2 rahansiirtopalkkio tarvitaan. + + + + + (no label) + (ei nimeä) + + + + change from %1 (%2) + vaihdos %1 (%2) + + + + (change) + (vaihdos) + + + + EditAddressDialog + + + Edit Address + Muokkaa osoitetta + + + + &Label + &Nimi + + + + The label associated with this address book entry + Tämän syötteen nimike osoitekirjassa + + + + &Address + &Osoite + + + + The address associated with this address book entry. This can only be modified for sending addresses. + Tämän syötteen nimike osoitekirjassa. Nimikettä voidaan muuttaa vain lähetysosoitteille. + + + + New receiving address + Uusi vastaanottava osoite + + + + New sending address + Uusi lähettävä osoite + + + + Edit receiving address + Muokkaa vastaanottajan osoitetta + + + + Edit sending address + Muokkaa lähtevää osoitetta + + + + The entered address "%1" is already in the address book. + Osoite "%1" on jo osoitekirjassa. + + + + The entered address "%1" is not a valid Arepacoin address. + Syöttämäsi osoite "%1" ei ole hyväksytty Arepacoin-osoite. + + + + Could not unlock wallet. + Lompakkoa ei voitu avata. + + + + New key generation failed. + Uuden avaimen luonti epäonnistui. + + + + GUIUtil::HelpMessageBox + + + + Arepacoin-Qt + Arepacoin-Qt + + + + version + versio + + + + Usage: + Kulutus: + + + + command-line options + komentokehotteen asetukset + + + + UI options + Käyttäjärajapinnan asetukset + + + + Set language, for example "de_DE" (default: system locale) + Aseta kieli, esimerkiksi "fi_FI" (oletus: järjestelmän oma) + + + + Start minimized + Käynnistä pienennettynä + + + + Show splash screen on startup (default: 1) + Näytä logo käynnistettäessä (oletus: 1) + + + + OptionsDialog + + + Options + Asetukset + + + + &Main + &Yleiset + + + + Optional transaction fee per kB that helps make sure your transactions are processed quickly. Most transactions are 1 kB. Fee 0.01 recommended. + Vapaavalintainen rahansiirtopalkkio kilotavua kohden auttaa varmistamaan että rahansiirtosi käsitellään nopeasti. Suurin osa rahansiirroista on alle yhden kilotavun. Palkkiota 0.01 suositellaan. + + + + Pay transaction &fee + Maksa rahansiirtopalkkio + + + + Reserved amount does not participate in staking and is therefore spendable at any time. + Varattu määrä ei vaadi osakkuutta jonka vuoksi se on mahdollista käyttää milloin tahansa. + + + + Reserve + Varattuna + + + + Automatically start Arepacoin after logging in to the system. + Käynnistä Arepacoin-asiakasohjelma automaattisesti kun olet kirjautunut järjestelmään. + + + + &Start Arepacoin on system login + %Käynnistä Arepacoin-asiakasohjelma kirjautuessasi + + + + Detach block and address databases at shutdown. This means they can be moved to another data directory, but it slows down shutdown. The wallet is always detached. + Irroita lohko- ja osoitetietokannat lopetettaessa. Tämä tarkoittaa, että tietokannat voidaan siirtää eri hakemistoon mutta se hidastaa ohjelman sammumista. Lompakko on aina irroitettuna. + + + + &Detach databases at shutdown + %Irroita tietokannat lopetettaessa + + + + &Network + &Verkko + + + + Automatically open the Arepacoin client port on the router. This only works when your router supports UPnP and it is enabled. + Avaa Arepacoin-asiakkaalle automaattisesti portti reitittimestä. Tämä toimii vain, kun reitittimesi tukee UPnP:tä ja se on aktivoituna. + + + + Map port using &UPnP + Portin uudelleenohjaus &UPnP:llä + + + + Connect to the Arepacoin network through a SOCKS proxy (e.g. when connecting through Tor). + Yhdistä Arepacoin-verkkoon SOCKS-välityspalvelimen lävitse. (esim. yhdistettäessä Tor:n läpi). + + + + &Connect through SOCKS proxy: + %Yhdistä SOCKS-välityspalvelimen läpi: + + + + Proxy &IP: + Proxyn &IP: + + + + IP address of the proxy (e.g. 127.0.0.1) + Välityspalvelimen IP-osoite (esim. 127.0.0.1) + + + + &Port: + &Portti + + + + Port of the proxy (e.g. 9050) + Proxyn Portti (esim. 9050) + + + + SOCKS &Version: + SOCKS &Versio: + + + + SOCKS version of the proxy (e.g. 5) + Proxyn SOCKS-versio (esim. 5) + + + + &Window + &Ikkuna + + + + Show only a tray icon after minimizing the window. + Näytä ainoastaan ilmaisinalueella ikkunan pienentämisen jälkeen. + + + + &Minimize to the tray instead of the taskbar + &Pienennä ilmaisinalueelle työkalurivin sijasta + + + + Minimize instead of exit the application when the window is closed. When this option is enabled, the application will be closed only after selecting Quit in the menu. + Ikkunaa suljettaessa vain pienentää Bitcoin-ohjelman ikkunan lopettamatta itse ohjelmaa. Kun tämä asetus on valittuna, ohjelman voi sulkea vain valitsemalla Lopeta ohjelman valikosta. + + + + M&inimize on close + P&ienennä suljettaessa + + + + &Display + &Käyttöliittymä + + + + User Interface &language: + &Käyttöliittymän kieli + + + + The user interface language can be set here. This setting will take effect after restarting Arepacoin. + Käyttöliittymän kieli voidaan valita tästä. Tämä asetus tulee voimaan vasta Arepacoin-asiakasohjelman uudelleenkäynnistyksen jälkeen. + + + + &Unit to show amounts in: + Yksikkö jona bitcoin-määrät näytetään + + + + Choose the default subdivision unit to show in the interface and when sending coins. + Valitse mitä yksikköä käytetään ensisijaisesti bitcoin-määrien näyttämiseen. + + + + Whether to show Arepacoin addresses in the transaction list or not. + Näytä tai piilota Arepacoin-osoitteet rahansiirtolistassa. + + + + &Display addresses in transaction list + &Näytä osoitteet rahansiirrot listassa + + + + Whether to show coin control features or not. + Näytä tai piilota rahanhallintaominaisuudet. + + + + Display coin &control features (experts only!) + Näytä rahan&hallinnan ominaisuudet (vain kokeneille käyttäjille!) + + + + &OK + &OK + + + + &Cancel + &Peruuta + + + + &Apply + %Käytä + + + + default + oletus + + + + + Warning + Varoitus + + + + + This setting will take effect after restarting Arepacoin. + Tämä asetus tulee voimaan vasta Arepacoin-asiakasohjelman uudelleenkäynnistyksen jälkeen. + + + + The supplied proxy address is invalid. + Antamasi proxy-osoite on virheellinen. + + + + OverviewPage + + + Form + Lomake + + + + + The displayed information may be out of date. Your wallet automatically synchronizes with the Arepacoin network after a connection is established, but this process has not completed yet. + Näytettävät tiedot voivat olla vanhentuneet. Lompakkosi synkronoituu automaattisesti Arepacoin-verkon kanssa kun yhteys on muodostettu, mutta tätä prosessia ei ole viety vielä päätökseen. + + + + Stake: + Vaihdos: + + + + Unconfirmed: + Hyväksymätöntä: + + + + Wallet + Lompakko + + + + Spendable: + Käytettävissä: + + + + Your current spendable balance + Käytettävissä olevat varat: + + + + Immature: + Epäkypsää: + + + + Mined balance that has not yet matured + Louhittu saldo, joka ei ole vielä kypsynyt + + + + Total: + Yhteensä: + + + + Your current total balance + Tililläsi tällä hetkellä olevien Bitcoinien määrä + + + + <b>Recent transactions</b> + <b>Viimeisimmät rahansiirrot</b> + + + + Total of transactions that have yet to be confirmed, and do not yet count toward the current balance + Kaikki vahvistamattomat rahansiirrot yhteensä, joita ei vielä lasketa saldoosi. + + + + Total of coins that was staked, and do not yet count toward the current balance + Kolikoiden kokoinaismäärä, jotka eivät vielä ole laskettu tämänhetkiseen saldoon. + + + + + out of sync + Ei ajan tasalla + + + + QRCodeDialog + + + QR Code Dialog + QR-koodidialogi + + + + Request Payment + Pyydä rahansiirtoa + + + + Amount: + Määrä: + + + + Label: + Nimike: + + + + Message: + Viesti: + + + + &Save As... + %Tallenna nimellä... + + + + Error encoding URI into QR Code. + Virhe koodatessa linkkiä QR-koodiin. + + + + The entered amount is invalid, please check. + Syötetty määrä on epäkelpoinen; tarkista. + + + + Resulting URI too long, try to reduce the text for label / message. + Tuloksena liian pitkä URI, yritä lyhentää nimikkeen tai viestin pituutta. + + + + Save QR Code + Tallenna QR-koodi + + + + PNG Images (*.png) + PNG-kuvat (*.png) + + + + RPCConsole + + + Client name + Pääteohjelman nimi + + + + + + + + + + + + + N/A + Ei saatavilla + + + + Client version + Pääteohjelman versio + + + + &Information + T&ietoa + + + + Using OpenSSL version + Käytössä oleva OpenSSL-versio + + + + Startup time + Käynnistysaika + + + + Network + Verkko + + + + Number of connections + Yhteyksien lukumäärä + + + + On testnet + Testiverkossa + + + + Block chain + Lohkoketju + + + + Current number of blocks + Nykyinen Lohkojen määrä + + + + Estimated total blocks + Arvioitu lohkojen kokonaismäärä + + + + Last block time + Viimeisimmän lohkon aika + + + + &Open + &Avaa + + + + Command-line options + Komentokehotteen ominaisuudet + + + + Show the Arepacoin-Qt help message to get a list with possible Arepacoin command-line options. + Näytä Arepacoin-Qt:n avustusohje saadaksesi listan käytettävistä Arepacoinin komentokehotteen määritteistä. + + + + &Show + %Näytä + + + + &Console + &Konsoli + + + + Build date + Kääntöpäiväys + + + + Arepacoin - Debug window + Arepacoin - Debug-ikkuna + + + + Arepacoin Core + Arepacoinin ydin + + + + Debug log file + Debug lokitiedosto + + + + Open the Arepacoin debug log file from the current data directory. This can take a few seconds for large log files. + Avaa Arepacoin-asiakasohjelman debug-lokitiedosto nykyisestä hakemistostaan. Tämä voi kestää muutaman sekunnin avattaessa suuria lokitiedostoja. + + + + Clear console + Tyhjennä konsoli + + + + Welcome to the Arepacoin RPC console. + Tervetuloa Arepacoinin RPC-konsoliin. + + + + Use up and down arrows to navigate history, and <b>Ctrl-L</b> to clear screen. + Ylös- ja alas-nuolet selaavat historiaa ja <b>Ctrl-L</b> tyhjentää ruudun. + + + + Type <b>help</b> for an overview of available commands. + Kirjoita <b>help</b> nähdäksesi yleiskatsauksen käytettävissä olevista komennoista. + + + + SendCoinsDialog + + + + + + + + + + Send Coins + Lähetä Bitcoineja + + + + Coin Control Features + Kolikoidenhallinnan ominaisuudet + + + + Inputs... + Syötteet... + + + + automatically selected + automaattisesti valittu + + + + Insufficient funds! + Ei tarpeeksi varoja! + + + + Quantity: + Määrä: + + + + + 0 + 0 + + + + Bytes: + Tavua: + + + + Amount: + Määrä: + + + + + + + 0.00 BC + 123.456 BC {0.00 ?} + + + + Priority: + Prioriteetti: + + + + medium + keskikokoinen + + + + Fee: + Kulu: + + + + Low Output: + Heikko ulosanti: + + + + no + ei + + + + After Fee: + Kulujen jälkeen: + + + + Change + Vaihtoraha + + + + custom change address + erikseen määritetty vaihtorahaosoite + + + + Send to multiple recipients at once + Lähetä monelle vastaanottajalle + + + + Add &Recipient + Lisää &Vastaanottaja + + + + Remove all transaction fields + Tyhjennä kaikki rahansiirtokentät + + + + Clear &All + &Tyhjennnä Kaikki + + + + Balance: + Saldo: + + + + 123.456 BC + 123.456 BC + + + + Confirm the send action + Vahvista lähetys + + + + S&end + &Lähetä + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + Syötä Arepacoin-osoite (esim. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + Copy quantity + Kopioi määrä + + + + Copy amount + Kopioi määrä + + + + Copy fee + Kopioi rahansiirtokulu + + + + Copy after fee + Kopioi rahansiirtokulun jälkeen + + + + Copy bytes + Kopioi tavuja + + + + Copy priority + Kopioi prioriteetti + + + + Copy low output + Kopioi heikko ulosanti + + + + Copy change + Kopioi vaihtoraha + + + + <b>%1</b> to %2 (%3) + <b>%1</b>:sta %2 (%3) + + + + Confirm send coins + Hyväksy Bitcoinien lähettäminen + + + + Are you sure you want to send %1? + Oletko varma että haluat lähettää %1? + + + + and + ja + + + + The recipient address is not valid, please recheck. + Vastaanottajan osoite on virheellinen. Tarkista osoite. + + + + The amount to pay must be larger than 0. + Maksettavan summan tulee olla suurempi kuin 0 Bitcoinia. + + + + The amount exceeds your balance. + Määrä ylittää käytettävissä olevan saldon. + + + + The total exceeds your balance when the %1 transaction fee is included. + Kokonaismäärä ylittää saldosi kun %1 maksukulu lisätään summaan. + + + + Duplicate address found, can only send to each address once per send operation. + Sama osoite toistuu useamman kerran. Samaan osoitteeseen voi lähettää vain kerran per maksu. + + + + Error: Transaction creation failed. + Virhe: Rahansiirron luonti epäonnistui. + + + + 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. + Virhe: Rahansiirto evätty. Tämä voi tapahtua kun jotkut kolikot lompakossasi ovat jo käytetty, kuten myös tilanteessa jos käytit wallet.dat-tiedoston kopiota ja rahat olivat käytetty kopiossa, mutta eivät ole merkitty käytetyiksi tässä. + + + + WARNING: Invalid Arepacoin address + VAROITUS: Epäkelpo Arepacoin-osoite + + + + (no label) + (ei nimeä) + + + + WARNING: unknown change address + VAROITUS: Tuntematon vaihtorahaosoite + + + + SendCoinsEntry + + + Form + Kaavake + + + + A&mount: + M&äärä: + + + + Pay &To: + Maksun saaja: + + + + + Enter a label for this address to add it to your address book + Anna nimi tälle osoitteelle, jos haluat lisätä sen osoitekirjaan + + + + &Label: + &Nimi: + + + + The address to send the payment to (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + Osoite, johon maksu lähetetään (esim. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + Choose address from address book + Valitse osoite osoitekirjasta + + + + Alt+A + Alt+A + + + + Paste address from clipboard + Liitä osoite leikepöydältä + + + + Alt+P + Alt+P + + + + Remove this recipient + Poista tämä vastaanottaja + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + Syötä Arepacoin-osoite (esim. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + SignVerifyMessageDialog + + + Signatures - Sign / Verify a Message + Allekirjoitukset - Allekirjoita / Varmista viesti + + + + + &Sign Message + &Allekirjoita viesti + + + + You can sign messages with your addresses to prove you own them. Be careful not to sign anything vague, as phishing attacks may try to trick you into signing your identity over to them. Only sign fully-detailed statements you agree to. + Voit allekirjoittaa viestit omalla osoitteellasi todistaaksesi että omistat ne. Ole huolellinen, ettet allekirjoita mitään epämääräistä, sillä phishing-hyökkääjät voivat yrittää huijata sinua allekirjoittamaan henkilöllisyytesi heidän hyväksi. Allekirjoita vain se, mihin olet sitoutunut. + + + + The address to sign the message with (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + Osoite, jolle viesti kirjataan (esim. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Choose an address from the address book + Valitse osoite osoitekirjasta + + + + + Alt+A + Alt+A + + + + Paste address from clipboard + Liitä osoite leikepöydältä + + + + Alt+P + Alt+P + + + + Enter the message you want to sign here + Kirjoita viesti, jonka haluat allekirjoittaa tähän + + + + Copy the current signature to the system clipboard + Kopioi tämänhetkinen allekirjoitus järjestelmän leikepöydälle + + + + Sign the message to prove you own this Arepacoin address + Allekirjoita viesti vahvistaaksesi, että omistat tämän Arepacoin-osoitteen + + + + Reset all sign message fields + Tyhjennä kaikki allekirjoita-viesti-kentät + + + + + Clear &All + &Tyhjennä Kaikki + + + + + &Verify Message + &Varmista viesti + + + + Enter the signing address, message (ensure you copy line breaks, spaces, tabs, etc. exactly) and signature below to verify the message. Be careful not to read more into the signature than what is in the signed message itself, to avoid being tricked by a man-in-the-middle attack. + Syötä allekirjoittava osoite, viesti ja allekirjoitus alla oleviin kenttiin varmistaaksesi allekirjoituksen aitouden. Varmista että kopioit kaikki kentät täsmälleen oikein, myös rivinvaihdot, välilyönnit, tabulaattorit, jne. + + + + The address the message was signed with (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + Osoite, jolla viesti on allekirjoitettu (esim. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + Verify the message to ensure it was signed with the specified Arepacoin address + Vahvista viesti varmistaaksesi että se on allekirjoitettu kyseisellä Arepacoin-osoitteella + + + + Reset all verify message fields + Tyhjennä kaikki varmista-viesti-kentät + + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + Syötä Arepacoin-osoite (esim. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + Click "Sign Message" to generate signature + Klikkaa "Allekirjoita Viesti luodaksesi allekirjoituksen + + + + Enter Arepacoin signature + Syötä Arepacoin-allekirjoitus + + + + + The entered address is invalid. + Syötetty osoite on virheellinen. + + + + + + + Please check the address and try again. + Tarkista osoite ja yritä uudelleen. + + + + + The entered address does not refer to a key. + Syötetyn osoitteen avainta ei löydy. + + + + Wallet unlock was cancelled. + Lompakon avaaminen peruttiin. + + + + Private key for the entered address is not available. + Yksityistä avainta syötetylle osoitteelle ei ole saatavilla. + + + + Message signing failed. + Viestin allekirjoitus epäonnistui. + + + + Message signed. + Viesti allekirjoitettu. + + + + The signature could not be decoded. + Allekirjoitusta ei pystytty tulkitsemaan. + + + + + Please check the signature and try again. + Tarkista allekirjoitus ja yritä uudelleen. + + + + The signature did not match the message digest. + Allekirjoitus ei täsmää viestin tiivisteeseen. + + + + Message verification failed. + Viestin varmistus epäonnistui. + + + + Message verified. + Viesti varmistettu. + + + + TransactionDesc + + + Open until %1 + Avoinna %1 asti + + + + Open for %n block(s) + Avoinna %n:lle lohkolleAvoinna %n lohkolle + + + + conflicted + törmännyt + + + + %1/offline + %1/offline + + + + %1/unconfirmed + %1/vahvistamaton + + + + %1 confirmations + %1 vahvistusta + + + + Status + Tila + + + + , broadcast through %n node(s) + lähetetty %n noodin läpilähetetty %n noodin läpi + + + + Date + Päivämäärä + + + + Source + Lähde + + + + Generated + Generoitu + + + + + From + Lähettäjä + + + + + + To + Saaja + + + + + own address + oma osoite + + + + label + nimi + + + + + + + + Credit + Credit + + + + matures in %n more block(s) + kypsyy %n lohkon kuluttuakypsyy %n lohkon kuluttua + + + + not accepted + ei hyväksytty + + + + + + + Debit + Debit + + + + Transaction fee + Maksukulu + + + + Net amount + Netto määrä + + + + Message + Viesti + + + + Comment + Viesti + + + + Transaction ID + Siirtotunnus + + + + Generated coins must mature 6 blocks before they can be spent. When you generated this block, it was broadcast to the network to be added to the block chain. If it fails to get into the chain, its state will change to "not accepted" and it won't be spendable. This may occasionally happen if another node generates a block within a few seconds of yours. + Luotujen kolikoiden on eräännyttävä 6 lohkon ajan ennenkuin niitä voidaan käyttää. Kun loit tämän lohkon, se oli lähetetty verkkoon lohkoketjuun lisättäväksi. Jos lohkon siirtyminen ketjuun epäonnistuu, tilaksi muuttuu "ei hyväksytty" ja sillon sitä ei voida käyttää. Tämä voi tapahtua joskus jos toinen verkon noodi luo lohkon muutaman sekunnin sisällä luodusta lohkostasi. + + + + Debug information + Debug tiedot + + + + Transaction + Rahansiirto + + + + Inputs + Sisääntulot + + + + Amount + Määrä + + + + true + tosi + + + + false + epätosi + + + + , has not been successfully broadcast yet + , ei ole vielä onnistuneesti lähetetty + + + + unknown + tuntematon + + + + TransactionDescDialog + + + Transaction details + Rahansiirron yksityiskohdat + + + + This pane shows a detailed description of the transaction + Tämä ruutu näyttää yksityiskohtaisen tiedon rahansiirrosta + + + + TransactionTableModel + + + Date + Päivämäärä + + + + Type + Laatu + + + + Address + Osoite + + + + Amount + Määrä + + + + Open until %1 + Avoinna %1 asti + + + + Confirmed (%1 confirmations) + Vahvistettu (%1 vahvistusta) + + + + Open for %n more block(s) + Avoinna %n lohkolleAvoinna %n lohkolle + + + + Offline + Offline-tila + + + + Unconfirmed + Vahvistamaton + + + + Confirming (%1 of %2 recommended confirmations) + Vahvistetaan (%1 %2:sta suositellusta vahvistuksesta) + + + + Conflicted + Törmännyt + + + + Immature (%1 confirmations, will be available after %2) + Ei vahvistettu (%1 vahvistusta, on saatavilla %2:n jälkeen) + + + + This block was not received by any other nodes and will probably not be accepted! + Tätä lohkoa ei vastaanotettu mistään muusta solmusta ja sitä ei mahdollisesti hyväksytä! + + + + Generated but not accepted + Generoitu mutta ei hyväksytty + + + + Received with + Vastaanotettu osoitteella + + + + Received from + Vastaanotettu + + + + Sent to + Saaja + + + + Payment to yourself + Maksu itsellesi + + + + Mined + Louhittu + + + + (n/a) + (ei saatavilla) + + + + Transaction status. Hover over this field to show number of confirmations. + Rahansiirron tila. Siirrä osoitin kentän päälle nähdäksesi vahvistusten lukumäärä. + + + + Date and time that the transaction was received. + Rahansiirron vastaanottamisen päivämäärä ja aika. + + + + Type of transaction. + Rahansiirron laatu. + + + + Destination address of transaction. + Rahansiirron kohteen Bitcoin-osoite + + + + Amount removed from or added to balance. + Saldoon lisätty tai siitä vähennetty määrä. + + + + TransactionView + + + + All + Kaikki + + + + Today + Tänään + + + + This week + Tällä viikolla + + + + This month + Tässä kuussa + + + + Last month + Viime kuussa + + + + This year + Tänä vuonna + + + + Range... + Alue... + + + + Received with + Vastaanotettu osoitteella + + + + Sent to + Saaja + + + + To yourself + Itsellesi + + + + Mined + Louhittu + + + + Other + Muu + + + + Enter address or label to search + Anna etsittävä osoite tai tunniste + + + + Min amount + Minimimäärä + + + + Copy address + Kopioi osoite + + + + Copy label + Kopioi nimi + + + + Copy amount + Kopioi määrä + + + + Copy transaction ID + Kopioi rahansiirron ID + + + + Edit label + Muokkaa nimeä + + + + Show transaction details + Näytä rahansiirron yksityiskohdat + + + + Export Transaction Data + Vie tiedot rahansiirrosta + + + + Comma separated file (*.csv) + Comma separated file (*.csv) + + + + Confirmed + Vahvistettu + + + + Date + Aika + + + + Type + Laatu + + + + Label + Nimi + + + + Address + Osoite + + + + Amount + Määrä + + + + ID + ID + + + + Error exporting + Virhe vietäessä + + + + Could not write to file %1. + Ei voida kirjoittaa tiedostoon %1. + + + + Range: + Alue: + + + + to + kenelle + + + + WalletModel + + + Sending... + Lähetetään... + + + + bitcoin-core + + + Arepacoin version + Arepacoinin versio + + + + Usage: + Käyttö: + + + + Send command to -server or arepacoind + Syötä komento kohteeseen -server tai arepacoind + + + + List commands + Lista komennoista + + + + Get help for a command + Hanki apua käskyyn + + + + Options: + Asetukset: + + + + Specify configuration file (default: arepacoin.conf) + Määritä asetustiedosto (oletus: arepacoin.conf) + + + + Specify pid file (default: arepacoind.pid) + Määritä prosessitiedosto (oletus: arepacoin.pid) + + + + Specify wallet file (within data directory) + Määritä lompakkotiedosto (datahakemiston sisällä) + + + + Specify data directory + Määritä data-hakemisto + + + + Set database cache size in megabytes (default: 25) + Aseta tietokannan välimuistin koko megatavuina (oletus: 25) + + + + Set database disk log size in megabytes (default: 100) + Aseta tietokannan lokien maksimikoko megatavuissa (oletus: 100) + + + + Listen for connections on <port> (default: 9853 or testnet: 19853) + Kuuntele yhteyksiä portissa <port> (oletus: 9853 tai testiverkko: 19853) + + + + Maintain at most <n> connections to peers (default: 125) + Pidä enintään <n> yhteyttä verkkoihin (oletus: 125) + + + + Connect to a node to retrieve peer addresses, and disconnect + Yhdistä noodiin hakeaksesi naapurien osoitteet ja katkaise yhteys + + + + Specify your own public address + Määritä julkinen osoitteesi + + + + Bind to given address. Use [host]:port notation for IPv6 + Liitä annettuun osoitteeseen. Käytä [host]:port merkintää IPv6:lle + + + + Stake your coins to support network and gain reward (default: 1) + Panosta rahasi tukeaksi verkkoa ja saadaksesi palkkiota (oletus: 1) + + + + Threshold for disconnecting misbehaving peers (default: 100) + Kynnysarvo aikakatkaisulle heikosti toimiville verkoille (oletus: 100) + + + + Number of seconds to keep misbehaving peers from reconnecting (default: 86400) + Sekuntien määrä, kuinka kauan uudelleenkytkeydytään verkkoihin (oletus: 86400) + + + + An error occurred while setting up the RPC port %u for listening on IPv4: %s + Virhe valmisteltaessa RPC-portin %u avaamista kuunneltavaksi: %s + + + + Detach block and address databases. Increases shutdown time (default: 0) + Irroita lohko- ja osoitetietokannat lopetuksessa. Nostaa ohjelman lopetusaikaa (oletus: 0) + + + + 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. + Virhe: Rahansiirto on evätty. Tämä voi tapahtua jos joitakin kolikoistasi lompakossasi on jo käytetty, tai jos olet käyttänyt wallet.dat-tiedoston kopiota ja rahat olivat käytetyt kopiossa, mutta ei merkitty käytetyksi tässä. + + + + Error: This transaction requires a transaction fee of at least %s because of its amount, complexity, or use of recently received funds + Virhe: Tämä rahansiirto tarvitsee rahansiirtopalkkion, kooltaan %s, kokonsa, monimutkaisuutensa tai aikaisemmin saatujen varojen käytön takia. + + + + Listen for JSON-RPC connections on <port> (default: 9852 or testnet: 19852) + Kuuntele JSON-RPC-yhteyksiä portissa <port> (oletus: 9852 tai testiverkko: 19852) + + + + Accept command line and JSON-RPC commands + Hyväksy merkkipohjaiset- ja JSON-RPC-käskyt + + + + Error: Transaction creation failed + Virhe: Rahansiirron luonti epäonnistui + + + + Error: Wallet locked, unable to create transaction + Virhe: Lompakko lukittu, rahansiirtoa ei voida luoda + + + + Importing blockchain data file. + Tuodaan lohkoketjun datatiedostoa. + + + + Importing bootstrap blockchain data file. + Tuodaan esilatausohjelma lohkoketjun datatiedostolle. + + + + Run in the background as a daemon and accept commands + Aja taustalla daemonina ja hyväksy komennot + + + + Use the test network + Käytä test -verkkoa + + + + Accept connections from outside (default: 1 if no -proxy or -connect) + Hyväksy yhteyksiä ulkopuolelta (vakioasetus: 1 jos -proxy tai -connect ei määritelty) + + + + An error occurred while setting up the RPC port %u for listening on IPv6, falling back to IPv4: %s + Virhe ilmennyt asetettaessa RPC-porttia %u IPv6:n kuuntelemiseksi, palataan takaisin IPv4:ään %s + + + + Error initializing database environment %s! To recover, BACKUP THAT DIRECTORY, then remove everything from it except for wallet.dat. + Virhe alustettaessa tietokantaympäristöä %s! Palauttaaksesi sen, TEE VARMUUSKOPIO HAKEMISTOSTA ja poista tämän jälkeen kaikki hakemiston tiedostot paitsi wallet.dat-tiedosto. + + + + Set maximum size of high-priority/low-fee transactions in bytes (default: 27000) + Aseta maksimikoko korkean prioriteetin/pienen siirtokulun maksutapahtumille tavuina (oletus: 27000) + + + + Warning: -paytxfee is set very high! This is the transaction fee you will pay if you send a transaction. + Varoitus: -paytxfee on asetettu erittäin korkeaksi! Tämä on maksukulu jonka tulet maksamaan kun lähetät siirron. + + + + Warning: Please check that your computer's date and time are correct! If your clock is wrong Arepacoin will not work properly. + Varoitus: Tarkista, että tietokoneesi aika ja päivämäärä ovat oikeassa! Jos kellosi on väärässä, Arepacoin ei toimi oikein. + + + + Warning: error reading wallet.dat! All keys read correctly, but transaction data or address book entries might be missing or incorrect. + Varoitus: Virhe luettaessa wallet.dat-tiedostoa! Kaikki avaimet luettiin oikein, mutta rahansiirtodata tai osoitekirjan kentät voivat olla puuttuvat tai väärät. + + + + Warning: wallet.dat corrupt, data salvaged! Original wallet.dat saved as wallet.{timestamp}.bak in %s; if your balance or transactions are incorrect you should restore from a backup. + Varoitus: wallet.dat-tiedosto on korruptoitunut, data pelastettu! Alkuperäinen wallet.dat on tallennettu nimellä wallet.{aikaleima}.bak kohteeseen %s; Jos saldosi tai rahansiirrot ovat väärät, sinun tulee palauttaa lompakko varmuuskopiosta. + + + + Attempt to recover private keys from a corrupt wallet.dat + Yritetään palauttaa yksityisiä salausavaimia korruptoituneesta wallet.dat-tiedostosta + + + + Block creation options: + Lohkon luonnin asetukset: + + + + Connect only to the specified node(s) + Yhidstä ainoastaan määrättyihin noodeihin + + + + Discover own IP address (default: 1 when listening and no -externalip) + Hae oma IP osoite (vakioasetus: 1 kun kuuntelemassa ja ei -externalip) + + + + Failed to listen on any port. Use -listen=0 if you want this. + Ei onnistuttu kuuntelemaan missään portissa. Käytä -listen=0 jos haluat tätä. + + + + Find peers using DNS lookup (default: 1) + Etsi vertaisiasi käyttäen DNS-nimihakua (oletus: 1) + + + + Sync checkpoints policy (default: strict) + Synkronoi tallennuspisteiden käytännöt (oletus: strict) + + + + Invalid -tor address: '%s' + Epäkelpo -tor-osoite: '%s' + + + + Invalid amount for -reservebalance=<amount> + Epäkelpo määrä -reservebalance=<amount> + + + + Maximum per-connection receive buffer, <n>*1000 bytes (default: 5000) + Suurin vastaanottopuskuri yksittäiselle yhteydelle, <n>*1000 tavua (vakioasetus: 5000) + + + + Maximum per-connection send buffer, <n>*1000 bytes (default: 1000) + Suurin lähetyspuskuri yksittäiselle yhteydelle, <n>*1000 tavua (vakioasetus: 1000) + + + + Only connect to nodes in network <net> (IPv4, IPv6 or Tor) + Yhdistä vain noodeihin verkossa <net> (IPv4, IPv6 tai Tor) + + + + Output extra debugging information. Implies all other -debug* options + Tulosta lisäksi debug-tietoa, seuraa kaikkia muita -debug*-asetuksia + + + + Output extra network debugging information + Tulosta lisäksi verkon debug-tietoa + + + + Prepend debug output with timestamp + Lisää debug-tulosteiden alkuun aikaleimat + + + + SSL options: (see the Bitcoin Wiki for SSL setup instructions) + SSL asetukset (katso Bitcoin Wikistä tarkemmat SSL ohjeet) + + + + Select the version of socks proxy to use (4-5, default: 5) + Valitse SOCKS-välityspalvelimen versio (4-5, oletus 5) + + + + Send trace/debug info to console instead of debug.log file + Lähetä jäljitys/debug-tieto konsoliin, debug.log-tiedoston sijaan + + + + Send trace/debug info to debugger + Lähetä debug-tuloste kehittäjille + + + + Set maximum block size in bytes (default: 250000) + Aseta lohkon maksimikoko tavuissa (oletus: 250000) + + + + Set minimum block size in bytes (default: 0) + Asetan pienin lohkon koko tavuissa (vakioasetus: 0) + + + + Shrink debug.log file on client startup (default: 1 when no -debug) + Pienennä debug.log tiedosto käynnistyksen yhteydessä (vakioasetus: 1 kun ei -debug) + + + + Specify connection timeout in milliseconds (default: 5000) + Määritä yhteyden aikakataisu millisekunneissa (vakioasetus: 5000) + + + + Unable to sign checkpoint, wrong checkpointkey? + + Ei voitu kirjata tallennuspistettä, väärä checkpointkey? + + + + + Use UPnP to map the listening port (default: 0) + Käytä UPnP:tä kuunneltavan portin avaamiseen (vakioasetus: 0) + + + + Use UPnP to map the listening port (default: 1 when listening) + Käytä UPnP:tä kuunneltavan portin avaamiseen (vakioasetus: 1 kun kuuntelemassa) + + + + Use proxy to reach tor hidden services (default: same as -proxy) + Käytä välityspalvelinta saavuttaaksesi tor:n piilotetut palvelut (oletus: sama kuin -proxy) + + + + Username for JSON-RPC connections + Käyttäjätunnus JSON-RPC-yhteyksille + + + + Verifying database integrity... + Tarkistetaan tietokannan eheyttä... + + + + WARNING: syncronized checkpoint violation detected, but skipped! + VAROITUS: synkronoidun tallennuspisteen rikkomista havaittu, mutta ohitettu! + + + + Warning: Disk space is low! + Varoitus: Kiintolevytila on vähissä! + + + + Warning: This version is obsolete, upgrade required! + Varoitus: Tämä versio on vanhentunut, päivitys tarpeen! + + + + wallet.dat corrupt, salvage failed + wallet.dat on korruptoitunut, pelastusyritys epäonnistui + + + + Password for JSON-RPC connections + Salasana JSON-RPC-yhteyksille + + + + %s, you must set a rpcpassword in the configuration file: + %s +It is recommended you use the following random password: +rpcuser=arepacoinrpc +rpcpassword=%s +(you do not need to remember this password) +The username and password MUST NOT be the same. +If the file does not exist, create it with owner-readable-only file permissions. +It is also recommended to set alertnotify so you are notified of problems; +for example: alertnotify=echo %%s | mail -s "Arepacoin Alert" admin@foo.com + + %s, sinun on asetettava rpcpassword asetustiedostoon: +%s +On suositeltavaa, että käytät seuraavaa arvottua salasanaa: +rpcuser=arepacoinrpc +rpcpassword=%s +(Sinun ei tarvitse muistaa tätä salasanaa) +Käyttäjänimen ja salasanan EI TULE OLLA SAMOJA. +Jos tiedostoa ei ole olemassa, luo se asettaen samalla omistajan lukuoikeudet. +On myös suositeltavaa asettaa alertnotify jolloin olet tiedotettu ongelmista; esimerkiksi: alertnotify=echo %%s | mail -s "Arepacoin Alert" admin@foo.com + + + + + Find peers using internet relay chat (default: 0) + Etsi vertaisiasi käyttäen Internet Relay Chatia (oletus: 1) {0)?} + + + + Sync time with other nodes. Disable if time on your system is precise e.g. syncing with NTP (default: 1) + Synkronoi kello muiden noodien kanssa. Poista käytöstä, jos järjestelmäsi aika on tarkka esim. päivittää itsensä NTP-palvelimelta. (oletus: 1) + + + + When creating transactions, ignore inputs with value less than this (default: 0.01) + Rahansiirtoja luodessa jätä huomioimatta syötteet joiden arvo on vähemmän kuin tämä (oletus: 0.01) + + + + Allow JSON-RPC connections from specified IP address + Salli JSON-RPC yhteydet tietystä ip-osoitteesta + + + + Send commands to node running on <ip> (default: 127.0.0.1) + Lähetä käskyjä solmuun osoitteessa <ip> (oletus: 127.0.0.1) + + + + Execute command when the best block changes (%s in cmd is replaced by block hash) + Suorita käsky kun paras lohko muuttuu (%s cmd on vaihdettu block hashin kanssa) + + + + Execute command when a wallet transaction changes (%s in cmd is replaced by TxID) + Suorita komento kun lompakon rahansiirrossa muutoksia (%s komennossa on korvattu TxID:llä) + + + + Require a confirmations for change (default: 0) + Vaadi vaihtorahalle vahvistus (oletus: 0) + + + + Enforce transaction scripts to use canonical PUSH operators (default: 1) + Vahvista, että rahansiirtoskriptit käyttävät sääntöjen mukaisia PUSH-toimijoita (oletus: 1) + + + + Execute command when a relevant alert is received (%s in cmd is replaced by message) + Suorita komento kun olennainen varoitus on saatu (%s komennossa korvattu viestillä) + + + + Upgrade wallet to latest format + Päivitä lompakko uusimpaan formaattiin + + + + Set key pool size to <n> (default: 100) + Aseta avainpoolin koko arvoon <n> (oletus: 100) + + + + Rescan the block chain for missing wallet transactions + Skannaa uudelleen lohkoketju lompakon puuttuvien rahasiirtojen vuoksi + + + + How many blocks to check at startup (default: 2500, 0 = all) + Kuinka monta lohkoa tarkistetaan käynnistyksen yhteydessä (oletus: 2500, 0 = kaikki) + + + + How thorough the block verification is (0-6, default: 1) + Kuinka perusteellisesti lohko vahvistetaan (0-6, oletus: 1) + + + + Imports blocks from external blk000?.dat file + Tuo lohkoja erillisestä blk000?.dat-tiedostosta + + + + Use OpenSSL (https) for JSON-RPC connections + Käytä OpenSSL:ää (https) JSON-RPC-yhteyksille + + + + Server certificate file (default: server.cert) + Palvelimen sertifikaatti-tiedosto (oletus: server.cert) + + + + Server private key (default: server.pem) + Palvelimen yksityisavain (oletus: server.pem) + + + + Acceptable ciphers (default: TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH) + Hyväksytyt salaustyypit (oletus: TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH) + + + + Error: Wallet unlocked for staking only, unable to create transaction. + Virhe: Lompakko avattu vain osakkuutta varten, rahansiirtoja ei voida luoda. + + + + WARNING: Invalid checkpoint found! Displayed transactions may not be correct! You may need to upgrade, or notify developers. + VAROITUS: Epäkelpo tarkistuspiste löydetty! Ilmoitetut rahansiirrot eivät välttämättä pidä paikkaansa! Sinun täytyy päivittää asiakasohjelma, tai ilmoittaa kehittäjille ongelmasta. + + + + This help message + Tämä ohjeviesti + + + + Wallet %s resides outside data directory %s. + Lompakko %s on datahakemiston %s ulkopuolella. + + + + Cannot obtain a lock on data directory %s. Arepacoin is probably already running. + Ei voida saavuttaa lukkoa datatiedostossa %s. Arepacoin-asiakasohjelma on ehkä jo käynnissä. + + + + Arepacoin + Arepacoin + + + + Unable to bind to %s on this computer (bind returned error %d, %s) + Kytkeytyminen %s tällä tietokonella ei onnistu (kytkeytyminen palautti virheen %d, %s) + + + + Connect through socks proxy + Yhdistä SOCKS-välityspalvelimen lävitse + + + + Allow DNS lookups for -addnode, -seednode and -connect + Salli DNS kyselyt -addnode, -seednode ja -connect yhteydessä + + + + Loading addresses... + Ladataan osoitteita... + + + + Error loading blkindex.dat + Virhe ladattaessa blkindex.dat-tiedostoa + + + + Error loading wallet.dat: Wallet corrupted + Virhe ladattaessa wallet.dat-tiedostoa: Lompakko vioittunut + + + + Error loading wallet.dat: Wallet requires newer version of Arepacoin + Virhe ladattaessa wallet.dat-tiedostoa: Lompakko tarvitsee uudemman version Arepacoin-asiakasohjelmasta + + + + Wallet needed to be rewritten: restart Arepacoin to complete + Lompakko on kirjoitettava uudelleen: käynnistä Arepacoin-asiakasohjelma uudelleen päättääksesi toiminnon + + + + Error loading wallet.dat + Virhe ladattaessa wallet.dat-tiedostoa + + + + Invalid -proxy address: '%s' + Virheellinen proxy-osoite '%s' + + + + Unknown network specified in -onlynet: '%s' + Tuntematon verkko -onlynet parametrina: '%s' + + + + Unknown -socks proxy version requested: %i + Tuntematon -socks proxy versio pyydetty: %i + + + + Cannot resolve -bind address: '%s' + -bind osoitteen '%s' selvittäminen epäonnistui + + + + Cannot resolve -externalip address: '%s' + -externalip osoitteen '%s' selvittäminen epäonnistui + + + + Invalid amount for -paytxfee=<amount>: '%s' + -paytxfee=<amount>: '%s' on virheellinen + + + + Error: could not start node + Virhe: Ei voitu käynnistää noodia + + + + Sending... + Lähetetään... + + + + Invalid amount + Virheellinen määrä + + + + Insufficient funds + Lompakon saldo ei riitä + + + + Loading block index... + Ladataan lohkoindeksiä... + + + + Add a node to connect to and attempt to keep the connection open + Linää solmu mihin liittyä pitääksesi yhteyden auki + + + + Unable to bind to %s on this computer. Arepacoin is probably already running. + Ei voitu liittää %s tällä tietokoneella. Arepacoin-asiakasohjelma on jo ehkä päällä. + + + + Fee per KB to add to transactions you send + Rahansiirtopalkkio kilotavua kohden lähetettäviin rahansiirtoihisi + + + + Invalid amount for -mininput=<amount>: '%s' + Epäkelpo määrä parametrille -mininput=<amount>: '%s' + + + + Loading wallet... + Ladataan lompakkoa... + + + + Cannot downgrade wallet + Et voi päivittää lompakkoasi vanhempaan versioon + + + + Cannot initialize keypool + Ei voida alustaa avainallasta + + + + Cannot write default address + Oletusosoitetta ei voi kirjoittaa + + + + Rescanning... + Skannataan uudelleen... + + + + Done loading + Lataus on valmis + + + + To use the %s option + Käytä %s optiota + + + + Error + Virhe + + + + You must set rpcpassword=<password> in the configuration file: +%s +If the file does not exist, create it with owner-readable-only file permissions. + Sinun täytyy asettaa rpcpassword=<password> asetustiedostoon: +%s +Jos tiedostoa ei ole, niin luo se ainoastaan omistajan kirjoitusoikeuksin. + + + \ No newline at end of file diff --git a/src/qt/locale/bitcoin_fr.ts b/src/qt/locale/bitcoin_fr.ts new file mode 100755 index 0000000..cfc70d8 --- /dev/null +++ b/src/qt/locale/bitcoin_fr.ts @@ -0,0 +1,3313 @@ + + + AboutDialog + + + About Arepacoin + Au sujet de Arepacoin + + + + <b>Arepacoin</b> version + Version de <b>Arepacoin</b> + + + + Copyright © 2009-2014 The Bitcoin developers +Copyright © 2012-2014 The NovaCoin developers +Copyright © 2014 The Arepacoin developers + Copyright © 2009-2014 Les développeurs Bitcoin +Copyright © 2012-2014 Les développeurs NovaCoin +Copyright © 2014 Les développeurs Arepacoin + + + + +This is experimental software. + +Distributed under the MIT/X11 software license, see the accompanying file COPYING or http://www.opensource.org/licenses/mit-license.php. + +This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit (http://www.openssl.org/) and cryptographic software written by Eric Young (eay@cryptsoft.com) and UPnP software written by Thomas Bernard. + + Ce logiciel est expérimental. + + Distribué sous licence logicielle MIT/X11, voir le fichier COPYING joint ou http://www.opensource.org/licenses/mit-license.php. + + Ce produit comprend des logiciels développés par le projet OpenSSL afin d'être utilisés dans la boîte à outils OpenSSL (http://www.openssl.org/), un logiciel de chiffrement écrit par Eric Young (eay@cryptsoft.com), et un logiciel UPnP développé par Thomas Bernard. + + + + AddressBookPage + + + Address Book + Répertoire d'adresses + + + + Double-click to edit address or label + Double cliquer afin de modifier l'adresse ou l'étiquette + + + + Create a new address + Créer une nouvelle adresse + + + + Copy the currently selected address to the system clipboard + Copier l'adresse sélectionnée vers le presse-papier système + + + + &New Address + &Nouvelle adresse + + + + These are your Arepacoin addresses for receiving payments. You may want to give a different one to each sender so you can keep track of who is paying you. + Ce sont vos adresses pour recevoir vos paiements. Vous pouvez utiliser une adresse différente pour chaque réception afin d'identifier facilement le payeur. + + + + &Copy Address + &Copier l'adresse + + + + Show &QR Code + Montrer le &QR Code + + + + Sign a message to prove you own a Arepacoin address + Signer un message afin de valider l'identité de votre adresse Arepacoin + + + + Sign &Message + Signer le &message + + + + Delete the currently selected address from the list + Effacer l'adresse actuellement sélectionnée de la liste + + + + Verify a message to ensure it was signed with a specified Arepacoin address + Vérifier un message pour s'assurer qu'il vient d'un adresse Arepacoin spécifique. + + + + &Verify Message + &Vérifier un message + + + + &Delete + &Supprimer + + + + Copy &Label + Copier l'&Étiquette + + + + &Edit + &Modifier + + + + Export Address Book Data + Exporter votre répertoire d'adresses + + + + Comma separated file (*.csv) + Fichier de valeurs séparées par des virgules (*.csv) + + + + Error exporting + Erreur lors de l'export + + + + Could not write to file %1. + Impossible d'écrire dans le fichier %1. + + + + AddressTableModel + + + Label + Étiquette + + + + Address + Adresse + + + + (no label) + (aucune étiquette) + + + + AskPassphraseDialog + + + Passphrase Dialog + Dialogue de phrase de passe + + + + Enter passphrase + Saisir la phrase de passe + + + + New passphrase + Nouvelle phrase de passe + + + + Repeat new passphrase + Répéter la phrase de passe + + + + Serves to disable the trivial sendmoney when OS account compromised. Provides no real security. + Sert à désactiver les transactions sortantes si votre compte de système d'exploitation est compromis. Ne procure pas de réelle sécurité. + + + + For staking only + Pour "staking" seulement + + + + Enter the new passphrase to the wallet.<br/>Please use a passphrase of <b>10 or more random characters</b>, or <b>eight or more words</b>. + Saisir la nouvelle phrase de passe pour le portefeuille. <br/>Veuillez utiliser une phrase de passe de <b>10 caractères aléatoires ou plus</b>, ou de <b>huit mots ou plus</b>. + + + + Encrypt wallet + Chiffrer le portefeuille + + + + This operation needs your wallet passphrase to unlock the wallet. + Cette opération nécessite votre phrase de passe pour déverrouiller le portefeuille. + + + + Unlock wallet + Déverrouiller le portefeuille + + + + This operation needs your wallet passphrase to decrypt the wallet. + Cette opération nécessite votre phrase de passe pour déchiffrer le portefeuille. + + + + Decrypt wallet + Déchiffrer le portefeuille + + + + Change passphrase + Changer la phrase de passe + + + + Enter the old and new passphrase to the wallet. + Saisir l’ancienne phrase de passe pour le portefeuille ainsi que la nouvelle. + + + + Confirm wallet encryption + Confirmer le chiffrement du portefeuille + + + + Warning: If you encrypt your wallet and lose your passphrase, you will <b>LOSE ALL OF YOUR COINS</b>! + Avertissement : Si vous chiffrez votre portefeuille et perdez votre passphrase, vous ne pourrez <b>plus accéder à vos Arepacoins</b>! + + + + Are you sure you wish to encrypt your wallet? + Êtes-vous sûr de vouloir chiffrer votre portefeuille ? + + + + IMPORTANT: Any previous backups you have made of your wallet file should be replaced with the newly generated, encrypted wallet file. For security reasons, previous backups of the unencrypted wallet file will become useless as soon as you start using the new, encrypted wallet. + IMPORTANT : Toute sauvegarde précédente de votre fichier de portefeuille devrait être remplacée par le nouveau fichier de portefeuille chiffré. Pour des raisons de sécurité, les sauvegardes précédentes de votre fichier de portefeuille non chiffré deviendront inutilisables dès lors que vous commencerez à utiliser le nouveau portefeuille chiffré. + + + + + Warning: The Caps Lock key is on! + Attention : la touche Verr. Maj. est activée ! + + + + + Wallet encrypted + Portefeuille chiffré + + + + Arepacoin will close now to finish the encryption process. Remember that encrypting your wallet cannot fully protect your coins from being stolen by malware infecting your computer. + L'application Arepacoin va désormais se terminer afin de finaliser le processus de chiffrage. Merci de noter que le chiffrage du portefeuille ne garantit pas de se prémunir du vol via utilisation de malware, qui auraient pu infecter votre ordinateur. + + + + + + + Wallet encryption failed + Le chiffrement du portefeuille a échoué + + + + Wallet encryption failed due to an internal error. Your wallet was not encrypted. + Le chiffrement du portefeuille a échoué en raison d'une erreur interne. Votre portefeuille n'a pas été chiffré. + + + + + The supplied passphrases do not match. + Les phrases de passe saisies ne correspondent pas. + + + + Wallet unlock failed + Le déverrouillage du portefeuille a échoué + + + + + + The passphrase entered for the wallet decryption was incorrect. + La phrase de passe saisie pour déchiffrer le portefeuille est incorrecte. + + + + Wallet decryption failed + Le déchiffrage du portefeuille a échoué + + + + Wallet passphrase was successfully changed. + La phrase de passe du portefeuille a été modifiée avec succès. + + + + BitcoinGUI + + + Sign &message... + Signer le &message... + + + + Synchronizing with network... + Synchronisation avec le réseau en cours… + + + + &Overview + &Vue d'ensemble + + + + Show general overview of wallet + Afficher une vue d’ensemble du portefeuille + + + + &Transactions + &Transactions + + + + Browse transaction history + Parcourir l'historique des transactions + + + + &Address Book + Carnet d'adresses + + + + Edit the list of stored addresses and labels + Éditer la liste d'adresses et étiquettes + + + + &Receive coins + &Recevoir des monnaies + + + + Show the list of addresses for receiving payments + Montrer la liste d'adresses de réception de paiements + + + + &Send coins + &Envoyer des monnaies + + + + E&xit + Q&uitter + + + + Quit application + Quitter l’application + + + + Show information about Arepacoin + Afficher des informations au sujet de Arepacoin + + + + About &Qt + À propos de &Qt + + + + Show information about Qt + Afficher les informations au sujet de Qt + + + + &Options... + &Options… + + + + &Encrypt Wallet... + &Chiffrer le portefeuille... + + + + &Backup Wallet... + Sauvegarder le &portefeuille... + + + + &Change Passphrase... + &Changer la phrase de passe... + + + + ~%n block(s) remaining + ~%n blocks restants~%n blocs restants + + + + Downloaded %1 of %2 blocks of transaction history (%3% done). + Téléchargement des blocks de l'historique des transactions : 1% sur 2% (%3% effectués). + + + + &Export... + &Exporter... + + + + Send coins to a Arepacoin address + Envoyer des monnaies vers une adresse Arepacoin + + + + Modify configuration options for Arepacoin + Modification des options de configuration de Arepacoin + + + + Export the data in the current tab to a file + Export des données de l'onglet courant vers un fichier + + + + Encrypt or decrypt wallet + Chiffrer ou déchiffrer le portefeuille + + + + Backup wallet to another location + Sauvegarder le portefeuille vers un autre emplacement + + + + Change the passphrase used for wallet encryption + Modifier la phrase de passe utilisée pour le chiffrement du portefeuille + + + + &Debug window + &Fenêtre de débogage + + + + Open debugging and diagnostic console + Ouvrir la console de débogage et de diagnostic + + + + &Verify message... + &Vérifier un message... + + + + Arepacoin + Arepacoin + + + + Wallet + Portefeuille + + + + &About Arepacoin + &Au sujet de Arepacoin + + + + &Show / Hide + &Montrer / Masquer + + + + Unlock wallet + Déverrouiller le portefeuille + + + + &Lock Wallet + &Verrouiller le portefeuille + + + + Lock wallet + Verrouiller le portefeuille + + + + &File + &Fichier + + + + &Settings + &Paramètres + + + + &Help + &Aide + + + + Tabs toolbar + Barre d'onglets + + + + Actions toolbar + Barre d'actions + + + + + [testnet] + [testnet] + + + + + Arepacoin client + Client Arepacoin + + + + %n active connection(s) to Arepacoin network + %n connexion active au réseau Arepacoin%n connexions actives au réseau Arepacoin + + + + Downloaded %1 blocks of transaction history. + Téléchargement de blocs de l'historique de transactions : 1% blocks + + + + Staking.<br>Your weight is %1<br>Network weight is %2<br>Expected time to earn reward is %3 + Staking.<br>Votre poids est de %1<br>Le poids du réseau est de %2<br>Temps estimé avant récompense %3 + + + + Not staking because wallet is locked + Pas de staking car votre portefeuille est verouillé + + + + Not staking because wallet is offline + Pas de staking car votre portefeuille est hors ligne + + + + Not staking because wallet is syncing + Pas de staking car votre portefeuille est en cours de synchronisation + + + + Not staking because you don't have mature coins + Pas de staking car vos monnaies ne sont pas encore matures + + + + %n second(s) ago + il y a %n secondeil y a %n secondes + + + + &Unlock Wallet... + &Déverrouiller le portefeuille... + + + + %n minute(s) ago + il y a %n minuteil y a %n minutes + + + + %n hour(s) ago + il y a %n heureil y a %n heures + + + + %n day(s) ago + il y a %n jouril y a %n jours + + + + Up to date + À jour + + + + Catching up... + Rattrapage en cours… + + + + Last received block was generated %1. + Le dernier block reçu à été généré %1. + + + + This transaction is over the size limit. You can still send it for a fee of %1, which goes to the nodes that process your transaction and helps to support the network. Do you want to pay the fee? + Cette transaction dépasse la limite autorisée. Vous pouvez tout de même effectuer cette opération, moyennant %1 de frais, qui seront envoyés aux noeuds qui valideront cette transaction, et dont l'objectif vise à supporter le réseau. Souhaitez-vous payer ces frais ? + + + + Confirm transaction fee + Confirmer le paiement des frais de transaction + + + + Sent transaction + Transaction envoyée + + + + Incoming transaction + Transaction entrante + + + + Date: %1 +Amount: %2 +Type: %3 +Address: %4 + + Date : %1 +Montant : %2 +Type : %3 +Adresse : %4 + + + + + + URI handling + Prise en charge de l'URL + + + + + URI can not be parsed! This can be caused by an invalid Arepacoin address or malformed URI parameters. + L'adresse du portefeuille Arepacoin n'as pas pu être correctement identifiée, car invalide ou malformée. + + + + Wallet is <b>encrypted</b> and currently <b>unlocked</b> + Le portefeuille est <b>chiffré</b> et est actuellement <b>déverrouillé</b> + + + + Wallet is <b>encrypted</b> and currently <b>locked</b> + Le portefeuille est <b>chiffré</b> et actuellement <b>verrouillé</b> + + + + Backup Wallet + Sauvegarder le portefeuille + + + + Wallet Data (*.dat) + Données liées au portefeuille (*.dat) + + + + Backup Failed + Echec de la sauvegarde + + + + There was an error trying to save the wallet data to the new location. + Une erreur a été rencontrée lors de la sauvegarde du portefeuille vers la nouvelle destination. + + + + %n second(s) + %n seconde%n secondes + + + + %n minute(s) + %n minute%n minutes + + + + %n hour(s) + %n heure%n heures + + + + %n day(s) + %n jour%n jours + + + + Not staking + Pas de staking + + + + A fatal error occurred. Arepacoin can no longer continue safely and will quit. + Une erreur fatale a été rencontrée. L'application Arepacoin ne peut plus être s'exécuter de façon correcte et va se terminer. + + + + ClientModel + + + Network Alert + Alerte réseau + + + + CoinControlDialog + + + Coin Control + Fonctions de contrôle des monnaies + + + + Quantity: + Quantité : + + + + Bytes: + Octets : + + + + Amount: + Montant : + + + + Priority: + Priorité : + + + + Fee: + Frais : + + + + Low Output: + Sortie faible: + + + + no + non + + + + After Fee: + Après les frais : + + + + Change: + Monnaie : + + + + (un)select all + Tout (dé)sélectionner + + + + Tree mode + Mode arborescence + + + + List mode + Mode liste + + + + Amount + Montant + + + + Label + Étiquette + + + + Address + Adresse + + + + Date + Date + + + + Confirmations + Confirmations + + + + Confirmed + Confirmée + + + + Priority + Priorité + + + + Copy address + Copier l’adresse + + + + Copy label + Copier l’étiquette + + + + + Copy amount + Copier le montant + + + + Copy transaction ID + Copier l'ID de la transaction + + + + Copy quantity + Copier la quantité + + + + Copy fee + Copier les frais + + + + Copy after fee + Copier le montant après les frais + + + + Copy bytes + Copier les octets + + + + Copy priority + Copier la priorité + + + + Copy low output + Copier la sortie faible + + + + Copy change + Copier la monnaie + + + + highest + la plus élevée + + + + high + élevée + + + + medium-high + moyennement-élevée + + + + medium + moyenne + + + + low-medium + moyennement-basse + + + + low + basse + + + + lowest + la plus basse + + + + DUST + DUST + + + + yes + oui + + + + This label turns red, if the transaction size is bigger than 10000 bytes. + + This means a fee of at least %1 per kb is required. + + Can vary +/- 1 Byte per input. + Cette étiquette passe au rouge, si la taille de la transaction est supérieure à 10000 bytes. + +Cela implique que des frais à hauteur d'au moins %1 par kb seront nécessaires. + +Ceux-ci Peuvent varier de +/- 1 Byte par entrée. + + + + Transactions with higher priority get more likely into a block. + +This label turns red, if the priority is smaller than "medium". + + This means a fee of at least %1 per kb is required. + Les transactions avec une priorité haute ont plus de chances d'être traitées en un block. + +L'étiquette passe au rouge si votre priorité est plus basse que la "moyenne". + +Cela implique que des frais d'un minimum de %1 par kb sont requis + + + + This label turns red, if any recipient receives an amount smaller than %1. + + This means a fee of at least %2 is required. + + Amounts below 0.546 times the minimum relay fee are shown as DUST. + Cette étiquette passe au rouge, Lorsqu'un destinataire reçoit un montant inférieur à %1. + +Cela implique que des frais à hauteur de %2 seront nécessaire + +Les montants inférieurs à 0.546 fois les frais minimum de relais apparaissent en tant que DUST. + + + + This label turns red, if the change is smaller than %1. + + This means a fee of at least %2 is required. + Cette étiquette passe au rouge, lorsque la différence est inférieure à %1. + +Cela implique que des frais à hauteur d'au moins %2 seront nécessaires. + + + + + (no label) + (aucune étiquette) + + + + change from %1 (%2) + monnaie de %1 (%2) + + + + (change) + (monnaie) + + + + EditAddressDialog + + + Edit Address + Modifier l'adresse + + + + &Label + &Étiquette + + + + The label associated with this address book entry + L'étiquette associée à cette entrée du carnet d'adresse + + + + &Address + &Adresse + + + + The address associated with this address book entry. This can only be modified for sending addresses. + L'adresse associée à cette entrée du carnet d'adresse. Seules les adresses d'envoi peuvent être modifiées. + + + + New receiving address + Nouvelle adresse de réception + + + + New sending address + Nouvelle adresse d’envoi + + + + Edit receiving address + Modifier l’adresse de réception + + + + Edit sending address + Modifier l’adresse d'envoi + + + + The entered address "%1" is already in the address book. + L’adresse fournie « %1 » est déjà présente dans le carnet d'adresses. + + + + The entered address "%1" is not a valid Arepacoin address. + L'adresse "%1" renseignée n'est pas une adresse Arepacoin valide. + + + + Could not unlock wallet. + Impossible de déverrouiller le portefeuille. + + + + New key generation failed. + Échec de génération de la nouvelle clef. + + + + GUIUtil::HelpMessageBox + + + + Arepacoin-Qt + Arepacoin-Qt + + + + version + version + + + + Usage: + Utilisation: + + + + command-line options + Options de ligne de commande + + + + UI options + Options graphiques + + + + Set language, for example "de_DE" (default: system locale) + Définir la langue, par exemple « fr_FR » (par défaut: la langue du système) + + + + Start minimized + Démarrer en mode réduit + + + + Show splash screen on startup (default: 1) + Affichage de l'écran de démarrage (par défaut: 1) + + + + OptionsDialog + + + Options + Options + + + + &Main + Réglages &principaux + + + + Optional transaction fee per kB that helps make sure your transactions are processed quickly. Most transactions are 1 kB. Fee 0.01 recommended. + Frais de transaction optionnels par kB permettant d'assurer la rapidité de traitement de votre transaction. La plupart des transactions sont de 1 kB. Frais de 0.01 recommandés. + + + + Pay transaction &fee + Payer des &frais de transaction + + + + Reserved amount does not participate in staking and is therefore spendable at any time. + Montants réservés ne participant pas au "staking" pouvant être utilisés pour dépensés à tout moment. + + + + Reserve + Réserve + + + + Automatically start Arepacoin after logging in to the system. + Démarrage automatique du client Arepacoin lors de la connexion au système + + + + &Start Arepacoin on system login + &Démarrage du client Arepacoin à la connexion au système + + + + Detach block and address databases at shutdown. This means they can be moved to another data directory, but it slows down shutdown. The wallet is always detached. + Détacher la base des blocs et adresses à la fermeture. Vous pourrez les utiliser dans un autre dossier mais cela ralentit la fermeture. Le portefeuille est lui toujours détaché. + + + + &Detach databases at shutdown + &Détacher la base de données lors de la fermeture du logiciel + + + + &Network + &Réseau + + + + Automatically open the Arepacoin client port on the router. This only works when your router supports UPnP and it is enabled. + Ouvrir automatiquemwnr le port client de Arepacoin sur le routeur. Ceci ne fonctionne que dans le cas où le support UPnP sur votre routeur existe et est actif. + + + + Map port using &UPnP + Mapper le port avec l'&UPnP + + + + Connect to the Arepacoin network through a SOCKS proxy (e.g. when connecting through Tor). + Connexion au réseau Arepacoin à travers un proxy SOCKS (e.g. Connexion via le réseau Tor). + + + + &Connect through SOCKS proxy: + &Connexion à travers du proxy SOCKS: + + + + Proxy &IP: + &IP du serveur Proxy mandataire : + + + + IP address of the proxy (e.g. 127.0.0.1) + Addresse IP du proxy (e.g. 127.0.0.1) + + + + &Port: + &Port: + + + + Port of the proxy (e.g. 9050) + Port du serveur Proxy mandataire (par ex. 9050) + + + + SOCKS &Version: + &Version SOCKS : + + + + SOCKS version of the proxy (e.g. 5) + Version SOCKS du serveur mandataire (par ex. 5) + + + + &Window + &Fenêtre + + + + Show only a tray icon after minimizing the window. + Afficher uniquement une icône système après minimisation. + + + + &Minimize to the tray instead of the taskbar + &Minimiser dans la barre système au lieu de la barre des tâches + + + + Minimize instead of exit the application when the window is closed. When this option is enabled, the application will be closed only after selecting Quit in the menu. + Minimiser au lieu de quitter l'application lorsque la fenêtre est fermée. Si cette option est activée, l'application ne pourra être fermée qu'en sélectionnant Quitter dans le menu. + + + + M&inimize on close + M&inimiser lors de la fermeture + + + + &Display + &Affichage + + + + User Interface &language: + &Langue de l'interface utilisateur : + + + + The user interface language can be set here. This setting will take effect after restarting Arepacoin. + La langue d'interface de l'utilisateur peut être définie ici. Les modification seront prises en compte après redémarrage de l'application Arepacoin + + + + &Unit to show amounts in: + &Unité d'affichage des montants: + + + + Choose the default subdivision unit to show in the interface and when sending coins. + Choisissez la sous-unité par défaut pour l'affichage dans l'interface et lors de l'envoi de pièces. + + + + Whether to show Arepacoin addresses in the transaction list or not. + Afficher les adresses Arepacoin au sein de la liste de transactions + + + + &Display addresses in transaction list + &Afficher les adresses sur la liste des transactions + + + + Whether to show coin control features or not. + Afficher ou non les fonctions de contrôle des pièces. + + + + Display coin &control features (experts only!) + Afficher les options de monnaie & contrôle (mode expert) + + + + &OK + &OK + + + + &Cancel + &Annuler + + + + &Apply + &Appliquer + + + + default + par défaut + + + + + Warning + Avertissement + + + + + This setting will take effect after restarting Arepacoin. + Les paramètres prendront effet après redémarrage du client Arepacoin + + + + The supplied proxy address is invalid. + L'adresse de serveur mandataire -proxy- fournie est invalide. + + + + OverviewPage + + + Form + Formulaire + + + + + The displayed information may be out of date. Your wallet automatically synchronizes with the Arepacoin network after a connection is established, but this process has not completed yet. + Les informations affichées peuvent être obsolètes. Votre portefeuille se synchronise automatiquement avec le réseau Arepacoin mais ce processus n'est pas encore terminé. + + + + Stake: + Stake: + + + + Unconfirmed: + Non confirmé: + + + + Wallet + Portefeuille + + + + Spendable: + Disponible pour dépense: + + + + Your current spendable balance + Votre solde actuel pouvant être dépensé + + + + Immature: + Immature: + + + + Mined balance that has not yet matured + Le solde généré n'est pas encore mature + + + + Total: + Total: + + + + Your current total balance + Votre solde total actuel + + + + <b>Recent transactions</b> + <b>Transactions récentes</b> + + + + Total of transactions that have yet to be confirmed, and do not yet count toward the current balance + Montant total des transactions nécessitant confirmation, et ne figurant pas encore dans le solde actuel + + + + Total of coins that was staked, and do not yet count toward the current balance + Montant total des transactions en "staking" et ne figurant pas encore dans le solde actuel + + + + + out of sync + désynchronisé + + + + QRCodeDialog + + + QR Code Dialog + Boîte de dialogue QR Code + + + + Request Payment + Demander un paiement + + + + Amount: + Montant: + + + + Label: + Étiquette: + + + + Message: + Message: + + + + &Save As... + &Enregistrer sous... + + + + Error encoding URI into QR Code. + Erreur d'encodage de l'URI en code QR. + + + + The entered amount is invalid, please check. + Le montant indiqué est invalide, veuillez vérifier. + + + + Resulting URI too long, try to reduce the text for label / message. + L'URI résultant est trop long, essayez de réduire le texte d'étiquette / de message. + + + + Save QR Code + Sauvegarder le QR Code + + + + PNG Images (*.png) + Images PNG (*.png) + + + + RPCConsole + + + Client name + Nom du client + + + + + + + + + + + + + N/A + N.D. + + + + Client version + Version du client + + + + &Information + &Informations + + + + Using OpenSSL version + Version d'OpenSSL utilisée + + + + Startup time + Heure de démarrage + + + + Network + Réseau + + + + Number of connections + Nombre de connexions + + + + On testnet + Sur testnet + + + + Block chain + Chaîne de blocs + + + + Current number of blocks + Nombre actuel de blocs + + + + Estimated total blocks + Nombre total de blocs estimé + + + + Last block time + Horodatage du dernier bloc + + + + &Open + &Ouvrir + + + + Command-line options + Options de ligne de commande + + + + Show the Arepacoin-Qt help message to get a list with possible Arepacoin command-line options. + Afficher le message d'aide Arepacoin-Qt afin d'obtenir la liste des options de de L'outil en ligne de commande Arepacoin + + + + &Show + &Afficher + + + + &Console + &Console + + + + Build date + Date de compilation + + + + Arepacoin - Debug window + Arepacoin - Fenêtre de déboggage + + + + Arepacoin Core + Arepacoin Core + + + + Debug log file + Journal de débogage + + + + Open the Arepacoin debug log file from the current data directory. This can take a few seconds for large log files. + Ouvrir le fichier journal de debug Arepacoin au sein du répertoire courant. Cette opération peut prendre quelques secondes dans le cas de fichiers journaux volumineux. + + + + Clear console + Nettoyer la console + + + + Welcome to the Arepacoin RPC console. + Bienvenue sur la console RPC de Arepacoin. + + + + Use up and down arrows to navigate history, and <b>Ctrl-L</b> to clear screen. + Utiliser les touches de curseur pour naviguer dans l'historique et <b>Ctrl-L</b> pour effacer l'écran. + + + + Type <b>help</b> for an overview of available commands. + Taper <b>help</b> pour afficher une vue générale des commandes disponibles. + + + + SendCoinsDialog + + + + + + + + + + Send Coins + Envoyer des monnaies + + + + Coin Control Features + Fonctions de contrôle des monnaies + + + + Inputs... + Entrants... + + + + automatically selected + choisi automatiquement + + + + Insufficient funds! + Fonds insuffisants! + + + + Quantity: + Quantité: + + + + + 0 + 0 + + + + Bytes: + Octets: + + + + Amount: + Montant: + + + + + + + 0.00 BC + 123.456 BC {0.00 ?} + + + + Priority: + Priorité: + + + + medium + medium + + + + Fee: + Frais: + + + + Low Output: + Sortie faible + + + + no + non + + + + After Fee: + Après frais: + + + + Change + Monnaie : + + + + custom change address + adresse de change personnalisée + + + + Send to multiple recipients at once + Envoyer à plusieurs destinataires à la fois + + + + Add &Recipient + Ajouter un &Destinataire + + + + Remove all transaction fields + Réinitialiser tous les champs liés à la transaction + + + + Clear &All + &Tout nettoyer + + + + Balance: + Solde: + + + + 123.456 BC + 123.456 BC + + + + Confirm the send action + Confirmer l’action d'envoi + + + + S&end + E&nvoyer + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + Entrer une adresse Arepacoin (par ex: AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + Copy quantity + Copier la quantité + + + + Copy amount + Copier le montant + + + + Copy fee + Copier les frais + + + + Copy after fee + Copier le montant après les frais + + + + Copy bytes + Copier les octets + + + + Copy priority + Copier la priorité + + + + Copy low output + Copier la sortie faible + + + + Copy change + Copier la monnaie + + + + <b>%1</b> to %2 (%3) + <b>%1</b> à %2 (%3) + + + + Confirm send coins + Confirmer l’envoi des pièces + + + + Are you sure you want to send %1? + Etes-vous sûr de vouloir envoyer %1? + + + + and + et + + + + The recipient address is not valid, please recheck. + L'adresse du destinataire n’est pas valide, veuillez la vérifier. + + + + The amount to pay must be larger than 0. + Le montant à payer doit être supérieur à 0. + + + + The amount exceeds your balance. + Le montant dépasse votre solde. + + + + The total exceeds your balance when the %1 transaction fee is included. + Le montant dépasse votre solde lorsque les frais de transaction de %1 sont inclus. + + + + Duplicate address found, can only send to each address once per send operation. + Adresse indentique trouvée, il n'est possible d'envoyer qu'une fois à chaque adresse par opération d'envoi. + + + + Error: Transaction creation failed. + Erreur: Echec lors de la création de la transaction + + + + 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. + Erreur: La transaction a été rejetée. Cela peut se produire si une quantité d'argent de votre portefeuille a déjà été dépensée, comme dans le cas où une copie du fichier wallet.dat aurait été utilisée afin d'effectuer des dépenses, à la place du fichier courant. + + + + WARNING: Invalid Arepacoin address + AVERTISSEMENT: Adresse Arepacoin Invalide + + + + (no label) + (pas d'étiquette) + + + + WARNING: unknown change address + AVERTISSEMENT: Adresse Arepacoin Invalide + + + + SendCoinsEntry + + + Form + Formulaire + + + + A&mount: + &Montant: + + + + Pay &To: + &Payer à: + + + + + Enter a label for this address to add it to your address book + Saisir une étiquette pour cette adresse afin de l’ajouter à votre carnet d’adresses + + + + &Label: + &Étiquette : + + + + The address to send the payment to (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + Adresse destinataire du paiement (par ex: AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + Choose address from address book + Choisir une adresse du carnet d'adresse + + + + Alt+A + Alt+A + + + + Paste address from clipboard + Coller l'adresse depuis le presse-papier + + + + Alt+P + Alt+P + + + + Remove this recipient + Supprimer ce destinataire + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + Entrer une adresse Arepacoin (par ex: AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + SignVerifyMessageDialog + + + Signatures - Sign / Verify a Message + Signatures - Signer / Vérifier un message + + + + + &Sign Message + &Signer un message + + + + You can sign messages with your addresses to prove you own them. Be careful not to sign anything vague, as phishing attacks may try to trick you into signing your identity over to them. Only sign fully-detailed statements you agree to. + Vous pouvez signer des messages avec vos adresses pour prouver que vous les détenez. Faites attention de ne rien signer de suspect car des attaques d'hameçonnage peuvent essayer d'usurper votre identité par votre signature. Ne signez que des déclarations entièrement détaillées et avec lesquelles vous serez d'accord. + + + + The address to sign the message with (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + Entrer une adresse Arepacoin (par ex: AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Choose an address from the address book + Choisir une adresse du carnet d'adresse + + + + + Alt+A + Alt+A + + + + Paste address from clipboard + Coller une adresse depuis le presse-papier + + + + Alt+P + Alt+P + + + + Enter the message you want to sign here + Saisir ici le message que vous désirez signer + + + + Copy the current signature to the system clipboard + Copier la signature actuelle dans le presse-papier + + + + Sign the message to prove you own this Arepacoin address + Signer le message afin de prouver l'identité de votre adresse Arepacoin + + + + Reset all sign message fields + Réinitialiser tous les champs de signature de message + + + + + Clear &All + &Tout nettoyer + + + + + &Verify Message + &Vérifier un message + + + + Enter the signing address, message (ensure you copy line breaks, spaces, tabs, etc. exactly) and signature below to verify the message. Be careful not to read more into the signature than what is in the signed message itself, to avoid being tricked by a man-in-the-middle attack. + Saisir ci-dessous l'adresse de signature, le message (assurez-vous d'avoir copié exactement les retours à la ligne, les espaces, tabulations etc...) et la signature pour vérifier le message. Faire attention à ne pas déduire davantage de la signature que ce qui est contenu dans le message signé lui-même pour éviter d'être trompé par une attaque d'homme du milieu. + + + + The address the message was signed with (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + L'adresse avec laquelle le message à été signé (ex: AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + Verify the message to ensure it was signed with the specified Arepacoin address + Vérifiez le message afin de vous assurer qu'il provient de l'adresse Arepacoin spécifiée. + + + + Reset all verify message fields + Réinitialiser tous les champs de vérification de message + + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + Entrer une adresse Arepacoin (par ex: AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + Click "Sign Message" to generate signature + Cliquez sur « Signer le message » pour générer la signature + + + + Enter Arepacoin signature + Entrer une signature Arepacoin + + + + + The entered address is invalid. + L'adresse saisie est invalide. + + + + + + + Please check the address and try again. + Veuillez vérifier l'adresse et réessayer. + + + + + The entered address does not refer to a key. + L'adresse saisie ne fait pas référence à une clef. + + + + Wallet unlock was cancelled. + Le déverrouillage du portefeuille a été annulé. + + + + Private key for the entered address is not available. + La clef privée pour l'adresse indiquée n'est pas disponible. + + + + Message signing failed. + La signature du message a échoué. + + + + Message signed. + Le message a été signé. + + + + The signature could not be decoded. + La signature n'a pu être décodée. + + + + + Please check the signature and try again. + Veuillez vérifier la signature et réessayer. + + + + The signature did not match the message digest. + La signature ne correspond pas à l'empreinte du message. + + + + Message verification failed. + Échec de la vérification du message. + + + + Message verified. + Message vérifié. + + + + TransactionDesc + + + Open until %1 + Ouvert jusqu'à %1 + + + + Open for %n block(s) + Ouvert pour %n blocOuvert pour %n blocks + + + + conflicted + en conflit + + + + %1/offline + %1/hors ligne + + + + %1/unconfirmed + %1/non confirmée + + + + %1 confirmations + %1 confirmations + + + + Status + État + + + + , broadcast through %n node(s) + , diffusée à travers %n nœud, diffusée à travers %n nœuds + + + + Date + Date + + + + Source + Source + + + + Generated + Généré + + + + + From + De + + + + + + To + À + + + + + own address + votre propre adresse + + + + label + étiquette + + + + + + + + Credit + Crédit + + + + matures in %n more block(s) + arrive à maturité dans %n bloc de plusarrive à maturité dans %n blocks supplémentaires + + + + not accepted + refusé + + + + + + + Debit + Débit + + + + Transaction fee + Frais de transaction + + + + Net amount + Montant net + + + + Message + Message + + + + Comment + Commentaire + + + + Transaction ID + ID de la transaction + + + + Generated coins must mature 6 blocks before they can be spent. When you generated this block, it was broadcast to the network to be added to the block chain. If it fails to get into the chain, its state will change to "not accepted" and it won't be spendable. This may occasionally happen if another node generates a block within a few seconds of yours. + Les pièces de monnaie générées nécessitent une maturation de 6 blocks avant de pouvoir être utilisées. Lors de la génération d'un blokc, celui-ci est diffusé sur le réseau afin d'être ajouté à la chaîne de blocks. En cas d'échec, son état passera en "non accepté" et celui-ci ne pourra pas être dépensé. Cela peut occasionnellement se produire, lorsqu'un noeud différent génère un block à quelques secondes d'intervalle du vôtre. + + + + Debug information + Informations de débogage + + + + Transaction + Transaction + + + + Inputs + Entrants + + + + Amount + Montant + + + + true + vrai + + + + false + faux + + + + , has not been successfully broadcast yet + , n’a pas encore été diffusée avec succès + + + + unknown + inconnu + + + + TransactionDescDialog + + + Transaction details + Détails de la transaction + + + + This pane shows a detailed description of the transaction + Ce panneau affiche une description détaillée de la transaction + + + + TransactionTableModel + + + Date + Date + + + + Type + Type + + + + Address + Adresse + + + + Amount + Montant + + + + Open until %1 + Ouvert jusqu'à %1 + + + + Confirmed (%1 confirmations) + Confirmée (%1 confirmations) + + + + Open for %n more block(s) + Ouvert pour %n bloc de plusOuvert pour %n blocs de plus + + + + Offline + Hors ligne + + + + Unconfirmed + Non confirmé + + + + Confirming (%1 of %2 recommended confirmations) + En cours de confirmation (%1 sur %2 confirmations recommandées) + + + + Conflicted + En conflit + + + + Immature (%1 confirmations, will be available after %2) + Immature (%1 confirmations, sera disponible après %2) + + + + This block was not received by any other nodes and will probably not be accepted! + Ce bloc n’a été reçu par aucun autre nœud et ne sera probablement pas accepté! + + + + Generated but not accepted + Généré mais pas accepté + + + + Received with + Reçue avec + + + + Received from + Reçue de + + + + Sent to + Envoyée à + + + + Payment to yourself + Paiement à vous-même + + + + Mined + Extrait + + + + (n/a) + (n.d) + + + + Transaction status. Hover over this field to show number of confirmations. + État de la transaction. Laissez le pointeur de la souris sur ce champ pour voir le nombre de confirmations. + + + + Date and time that the transaction was received. + Date et heure de réception de la transaction. + + + + Type of transaction. + Type de transaction. + + + + Destination address of transaction. + L’adresse de destination de la transaction. + + + + Amount removed from or added to balance. + Montant ajouté ou enlevé au solde. + + + + TransactionView + + + + All + Toutes + + + + Today + Aujourd’hui + + + + This week + Cette semaine + + + + This month + Ce mois-ci + + + + Last month + Le mois dernier + + + + This year + Cette année + + + + Range... + Intervalle… + + + + Received with + Reçue avec + + + + Sent to + Envoyée à + + + + To yourself + À vous-même + + + + Mined + Extrait + + + + Other + Autres + + + + Enter address or label to search + Saisir une adresse ou une étiquette à rechercher + + + + Min amount + Montant min. + + + + Copy address + Copier l’adresse + + + + Copy label + Copier l’étiquette + + + + Copy amount + Copier le montant + + + + Copy transaction ID + Copier l'ID de la transaction + + + + Edit label + Modifier l’étiquette + + + + Show transaction details + Afficher les détails de la transaction + + + + Export Transaction Data + Exporter les données de la transaction + + + + Comma separated file (*.csv) + Fichier de valeurs séparées par des virgules (*.csv) + + + + Confirmed + Confirmée + + + + Date + Date + + + + Type + Type + + + + Label + Étiquette + + + + Address + Adresse + + + + Amount + Montant + + + + ID + ID + + + + Error exporting + Erreur lors de l'export + + + + Could not write to file %1. + Impossible d'écrire dans le fichier %1 + + + + Range: + Intervalle: + + + + to + à + + + + WalletModel + + + Sending... + Envoi... + + + + bitcoin-core + + + Arepacoin version + Version Arepacoin + + + + Usage: + Utilisation: + + + + Send command to -server or arepacoind + Envoyer commande à -server ou arepacoind + + + + List commands + Lister les commandes + + + + Get help for a command + Obtenir de l’aide pour une commande + + + + Options: + Options: + + + + Specify configuration file (default: arepacoin.conf) + Spécifier le fichier de configuration (par défaut: arepacoin.conf) + + + + Specify pid file (default: arepacoind.pid) + Spécifier le fichier pid (par défaut: arepacoind.pid) + + + + Specify wallet file (within data directory) + Spécifier le fichier de portefeuille (dans le répertoire de données) + + + + Specify data directory + Spécifier le répertoire de données + + + + Set database cache size in megabytes (default: 25) + Définir la taille du tampon de base de données en mégaoctets (par défaut : 25) + + + + Set database disk log size in megabytes (default: 100) + Définir la taille du journal de base de données en mégaoctets (par défaut : 100) + + + + Listen for connections on <port> (default: 9853 or testnet: 19853) + Écouter les connexions sur le <port> (par défault: 9853 ou testnet: 19853) + + + + Maintain at most <n> connections to peers (default: 125) + Garder au plus <n> connexions avec les pairs (par défaut : 125) + + + + Connect to a node to retrieve peer addresses, and disconnect + Se connecter à un nœud pour obtenir des adresses de pairs puis se déconnecter + + + + Specify your own public address + Spécifier votre propre adresse publique + + + + Bind to given address. Use [host]:port notation for IPv6 + Connexion à l'adresse fournie. Utiliser la notation [machine]:port pour les adresses IPv6 + + + + Stake your coins to support network and gain reward (default: 1) + Placer vos monnaies en staking, afin de soutenir le réseau et obtenir des intérêts (par défault: 1) + + + + Threshold for disconnecting misbehaving peers (default: 100) + Seuil de déconnexion des pairs de mauvaise qualité (par défaut : 100) + + + + Number of seconds to keep misbehaving peers from reconnecting (default: 86400) + Délai en secondes de refus de reconnexion aux pairs de mauvaise qualité (par défaut : 86400) + + + + An error occurred while setting up the RPC port %u for listening on IPv4: %s + Une erreur est survenue lors du positionnement du port RPC %u pour écouter sur une adresse IPv4 : %s + + + + Detach block and address databases. Increases shutdown time (default: 0) + Détacher la base de donnée des blocks et adresses. Augmente le temps de fermeture (default: 0) + + + + 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. + Erreur: La transaction a été rejetée. Cela peut se produire si une quantité d'argent de votre portefeuille a déjà été dépensée, comme dans le cas où une copie du fichier wallet.dat aurait été utilisée afin d'effectuer des dépenses, à la place du fichier courant. + + + + Error: This transaction requires a transaction fee of at least %s because of its amount, complexity, or use of recently received funds + Erreur: Cette transaction requière des frais minimum de %s a cause de son montant, de sa complexité ou de l'utilisation de fonds récemment reçus. + + + + Listen for JSON-RPC connections on <port> (default: 9852 or testnet: 19852) + Écouter les connexions JSON-RPC sur le <port> (default: 9852 or testnet: 19852) + + + + Accept command line and JSON-RPC commands + Accepter les commandes de JSON-RPC et de la ligne de commande + + + + Error: Transaction creation failed + Erreur: La création de cette transaction à échouée + + + + Error: Wallet locked, unable to create transaction + Erreur: Portefeuille verrouillé, impossible d'effectuer cette transaction + + + + Importing blockchain data file. + Import en cours du fichier de chaîne de blocs + + + + Importing bootstrap blockchain data file. + Import en masse du fichier de chaîne bloc + + + + Run in the background as a daemon and accept commands + Fonctionner en arrière-plan en tant que démon et accepter les commandes + + + + Use the test network + Utiliser le réseau de test + + + + Accept connections from outside (default: 1 if no -proxy or -connect) + Accepter les connexions entrantes (par défaut : 1 si aucun -proxy ou -connect ) + + + + An error occurred while setting up the RPC port %u for listening on IPv6, falling back to IPv4: %s + Une erreur est survenue lors du réglage du port RPC %u pour écouter sur IPv6, retour à IPv4 : %s + + + + Error initializing database environment %s! To recover, BACKUP THAT DIRECTORY, then remove everything from it except for wallet.dat. + Erreur lors de l'initialisation de l'environnement de base de données %s! Afin de procéder à la récupération, une SAUVEGARDE DE CE REPERTOIRE est nécessaire, puis, supprimez le contenu entier de ce répertoire, à l'exception du fichier wallet.dat + + + + Set maximum size of high-priority/low-fee transactions in bytes (default: 27000) + Fixer la taille maximale d'un bloc en octets (par défault: 27000) + + + + Warning: -paytxfee is set very high! This is the transaction fee you will pay if you send a transaction. + Attention : -paytxfee est réglée sur un montant très élevé ! Il s'agit des frais de transaction que vous payerez si vous envoyez une transaction. + + + + Warning: Please check that your computer's date and time are correct! If your clock is wrong Arepacoin will not work properly. + Avertissement: Veuillez vérifier la date et l'heure de votre ordinateur. Arepacoin ne pourra pas fonctionner correctement si l'horloge est réglée de façon incorrecte + + + + Warning: error reading wallet.dat! All keys read correctly, but transaction data or address book entries might be missing or incorrect. + Avertissement : une erreur est survenue lors de la lecture de wallet.dat ! Toutes les clefs ont été lues correctement mais les données de transaction ou les entrées du carnet d'adresses sont peut-être incorrectes ou manquantes. + + + + Warning: wallet.dat corrupt, data salvaged! Original wallet.dat saved as wallet.{timestamp}.bak in %s; if your balance or transactions are incorrect you should restore from a backup. + Avertissement : wallet.dat corrompu, données récupérées ! Le fichier wallet.dat original a été enregistré en tant que wallet.{timestamp}.bak dans %s ; si votre solde ou transactions sont incorrects vous devriez effectuer une restauration depuis une sauvegarde. + + + + Attempt to recover private keys from a corrupt wallet.dat + Tenter de récupérer les clefs privées d'un wallet.dat corrompu + + + + Block creation options: + Options de création de bloc: + + + + Connect only to the specified node(s) + Ne se connecter qu'au(x) nœud(s) spécifié(s) + + + + Discover own IP address (default: 1 when listening and no -externalip) + Découvrir sa propre adresse IP (par défaut: 1 lors de l'écoute et si aucun -externalip) + + + + Failed to listen on any port. Use -listen=0 if you want this. + Échec de l'écoute sur un port quelconque. Utilisez -listen=0 si vous voulez ceci. + + + + Find peers using DNS lookup (default: 1) + Trouvez des peers utilisant DNS lookup (default: 1) + + + + Sync checkpoints policy (default: strict) + Politique de synchronisation des checkpoints (default: strict) + + + + Invalid -tor address: '%s' + Adresse -tor invalide: '%s' + + + + Invalid amount for -reservebalance=<amount> + Montant incorrect pour -reservebalance=<montant> + + + + Maximum per-connection receive buffer, <n>*1000 bytes (default: 5000) + Tampon maximal de réception par « -connection » <n>*1 000 octets (par défaut : 5 000) + + + + Maximum per-connection send buffer, <n>*1000 bytes (default: 1000) + Tampon maximal d'envoi par « -connection », <n>*1 000 octets (par défaut : 1 000) + + + + Only connect to nodes in network <net> (IPv4, IPv6 or Tor) + Se connecter uniquement aux nœuds du réseau <net> (IPv4, IPv6 ou Tor) + + + + Output extra debugging information. Implies all other -debug* options + Voir les autres informations de débogage. Implique toutes les autres options -debug* + + + + Output extra network debugging information + Voir les autres informations de débogage du réseau + + + + Prepend debug output with timestamp + Horodater les messages de debug + + + + SSL options: (see the Bitcoin Wiki for SSL setup instructions) + Options SSL : (voir le Wiki de Bitcoin pour les instructions de configuration du SSL) + + + + Select the version of socks proxy to use (4-5, default: 5) + Sélectionner la version du proxy socks à utiliser (4-5, par défaut: 5) + + + + Send trace/debug info to console instead of debug.log file + Envoyer les informations de débogage/trace à la console au lieu du fichier debug.log + + + + Send trace/debug info to debugger + Envoyer les informations de débogage/trace à la console au lieu du fichier debug.log + + + + Set maximum block size in bytes (default: 250000) + Fixer la taille maximale d'un block en bytes (default: 250000) + + + + Set minimum block size in bytes (default: 0) + Définir la taille minimale de bloc en octets (par défaut : 0) + + + + Shrink debug.log file on client startup (default: 1 when no -debug) + Réduire le fichier debug.log lors du démarrage du client (par défaut : 1 lorsque -debug n'est pas présente) + + + + Specify connection timeout in milliseconds (default: 5000) + Spécifier le délai d'expiration de la connexion en millisecondes (par défaut: 5000) + + + + Unable to sign checkpoint, wrong checkpointkey? + + Impossible de "signer" le checkpoint, mauvaise clef de checkpoint? + + + + + Use UPnP to map the listening port (default: 0) + Utiliser l'UPnP pour rediriger le port d'écoute (par défaut: 0) + + + + Use UPnP to map the listening port (default: 1 when listening) + Utiliser l'UPnP pour rediriger le port d'écoute (par défaut: 1 lors de l'écoute) + + + + Use proxy to reach tor hidden services (default: same as -proxy) + Utiliser un proxy pour atteindre les services cachés (par défaut: équivalent à -proxy) + + + + Username for JSON-RPC connections + Nom d'utilisateur pour les connexions JSON-RPC + + + + Verifying database integrity... + Vérification d'intégrité de la base de données... + + + + WARNING: syncronized checkpoint violation detected, but skipped! + ATTENTION : violation du checkpoint de synchronisation, mais ignorée! + + + + Warning: Disk space is low! + Avertissement: Espace disque faible! + + + + Warning: This version is obsolete, upgrade required! + Avertissement : cette version est obsolète, une mise à niveau est nécessaire ! + + + + wallet.dat corrupt, salvage failed + wallet.dat corrompu, la récupération a échoué + + + + Password for JSON-RPC connections + Mot de passe pour les connexions JSON-RPC + + + + %s, you must set a rpcpassword in the configuration file: + %s +It is recommended you use the following random password: +rpcuser=arepacoinrpc +rpcpassword=%s +(you do not need to remember this password) +The username and password MUST NOT be the same. +If the file does not exist, create it with owner-readable-only file permissions. +It is also recommended to set alertnotify so you are notified of problems; +for example: alertnotify=echo %%s | mail -s "Arepacoin Alert" admin@foo.com + + %s, vous devez définir un mot de passe rpc 'rpcpassword' au sein du fichier de configuration: + %s +Il est recommandé d'utiliser le mot de passe aléatoire suivant: +rpcuser=arepacoinrpc +rpcpassword=%s +(il n'est pas nécessaire de retenir ce mot de passe) +Le nom d'utilisateur et le mot de passe doivent IMPERATIVEMENT être différents. +Si le fichier n'existe pas, il est nécessaire de le créer, avec les droit de lecture au propriétaire seulement. +Il est également recommandé d'utiliser l'option alertnotify afin d'être notifié des problèmes; +par exemple: alertnotify=echo %%s | mail -s "Alerte Arepacoin" admin@foo.com + + + + + Find peers using internet relay chat (default: 0) + Trouvez des pairs utilisant DNS lookup (par défault: 1) {0)?} + + + + Sync time with other nodes. Disable if time on your system is precise e.g. syncing with NTP (default: 1) + Synchronisation de l'horloge avec d'autres noeuds. Désactiver si votre serveur est déjà synchronisé avec le protocole NTP (défaut: 1) + + + + When creating transactions, ignore inputs with value less than this (default: 0.01) + Lors de la création de transactions, ignorer les entrées dont la valeur sont inférieures (défaut: 0.01) + + + + Allow JSON-RPC connections from specified IP address + Autoriser les connexions JSON-RPC depuis l'adresse IP spécifiée + + + + Send commands to node running on <ip> (default: 127.0.0.1) + Envoyer des commandes au nœud fonctionnant sur <ip> (par défaut : 127.0.0.1) + + + + Execute command when the best block changes (%s in cmd is replaced by block hash) + Exécuter la commande lorsque le meilleur bloc change (%s dans cmd est remplacé par le hachage du bloc) + + + + Execute command when a wallet transaction changes (%s in cmd is replaced by TxID) + Exécuter la commande lorsqu'une transaction du portefeuille change (%s dans la commande est remplacée par TxID) + + + + Require a confirmations for change (default: 0) + Nécessite a confirmations pour modification (par défaut: 0) + + + + Enforce transaction scripts to use canonical PUSH operators (default: 1) + Force les scripts de transaction à utiliser des opérateurs PUSH canoniques (défaut: 1) + + + + Execute command when a relevant alert is received (%s in cmd is replaced by message) + Exécute une commande lorsqu'une alerte correspondante est reçue (%s dans la commande est remplacé par message) + + + + Upgrade wallet to latest format + Mettre à niveau le portefeuille vers le format le plus récent + + + + Set key pool size to <n> (default: 100) + Régler la taille de la réserve de clefs sur <n> (par défaut : 100) + + + + Rescan the block chain for missing wallet transactions + Réanalyser la chaîne de blocs pour les transactions de portefeuille manquantes + + + + How many blocks to check at startup (default: 2500, 0 = all) + Nombre de blocs à vérifier lors du démarrage (par défaut: 2500, 0 = tous) + + + + How thorough the block verification is (0-6, default: 1) + Niveau d'approfondissement de la vérification des blocs (0-6, default: 1) + + + + Imports blocks from external blk000?.dat file + Importe les blocs d'un fichier externe blk000?.dat + + + + Use OpenSSL (https) for JSON-RPC connections + Utiliser OpenSSL (https) pour les connexions JSON-RPC + + + + Server certificate file (default: server.cert) + Fichier de certificat serveur (par défaut : server.cert) + + + + Server private key (default: server.pem) + Clef privée du serveur (par défaut : server.pem) + + + + Acceptable ciphers (default: TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH) + Algorithmes de chiffrements acceptés (par défaut: TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH) + + + + Error: Wallet unlocked for staking only, unable to create transaction. + Erreur: Portefeuille déverrouillé uniquement pour "staking" , impossible d'effectuer cette transaction + + + + WARNING: Invalid checkpoint found! Displayed transactions may not be correct! You may need to upgrade, or notify developers. + AVERTISSEMENT: point de contrôle invalide! Les transactions affichées peuvent être incorrectes! Il est peut-être nécessaire d'effectuer une mise à jour, ou d'avertir les développeurs du projet. + + + + This help message + Ce message d'aide + + + + Wallet %s resides outside data directory %s. + Le portefeuille %s est situé en dehors du répertoire de données %s + + + + Cannot obtain a lock on data directory %s. Arepacoin is probably already running. + Echec lors de la tentative de verrou des données du répertoire %s. L'application Arepacoin est probablement déjà en cours d'exécution + + + + Arepacoin + Arepacoin + + + + Unable to bind to %s on this computer (bind returned error %d, %s) + Impossible de se lier à %s sur cet ordinateur (bind a retourné l'erreur %d, %s) + + + + Connect through socks proxy + Se connecter à travers un proxy socks + + + + Allow DNS lookups for -addnode, -seednode and -connect + Autoriser les recherches DNS pour -addnode, -seednode et -connect + + + + Loading addresses... + Chargement des adresses… + + + + Error loading blkindex.dat + Erreur de chargement du fichier blkindex.dat + + + + Error loading wallet.dat: Wallet corrupted + Erreur lors du chargement de wallet.dat: portefeuille corrompu + + + + Error loading wallet.dat: Wallet requires newer version of Arepacoin + Erreur de chargement du fichier wallet.dat: le portefeuille nécessite une version plus récente de l'application Arepacoin + + + + Wallet needed to be rewritten: restart Arepacoin to complete + Le portefeuille nécessite d'être réédité : Merci de relancer l'application Arepacoin + + + + Error loading wallet.dat + Erreur lors du chargement du fichier wallet.dat + + + + Invalid -proxy address: '%s' + Adresse -proxy invalide : « %s » + + + + Unknown network specified in -onlynet: '%s' + Réseau inconnu spécifié sur -onlynet : « %s » + + + + Unknown -socks proxy version requested: %i + Version inconnue de serveur mandataire -socks demandée : %i + + + + Cannot resolve -bind address: '%s' + Impossible de résoudre l'adresse -bind : « %s » + + + + Cannot resolve -externalip address: '%s' + Impossible de résoudre l'adresse -externalip : « %s » + + + + Invalid amount for -paytxfee=<amount>: '%s' + Montant invalide pour -paytxfee=<montant> : « %s » + + + + Error: could not start node + Erreur: Impossible de démarrer le noeud + + + + Sending... + Envoi... + + + + Invalid amount + Montant invalide + + + + Insufficient funds + Fonds insuffisants + + + + Loading block index... + Chargement de l’index des blocs… + + + + Add a node to connect to and attempt to keep the connection open + Ajouter un nœud auquel se connecter et tenter de garder la connexion ouverte + + + + Unable to bind to %s on this computer. Arepacoin is probably already running. + Connexion au port %s impossible. L'application Arepacoin est probablement déjà en cours d'exécution + + + + Fee per KB to add to transactions you send + Frais par KB à ajouter à vos transactions sortantes + + + + Invalid amount for -mininput=<amount>: '%s' + Montant invalide pour -mininput=<amount>: '%s' + + + + Loading wallet... + Chargement du portefeuille… + + + + Cannot downgrade wallet + Impossible de revenir à une version inférieure du portefeuille + + + + Cannot initialize keypool + Impossible d'initialiser la "keypool" + + + + Cannot write default address + Impossible d'écrire l'adresse par défaut + + + + Rescanning... + Nouvelle analyse… + + + + Done loading + Chargement terminé + + + + To use the %s option + Pour utiliser l'option %s + + + + Error + Erreur + + + + You must set rpcpassword=<password> in the configuration file: +%s +If the file does not exist, create it with owner-readable-only file permissions. + Vous devez ajouter la ligne rpcpassword=<mot-de-passe> au fichier de configuration : +%s +Si le fichier n'existe pas, créez-le avec les droits de lecture seule accordés au propriétaire. + + + \ No newline at end of file diff --git a/src/qt/locale/bitcoin_fr_CA.ts b/src/qt/locale/bitcoin_fr_CA.ts new file mode 100755 index 0000000..9a3cee8 --- /dev/null +++ b/src/qt/locale/bitcoin_fr_CA.ts @@ -0,0 +1,3314 @@ + + + AboutDialog + + + About Arepacoin + Au sujet de Arepacoin + + + + <b>Arepacoin</b> version + Version de <b>Arepacoin</b> + + + + Copyright © 2009-2014 The Bitcoin developers +Copyright © 2012-2014 The NovaCoin developers +Copyright © 2014 The Arepacoin developers + Copyright © 2009-2014 Les développeurs Bitcoin +Copyright © 2012-2014 Les développeurs NovaCoin +Copyright © 2014 Les développeurs Arepacoin + + + + +This is experimental software. + +Distributed under the MIT/X11 software license, see the accompanying file COPYING or http://www.opensource.org/licenses/mit-license.php. + +This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit (http://www.openssl.org/) and cryptographic software written by Eric Young (eay@cryptsoft.com) and UPnP software written by Thomas Bernard. + + Ce logiciel est expérimental. + + Distribué sous licence logicielle MIT/X11, voir le fichier COPYING joint ou http://www.opensource.org/licenses/mit-license.php. + + Ce produit comprend des logiciels développés par le projet OpenSSL afin d'être utilisés dans la boîte à outils OpenSSL (http://www.openssl.org/), un logiciel de chiffrement écrit par Eric Young (eay@cryptsoft.com), et un logiciel UPnP développé par Thomas Bernard. + + + + AddressBookPage + + + Address Book + Répertoire d'adresses + + + + Double-click to edit address or label + Double cliquer afin de modifier l'adresse ou l'étiquette + + + + Create a new address + Créer une nouvelle adresse + + + + Copy the currently selected address to the system clipboard + Copier l'adresse sélectionnée vers le presse-papier système + + + + &New Address + &Nouvelle adresse + + + + These are your Arepacoin addresses for receiving payments. You may want to give a different one to each sender so you can keep track of who is paying you. + Ce sont vos adresses pour recevoir vos paiements. Vous pouvez utiliser une adresse différente pour chaque réception afin d'identifier facilement le payeur. + + + + &Copy Address + &Copier l'adresse + + + + Show &QR Code + Montrer le &QR Code + + + + Sign a message to prove you own a Arepacoin address + Signer un message afin de valider l'identité de votre adresse Arepacoin + + + + Sign &Message + Signer le &message + + + + Delete the currently selected address from the list + Effacer l'adresse actuellement sélectionnée de la liste + + + + Verify a message to ensure it was signed with a specified Arepacoin address + Vérifier un message pour s'assurer qu'il vient d'un adresse Arepacoin spécifique. + + + + &Verify Message + &Vérifier un message + + + + &Delete + &Supprimer + + + + Copy &Label + Copier l'&Étiquette + + + + &Edit + &Modifier + + + + Export Address Book Data + Exporter votre répertoire d'adresses + + + + Comma separated file (*.csv) + Fichier de valeurs séparées par des virgules (*.csv) + + + + Error exporting + Erreur lors de l'export + + + + Could not write to file %1. + Impossible d'écrire dans le fichier %1. + + + + AddressTableModel + + + Label + Étiquette + + + + Address + Adresse + + + + (no label) + (aucune étiquette) + + + + AskPassphraseDialog + + + Passphrase Dialog + Dialogue de phrase de passe + + + + Enter passphrase + Saisir la phrase de passe + + + + New passphrase + Nouvelle phrase de passe + + + + Repeat new passphrase + Répéter la phrase de passe + + + + Serves to disable the trivial sendmoney when OS account compromised. Provides no real security. + Sert à désactiver les transactions sortantes si votre compte de système d'exploitation est compromis. Ne procure pas de réelle sécurité. + + + + For staking only + Pour "staking" seulement + + + + Enter the new passphrase to the wallet.<br/>Please use a passphrase of <b>10 or more random characters</b>, or <b>eight or more words</b>. + Saisir la nouvelle phrase de passe pour le portefeuille. <br/>Veuillez utiliser une phrase de passe de <b>10 caractères aléatoires ou plus</b>, ou de <b>huit mots ou plus</b>. + + + + Encrypt wallet + Crypter le portefeuille + + + + This operation needs your wallet passphrase to unlock the wallet. + Cette opération nécessite votre phrase de passe pour déverrouiller le portefeuille. + + + + Unlock wallet + Déverrouiller le portefeuille + + + + This operation needs your wallet passphrase to decrypt the wallet. + Cette opération nécessite votre phrase de passe pour déchiffrer le portefeuille. + + + + Decrypt wallet + Déchiffrer le portefeuille + + + + Change passphrase + Changer la phrase de passe + + + + Enter the old and new passphrase to the wallet. + Saisir l’ancienne et la nouvelle phrase de passe du portefeuille + + + + Confirm wallet encryption + Confirmer le cryptage du portefeuille + + + + Warning: If you encrypt your wallet and lose your passphrase, you will <b>LOSE ALL OF YOUR COINS</b>! + ATTENTION : Si vous cryptez votre portefeuille et perdez votre passphrase, vous ne pourrez plus accéder à vos Arepacoins + + + + Are you sure you wish to encrypt your wallet? + Êtes-vous sûr de vouloir crypter votre portefeuille ? + + + + IMPORTANT: Any previous backups you have made of your wallet file should be replaced with the newly generated, encrypted wallet file. For security reasons, previous backups of the unencrypted wallet file will become useless as soon as you start using the new, encrypted wallet. + IMPORTANT : Toute sauvegarde précédente de votre fichier de portefeuille devrait être remplacée par le nouveau fichier de portefeuille crypté. Pour des raisons de sécurité, les sauvegardes précédentes de votre fichier de portefeuille non crypté deviendront inutilisables dès lors que vous commencerez à utiliser le nouveau portefeuille crypté. + + + + + Warning: The Caps Lock key is on! + Attention : la touche Verr. Maj. est activée ! + + + + + Wallet encrypted + Portefeuille crypté + + + + Arepacoin will close now to finish the encryption process. Remember that encrypting your wallet cannot fully protect your coins from being stolen by malware infecting your computer. + L'application Arepacoin va désormais se terminer afin de finaliser le processus de cryptage. Merci de noter que le cryptage du portefeuille ne garantit pas de se prémunir du vol via l'utilisation de malware, qui auraient pu infecter votre ordinateur. + + + + + + + Wallet encryption failed + Le cryptage du portefeuille a échoué + + + + Wallet encryption failed due to an internal error. Your wallet was not encrypted. + Le cryptage du portefeuille a échoué en raison d'une erreur interne. Votre portefeuille n'a pas été crypté. + + + + + The supplied passphrases do not match. + Les phrases de passe saisies ne correspondent pas. + + + + Wallet unlock failed + Le déverrouillage du portefeuille a échoué + + + + + + The passphrase entered for the wallet decryption was incorrect. + La phrase de passe saisie pour décrypter le portefeuille était incorrecte. + + + + Wallet decryption failed + Le décryptage du portefeuille a échoué + + + + Wallet passphrase was successfully changed. + La phrase de passe du portefeuille a été modifiée avec succès. + + + + BitcoinGUI + + + Sign &message... + Signer le &message... + + + + Synchronizing with network... + Synchronisation avec le réseau en cours… + + + + &Overview + &Vue d'ensemble + + + + Show general overview of wallet + Afficher une vue d’ensemble du portefeuille + + + + &Transactions + &Transactions + + + + Browse transaction history + Parcourir l'historique des transactions + + + + &Address Book + Carnet d'adresses + + + + Edit the list of stored addresses and labels + Éditer la liste d'adresses et libellés + + + + &Receive coins + &Recevoir des monnaies + + + + Show the list of addresses for receiving payments + Montrer la liste d'adresses de réception des paiements + + + + &Send coins + &Envoyer des monnaies + + + + E&xit + Q&uitter + + + + Quit application + Quitter l’application + + + + Show information about Arepacoin + Afficher des informations au sujet du Arepacoin + + + + About &Qt + À propos de &Qt + + + + Show information about Qt + Afficher des informations sur Qt + + + + &Options... + &Options… + + + + &Encrypt Wallet... + &Crypter le portefeuille... + + + + &Backup Wallet... + Sauvegarder le &portefeuille... + + + + &Change Passphrase... + &Changer la phrase de passe... + + + + ~%n block(s) remaining + ~%n blocks restants~%n blocs restants + + + + Downloaded %1 of %2 blocks of transaction history (%3% done). + Téléchargement des blocks de l'historique des transactions : 1% sur 2% (%3% effectués). + + + + &Export... + &Export... + + + + Send coins to a Arepacoin address + Envoyer des monnaies vers une adresse Arepacoin + + + + Modify configuration options for Arepacoin + Modification des options de configuration de Arepacoin + + + + Export the data in the current tab to a file + Export des données de l'onglet courant vers un fichier + + + + Encrypt or decrypt wallet + Crypter ou décrypter le portefeuille + + + + Backup wallet to another location + Sauvegarder le portefeuille vers un autre emplacement + + + + Change the passphrase used for wallet encryption + Modifier la phrase de passe utilisée pour le cryptage du portefeuille + + + + &Debug window + &Fenêtre de débogage + + + + Open debugging and diagnostic console + Ouvrir une console de débogage et de diagnostic + + + + &Verify message... + &Vérifier un message... + + + + Arepacoin + Arepacoin + + + + Wallet + Portefeuille + + + + &About Arepacoin + A propos de Arepacoin + + + + &Show / Hide + &Afficher / Cacher + + + + Unlock wallet + Déverrouiller le portefeuille + + + + &Lock Wallet + &Verrouiller le portefeuille + + + + Lock wallet + Verrouiller le portefeuille + + + + &File + &Fichier + + + + &Settings + &Réglages + + + + &Help + &Aide + + + + Tabs toolbar + Barre d'outils des onglets + + + + Actions toolbar + Barre d'actions + + + + + [testnet] + [testnet] + + + + + Arepacoin client + Client Arepacoin + + + + %n active connection(s) to Arepacoin network + %n connexion active au réseau Arepacoin%n connexions actives au réseau Arepacoin + + + + Downloaded %1 blocks of transaction history. + Téléchargement de blocs de l'historique de transactions : 1% blocks + + + + Staking.<br>Your weight is %1<br>Network weight is %2<br>Expected time to earn reward is %3 + Staking.<br>Votre poids est de %1<br>Le poids du réseau est de %2<br>Temps estimé avant récompense %3 + + + + Not staking because wallet is locked + Ne stack pas, votre portefeuilles est verouillé + + + + Not staking because wallet is offline + Ne stack pas, votre portefeuilles est hors ligne + + + + Not staking because wallet is syncing + Ne stack pas, votre portefeuille est en cours de synchronisation + + + + Not staking because you don't have mature coins + Ne stack pas, vos monnaies ne sont pas encore matures + + + + %n second(s) ago + il y a %n secondeil y a %n secondes + + + + &Unlock Wallet... + &Déverrouiller le portefeuille + + + + %n minute(s) ago + il y a %n minuteil y a %n minutes + + + + %n hour(s) ago + il y a %n heureil y a %n heures + + + + %n day(s) ago + il y a %n jouril y a %n jours + + + + Up to date + À jour + + + + Catching up... + Rattrapage en cours… + + + + Last received block was generated %1. + Le dernier block reçu à été généré %1. + + + + This transaction is over the size limit. You can still send it for a fee of %1, which goes to the nodes that process your transaction and helps to support the network. Do you want to pay the fee? + Cette transaction dépasse la limite autorisée. Vous pouvez tout de même effectuer cette opération, moyennant %1 de frais, qui seront envoyés aux noeuds qui valideront cette transaction, et dont l'objectif vise à supporter le réseau. Etes-vous d'accord pour payer ces frais ? + + + + Confirm transaction fee + Confirmer le Paiement des frais de transaction + + + + Sent transaction + Transaction envoyée + + + + Incoming transaction + Transaction entrante + + + + Date: %1 +Amount: %2 +Type: %3 +Address: %4 + + Date : %1 +Montant : %2 +Type : %3 +Adresse : %4 + + + + + + URI handling + Prise en charge de l'URL + + + + + URI can not be parsed! This can be caused by an invalid Arepacoin address or malformed URI parameters. + L'adresse du portefeuille Arepacoin n'as pas pu être correctement identifiée, car invalide ou malformée. + + + + Wallet is <b>encrypted</b> and currently <b>unlocked</b> + Le portefeuille est <b>crypté</b> et est actuellement <b>déverrouillé</b> + + + + Wallet is <b>encrypted</b> and currently <b>locked</b> + Le portefeuille est <b>crypté</b> et actuellement <b>verrouillé</b> + + + + Backup Wallet + Sauvegarder le portefeuille + + + + Wallet Data (*.dat) + Données liées au portefeuille (*.dat) + + + + Backup Failed + Echec de la sauvegarde + + + + There was an error trying to save the wallet data to the new location. + Une erreur a été rencontrée lors de la tentative de sauvegarde du portefeuille vers la nouvelle destination. + + + + %n second(s) + %n seconde%n secondes + + + + %n minute(s) + %n minute%n minutes + + + + %n hour(s) + %n heure%n heures + + + + %n day(s) + %n jour%n jours + + + + Not staking + Pas de stacking + + + + A fatal error occurred. Arepacoin can no longer continue safely and will quit. + Une erreur fatale a été rencontrée. L'application Arepacoin ne peut plus être s'exécuter de façon correcte et doit se terminer. + + + + ClientModel + + + Network Alert + Alerte réseau + + + + CoinControlDialog + + + Coin Control + Fonctions de contrôle des monnaies + + + + Quantity: + Quantité : + + + + Bytes: + Octets : + + + + Amount: + Montant : + + + + Priority: + Priorité : + + + + Fee: + Frais : + + + + Low Output: + Sortie faible : + + + + no + non + + + + After Fee: + Après les frais : + + + + Change: + Monnaie : + + + + (un)select all + Tout (dé)sélectionner + + + + Tree mode + Mode arborescence + + + + List mode + Mode liste + + + + Amount + Montant + + + + Label + Intitulé + + + + Address + Adresse + + + + Date + Date + + + + Confirmations + Confirmations + + + + Confirmed + Confirmée + + + + Priority + Priorité + + + + Copy address + Copier l’adresse + + + + Copy label + Copier l’étiquette + + + + + Copy amount + Copier le montant + + + + Copy transaction ID + Copier l'ID de la transaction + + + + Copy quantity + Copier la quantité + + + + Copy fee + Copier les frais + + + + Copy after fee + Copier le montant après les frais + + + + Copy bytes + Copier les octets + + + + Copy priority + Copier la priorité + + + + Copy low output + Copier la sortie faible + + + + Copy change + Copier la monnaie + + + + highest + la plus élevée + + + + high + élevée + + + + medium-high + moyennement-élevée + + + + medium + moyenne + + + + low-medium + moyennement-basse + + + + low + basse + + + + lowest + la plus basse + + + + DUST + DUST + + + + yes + oui + + + + This label turns red, if the transaction size is bigger than 10000 bytes. + + This means a fee of at least %1 per kb is required. + + Can vary +/- 1 Byte per input. + Cet intitulé passe au rouge, si la taille de la transaction est supérieure à 10000 bytes. + +Cela implique que des frais à hauteur d'au moins %1 par kb seront nécessaires. + +Ceux-ci Peuvent varier de +/- 1 Byte par entrée. + + + + Transactions with higher priority get more likely into a block. + +This label turns red, if the priority is smaller than "medium". + + This means a fee of at least %1 per kb is required. + Les transactions avec une priorité haute ont plus de chances d'être traitées en un block. + + Rouge si votre priorité est plus petite que "moyenne". + +Cela veut dire que des frais d'un minimum de %1 par kb sont requis + + + + This label turns red, if any recipient receives an amount smaller than %1. + + This means a fee of at least %2 is required. + + Amounts below 0.546 times the minimum relay fee are shown as DUST. + Ce label passe au rouge, Lorsqu'un destinataire reçoit un montant inférieur à %1. + + Cela implique que des frais à hauteur de %2 seront nécessaire + +Les montants inférieurs à 0.546 fois les frais minimum de relais apparaissent en tant que DUST. + + + + This label turns red, if the change is smaller than %1. + + This means a fee of at least %2 is required. + Ce label passe au rouge, lorsque la différence est inférieure à %1. + + Cela implique que des frais à hauteur d'au moins %2 seront nécessaires. + + + + + (no label) + (aucune étiquette) + + + + change from %1 (%2) + monnaie de %1 (%2) + + + + (change) + (monnaie) + + + + EditAddressDialog + + + Edit Address + Modifier l'adresse + + + + &Label + &Étiquette + + + + The label associated with this address book entry + L'intitulé associé à cette entrée du carnet d'adresse + + + + &Address + &Adresse + + + + The address associated with this address book entry. This can only be modified for sending addresses. + L'intitulé associé à cette entrée du carnet d'adresse. Seules les adresses d'envoi peuvent être modifiées. + + + + New receiving address + Nouvelle adresse de réception + + + + New sending address + Nouvelle adresse d’envoi + + + + Edit receiving address + Modifier l’adresse de réception + + + + Edit sending address + Modifier l’adresse d'envoi + + + + The entered address "%1" is already in the address book. + L’adresse fournie « %1 » est déjà présente dans le carnet d'adresses. + + + + The entered address "%1" is not a valid Arepacoin address. + L'adresse "%1" renseignée n'est pas une adresse Arepacoin valide. + + + + Could not unlock wallet. + Impossible de déverrouiller le portefeuille. + + + + New key generation failed. + Échec de génération de la nouvelle clef. + + + + GUIUtil::HelpMessageBox + + + + Arepacoin-Qt + Arepacoin-Qt + + + + version + version + + + + Usage: + Utilisation: + + + + command-line options + Options de ligne de commande + + + + UI options + Options graphiques + + + + Set language, for example "de_DE" (default: system locale) + Définir la langue, par exemple « fr_FR » (par défaut : la langue du système) + + + + Start minimized + Démarrer en mode réduit + + + + Show splash screen on startup (default: 1) + Affichage de l'écran de démarrage (défaut: 1) + + + + OptionsDialog + + + Options + Options + + + + &Main + Réglages &principaux + + + + Optional transaction fee per kB that helps make sure your transactions are processed quickly. Most transactions are 1 kB. Fee 0.01 recommended. + Frais de transaction optionnels par kB afin d'assurer la rapidité de traitement de votre transaction. La plupart des transactions sont de 1 kB. Frais de 0.01 recommandés. + + + + Pay transaction &fee + Payer des &frais de transaction + + + + Reserved amount does not participate in staking and is therefore spendable at any time. + Montant réservé qui ne "stake" pas est reste utilisable pour réalisés des envois à tout moment. + + + + Reserve + Réserve + + + + Automatically start Arepacoin after logging in to the system. + Démarrage automatique du client Arepacoin lors de la connexion au système + + + + &Start Arepacoin on system login + &Démarrage du client Arepacoin à la connexion au système + + + + Detach block and address databases at shutdown. This means they can be moved to another data directory, but it slows down shutdown. The wallet is always detached. + Détacher la base des block et adresses à la fermeture. Vous pourrez les utiliser dans un autre dossier mais cela ralenti la fermeture. Le portefeuille est lui toujours détaché. + + + + &Detach databases at shutdown + &Détacher la base de données à la fermeture + + + + &Network + &Réseau + + + + Automatically open the Arepacoin client port on the router. This only works when your router supports UPnP and it is enabled. + Ouverture automatique du port client de Arepacoin sur le routeur. Ceci ne fonctionne que dans le cas où le support UPnP sur votre routeur existe et est actif. + + + + Map port using &UPnP + Mapper le port avec l'&UPnP + + + + Connect to the Arepacoin network through a SOCKS proxy (e.g. when connecting through Tor). + Connexion au réseau Arepacoin à travers un proxy SOCKS (e.g. Connexion via le réseau Tor). + + + + &Connect through SOCKS proxy: + &Connexion à travers du proxy SOCKS: + + + + Proxy &IP: + &IP du serveur mandataire : + + + + IP address of the proxy (e.g. 127.0.0.1) + Addresse IP du proxy (e.g. 127.0.0.1) + + + + &Port: + &Port : + + + + Port of the proxy (e.g. 9050) + Port du serveur mandataire (par ex. 9050) + + + + SOCKS &Version: + &Version SOCKS : + + + + SOCKS version of the proxy (e.g. 5) + Version SOCKS du serveur mandataire (par ex. 5) + + + + &Window + &Fenêtre + + + + Show only a tray icon after minimizing the window. + Afficher uniquement une icône système après minimisation. + + + + &Minimize to the tray instead of the taskbar + &Minimiser dans la barre système au lieu de la barre des tâches + + + + Minimize instead of exit the application when the window is closed. When this option is enabled, the application will be closed only after selecting Quit in the menu. + Minimiser au lieu de quitter l'application lorsque la fenêtre est fermée. Si cette option est activée, l'application ne pourra être fermée qu'en sélectionnant Quitter dans le menu. + + + + M&inimize on close + M&inimiser lors de la fermeture + + + + &Display + &Affichage + + + + User Interface &language: + &Langue de l'interface utilisateur : + + + + The user interface language can be set here. This setting will take effect after restarting Arepacoin. + La langue d'interface de de l'utilisateur peut être définie ici. Ces modification seront effectives après redémarrage de l'application Arepacoin + + + + &Unit to show amounts in: + &Unité d'affichage des montants : + + + + Choose the default subdivision unit to show in the interface and when sending coins. + Choisissez la sous-unité par défaut pour l'affichage dans l'interface et lors de l'envoi de pièces. + + + + Whether to show Arepacoin addresses in the transaction list or not. + Afficher les adresses Arepacoin au sein de la liste de transactions + + + + &Display addresses in transaction list + &Afficher les adresses sur la liste des transactions + + + + Whether to show coin control features or not. + Afficher ou non les fonctions de contrôle des pièces. + + + + Display coin &control features (experts only!) + Afficher les options de monnaie & contrôle (mode expert) + + + + &OK + &OK + + + + &Cancel + &Annuler + + + + &Apply + &Exécuter + + + + default + par défaut + + + + + Warning + Avertissement + + + + + This setting will take effect after restarting Arepacoin. + Les paramètres prendront effet après redémarrage du client Arepacoin + + + + The supplied proxy address is invalid. + L'adresse de serveur mandataire -proxy- fournie est invalide. + + + + OverviewPage + + + Form + Formulaire + + + + + The displayed information may be out of date. Your wallet automatically synchronizes with the Arepacoin network after a connection is established, but this process has not completed yet. + Les informations affichées peuvent être obsolètes. Votre portefeuille se synchronise automatiquement avec le réseau Arepacoin mais ce processus n'est pas encore terminé. + + + + Stake: + Stake: + + + + Unconfirmed: + Non confirmé: + + + + Wallet + Portefeuille + + + + Spendable: + Disponible pour dépense: + + + + Your current spendable balance + Votre solde actuel pouvant être dépensé + + + + Immature: + Immature : + + + + Mined balance that has not yet matured + Le solde généré n'est pas encore mature + + + + Total: + Total : + + + + Your current total balance + Votre solde total actuel + + + + <b>Recent transactions</b> + <b>Transactions récentes</b> + + + + Total of transactions that have yet to be confirmed, and do not yet count toward the current balance + Montant total des transactions nécessitant confirmation, et ne figurant pas encore dans la balance actuelle + + + + Total of coins that was staked, and do not yet count toward the current balance + Montant total des transactions en "staking" et ne figurant pas encore dans la balance actuelle + + + + + out of sync + désynchronisé + + + + QRCodeDialog + + + QR Code Dialog + Boîte de dialogue QR Code + + + + Request Payment + Demander un paiement + + + + Amount: + Montant : + + + + Label: + Intitulé: + + + + Message: + Message: + + + + &Save As... + &Enregistrer sous... + + + + Error encoding URI into QR Code. + Erreur d'encodage de l'URI en code QR. + + + + The entered amount is invalid, please check. + Le montant indiqué est invalide, veuillez vérifier. + + + + Resulting URI too long, try to reduce the text for label / message. + L'URI résultant est trop long, essayez de réduire le texte d'étiquette / de message. + + + + Save QR Code + Sauvegarder le QR Code + + + + PNG Images (*.png) + Images PNG (*.png) + + + + RPCConsole + + + Client name + Nom du client + + + + + + + + + + + + + N/A + N.D. + + + + Client version + Version du client + + + + &Information + &Informations + + + + Using OpenSSL version + Version d'OpenSSL utilisée + + + + Startup time + Heure de démarrage + + + + Network + Réseau + + + + Number of connections + Nombre de connexions + + + + On testnet + Sur testnet + + + + Block chain + Chaîne de blocks + + + + Current number of blocks + Nombre actuel de blocks + + + + Estimated total blocks + Nombre total estimé de blocks + + + + Last block time + Horodatage du dernier block + + + + &Open + &Ouvrir + + + + Command-line options + Options de ligne de commande + + + + Show the Arepacoin-Qt help message to get a list with possible Arepacoin command-line options. + Afficher le message d'aide Arepacoin-Qt afin d'obtenir la liste des options de de L'outil en ligne de commande Arepacoin + + + + &Show + &Afficher + + + + &Console + &Console + + + + Build date + Date de compilation + + + + Arepacoin - Debug window + Arepacoin - Fenêtre de déboggage + + + + Arepacoin Core + Arepacoin Core + + + + Debug log file + Journal de débogage + + + + Open the Arepacoin debug log file from the current data directory. This can take a few seconds for large log files. + Ouvrir le fichier journal de debug Arepacoin au sein du répertoire courant. Cette opération peut prendre quelques secondes dans le cas de fichiers journaux volumineux. + + + + Clear console + Nettoyer la console + + + + Welcome to the Arepacoin RPC console. + Bienvenue sur la console Arepacoin RPC. + + + + Use up and down arrows to navigate history, and <b>Ctrl-L</b> to clear screen. + Utiliser les touches de curseur pour naviguer dans l'historique et <b>Ctrl-L</b> pour effacer l'écran. + + + + Type <b>help</b> for an overview of available commands. + Taper <b>help</b> pour afficher une vue générale des commandes disponibles. + + + + SendCoinsDialog + + + + + + + + + + Send Coins + Envoyer des monnaies + + + + Coin Control Features + Fonctions de contrôle des monnaies + + + + Inputs... + Entrants... + + + + automatically selected + choisi automatiquement + + + + Insufficient funds! + Fonds insuffisants ! + + + + Quantity: + Quantité : + + + + + 0 + 0 + + + + Bytes: + Octets : + + + + Amount: + Montant : + + + + + + + 0.00 BC + 123.456 BC {0.00 ?} + + + + Priority: + Priorité : + + + + medium + medium + + + + Fee: + Frais : + + + + Low Output: + Sortie faible + + + + no + non + + + + After Fee: + Après les frais : + + + + Change + Monnaie : + + + + custom change address + adresse de change personnalisée + + + + Send to multiple recipients at once + Envoyer à plusieurs destinataires à la fois + + + + Add &Recipient + Ajouter un &destinataire + + + + Remove all transaction fields + Réinitialiser tous les champs liés à la transaction + + + + Clear &All + &Tout nettoyer + + + + Balance: + Solde : + + + + 123.456 BC + 123.456 BC + + + + Confirm the send action + Confirmer l’action d'envoi + + + + S&end + E&nvoyer + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + Entrer une adresse Arepacoin (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + Copy quantity + Copier la quantité + + + + Copy amount + Copier le montant + + + + Copy fee + Copier les frais + + + + Copy after fee + Copier le montant après les frais + + + + Copy bytes + Copier les octets + + + + Copy priority + Copier la priorité + + + + Copy low output + Copier la sortie faible + + + + Copy change + Copier la monnaie + + + + <b>%1</b> to %2 (%3) + <b>%1</b> to %2 (%3) + + + + Confirm send coins + Confirmer l’envoi des pièces + + + + Are you sure you want to send %1? + Etes-vous sûr de vouloir envoyer %1? + + + + and + et + + + + The recipient address is not valid, please recheck. + L'adresse du destinataire n’est pas valide, veuillez la vérifier. + + + + The amount to pay must be larger than 0. + Le montant à payer doit être supérieur à 0. + + + + The amount exceeds your balance. + Le montant dépasse votre solde. + + + + The total exceeds your balance when the %1 transaction fee is included. + Le montant dépasse votre solde lorsque les frais de transaction de %1 sont inclus. + + + + Duplicate address found, can only send to each address once per send operation. + Adresse indentique trouvée, il n'est possible d'envoyer qu'une fois à chaque adresse par opération d'envoi. + + + + Error: Transaction creation failed. + Erreur: Echec lors de la création de la transaction + + + + 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. + Erreur: La transaction a été rejetée. Cela peut se produire si une quantité d'argent de votre portefeuille a déjà été dépensée, comme dans le cas où une copie du fichier wallet.dat aurait été utilisée afin d'effectuer des dépenses, à la place du fichier courant. + + + + WARNING: Invalid Arepacoin address + AVERTISSEMENT: Adresse Arepacoin Invalide + + + + (no label) + (pas d'étiquette) + + + + WARNING: unknown change address + AVERTISSEMET: Adresse Arepacoin Invalide + + + + SendCoinsEntry + + + Form + Formulaire + + + + A&mount: + &Montant : + + + + Pay &To: + &Payer à : + + + + + Enter a label for this address to add it to your address book + Saisir une étiquette pour cette adresse afin de l’ajouter à votre carnet d’adresses + + + + &Label: + &Étiquette : + + + + The address to send the payment to (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + Adresse destinataire du paiement ( ex : AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + Choose address from address book + Choisir une adresse du carnet d'adresse + + + + Alt+A + Alt+A + + + + Paste address from clipboard + Coller l'adresse depuis le presse-papier + + + + Alt+P + Alt+P + + + + Remove this recipient + Supprimer ce destinataire + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + Entrer une adresse Arepacoin (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + SignVerifyMessageDialog + + + Signatures - Sign / Verify a Message + Signatures - Signer / Vérifier un message + + + + + &Sign Message + &Signer un message + + + + You can sign messages with your addresses to prove you own them. Be careful not to sign anything vague, as phishing attacks may try to trick you into signing your identity over to them. Only sign fully-detailed statements you agree to. + Vous pouvez signer des messages avec vos adresses pour prouver que vous les détenez. Faites attention de ne rien signer de suspect car des attaques d'hameçonnage peuvent essayer d'usurper votre identité par votre signature. Ne signez que des déclarations entièrement détaillées et avec lesquelles vous serez d'accord. + + + + The address to sign the message with (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + Entrer une adresse Arepacoin (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Choose an address from the address book + Choisir une adresse du carnet d'adresse + + + + + Alt+A + Alt+A + + + + Paste address from clipboard + Coller une adresse depuis le presse-papier + + + + Alt+P + Alt+P + + + + Enter the message you want to sign here + Saisir ici le message que vous désirez signer + + + + Copy the current signature to the system clipboard + Copier la signature actuelle dans le presse-papier + + + + Sign the message to prove you own this Arepacoin address + Signer le message afin de prouver l'identité de votre adresse Arepacoin + + + + Reset all sign message fields + Réinitialiser tous les champs de signature de message + + + + + Clear &All + &Tout nettoyer + + + + + &Verify Message + &Vérifier un message + + + + Enter the signing address, message (ensure you copy line breaks, spaces, tabs, etc. exactly) and signature below to verify the message. Be careful not to read more into the signature than what is in the signed message itself, to avoid being tricked by a man-in-the-middle attack. + Saisir ci-dessous l'adresse de signature, le message (assurez-vous d'avoir copié exactement les retours à la ligne, les espaces, tabulations etc...) et la signature pour vérifier le message. Faire attention à ne pas déduire davantage de la signature que ce qui est contenu dans le message signé lui-même pour éviter d'être trompé par une attaque d'homme du milieu. + + + + The address the message was signed with (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + L'adresse avec laquelle le message à été signé (ex: AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + Verify the message to ensure it was signed with the specified Arepacoin address + Vérifier un message pour s'assurer qu'il vient d'un adresse Arepacoin spécifique. + + + + Reset all verify message fields + Réinitialiser tous les champs de vérification de message + + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + Entrer une adresse Arepacoin (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + Click "Sign Message" to generate signature + Cliquez sur « Signer le message » pour générer la signature + + + + Enter Arepacoin signature + Entrer une signature Arepacoin + + + + + The entered address is invalid. + L'adresse saisie est invalide. + + + + + + + Please check the address and try again. + Veuillez vérifier l'adresse et réessayer. + + + + + The entered address does not refer to a key. + L'adresse saisie ne fait pas référence à une clef. + + + + Wallet unlock was cancelled. + Le déverrouillage du portefeuille a été annulé. + + + + Private key for the entered address is not available. + La clef privée pour l'adresse indiquée n'est pas disponible. + + + + Message signing failed. + La signature du message a échoué. + + + + Message signed. + Le message a été signé. + + + + The signature could not be decoded. + La signature n'a pu être décodée. + + + + + Please check the signature and try again. + Veuillez vérifier la signature et réessayer. + + + + The signature did not match the message digest. + La signature ne correspond pas à l'empreinte du message. + + + + Message verification failed. + Échec de la vérification du message. + + + + Message verified. + Message vérifié. + + + + TransactionDesc + + + Open until %1 + Ouvert jusqu'à %1 + + + + Open for %n block(s) + Ouvert pour %n blocOuvert pour %n blocks + + + + conflicted + en conflit + + + + %1/offline + %1/hors ligne + + + + %1/unconfirmed + %1/non confirmée + + + + %1 confirmations + %1 confirmations + + + + Status + État + + + + , broadcast through %n node(s) + , diffusée à travers %n nœud, diffusée à travers %n nœuds + + + + Date + Date + + + + Source + Source + + + + Generated + Généré + + + + + From + De + + + + + + To + À + + + + + own address + votre propre adresse + + + + label + étiquette + + + + + + + + Credit + Crédit + + + + matures in %n more block(s) + arrive à maturité dans %n bloc de plusarrive à maturité dans %n blocks supplémentaires + + + + not accepted + refusé + + + + + + + Debit + Débit + + + + Transaction fee + Frais de transaction + + + + Net amount + Montant net + + + + Message + Message + + + + Comment + Commentaire + + + + Transaction ID + ID de la transaction + + + + Generated coins must mature 6 blocks before they can be spent. When you generated this block, it was broadcast to the network to be added to the block chain. If it fails to get into the chain, its state will change to "not accepted" and it won't be spendable. This may occasionally happen if another node generates a block within a few seconds of yours. + Les pièces de monnaie générées nécessitent une maturation de 6 blocks avant de pouvoir être utilisées. Lors de la génération d'un blokc, celui-ci est diffusé sur le réseau afin d'être ajouté à la chaîne de blocks. En cas d'échec, son état passera en "non accepté" et celui-ci ne pourra pas être dépensé. Cela peut occasionnellement se produire, lorsqu'un noeud différent génère un block à quelques secondes d'intervalle du vôtre. + + + + Debug information + Informations de débogage + + + + Transaction + Transaction + + + + Inputs + Entrants + + + + Amount + Montant + + + + true + vrai + + + + false + faux + + + + , has not been successfully broadcast yet + , n’a pas encore été diffusée avec succès + + + + unknown + inconnu + + + + TransactionDescDialog + + + Transaction details + Détails de la transaction + + + + This pane shows a detailed description of the transaction + Ce panneau affiche une description détaillée de la transaction + + + + TransactionTableModel + + + Date + Date + + + + Type + Type + + + + Address + Adresse + + + + Amount + Montant + + + + Open until %1 + Ouvert jusqu'à %1 + + + + Confirmed (%1 confirmations) + Confirmée (%1 confirmations) + + + + Open for %n more block(s) + Ouvert pour %n bloc de plusOuvert pour %n blocs de plus + + + + Offline + Hors ligne + + + + Unconfirmed + Non confirmé + + + + Confirming (%1 of %2 recommended confirmations) + Confirmation (%1 sur %2 confirmations recommandées) + + + + Conflicted + En conflit + + + + Immature (%1 confirmations, will be available after %2) + Immature (%1 confirmations, sera disponible après %2) + + + + This block was not received by any other nodes and will probably not be accepted! + Ce bloc n’a été reçu par aucun autre nœud et ne sera probablement pas accepté ! + + + + Generated but not accepted + Généré mais pas accepté + + + + Received with + Reçue avec + + + + Received from + Reçue de + + + + Sent to + Envoyée à + + + + Payment to yourself + Paiement à vous-même + + + + Mined + Extrait + + + + (n/a) + (n.d) + + + + Transaction status. Hover over this field to show number of confirmations. + État de la transaction. Laissez le pointeur de la souris sur ce champ pour voir le nombre de confirmations. + + + + Date and time that the transaction was received. + Date et heure de réception de la transaction. + + + + Type of transaction. + Type de transaction. + + + + Destination address of transaction. + L’adresse de destination de la transaction. + + + + Amount removed from or added to balance. + Montant ajouté ou enlevé au solde. + + + + TransactionView + + + + All + Toutes + + + + Today + Aujourd’hui + + + + This week + Cette semaine + + + + This month + Ce mois-ci + + + + Last month + Le mois dernier + + + + This year + Cette année + + + + Range... + Intervalle… + + + + Received with + Reçue avec + + + + Sent to + Envoyée à + + + + To yourself + À vous-même + + + + Mined + Extrait + + + + Other + Autres + + + + Enter address or label to search + Saisir une adresse ou une étiquette à rechercher + + + + Min amount + Montant min. + + + + Copy address + Copier l’adresse + + + + Copy label + Copier l’étiquette + + + + Copy amount + Copier le montant + + + + Copy transaction ID + Copier l'ID de la transaction + + + + Edit label + Modifier l’étiquette + + + + Show transaction details + Afficher les détails de la transaction + + + + Export Transaction Data + Exporter les données de la transaction + + + + Comma separated file (*.csv) + Valeurs séparées par des virgules (*.csv) + + + + Confirmed + Confirmée + + + + Date + Date + + + + Type + Type + + + + Label + Étiquette + + + + Address + Adresse + + + + Amount + Montant + + + + ID + ID + + + + Error exporting + Erreur lors de l'export + + + + Could not write to file %1. + Impossible d'écrire dans le fichier %1 + + + + Range: + Intervalle : + + + + to + à + + + + WalletModel + + + Sending... + Envoi... + + + + bitcoin-core + + + Arepacoin version + Version Arepacoin + + + + Usage: + Utilisation : + + + + Send command to -server or arepacoind + Envoyer commande à -server ou arepacoind + + + + List commands + Lister les commandes + + + + Get help for a command + Obtenir de l’aide pour une commande + + + + Options: + Options : + + + + Specify configuration file (default: arepacoin.conf) + Spécifier le fichier de configuration (defaut: arepacoin.conf) + + + + Specify pid file (default: arepacoind.pid) + Spécifier le fichier pid (defaut: arepacoind.pid) + + + + + Specify wallet file (within data directory) + Spécifiez le fichier de portefeuille (dans le répertoire de données) + + + + Specify data directory + Spécifier le répertoire de données + + + + Set database cache size in megabytes (default: 25) + Définir la taille du tampon en mégaoctets (par défaut : 25) + + + + Set database disk log size in megabytes (default: 100) + Définir la taille du tampon en mégaoctets (par défaut : 100) + + + + Listen for connections on <port> (default: 9853 or testnet: 19853) + Écouter les connexions sur le <port> (default: 9853 or testnet: 19853) + + + + Maintain at most <n> connections to peers (default: 125) + Garder au plus <n> connexions avec les pairs (par défaut : 125) + + + + Connect to a node to retrieve peer addresses, and disconnect + Se connecter à un nœud pour obtenir des adresses de pairs puis se déconnecter + + + + Specify your own public address + Spécifier votre propre adresse publique + + + + Bind to given address. Use [host]:port notation for IPv6 + Connexion à l'adresse fournie. Utiliser la notation [machine]:port pour les adresses IPv6 + + + + Stake your coins to support network and gain reward (default: 1) + Stacker vos monnaies afin de soutenir le réseau et d'obtenir des intérêts (default: 1) + + + + Threshold for disconnecting misbehaving peers (default: 100) + Seuil de déconnexion des pairs de mauvaise qualité (par défaut : 100) + + + + Number of seconds to keep misbehaving peers from reconnecting (default: 86400) + Délai en secondes de refus de reconnexion aux pairs de mauvaise qualité (par défaut : 86400) + + + + An error occurred while setting up the RPC port %u for listening on IPv4: %s + Une erreur est survenue lors du réglage du port RPC %u pour écouter sur IPv4 : %s + + + + Detach block and address databases. Increases shutdown time (default: 0) + Détacher la base de donnée des blocks et adresses. Augmente le temps de fermeture (default: 0) + + + + 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. + Erreur: La transaction a été rejetée. Cela peut se produire si une quantité d'argent de votre portefeuille a déjà été dépensée, comme dans le cas où une copie du fichier wallet.dat aurait été utilisée afin d'effectuer des dépenses, à la place du fichier courant. + + + + Error: This transaction requires a transaction fee of at least %s because of its amount, complexity, or use of recently received funds + Erreur: Cette transaction requière des frais minimum de %s a cause de son montant, de sa complexité ou de l'utilisation de fonds récemment reçus. + + + + Listen for JSON-RPC connections on <port> (default: 9852 or testnet: 19852) + Écouter les connexions JSON-RPC sur le <port> (default: 9852 or testnet: 19852) + + + + Accept command line and JSON-RPC commands + Accepter les commandes de JSON-RPC et de la ligne de commande + + + + Error: Transaction creation failed + Erreur: La création de cette transaction à échouée + + + + Error: Wallet locked, unable to create transaction + Erreur: Portefeuille verrouillé, impossible d'effectuer cette transaction + + + + Importing blockchain data file. + Importation du fichier blockchain + + + + Importing bootstrap blockchain data file. + Importation du fichier blockchain + + + + Run in the background as a daemon and accept commands + Fonctionner en arrière-plan en tant que démon et accepter les commandes + + + + Use the test network + Utiliser le réseau de test + + + + Accept connections from outside (default: 1 if no -proxy or -connect) + Accepter les connexions entrantes (par défaut : 1 si aucun -proxy ou -connect ) + + + + An error occurred while setting up the RPC port %u for listening on IPv6, falling back to IPv4: %s + Une erreur est survenue lors du réglage du port RPC %u pour écouter sur IPv6, retour à IPv4 : %s + + + + Error initializing database environment %s! To recover, BACKUP THAT DIRECTORY, then remove everything from it except for wallet.dat. + Erreur lors de l'initialisation de l'environnement de base de données %s! Afin de procéder à la récupération, une SAUVEGARDE DE CE REPERTOIRE est nécessaire, puis, supprimez le contenu entier de ce répertoire, à l'exception du fichier wallet.dat + + + + Set maximum size of high-priority/low-fee transactions in bytes (default: 27000) + Fixer la taille maximale d'un block en bytes (default: 27000) + + + + Warning: -paytxfee is set very high! This is the transaction fee you will pay if you send a transaction. + Attention : -paytxfee est réglée sur un montant très élevé ! Il s'agit des frais de transaction que vous payerez si vous envoyez une transaction. + + + + Warning: Please check that your computer's date and time are correct! If your clock is wrong Arepacoin will not work properly. + Avertissement: Veuillez vérifier la date et l'heure de votre ordinateur. Arepacoin ne pourra pas fonctionner correctement si l'horloge est réglée de façon incorrecte + + + + Warning: error reading wallet.dat! All keys read correctly, but transaction data or address book entries might be missing or incorrect. + Avertissement : une erreur est survenue lors de la lecture de wallet.dat ! Toutes les clefs ont été lues correctement mais les données de transaction ou les entrées du carnet d'adresses sont peut-être incorrectes ou manquantes. + + + + Warning: wallet.dat corrupt, data salvaged! Original wallet.dat saved as wallet.{timestamp}.bak in %s; if your balance or transactions are incorrect you should restore from a backup. + Avertissement : wallet.dat corrompu, données récupérées ! Le fichier wallet.dat original a été enregistré en tant que wallet.{timestamp}.bak dans %s ; si votre solde ou transactions sont incorrects vous devriez effectuer une restauration depuis une sauvegarde. + + + + Attempt to recover private keys from a corrupt wallet.dat + Tenter de récupérer les clefs privées d'un wallet.dat corrompu + + + + Block creation options: + Options de création de bloc : + + + + Connect only to the specified node(s) + Ne se connecter qu'au(x) nœud(s) spécifié(s) + + + + Discover own IP address (default: 1 when listening and no -externalip) + Découvrir sa propre adresse IP (par défaut : 1 lors de l'écoute et si aucun -externalip) + + + + Failed to listen on any port. Use -listen=0 if you want this. + Échec de l'écoute sur un port quelconque. Utilisez -listen=0 si vous voulez ceci. + + + + Find peers using DNS lookup (default: 1) + Trouvez des peers utilisant DNS lookup (default: 1) + + + + Sync checkpoints policy (default: strict) + Politique de synchronisation des checkpoints (default: strict) + + + + Invalid -tor address: '%s' + Adresse -tor invalide: '%s' + + + + Invalid amount for -reservebalance=<amount> + Montant incorrect pour -reservebalance=<montant> + + + + Maximum per-connection receive buffer, <n>*1000 bytes (default: 5000) + Tampon maximal de réception par « -connection » <n>*1 000 octets (par défaut : 5 000) + + + + Maximum per-connection send buffer, <n>*1000 bytes (default: 1000) + Tampon maximal d'envoi par « -connection », <n>*1 000 octets (par défaut : 1 000) + + + + Only connect to nodes in network <net> (IPv4, IPv6 or Tor) + Se connecter uniquement aux nœuds du réseau <net> (IPv4, IPv6 ou Tor) + + + + Output extra debugging information. Implies all other -debug* options + Voir les autres informations de débogage. Implique toutes les autres options -debug* + + + + Output extra network debugging information + Voir les autres informations de débogage du réseau + + + + Prepend debug output with timestamp + Horodater les messages de debug + + + + SSL options: (see the Bitcoin Wiki for SSL setup instructions) + Options SSL : (voir le Wiki de Bitcoin pour les instructions de configuration du SSL) + + + + Select the version of socks proxy to use (4-5, default: 5) + Sélectionner la version du proxy socks à utiliser (4-5, par défaut: 5) + + + + Send trace/debug info to console instead of debug.log file + Envoyer les informations de débogage/trace à la console au lieu du fichier debug.log + + + + Send trace/debug info to debugger + Envoyer les informations de débogage/trace à la console au lieu du fichier debug.log + + + + Set maximum block size in bytes (default: 250000) + Fixer la taille maximale d'un block en bytes (default: 250000) + + + + Set minimum block size in bytes (default: 0) + Définir la taille minimale de bloc en octets (par défaut : 0) + + + + Shrink debug.log file on client startup (default: 1 when no -debug) + Réduire le fichier debug.log lors du démarrage du client (par défaut : 1 lorsque -debug n'est pas présent) + + + + Specify connection timeout in milliseconds (default: 5000) + Spécifier le délai d'expiration de la connexion en millisecondes (par défaut : 5 000) + + + + Unable to sign checkpoint, wrong checkpointkey? + + Impossible de "signer" le checkpoint, mauvaise clef de checkpoint? + + + + + Use UPnP to map the listening port (default: 0) + Utiliser l'UPnP pour rediriger le port d'écoute (par défaut : 0) + + + + Use UPnP to map the listening port (default: 1 when listening) + Utiliser l'UPnP pour rediriger le port d'écoute (par défaut : 1 lors de l'écoute) + + + + Use proxy to reach tor hidden services (default: same as -proxy) + Utiliser un proxy pour atteindre les services cachés (défaut: équivalent à -proxy) + + + + Username for JSON-RPC connections + Nom d'utilisateur pour les connexions JSON-RPC + + + + Verifying database integrity... + Vérification d'intégrité de la base de données... + + + + WARNING: syncronized checkpoint violation detected, but skipped! + ATTENTION : violation du checkpoint de synchronisation, mais ignorée! + + + + Warning: Disk space is low! + Avertissement: Espace disque faible! + + + + Warning: This version is obsolete, upgrade required! + Avertissement : cette version est obsolète, une mise à niveau est nécessaire ! + + + + wallet.dat corrupt, salvage failed + wallet.dat corrompu, la récupération a échoué + + + + Password for JSON-RPC connections + Mot de passe pour les connexions JSON-RPC + + + + %s, you must set a rpcpassword in the configuration file: + %s +It is recommended you use the following random password: +rpcuser=arepacoinrpc +rpcpassword=%s +(you do not need to remember this password) +The username and password MUST NOT be the same. +If the file does not exist, create it with owner-readable-only file permissions. +It is also recommended to set alertnotify so you are notified of problems; +for example: alertnotify=echo %%s | mail -s "Arepacoin Alert" admin@foo.com + + %s, vous devez définir un mot de passe rpc 'rpcpassword' au sein du fichier de configuration: + %s +Il est recommandé d'utiliser le mot de passe aléatoire suivant: +rpcuser=arepacoinrpc +rpcpassword=%s +(il n'est pas nécessaire de retenir ce mot de passe) +Le nom d'utilisateur et le mot de passe doivent IMPERATIVEMENT être différents. +Si le fichier n'existe pas, il est nécessaire de le créer, avec les droit de lecture au propriétaire seulement. +Il est également recommandé d'utiliser l'option alertnotify afin d'être notifié des problèmes; +par exemple: alertnotify=echo %%s | mail -s "Alerte Arepacoin" admin@foo.com + + + + + Find peers using internet relay chat (default: 0) + Find peers using internet relay chat (default: 1) {0)?} + + + + Sync time with other nodes. Disable if time on your system is precise e.g. syncing with NTP (default: 1) + Synchronisation de l'horloge avec d'autres noeuds. Désactiver si votre serveur est déjà synchronisé avec le protocole NTP (défaut: 1) + + + + When creating transactions, ignore inputs with value less than this (default: 0.01) + Lors de la création de transactions, ignore les entrées dont la valeur sont inférieures (défaut: 0.01) + + + + Allow JSON-RPC connections from specified IP address + Autoriser les connexions JSON-RPC depuis l'adresse IP spécifiée + + + + Send commands to node running on <ip> (default: 127.0.0.1) + Envoyer des commandes au nœud fonctionnant sur <ip> (par défaut : 127.0.0.1) + + + + Execute command when the best block changes (%s in cmd is replaced by block hash) + Exécuter la commande lorsque le meilleur bloc change (%s dans cmd est remplacé par le hachage du bloc) + + + + Execute command when a wallet transaction changes (%s in cmd is replaced by TxID) + Exécuter la commande lorsqu'une transaction de portefeuille change (%s dans la commande est remplacée par TxID) + + + + Require a confirmations for change (default: 0) + Nécessite a confirmations pour modification (défaut: 0) + + + + Enforce transaction scripts to use canonical PUSH operators (default: 1) + Force les scripts de transaction à utiliser des opérateurs PUSH canoniques (défaut: 1) + + + + Execute command when a relevant alert is received (%s in cmd is replaced by message) + Exécute une commande lorsqu'une alerte correspondante est reçue (%s dans la commande est remplacé par message) + + + + Upgrade wallet to latest format + Mettre à niveau le portefeuille vers le format le plus récent + + + + Set key pool size to <n> (default: 100) + Régler la taille de la réserve de clefs sur <n> (par défaut : 100) + + + + Rescan the block chain for missing wallet transactions + Réanalyser la chaîne de blocs pour les transactions de portefeuille manquantes + + + + How many blocks to check at startup (default: 2500, 0 = all) + Nombre de blocs à vérifier loes du démarrage (défaut: 2500, 0 = tous) + + + + How thorough the block verification is (0-6, default: 1) + Niveau d'approfondissement de la vérification des blocs (0-6, default: 1) + + + + Imports blocks from external blk000?.dat file + Importe les blocs d'un fichier externe blk000?.dat + + + + Use OpenSSL (https) for JSON-RPC connections + Utiliser OpenSSL (https) pour les connexions JSON-RPC + + + + Server certificate file (default: server.cert) + Fichier de certificat serveur (par défaut : server.cert) + + + + Server private key (default: server.pem) + Clef privée du serveur (par défaut : server.pem) + + + + Acceptable ciphers (default: TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH) + Algorithmes de chiffrements acceptés (défaut: TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH) + + + + Error: Wallet unlocked for staking only, unable to create transaction. + Erreur: Portefeuille déverrouillé uniquement pour "stacking" , impossible d'effectuer cette transaction + + + + WARNING: Invalid checkpoint found! Displayed transactions may not be correct! You may need to upgrade, or notify developers. + AVERTISSEMENT: point de contrôle invalide! Les transactions affichées peuvent être incorrectes! Il est peut-être nécessaire d'effectuer une mise à jour, ou d'avertir les développeurs du projet. + + + + This help message + Ce message d'aide + + + + Wallet %s resides outside data directory %s. + Le portefeuille %s réside en dehors répertoire de données %s + + + + Cannot obtain a lock on data directory %s. Arepacoin is probably already running. + Echec lors de la tentative de verrouillage des données du répertoire %s. L'application Arepacoin est probablement déjà en cours d'exécution + + + + Arepacoin + Arepacoin + + + + Unable to bind to %s on this computer (bind returned error %d, %s) + Impossible de se lier à %s sur cet ordinateur (bind a retourné l'erreur %d, %s) + + + + Connect through socks proxy + Se connecter à travers un proxy socks + + + + Allow DNS lookups for -addnode, -seednode and -connect + Autoriser les recherches DNS pour -addnode, -seednode et -connect + + + + Loading addresses... + Chargement des adresses… + + + + Error loading blkindex.dat + Erreur de chargement du fichier blkindex.dat + + + + Error loading wallet.dat: Wallet corrupted + Erreur lors du chargement de wallet.dat : portefeuille corrompu + + + + Error loading wallet.dat: Wallet requires newer version of Arepacoin + Erreur de chargement du fichier wallet.dat: le portefeuille nécessite une version plus récente de l'application Arepacoin + + + + Wallet needed to be rewritten: restart Arepacoin to complete + le portefeuille nécessite d'être réédité : Merci de relancer l'application Arepacoin + + + + Error loading wallet.dat + Erreur lors du chargement de wallet.dat + + + + Invalid -proxy address: '%s' + Adresse -proxy invalide : « %s » + + + + Unknown network specified in -onlynet: '%s' + Réseau inconnu spécifié sur -onlynet : « %s » + + + + Unknown -socks proxy version requested: %i + Version inconnue de serveur mandataire -socks demandée : %i + + + + Cannot resolve -bind address: '%s' + Impossible de résoudre l'adresse -bind : « %s » + + + + Cannot resolve -externalip address: '%s' + Impossible de résoudre l'adresse -externalip : « %s » + + + + Invalid amount for -paytxfee=<amount>: '%s' + Montant invalide pour -paytxfee=<montant> : « %s » + + + + Error: could not start node + Erreur: Impossible de démarrer le noeud + + + + Sending... + Envoi... + + + + Invalid amount + Montant invalide + + + + Insufficient funds + Fonds insuffisants + + + + Loading block index... + Chargement de l’index des blocs… + + + + Add a node to connect to and attempt to keep the connection open + Ajouter un nœud auquel se connecter et tenter de garder la connexion ouverte + + + + Unable to bind to %s on this computer. Arepacoin is probably already running. + Connexion au port %s impossible. L'application Arepacoin est probablement déjà en cours d'exécution + + + + Fee per KB to add to transactions you send + Frais par KB à ajouter à vos transactions sortantes + + + + Invalid amount for -mininput=<amount>: '%s' + Montant invalide pour -mininput=<amount>: '%s' + + + + Loading wallet... + Chargement du portefeuille… + + + + Cannot downgrade wallet + Impossible de revenir à une version inférieure du portefeuille + + + + Cannot initialize keypool + Impossible d'initialiser la "keypool" + + + + Cannot write default address + Impossible d'écrire l'adresse par défaut + + + + Rescanning... + Nouvelle analyse… + + + + Done loading + Chargement terminé + + + + To use the %s option + Pour utiliser l'option %s + + + + Error + Erreur + + + + You must set rpcpassword=<password> in the configuration file: +%s +If the file does not exist, create it with owner-readable-only file permissions. + Vous devez ajouter la ligne rpcpassword=<mot-de-passe> au fichier de configuration : +%s +Si le fichier n'existe pas, créez-le avec les droits de lecture seule accordés au propriétaire. + + + \ No newline at end of file diff --git a/src/qt/locale/bitcoin_gl.ts b/src/qt/locale/bitcoin_gl.ts new file mode 100755 index 0000000..52e834b --- /dev/null +++ b/src/qt/locale/bitcoin_gl.ts @@ -0,0 +1,3286 @@ + + + AboutDialog + + + About Arepacoin + Acerca de Arepacoin + + + + <b>Arepacoin</b> version + Versión <b>Arepacoin</b> . + + + + Copyright © 2009-2014 The Bitcoin developers +Copyright © 2012-2014 The NovaCoin developers +Copyright © 2014 The Arepacoin developers + + + + + +This is experimental software. + +Distributed under the MIT/X11 software license, see the accompanying file COPYING or http://www.opensource.org/licenses/mit-license.php. + +This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit (http://www.openssl.org/) and cryptographic software written by Eric Young (eay@cryptsoft.com) and UPnP software written by Thomas Bernard. + +Isto é software experimental. + +Distribuído baixo a licencia de software MIT/X11, véxase o arquivo que acompaña COPYING ou http://www.opensource.org/licenses/mit-license.php. + +Este produto inclúe software desenvolvido polo OpenSSL Project para o uso no OpenSSL Toolkit (http://www.openssl.org/) e software criptográfico escrito por Eric Young (eay@cryptsoft.com) e software UPnP escrito por Thomas Bernard. + + + + AddressBookPage + + + Address Book + Libreta de direccións + + + + Double-click to edit address or label + Doble click para editar a dirección ou a etiqueta + + + + Create a new address + Crear unha nova dirección + + + + Copy the currently selected address to the system clipboard + Copiar a dirección seleccionada ao cartafol + + + + &New Address + &Nova dirección. + + + + These are your Arepacoin addresses for receiving payments. You may want to give a different one to each sender so you can keep track of who is paying you. + Estas son as túas dIreccións de Arepacoin para recibir os pagos. Pode que quieras asignarlle unha a cada remitente e así reconocer quen te está a pagar. + + + + &Copy Address + &Copiar Dirección + + + + Show &QR Code + Amosar &QR Code + + + + Sign a message to prove you own a Arepacoin address + Firma a mensaxe para probar que tes unha dirección Arepacoin + + + + Sign &Message + Firmar &Mensaxe + + + + Delete the currently selected address from the list + Borrar a dirección actualmente seleccionada da listaxe + + + + Verify a message to ensure it was signed with a specified Arepacoin address + Verifica a mensaxe para asegurar que foi asinada por unha concreta dirección de Arepacoin + + + + &Verify Message + &Verificar Mensaxe. + + + + &Delete + &Borrar + + + + Copy &Label + Copiar &Etiqueta + + + + &Edit + &Modificar + + + + Export Address Book Data + Exportar datos da libreta de direccións. + + + + Comma separated file (*.csv) + Arquivo separado por comas (*.csv) + + + + Error exporting + Error exportando + + + + Could not write to file %1. + Non se puido escribir a arquivo %1 + + + + AddressTableModel + + + Label + Etiqueta + + + + Address + Dirección + + + + (no label) + (sen etiqueta) + + + + AskPassphraseDialog + + + Passphrase Dialog + Diálogo de Contrasinal + + + + Enter passphrase + Introduce contrasinal + + + + New passphrase + Novo contrasinal + + + + Repeat new passphrase + Repite novo contrasinal + + + + Serves to disable the trivial sendmoney when OS account compromised. Provides no real security. + + + + + For staking only + Para "staking" só + + + + Enter the new passphrase to the wallet.<br/>Please use a passphrase of <b>10 or more random characters</b>, or <b>eight or more words</b>. + Introduce o novo contrasinal ao moedeiro.<br/>Por favor empregue un contrasinal de <b>10 ou máis caracteres aleatorios</b>, ou <b>oito ou máis palabras</b>. + + + + Encrypt wallet + Encriptar moedeiro + + + + This operation needs your wallet passphrase to unlock the wallet. + Esta operación precisa o contrasinal do teu moedeiro para desbloquear o moedeiro. + + + + Unlock wallet + Desbloquear moedeiro + + + + This operation needs your wallet passphrase to decrypt the wallet. + Esta operación precisa o contrasinal do teu moedeiro para desencriptar o moedeiro. + + + + Decrypt wallet + Desencriptar moedeiro + + + + Change passphrase + Cambiar contrasinal + + + + Enter the old and new passphrase to the wallet. + Introduce o vello e novo contrasinais no moedeiro. + + + + Confirm wallet encryption + Confirmar encriptación de moedeiro + + + + Warning: If you encrypt your wallet and lose your passphrase, you will <b>LOSE ALL OF YOUR COINS</b>! + Coidado: Se enctriptas a tua carteira e perdes o contrasinal, <b>PERDERÁS TODAS AS TÚAS MOEDAS</b>! + + + + Are you sure you wish to encrypt your wallet? + Estás seguro de que desexas encriptar o teu moedeiro? + + + + IMPORTANT: Any previous backups you have made of your wallet file should be replaced with the newly generated, encrypted wallet file. For security reasons, previous backups of the unencrypted wallet file will become useless as soon as you start using the new, encrypted wallet. + IMPORTANTE: Calquera copia de seguridade previa que fixeses do teu arquivo de moedeiro debería ser substituída polo recén xerado arquivo encriptado de moedeiro. Por razóns de seguridade, as copias de seguridade previas de un arquivo de moedeiro desencriptado tornaránse inútiles no momento no que comeces a emprega-lo novo, encriptado, moedeiro. + + + + + Warning: The Caps Lock key is on! + Precaución: A tecla de Bloqueo de Maiúsculas está activada! + + + + + Wallet encrypted + Moedeiro encriptado + + + + Arepacoin will close now to finish the encryption process. Remember that encrypting your wallet cannot fully protect your coins from being stolen by malware infecting your computer. + Arepacoin pecharase agora para rematar o proceso de encriptación. Recorda que encriptar a túa carteira non te protexe na totalidade do roubo das tuas moedas por infeccións de malware no teu ordenador. + + + + + + + Wallet encryption failed + Encriptación de moedeiro fallida + + + + Wallet encryption failed due to an internal error. Your wallet was not encrypted. + A encriptación do moedeiro fallou por mor dun erro interno. O teu moedeiro non foi encriptado. + + + + + The supplied passphrases do not match. + Os contrasinais suministrados non coinciden. + + + + Wallet unlock failed + Desbloqueo de moedeiro fallido + + + + + + The passphrase entered for the wallet decryption was incorrect. + O contrasinal introducido para a desencriptación do moedeiro foi incorrecto. + + + + Wallet decryption failed + Desencriptación de moedeiro fallida + + + + Wallet passphrase was successfully changed. + Cambiouse con éxito o contrasinal do moedeiro. + + + + BitcoinGUI + + + Sign &message... + &Asinar mensaxe... + + + + Synchronizing with network... + Sincronizando coa rede... + + + + &Overview + &Vista xeral + + + + Show general overview of wallet + Amosar vista xeral do moedeiro + + + + &Transactions + &Transacciones + + + + Browse transaction history + Navegar historial de transaccións + + + + &Address Book + &Libreta de Direccións + + + + Edit the list of stored addresses and labels + Edita a lista de direccións e etiquetas almaceadas + + + + &Receive coins + &Recibe moedas + + + + Show the list of addresses for receiving payments + Amosa a lista de dirección para recibir os pagos + + + + &Send coins + &Enviar moedas + + + + E&xit + &Saír + + + + Quit application + Saír da aplicación + + + + Show information about Arepacoin + Amosa información sobre Arepacoin + + + + About &Qt + Acerca de &Qt + + + + Show information about Qt + Amosar información acerca de Qt + + + + &Options... + &Opcións... + + + + &Encrypt Wallet... + &Encriptar Moedeiro... + + + + &Backup Wallet... + Copia de &Seguridade do Moedeiro... + + + + &Change Passphrase... + &Cambiar contrasinal... + + + + ~%n block(s) remaining + ~%n bloque restante~%n bloques restantes + + + + Downloaded %1 of %2 blocks of transaction history (%3% done). + Descargado %1 de %2 bloques de historial de transaccións (%3% feito). + + + + &Export... + &Exportar... + + + + Send coins to a Arepacoin address + Enviar moedas a unha dirección Arepacoin + + + + Modify configuration options for Arepacoin + Modificar opcións de configuración para Arepacoin + + + + Export the data in the current tab to a file + Exportar datos da pestana actual a un arquivo + + + + Encrypt or decrypt wallet + Encriptar ou desencriptar carteira + + + + Backup wallet to another location + Facer copia de seguridade do moedeiro noutra localización + + + + Change the passphrase used for wallet encryption + Cambiar o contrasinal empregado para a encriptación do moedeiro + + + + &Debug window + Ventana de &Depuración + + + + Open debugging and diagnostic console + Abrir consola de depuración e diagnóstico + + + + &Verify message... + &Verificar mensaxe... + + + + Arepacoin + Arepacoin + + + + Wallet + Moedeiro + + + + &About Arepacoin + &Sobre Arepacoin + + + + &Show / Hide + &Amosar/Agachar + + + + Unlock wallet + Desbloquear carteira + + + + &Lock Wallet + &Bloquear Carteira + + + + Lock wallet + Bloquear carteira + + + + &File + &Arquivo + + + + &Settings + Axus&tes + + + + &Help + A&xuda + + + + Tabs toolbar + Barra de ferramentas + + + + Actions toolbar + + + + + + [testnet] + [testnet] + + + + + Arepacoin client + Cliente Arepacoin + + + + %n active connection(s) to Arepacoin network + %n conexión activa á red de Arepacoin%n conexións activas á red de Arepacoin + + + + Downloaded %1 blocks of transaction history. + Descargados %1 bloques do historial de transaccións. + + + + Staking.<br>Your weight is %1<br>Network weight is %2<br>Expected time to earn reward is %3 + "Staking".<br>O teu peso na rede é %1<br>O peso da rede é %2<br>Tempo esperado para gañar a recompensa %3 + + + + Not staking because wallet is locked + Non "staking" porque a carteira está bloqueada + + + + Not staking because wallet is offline + Non "staking" porque a carteira está sen conexión + + + + Not staking because wallet is syncing + Non "staking" porque a carteira está a sincronizar. + + + + Not staking because you don't have mature coins + Non "staking" porque non tes moedas maduras + + + + %n second(s) ago + Fai %n segundoFai %n segundos + + + + &Unlock Wallet... + &Desbloquear Carteira... + + + + %n minute(s) ago + Fai %n minutoFai %n minutos + + + + %n hour(s) ago + Fai %n horaFai %n horas + + + + %n day(s) ago + Fai %n díaFai %n días + + + + Up to date + Actualizado + + + + Catching up... + Poñendo ao día... + + + + Last received block was generated %1. + Último bloque recibido foi generado %1. + + + + This transaction is over the size limit. You can still send it for a fee of %1, which goes to the nodes that process your transaction and helps to support the network. Do you want to pay the fee? + + + + + Confirm transaction fee + Confirmar cuota da transacción + + + + Sent transaction + Transacción enviada + + + + Incoming transaction + Transacción entrante + + + + Date: %1 +Amount: %2 +Type: %3 +Address: %4 + + Data: %1 +Cantidade: %2 +Tipo: %3 +Dirección: %4 + + + + + + URI handling + + + + + + URI can not be parsed! This can be caused by an invalid Arepacoin address or malformed URI parameters. + + + + + Wallet is <b>encrypted</b> and currently <b>unlocked</b> + O moedeiro está <b>encriptado</b> e actualmente <b>desbloqueado</b> + + + + Wallet is <b>encrypted</b> and currently <b>locked</b> + O moedeiro está <b>encriptado</b> e actualmente <b>bloqueado</b> + + + + Backup Wallet + + + + + Wallet Data (*.dat) + + + + + Backup Failed + + + + + There was an error trying to save the wallet data to the new location. + + + + + %n second(s) + + + + + %n minute(s) + + + + + %n hour(s) + %n hora%n horas + + + + %n day(s) + %n día%n días + + + + Not staking + Non "staking" + + + + A fatal error occurred. Arepacoin can no longer continue safely and will quit. + + + + + ClientModel + + + Network Alert + Alerta de Rede + + + + CoinControlDialog + + + Coin Control + + + + + Quantity: + Cantidade: + + + + Bytes: + Bytes: + + + + Amount: + Importe: + + + + Priority: + Prioridade: + + + + Fee: + Pago: + + + + Low Output: + + + + + no + non + + + + After Fee: + + + + + Change: + Cambiar: + + + + (un)select all + (des)selecciona todo + + + + Tree mode + Modo árbore + + + + List mode + Modo lista + + + + Amount + Cantidade + + + + Label + + + + + Address + Dirección + + + + Date + Data + + + + Confirmations + Confirmacións + + + + Confirmed + Confirmado + + + + Priority + Prioridade + + + + Copy address + Copiar dirección + + + + Copy label + Copiar etiqueta + + + + + Copy amount + Copiar cantidade + + + + Copy transaction ID + Copiar ID de transacción + + + + Copy quantity + Copiar cantidade + + + + Copy fee + Copiar pago + + + + Copy after fee + Copiar despóis do pago + + + + Copy bytes + Copiar bytes + + + + Copy priority + Copiar prioridade + + + + Copy low output + + + + + Copy change + Copiar cambio + + + + highest + O máis alto + + + + high + alto + + + + medium-high + medio-alto + + + + medium + + + + + low-medium + medio-baixo + + + + low + baixo + + + + lowest + o máis baixo + + + + DUST + + + + + yes + Si + + + + This label turns red, if the transaction size is bigger than 10000 bytes. + + This means a fee of at least %1 per kb is required. + + Can vary +/- 1 Byte per input. + + + + + Transactions with higher priority get more likely into a block. + +This label turns red, if the priority is smaller than "medium". + + This means a fee of at least %1 per kb is required. + + + + + This label turns red, if any recipient receives an amount smaller than %1. + + This means a fee of at least %2 is required. + + Amounts below 0.546 times the minimum relay fee are shown as DUST. + + + + + This label turns red, if the change is smaller than %1. + + This means a fee of at least %2 is required. + + + + + + (no label) + (sen etiqueta) + + + + change from %1 (%2) + + + + + (change) + (cambio) + + + + EditAddressDialog + + + Edit Address + Modificar Dirección + + + + &Label + &Etiqueta + + + + The label associated with this address book entry + + + + + &Address + &Dirección + + + + The address associated with this address book entry. This can only be modified for sending addresses. + + + + + New receiving address + Nova dirección para recibir + + + + New sending address + Nova dirección para enviar + + + + Edit receiving address + Modificar dirección para recibir + + + + Edit sending address + Modificar dirección para enviar + + + + The entered address "%1" is already in the address book. + A dirección introducida "%1" xa está no libro de direccións. + + + + The entered address "%1" is not a valid Arepacoin address. + + + + + Could not unlock wallet. + Non se puido desbloquear o moedeiro. + + + + New key generation failed. + A xeración de nova clave fallou. + + + + GUIUtil::HelpMessageBox + + + + Arepacoin-Qt + Arepacoin-Qt + + + + version + + + + + Usage: + + + + + command-line options + + + + + UI options + Opcións UI + + + + Set language, for example "de_DE" (default: system locale) + + + + + Start minimized + Comezar minimizado + + + + Show splash screen on startup (default: 1) + + + + + OptionsDialog + + + Options + Opcións + + + + &Main + &Principal + + + + Optional transaction fee per kB that helps make sure your transactions are processed quickly. Most transactions are 1 kB. Fee 0.01 recommended. + + + + + Pay transaction &fee + Pagar &tarifa da transacción + + + + Reserved amount does not participate in staking and is therefore spendable at any time. + + + + + Reserve + Reserva + + + + Automatically start Arepacoin after logging in to the system. + + + + + &Start Arepacoin on system login + + + + + Detach block and address databases at shutdown. This means they can be moved to another data directory, but it slows down shutdown. The wallet is always detached. + + + + + &Detach databases at shutdown + + + + + &Network + &Rede + + + + Automatically open the Arepacoin client port on the router. This only works when your router supports UPnP and it is enabled. + + + + + Map port using &UPnP + Mapear porto empregando &UPnP + + + + Connect to the Arepacoin network through a SOCKS proxy (e.g. when connecting through Tor). + + + + + &Connect through SOCKS proxy: + + + + + Proxy &IP: + &IP do Proxy: + + + + IP address of the proxy (e.g. 127.0.0.1) + + + + + &Port: + &Porto: + + + + Port of the proxy (e.g. 9050) + Porto do proxy (exemplo: 9050) + + + + SOCKS &Version: + &Version de SOCKS: + + + + SOCKS version of the proxy (e.g. 5) + Versión SOCKS del proxy (exemplo: 5) + + + + &Window + &Xanela + + + + Show only a tray icon after minimizing the window. + Amosar so un icono na bandexa tras minimiza-la xanela. + + + + &Minimize to the tray instead of the taskbar + &Minimizar á bandexa en lugar de á barra de tarefas. + + + + Minimize instead of exit the application when the window is closed. When this option is enabled, the application will be closed only after selecting Quit in the menu. + Minimizar en lugar de saír da aplicación cando se pecha a xanela. Cando se habilita esta opción, a aplicación so se pechará tras seleccionar Saír no menú. + + + + M&inimize on close + M&inimizar ao pechar + + + + &Display + &Visualización + + + + User Interface &language: + &Linguaxe de interface de usuario: + + + + The user interface language can be set here. This setting will take effect after restarting Arepacoin. + + + + + &Unit to show amounts in: + &Unidade na que amosar as cantidades: + + + + Choose the default subdivision unit to show in the interface and when sending coins. + Escolle a unidade de subdivisión por defecto para amosar na interface e ao enviar moedas. + + + + Whether to show Arepacoin addresses in the transaction list or not. + + + + + &Display addresses in transaction list + &Visualizar direccións na listaxe de transaccións + + + + Whether to show coin control features or not. + + + + + Display coin &control features (experts only!) + + + + + &OK + &OK + + + + &Cancel + &Cancelar + + + + &Apply + + + + + default + por defecto + + + + + Warning + + + + + + This setting will take effect after restarting Arepacoin. + + + + + The supplied proxy address is invalid. + A dirección de proxy suministrada é inválida. + + + + OverviewPage + + + Form + Formulario + + + + + The displayed information may be out of date. Your wallet automatically synchronizes with the Arepacoin network after a connection is established, but this process has not completed yet. + + + + + Stake: + + + + + Unconfirmed: + Sen confirmar: + + + + Wallet + Moedeiro + + + + Spendable: + + + + + Your current spendable balance + O teu balance actualmente dispoñible + + + + Immature: + Inmaduro: + + + + Mined balance that has not yet matured + O balance minado todavía non madurou + + + + Total: + Total: + + + + Your current total balance + O teu balance actual total + + + + <b>Recent transactions</b> + <b>Transaccións recentes</b> + + + + Total of transactions that have yet to be confirmed, and do not yet count toward the current balance + + + + + Total of coins that was staked, and do not yet count toward the current balance + + + + + + out of sync + non sincronizado + + + + QRCodeDialog + + + QR Code Dialog + + + + + Request Payment + + + + + Amount: + + + + + Label: + + + + + Message: + + + + + &Save As... + + + + + Error encoding URI into QR Code. + + + + + The entered amount is invalid, please check. + + + + + Resulting URI too long, try to reduce the text for label / message. + + + + + Save QR Code + + + + + PNG Images (*.png) + + + + + RPCConsole + + + Client name + Nome do cliente + + + + + + + + + + + + + N/A + N/A + + + + Client version + Versión do cliente + + + + &Information + &Información + + + + Using OpenSSL version + Usar versión OpenSSL + + + + Startup time + Tempo de arranque + + + + Network + Rede + + + + Number of connections + Número de conexións + + + + On testnet + + + + + Block chain + Cadea de bloques + + + + Current number of blocks + Número actual de bloques + + + + Estimated total blocks + Bloques totais estimados + + + + Last block time + Hora do último bloque + + + + &Open + &Abrir + + + + Command-line options + + + + + Show the Arepacoin-Qt help message to get a list with possible Arepacoin command-line options. + + + + + &Show + + + + + &Console + &Consola + + + + Build date + Data de construción + + + + Arepacoin - Debug window + + + + + Arepacoin Core + + + + + Debug log file + Arquivo de log de depuración + + + + Open the Arepacoin debug log file from the current data directory. This can take a few seconds for large log files. + + + + + Clear console + Limpar consola + + + + Welcome to the Arepacoin RPC console. + + + + + Use up and down arrows to navigate history, and <b>Ctrl-L</b> to clear screen. + Emprega as flechas arriba e abaixo para navegar polo historial, e <b>Ctrl-L</b> para limpar a pantalla. + + + + Type <b>help</b> for an overview of available commands. + Escribe <b>axuda</b> para unha vista xeral dos comandos dispoñibles. + + + + SendCoinsDialog + + + + + + + + + + Send Coins + Moedas Enviadas + + + + Coin Control Features + + + + + Inputs... + + + + + automatically selected + + + + + Insufficient funds! + + + + + Quantity: + Cantidade: + + + + + 0 + + + + + Bytes: + Bytes: + + + + Amount: + Importe: + + + + + + + 0.00 BC + + + + + Priority: + Prioridade: + + + + medium + + + + + Fee: + Pago: + + + + Low Output: + + + + + no + + + + + After Fee: + + + + + Change + + + + + custom change address + + + + + Send to multiple recipients at once + Enviar a múltiples receptores á vez + + + + Add &Recipient + Engadir &Receptor + + + + Remove all transaction fields + + + + + Clear &All + Limpar &Todo + + + + Balance: + Balance: + + + + 123.456 BC + + + + + Confirm the send action + Confirmar a acción de envío + + + + S&end + &Enviar + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Copy quantity + Copiar cantidade + + + + Copy amount + Copiar cantidade + + + + Copy fee + Copiar pago + + + + Copy after fee + Copiar despóis do pago + + + + Copy bytes + Copiar bytes + + + + Copy priority + Copiar prioridade + + + + Copy low output + + + + + Copy change + Copiar cambio + + + + <b>%1</b> to %2 (%3) + + + + + Confirm send coins + Confirmar envío de moedas + + + + Are you sure you want to send %1? + + + + + and + + + + + The recipient address is not valid, please recheck. + A dirección de recepción non é válida, por favor compróbea. + + + + The amount to pay must be larger than 0. + A cantidade a pagar debe ser maior que 0. + + + + The amount exceeds your balance. + A cantidade sobrepasa o teu balance. + + + + The total exceeds your balance when the %1 transaction fee is included. + O total sobrepasa o teu balance cando se inclúe a tarifa de transacción %1. + + + + Duplicate address found, can only send to each address once per send operation. + Atopouse dirección duplicada, so se pode enviar a cada dirección unha vez por operación. + + + + Error: Transaction creation failed. + + + + + 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. + + + + + WARNING: Invalid Arepacoin address + + + + + (no label) + (sen etiqueta) + + + + WARNING: unknown change address + + + + + SendCoinsEntry + + + Form + + + + + A&mount: + &Cantidade: + + + + Pay &To: + Pagar &A: + + + + + Enter a label for this address to add it to your address book + Introduce unha etiqueta para esta dirección para engadila ao teu libro de direccións + + + + &Label: + &Etiqueta: + + + + The address to send the payment to (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Choose address from address book + + + + + Alt+A + Alt+A + + + + Paste address from clipboard + Pegar dirección dende portapapeis + + + + Alt+P + Alt+P + + + + Remove this recipient + + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + SignVerifyMessageDialog + + + Signatures - Sign / Verify a Message + Sinaturas - Asinar / Verificar unha Mensaxe + + + + + &Sign Message + &Asinar Mensaxe + + + + You can sign messages with your addresses to prove you own them. Be careful not to sign anything vague, as phishing attacks may try to trick you into signing your identity over to them. Only sign fully-detailed statements you agree to. + Podes asinar mensaxes coas túas direccións para probar que ti as posees. Ten conta de non asinar nada vago, xa que hai ataques de phishing que tentarán que asines coa túa identidade por riba deles. Asina únicamente declaracións totalmente detalladas coas que esteas de acordo. + + + + The address to sign the message with (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + + Choose an address from the address book + + + + + + Alt+A + Alt+A + + + + Paste address from clipboard + Pegar dirección dende portapapeis + + + + Alt+P + Alt+P + + + + Enter the message you want to sign here + Introduce a mensaxe que queres asinar aquí + + + + Copy the current signature to the system clipboard + Copiar a sinatura actual ao portapapeis do sistema + + + + Sign the message to prove you own this Arepacoin address + + + + + Reset all sign message fields + Restaurar todos os campos de sinatura de mensaxe + + + + + Clear &All + Limpar &Todo + + + + + &Verify Message + &Verificar Mensaxe + + + + Enter the signing address, message (ensure you copy line breaks, spaces, tabs, etc. exactly) and signature below to verify the message. Be careful not to read more into the signature than what is in the signed message itself, to avoid being tricked by a man-in-the-middle attack. + Introduce a dirección coa que asinar, a mensaxe (asegúrate de copiar exactamente os saltos de liña, espacios, tabulacións, etc.) e a sinatura debaixo para verificar a mensaxe. Ten coidado de non ler máis na sinatura do que hai no mensaxe asinado mesmo, a fin de evitar ser cazado nun ataque de home no medio. + + + + The address the message was signed with (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Verify the message to ensure it was signed with the specified Arepacoin address + + + + + Reset all verify message fields + Restaurar todos os campos de verificación de mensaxe + + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Click "Sign Message" to generate signature + Click en "Asinar Mensaxe" para xerar sinatura + + + + Enter Arepacoin signature + + + + + + The entered address is invalid. + A dirección introducida é inválida. + + + + + + + Please check the address and try again. + Por favor comproba a dirección e proba de novo. + + + + + The entered address does not refer to a key. + A dirección introducida non se refire a ninguna clave. + + + + Wallet unlock was cancelled. + Cancelouse o desbloqueo do moedeiro. + + + + Private key for the entered address is not available. + A clave privada da dirección introducida non está dispoñible. + + + + Message signing failed. + Fallou a sinatura da mensaxe. + + + + Message signed. + Mensaxe asinada. + + + + The signature could not be decoded. + A sinatura non puido ser decodificada. + + + + + Please check the signature and try again. + Por favor revise a sinatura e probe de novo. + + + + The signature did not match the message digest. + A sinatura non coincide co resumo da mensaxe. + + + + Message verification failed. + A verificación da mensaxe fallou. + + + + Message verified. + Mensaxe verificada. + + + + TransactionDesc + + + Open until %1 + Aberto ata %1 + + + + Open for %n block(s) + + + + + conflicted + + + + + %1/offline + %1/fóra de liña + + + + %1/unconfirmed + %1/sen confirmar + + + + %1 confirmations + %1 confirmacións + + + + Status + Estado + + + + , broadcast through %n node(s) + , propagado a % nodo, propagado a % nodos + + + + Date + Data + + + + Source + Orixe + + + + Generated + Xerado + + + + + From + Dende + + + + + + To + A + + + + + own address + dirección propia + + + + label + etiqueta + + + + + + + + Credit + Crédito + + + + matures in %n more block(s) + madura nun bloque máismadura en %n bloques máis + + + + not accepted + non aceptado + + + + + + + Debit + Débito + + + + Transaction fee + Tarifa de transacción + + + + Net amount + Cantidade neta + + + + Message + Mensaxe + + + + Comment + Comentario + + + + Transaction ID + ID de Transacción + + + + Generated coins must mature 6 blocks before they can be spent. When you generated this block, it was broadcast to the network to be added to the block chain. If it fails to get into the chain, its state will change to "not accepted" and it won't be spendable. This may occasionally happen if another node generates a block within a few seconds of yours. + + + + + Debug information + Información de depuración + + + + Transaction + Transacción + + + + Inputs + Entradas + + + + Amount + Cantidade + + + + true + verdadeiro + + + + false + falso + + + + , has not been successfully broadcast yet + , non foi propagado con éxito todavía + + + + unknown + descoñecido + + + + TransactionDescDialog + + + Transaction details + Detalles de transacción + + + + This pane shows a detailed description of the transaction + Este panel amosa unha descripción detallada da transacción + + + + TransactionTableModel + + + Date + Data + + + + Type + Tipo + + + + Address + Dirección + + + + Amount + Cantidade + + + + Open until %1 + Aberto ata %1 + + + + Confirmed (%1 confirmations) + Confirmado (%1 confirmacións) + + + + Open for %n more block(s) + Abrir para %n bloque máisAbrir para %n bloques máis + + + + Offline + + + + + Unconfirmed + + + + + Confirming (%1 of %2 recommended confirmations) + + + + + Conflicted + + + + + Immature (%1 confirmations, will be available after %2) + + + + + This block was not received by any other nodes and will probably not be accepted! + Este bloque non foi recibido por ningún outro nodo e probablemente non será aceptado! + + + + Generated but not accepted + Xerado pero non aceptado + + + + Received with + Recibido con + + + + Received from + Recibido de + + + + Sent to + Enviado a + + + + Payment to yourself + Pago a ti mesmo + + + + Mined + Minado + + + + (n/a) + (n/a) + + + + Transaction status. Hover over this field to show number of confirmations. + Estado da transacción. Pasa por riba deste campo para amosar o número de confirmacións. + + + + Date and time that the transaction was received. + Data e hora na que foi recibida a transacción. + + + + Type of transaction. + Tipo de transacción. + + + + Destination address of transaction. + Dirección de destino da transacción. + + + + Amount removed from or added to balance. + Cantidade borrada ou engadida no balance. + + + + TransactionView + + + + All + Todo + + + + Today + Hoxe + + + + This week + Esta semana + + + + This month + Este mes + + + + Last month + O último mes + + + + This year + Este ano + + + + Range... + Periodo... + + + + Received with + Recibido con + + + + Sent to + Enviado a + + + + To yourself + A ti mesmo + + + + Mined + Minado + + + + Other + Outro + + + + Enter address or label to search + Introduce dirección ou etiqueta para buscar + + + + Min amount + Cantidade mínima + + + + Copy address + Copiar dirección + + + + Copy label + Copiar etiqueta + + + + Copy amount + Copiar cantidade + + + + Copy transaction ID + Copiar ID de transacción + + + + Edit label + Modificar etiqueta + + + + Show transaction details + Amosar detalles da transacción + + + + Export Transaction Data + + + + + Comma separated file (*.csv) + Arquivo separado por comas (*.csv) + + + + Confirmed + Confirmado + + + + Date + Data + + + + Type + Tipo + + + + Label + Etiqueta + + + + Address + Dirección + + + + Amount + Cantidade + + + + ID + ID + + + + Error exporting + + + + + Could not write to file %1. + + + + + Range: + Periodo: + + + + to + a + + + + WalletModel + + + Sending... + + + + + bitcoin-core + + + Arepacoin version + + + + + Usage: + Emprego: + + + + Send command to -server or arepacoind + + + + + List commands + Listar comandos + + + + Get help for a command + Obter axuda para un comando + + + + Options: + Opcións: + + + + Specify configuration file (default: arepacoin.conf) + + + + + Specify pid file (default: arepacoind.pid) + + + + + Specify wallet file (within data directory) + Especificar arquivo do moedeiro (dentro do directorio de datos) + + + + Specify data directory + Especificar directorio de datos + + + + Set database cache size in megabytes (default: 25) + Fixar tamaño da caché da base de datos en megabytes (por defecto: 25) + + + + Set database disk log size in megabytes (default: 100) + + + + + Listen for connections on <port> (default: 9853 or testnet: 19853) + + + + + Maintain at most <n> connections to peers (default: 125) + Manter como moito <n> conexións con pares (por defecto: 125) + + + + Connect to a node to retrieve peer addresses, and disconnect + Conectar a nodo para recuperar direccións de pares, e desconectar + + + + Specify your own public address + Especificar a túa propia dirección pública + + + + Bind to given address. Use [host]:port notation for IPv6 + + + + + Stake your coins to support network and gain reward (default: 1) + + + + + Threshold for disconnecting misbehaving peers (default: 100) + Umbral para desconectar pares con mal comportamento (por defecto: 100) + + + + Number of seconds to keep misbehaving peers from reconnecting (default: 86400) + Número de segundos para manter sen reconectar aos pares con mal comportamento (por defecto: 86400) + + + + An error occurred while setting up the RPC port %u for listening on IPv4: %s + Ocorreu un erro mentres se establecía o porto RPC %u para escoitar sobre IPv4: %s + + + + Detach block and address databases. Increases shutdown time (default: 0) + + + + + 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. + + + + + Error: This transaction requires a transaction fee of at least %s because of its amount, complexity, or use of recently received funds + + + + + Listen for JSON-RPC connections on <port> (default: 9852 or testnet: 19852) + + + + + Accept command line and JSON-RPC commands + Aceptar liña de comandos e comandos JSON-RPC + + + + Error: Transaction creation failed + + + + + Error: Wallet locked, unable to create transaction + + + + + Importing blockchain data file. + + + + + Importing bootstrap blockchain data file. + + + + + Run in the background as a daemon and accept commands + Executar no fondo como un demo e aceptar comandos + + + + Use the test network + Empregar a rede de proba + + + + Accept connections from outside (default: 1 if no -proxy or -connect) + Aceptar conexións de fóra (por defecto: 1 se non -proxy ou -connect) + + + + An error occurred while setting up the RPC port %u for listening on IPv6, falling back to IPv4: %s + Ocorreu un erro mentres se establecía o porto RPC %u para escoitar sobre IPv6, voltando a IPv4: %s + + + + Error initializing database environment %s! To recover, BACKUP THAT DIRECTORY, then remove everything from it except for wallet.dat. + + + + + Set maximum size of high-priority/low-fee transactions in bytes (default: 27000) + + + + + Warning: -paytxfee is set very high! This is the transaction fee you will pay if you send a transaction. + Precaución: -paytxfee está posto moi algo! Esta é a tarifa de transacción que ti pagarás se envías unha transacción. + + + + Warning: Please check that your computer's date and time are correct! If your clock is wrong Arepacoin will not work properly. + + + + + Warning: error reading wallet.dat! All keys read correctly, but transaction data or address book entries might be missing or incorrect. + Precaución: erro lendo wallet.dat! Tódalas claves lidas correctamente, pero os datos de transacción ou as entradas do libro de direccións podrían estar ausentes ou incorrectos. + + + + Warning: wallet.dat corrupt, data salvaged! Original wallet.dat saved as wallet.{timestamp}.bak in %s; if your balance or transactions are incorrect you should restore from a backup. + Precaución: wallet.dat corrupto, datos salvagardados! O wallet.dat orixinal foi gardado como wallet.{timestamp}.bak en %s; se o teu balance ou transaccións son incorrectas deberías restauralas dende unha copia de seguridade. + + + + Attempt to recover private keys from a corrupt wallet.dat + Tentar recuperar claves privadas dende un wallet.dat corrupto + + + + Block creation options: + Opcións de creación de bloque: + + + + Connect only to the specified node(s) + Conectar so ao(s) nodo(s) especificado(s) + + + + Discover own IP address (default: 1 when listening and no -externalip) + Descobrir dirección IP propia (por defecto: 1 se á escoita e non -externalip) + + + + Failed to listen on any port. Use -listen=0 if you want this. + Fallou escoitar en calquera porto. Emprega -listen=0 se queres esto. + + + + Find peers using DNS lookup (default: 1) + + + + + Sync checkpoints policy (default: strict) + + + + + Invalid -tor address: '%s' + + + + + Invalid amount for -reservebalance=<amount> + + + + + Maximum per-connection receive buffer, <n>*1000 bytes (default: 5000) + Máximo buffer por-conexión para recibir, <n>*1000 bytes (por defecto: 5000) + + + + Maximum per-connection send buffer, <n>*1000 bytes (default: 1000) + Máximo buffer por-conexión para enviar, <n>*1000 bytes (por defecto: 1000) + + + + Only connect to nodes in network <net> (IPv4, IPv6 or Tor) + Conectar so a nodos na rede <net> (IPv4, IPv6 ou Tor) + + + + Output extra debugging information. Implies all other -debug* options + + + + + Output extra network debugging information + + + + + Prepend debug output with timestamp + + + + + SSL options: (see the Bitcoin Wiki for SSL setup instructions) + Opcións SSL: (ver ńa Wiki Bitcoin as instrucción de configuración de SSL) + + + + Select the version of socks proxy to use (4-5, default: 5) + + + + + Send trace/debug info to console instead of debug.log file + Enviar traza/información de depuración á consola en lugar de ao arquivo debug.log + + + + Send trace/debug info to debugger + + + + + Set maximum block size in bytes (default: 250000) + + + + + Set minimum block size in bytes (default: 0) + Fixar tamaño mínimo de bloque en bytes (por defecto: 0) + + + + Shrink debug.log file on client startup (default: 1 when no -debug) + Recortar o arquivo debug.log ao arrancar o cliente (por defecto: 1 cando no-debug) + + + + Specify connection timeout in milliseconds (default: 5000) + Especificar tempo límite da conexión en milisegundos (por defecto: 5000) + + + + Unable to sign checkpoint, wrong checkpointkey? + + + + + + Use UPnP to map the listening port (default: 0) + Usar UPnP para mapear o porto de escoita (por defecto: 0) + + + + Use UPnP to map the listening port (default: 1 when listening) + Usar UPnP para mapear o porto de escoita (por defecto: 1 se á escoita) + + + + Use proxy to reach tor hidden services (default: same as -proxy) + + + + + Username for JSON-RPC connections + Nome de usuario para conexións JSON-RPC + + + + Verifying database integrity... + + + + + WARNING: syncronized checkpoint violation detected, but skipped! + + + + + Warning: Disk space is low! + + + + + Warning: This version is obsolete, upgrade required! + Precaución: Esta versión é obsoleta, precísase unha actualización! + + + + wallet.dat corrupt, salvage failed + wallet.dat corrupto, fallou o gardado + + + + Password for JSON-RPC connections + Contrasinal para conexións JSON-RPC + + + + %s, you must set a rpcpassword in the configuration file: + %s +It is recommended you use the following random password: +rpcuser=arepacoinrpc +rpcpassword=%s +(you do not need to remember this password) +The username and password MUST NOT be the same. +If the file does not exist, create it with owner-readable-only file permissions. +It is also recommended to set alertnotify so you are notified of problems; +for example: alertnotify=echo %%s | mail -s "Arepacoin Alert" admin@foo.com + + + + + + Find peers using internet relay chat (default: 0) + + + + + Sync time with other nodes. Disable if time on your system is precise e.g. syncing with NTP (default: 1) + + + + + When creating transactions, ignore inputs with value less than this (default: 0.01) + + + + + Allow JSON-RPC connections from specified IP address + Permitir conexións JSON-RPC dende direccións IP especificadas + + + + Send commands to node running on <ip> (default: 127.0.0.1) + Enviar comandos a nodo executando na <ip> (por defecto: 127.0.0.1) + + + + Execute command when the best block changes (%s in cmd is replaced by block hash) + Executar comando cando o mellor bloque cambie (%s no comando é sustituído polo hash do bloque) + + + + Execute command when a wallet transaction changes (%s in cmd is replaced by TxID) + Executar comando cando unha transacción do moedeiro cambia (%s no comando é substituído por TxID) + + + + Require a confirmations for change (default: 0) + + + + + Enforce transaction scripts to use canonical PUSH operators (default: 1) + + + + + Execute command when a relevant alert is received (%s in cmd is replaced by message) + + + + + Upgrade wallet to latest format + Actualizar moedeiro ao formato máis recente + + + + Set key pool size to <n> (default: 100) + Fixar tamaño do pool de claves a <n> (por defecto: 100) + + + + Rescan the block chain for missing wallet transactions + Rescanear transaccións ausentes na cadea de bloques + + + + How many blocks to check at startup (default: 2500, 0 = all) + + + + + How thorough the block verification is (0-6, default: 1) + + + + + Imports blocks from external blk000?.dat file + + + + + Use OpenSSL (https) for JSON-RPC connections + Empregar OpenSSL (https) para conexións JSON-RPC + + + + Server certificate file (default: server.cert) + Arquivo de certificado do servidor (por defecto: server.cert) + + + + Server private key (default: server.pem) + Clave privada do servidor (por defecto: server.perm) + + + + Acceptable ciphers (default: TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH) + + + + + Error: Wallet unlocked for staking only, unable to create transaction. + + + + + WARNING: Invalid checkpoint found! Displayed transactions may not be correct! You may need to upgrade, or notify developers. + + + + + This help message + Esta mensaxe de axuda + + + + Wallet %s resides outside data directory %s. + + + + + Cannot obtain a lock on data directory %s. Arepacoin is probably already running. + + + + + Arepacoin + + + + + Unable to bind to %s on this computer (bind returned error %d, %s) + Imposible enlazar con %s neste ordenador (enlace devolveu erro %d, %s) + + + + Connect through socks proxy + + + + + Allow DNS lookups for -addnode, -seednode and -connect + Permitir lookup de DNS para -addnote, -seednote e -connect + + + + Loading addresses... + Cargando direccións... + + + + Error loading blkindex.dat + + + + + Error loading wallet.dat: Wallet corrupted + Erro cargando wallet.dat: Moedeiro corrupto + + + + Error loading wallet.dat: Wallet requires newer version of Arepacoin + + + + + Wallet needed to be rewritten: restart Arepacoin to complete + + + + + Error loading wallet.dat + Erro cargando wallet.dat + + + + Invalid -proxy address: '%s' + Dirección -proxy inválida: '%s' + + + + Unknown network specified in -onlynet: '%s' + Rede descoñecida especificada en -onlynet: '%s' + + + + Unknown -socks proxy version requested: %i + Versión solicitada de proxy -socks descoñecida: %i + + + + Cannot resolve -bind address: '%s' + Non se pode resolver a dirección -bind: '%s' + + + + Cannot resolve -externalip address: '%s' + Non se pode resolver dirección -externalip: '%s' + + + + Invalid amount for -paytxfee=<amount>: '%s' + Cantidade inválida para -paytxfee=<cantidade>: '%s' + + + + Error: could not start node + + + + + Sending... + + + + + Invalid amount + Cantidade inválida + + + + Insufficient funds + Fondos insuficientes + + + + Loading block index... + Cargando índice de bloques... + + + + Add a node to connect to and attempt to keep the connection open + Engadir un nodo ao que conectarse e tentar manter a conexión aberta + + + + Unable to bind to %s on this computer. Arepacoin is probably already running. + + + + + Fee per KB to add to transactions you send + + + + + Invalid amount for -mininput=<amount>: '%s' + + + + + Loading wallet... + Cargando moedeiro... + + + + Cannot downgrade wallet + Non se pode desactualizar o moedeiro + + + + Cannot initialize keypool + + + + + Cannot write default address + Non se pode escribir a dirección por defecto + + + + Rescanning... + Rescaneando... + + + + Done loading + Carga completa + + + + To use the %s option + Empregar a opción %s + + + + Error + Erro + + + + You must set rpcpassword=<password> in the configuration file: +%s +If the file does not exist, create it with owner-readable-only file permissions. + Debes fixar rpcpassword=<contrasinal> no arquivo de configuración: +%s +Se o arquivo non existe, debes crealo con permisos de so lectura para o propietario. + + + \ No newline at end of file diff --git a/src/qt/locale/bitcoin_he.ts b/src/qt/locale/bitcoin_he.ts new file mode 100755 index 0000000..42e1969 --- /dev/null +++ b/src/qt/locale/bitcoin_he.ts @@ -0,0 +1,3285 @@ + + + AboutDialog + + + About Arepacoin + + + + + <b>Arepacoin</b> version + + + + + Copyright © 2009-2014 The Bitcoin developers +Copyright © 2012-2014 The NovaCoin developers +Copyright © 2014 The Arepacoin developers + + + + + +This is experimental software. + +Distributed under the MIT/X11 software license, see the accompanying file COPYING or http://www.opensource.org/licenses/mit-license.php. + +This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit (http://www.openssl.org/) and cryptographic software written by Eric Young (eay@cryptsoft.com) and UPnP software written by Thomas Bernard. + +זוהי תוכנה ניסיונית. + +מופצת תחת רישיון התוכנה MIT/X11, ראה את הקובץ המצורף COPYING או http://www.opensource.org/licenses/mit-license.php. + +המוצר הזה כולל תוכנה שפותחה ע"י פרויקט OpenSSL לשימוש בתיבת הכלים OpenSSL (http://www.openssl.org/) ותוכנה קריפטוגרפית שנכתבה ע"י אריק יאנג (eay@cryptsoft.com) ותוכנת UPnP שנכתבה ע"י תומס ברנרד. + + + + AddressBookPage + + + Address Book + + + + + Double-click to edit address or label + לחץ לחיצה כפולה לערוך כתובת או תוית + + + + Create a new address + יצירת כתובת חדשה + + + + Copy the currently selected address to the system clipboard + העתק את הכתובת המסומנת ללוח העריכה + + + + &New Address + + + + + These are your Arepacoin addresses for receiving payments. You may want to give a different one to each sender so you can keep track of who is paying you. + + + + + &Copy Address + העתק כתובת + + + + Show &QR Code + + + + + Sign a message to prove you own a Arepacoin address + + + + + Sign &Message + + + + + Delete the currently selected address from the list + מחק את הכתובת שנבחרה מהרשימה + + + + Verify a message to ensure it was signed with a specified Arepacoin address + + + + + &Verify Message + + + + + &Delete + &מחק + + + + Copy &Label + העתק תוית + + + + &Edit + עריכה + + + + Export Address Book Data + + + + + Comma separated file (*.csv) + קובץ מופרד בפסיקים (*.csv) + + + + Error exporting + + + + + Could not write to file %1. + + + + + AddressTableModel + + + Label + תוית + + + + Address + כתובת + + + + (no label) + (ללא תוית) + + + + AskPassphraseDialog + + + Passphrase Dialog + שיח סיסמא + + + + Enter passphrase + הכנס סיסמה + + + + New passphrase + סיסמה חדשה + + + + Repeat new passphrase + חזור על הסיסמה החדשה + + + + Serves to disable the trivial sendmoney when OS account compromised. Provides no real security. + + + + + For staking only + + + + + Enter the new passphrase to the wallet.<br/>Please use a passphrase of <b>10 or more random characters</b>, or <b>eight or more words</b>. + הכנס את הסיסמה החדשה לארנק. <br/>אנא השתמש בסיסמה המכילה <b>10 תוים אקראיים או יותר</b>, או <b>שמונה מילים או יותר</b>. + + + + Encrypt wallet + הצפן ארנק + + + + This operation needs your wallet passphrase to unlock the wallet. + הפעולה הזו דורשת את סיסמת הארנק שלך בשביל לפתוח את הארנק. + + + + Unlock wallet + פתיחת ארנק + + + + This operation needs your wallet passphrase to decrypt the wallet. + הפעולה הזו דורשת את סיסמת הארנק שלך בשביל לפענח את הארנק. + + + + Decrypt wallet + פענוח ארנק + + + + Change passphrase + שינוי סיסמה + + + + Enter the old and new passphrase to the wallet. + הכנס את הסיסמות הישנה והחדשה לארנק. + + + + Confirm wallet encryption + אשר הצפנת ארנק + + + + Warning: If you encrypt your wallet and lose your passphrase, you will <b>LOSE ALL OF YOUR COINS</b>! + + + + + Are you sure you wish to encrypt your wallet? + האם אתה בטוח שברצונך להצפין את הארנק? + + + + IMPORTANT: Any previous backups you have made of your wallet file should be replaced with the newly generated, encrypted wallet file. For security reasons, previous backups of the unencrypted wallet file will become useless as soon as you start using the new, encrypted wallet. + חשוב! כל גיבוי קודם שעשית לארנק שלך יש להחליף עם קובץ הארנק המוצפן שזה עתה נוצר. מסיבות אבטחה, גיבויים קודמים של קובץ הארנק הלא-מוצפן יהפכו לחסרי שימוש ברגע שתתחיל להשתמש בארנק החדש המוצפן. + + + + + Warning: The Caps Lock key is on! + זהירות: מקש Caps Lock מופעל! + + + + + Wallet encrypted + הארנק הוצפן + + + + Arepacoin will close now to finish the encryption process. Remember that encrypting your wallet cannot fully protect your coins from being stolen by malware infecting your computer. + + + + + + + + Wallet encryption failed + הצפנת הארנק נכשלה + + + + Wallet encryption failed due to an internal error. Your wallet was not encrypted. + הצפנת הארנק נכשלה עקב שגיאה פנימית. הארנק שלך לא הוצפן. + + + + + The supplied passphrases do not match. + הסיסמות שניתנו אינן תואמות. + + + + Wallet unlock failed + פתיחת הארנק נכשלה + + + + + + The passphrase entered for the wallet decryption was incorrect. + הסיסמה שהוכנסה לפענוח הארנק שגויה. + + + + Wallet decryption failed + פענוח הארנק נכשל + + + + Wallet passphrase was successfully changed. + סיסמת הארנק שונתה בהצלחה. + + + + BitcoinGUI + + + Sign &message... + חתום על הודעה + + + + Synchronizing with network... + מסתנכרן עם הרשת... + + + + &Overview + &סקירה + + + + Show general overview of wallet + הצג סקירה כללית של הארנק + + + + &Transactions + &פעולות + + + + Browse transaction history + דפדף בהיסטוריית הפעולות + + + + &Address Book + + + + + Edit the list of stored addresses and labels + + + + + &Receive coins + + + + + Show the list of addresses for receiving payments + + + + + &Send coins + + + + + E&xit + י&ציאה + + + + Quit application + סגור תוכנה + + + + Show information about Arepacoin + + + + + About &Qt + אודות Qt + + + + Show information about Qt + הצג מידע על Qt + + + + &Options... + &אפשרויות + + + + &Encrypt Wallet... + הצפן ארנק + + + + &Backup Wallet... + גיבוי ארנק + + + + &Change Passphrase... + שנה סיסמא + + + + ~%n block(s) remaining + + + + + Downloaded %1 of %2 blocks of transaction history (%3% done). + + + + + &Export... + + + + + Send coins to a Arepacoin address + + + + + Modify configuration options for Arepacoin + + + + + Export the data in the current tab to a file + + + + + Encrypt or decrypt wallet + + + + + Backup wallet to another location + גיבוי הארנק למקום אחר + + + + Change the passphrase used for wallet encryption + שנה את הסיסמה להצפנת הארנק + + + + &Debug window + חלון ניפוי + + + + Open debugging and diagnostic console + פתח את לוח הבקרה לאבחון וניפוי + + + + &Verify message... + אמת הודעה... + + + + Arepacoin + + + + + Wallet + ארנק + + + + &About Arepacoin + + + + + &Show / Hide + הצג / הסתר + + + + Unlock wallet + + + + + &Lock Wallet + + + + + Lock wallet + + + + + &File + &קובץ + + + + &Settings + ה&גדרות + + + + &Help + &עזרה + + + + Tabs toolbar + סרגל כלים טאבים + + + + Actions toolbar + + + + + + [testnet] + [רשת-בדיקה] + + + + + Arepacoin client + + + + + %n active connection(s) to Arepacoin network + + + + + Downloaded %1 blocks of transaction history. + + + + + Staking.<br>Your weight is %1<br>Network weight is %2<br>Expected time to earn reward is %3 + + + + + Not staking because wallet is locked + + + + + Not staking because wallet is offline + + + + + Not staking because wallet is syncing + + + + + Not staking because you don't have mature coins + + + + + %n second(s) ago + + + + + &Unlock Wallet... + + + + + %n minute(s) ago + + + + + %n hour(s) ago + + + + + %n day(s) ago + + + + + Up to date + עדכני + + + + Catching up... + מתעדכן... + + + + Last received block was generated %1. + + + + + This transaction is over the size limit. You can still send it for a fee of %1, which goes to the nodes that process your transaction and helps to support the network. Do you want to pay the fee? + + + + + Confirm transaction fee + + + + + Sent transaction + פעולה שנשלחה + + + + Incoming transaction + פעולה שהתקבלה + + + + Date: %1 +Amount: %2 +Type: %3 +Address: %4 + + תאריך: %1 +כמות: %2 +סוג: %3 +כתובת: %4 + + + + + URI handling + + + + + + URI can not be parsed! This can be caused by an invalid Arepacoin address or malformed URI parameters. + + + + + Wallet is <b>encrypted</b> and currently <b>unlocked</b> + הארנק <b>מוצפן</b> וכרגע <b>פתוח</b> + + + + Wallet is <b>encrypted</b> and currently <b>locked</b> + הארנק <b>מוצפן</b> וכרגע <b>נעול</b> + + + + Backup Wallet + + + + + Wallet Data (*.dat) + + + + + Backup Failed + + + + + There was an error trying to save the wallet data to the new location. + + + + + %n second(s) + + + + + %n minute(s) + + + + + %n hour(s) + %n שעה%n שעות + + + + %n day(s) + %n יום%n ימים + + + + Not staking + + + + + A fatal error occurred. Arepacoin can no longer continue safely and will quit. + + + + + ClientModel + + + Network Alert + אזעקת רשת + + + + CoinControlDialog + + + Coin Control + + + + + Quantity: + כמות: + + + + Bytes: + בייטים: + + + + Amount: + כמות: + + + + Priority: + קדימות: + + + + Fee: + תשלום: + + + + Low Output: + + + + + no + לא + + + + After Fee: + לאחר עמלה: + + + + Change: + שינוי: + + + + (un)select all + (מחק)(בחר) הכל + + + + Tree mode + מצב עץ + + + + List mode + מצר רשימה + + + + Amount + כמות + + + + Label + + + + + Address + כתובת + + + + Date + תאריך + + + + Confirmations + אישורים + + + + Confirmed + מאושר + + + + Priority + קדימות + + + + Copy address + העתק כתובת + + + + Copy label + העתק תוית + + + + + Copy amount + העתק כמות + + + + Copy transaction ID + העתק מזהה פעולה + + + + Copy quantity + העתק כמות + + + + Copy fee + העתק מחיר + + + + Copy after fee + + + + + Copy bytes + + + + + Copy priority + העתק קדימות + + + + Copy low output + + + + + Copy change + + + + + highest + הכי גבוה + + + + high + גבוה + + + + medium-high + בנוני גבוה + + + + medium + בינוני + + + + low-medium + בינוני - נמוך + + + + low + נמוך + + + + lowest + הכי נמוך + + + + DUST + + + + + yes + כן + + + + This label turns red, if the transaction size is bigger than 10000 bytes. + + This means a fee of at least %1 per kb is required. + + Can vary +/- 1 Byte per input. + + + + + Transactions with higher priority get more likely into a block. + +This label turns red, if the priority is smaller than "medium". + + This means a fee of at least %1 per kb is required. + + + + + This label turns red, if any recipient receives an amount smaller than %1. + + This means a fee of at least %2 is required. + + Amounts below 0.546 times the minimum relay fee are shown as DUST. + + + + + This label turns red, if the change is smaller than %1. + + This means a fee of at least %2 is required. + + + + + + (no label) + (ללא תוית) + + + + change from %1 (%2) + עודף מ־%1 (%2) + + + + (change) + (עודף) + + + + EditAddressDialog + + + Edit Address + ערוך כתובת + + + + &Label + ת&וית + + + + The label associated with this address book entry + + + + + &Address + &כתובת + + + + The address associated with this address book entry. This can only be modified for sending addresses. + + + + + New receiving address + כתובת חדשה לקבלה + + + + New sending address + כתובת חדשה לשליחה + + + + Edit receiving address + ערוך כתובת לקבלה + + + + Edit sending address + ערוך כתובת לשליחה + + + + The entered address "%1" is already in the address book. + הכתובת שהכנסת "%1" כבר נמצאת בפנקס הכתובות. + + + + The entered address "%1" is not a valid Arepacoin address. + + + + + Could not unlock wallet. + פתיחת הארנק נכשלה. + + + + New key generation failed. + יצירת מפתח חדש נכשלה. + + + + GUIUtil::HelpMessageBox + + + + Arepacoin-Qt + + + + + version + + + + + Usage: + + + + + command-line options + + + + + UI options + + + + + Set language, for example "de_DE" (default: system locale) + + + + + Start minimized + + + + + Show splash screen on startup (default: 1) + + + + + OptionsDialog + + + Options + אפשרויות + + + + &Main + ראשי + + + + Optional transaction fee per kB that helps make sure your transactions are processed quickly. Most transactions are 1 kB. Fee 0.01 recommended. + + + + + Pay transaction &fee + שלם &עמלת פעולה + + + + Reserved amount does not participate in staking and is therefore spendable at any time. + + + + + Reserve + + + + + Automatically start Arepacoin after logging in to the system. + + + + + &Start Arepacoin on system login + + + + + Detach block and address databases at shutdown. This means they can be moved to another data directory, but it slows down shutdown. The wallet is always detached. + + + + + &Detach databases at shutdown + + + + + &Network + רשת + + + + Automatically open the Arepacoin client port on the router. This only works when your router supports UPnP and it is enabled. + + + + + Map port using &UPnP + מיפוי פורט באמצעות UPnP + + + + Connect to the Arepacoin network through a SOCKS proxy (e.g. when connecting through Tor). + + + + + &Connect through SOCKS proxy: + + + + + Proxy &IP: + כתובת IP של פרוקסי: + + + + IP address of the proxy (e.g. 127.0.0.1) + + + + + &Port: + פורט: + + + + Port of the proxy (e.g. 9050) + הפורט של הפרוקסי (למשל 9050) + + + + SOCKS &Version: + גרסת SOCKS: + + + + SOCKS version of the proxy (e.g. 5) + גרסת SOCKS של הפרוקסי (למשל 5) + + + + &Window + חלון + + + + Show only a tray icon after minimizing the window. + הצג סמל מגש בלבד לאחר מזעור החלון. + + + + &Minimize to the tray instead of the taskbar + מ&זער למגש במקום לשורת המשימות + + + + Minimize instead of exit the application when the window is closed. When this option is enabled, the application will be closed only after selecting Quit in the menu. + מזער את התוכנה במקום לצאת ממנה כשהחלון נסגר. כשאפשרות זו פעילה, התוכנה תיסגר רק לאחר בחירת יציאה מהתפריט. + + + + M&inimize on close + מזער בעת סגירה + + + + &Display + תצוגה + + + + User Interface &language: + שפת ממשק המשתמש: + + + + The user interface language can be set here. This setting will take effect after restarting Arepacoin. + + + + + &Unit to show amounts in: + יחידת מדידה להצגת כמויות: + + + + Choose the default subdivision unit to show in the interface and when sending coins. + בחר את ברירת המחדל ליחידת החלוקה אשר תוצג בממשק ובעת שליחת מטבעות. + + + + Whether to show Arepacoin addresses in the transaction list or not. + + + + + &Display addresses in transaction list + הצג כתובות ברשימת הפעולות + + + + Whether to show coin control features or not. + + + + + Display coin &control features (experts only!) + + + + + &OK + אישור + + + + &Cancel + ביטול + + + + &Apply + + + + + default + ברירת מחדל + + + + + Warning + + + + + + This setting will take effect after restarting Arepacoin. + + + + + The supplied proxy address is invalid. + כתובת הפרוקסי שסופקה אינה תקינה. + + + + OverviewPage + + + Form + טופס + + + + + The displayed information may be out of date. Your wallet automatically synchronizes with the Arepacoin network after a connection is established, but this process has not completed yet. + + + + + Stake: + + + + + Unconfirmed: + + + + + Wallet + ארנק + + + + Spendable: + + + + + Your current spendable balance + היתרה הזמינה הנוכחית + + + + Immature: + לא בשל: + + + + Mined balance that has not yet matured + מאזן שנכרה וטרם הבשיל + + + + Total: + סך הכול: + + + + Your current total balance + סך כל היתרה הנוכחית שלך + + + + <b>Recent transactions</b> + <b>פעולות אחרונות</b> + + + + Total of transactions that have yet to be confirmed, and do not yet count toward the current balance + + + + + Total of coins that was staked, and do not yet count toward the current balance + + + + + + out of sync + לא מסונכרן + + + + QRCodeDialog + + + QR Code Dialog + + + + + Request Payment + + + + + Amount: + + + + + Label: + + + + + Message: + + + + + &Save As... + + + + + Error encoding URI into QR Code. + + + + + The entered amount is invalid, please check. + + + + + Resulting URI too long, try to reduce the text for label / message. + + + + + Save QR Code + + + + + PNG Images (*.png) + + + + + RPCConsole + + + Client name + שם ממשק + + + + + + + + + + + + + N/A + N/A + + + + Client version + גרסת ממשק + + + + &Information + מידע + + + + Using OpenSSL version + משתמש ב-OpenSSL גרסה + + + + Startup time + זמן אתחול + + + + Network + רשת + + + + Number of connections + מספר חיבורים + + + + On testnet + + + + + Block chain + שרשרת הבלוקים + + + + Current number of blocks + מספר הבלוקים הנוכחי + + + + Estimated total blocks + מספר כולל משוער של בלוקים + + + + Last block time + זמן הבלוק האחרון + + + + &Open + פתח + + + + Command-line options + + + + + Show the Arepacoin-Qt help message to get a list with possible Arepacoin command-line options. + + + + + &Show + + + + + &Console + לוח בקרה + + + + Build date + תאריך בניה + + + + Arepacoin - Debug window + + + + + Arepacoin Core + + + + + Debug log file + קובץ יומן ניפוי + + + + Open the Arepacoin debug log file from the current data directory. This can take a few seconds for large log files. + + + + + Clear console + נקה לוח בקרה + + + + Welcome to the Arepacoin RPC console. + + + + + Use up and down arrows to navigate history, and <b>Ctrl-L</b> to clear screen. + השתמש בחיצים למעלה ולמטה כדי לנווט בהיסטוריה, ו- <b>Ctrl-L</b> כדי לנקות את המסך. + + + + Type <b>help</b> for an overview of available commands. + הקלד <b>help</b> בשביל סקירה של הפקודות הזמינות. + + + + SendCoinsDialog + + + + + + + + + + Send Coins + שלח מטבעות + + + + Coin Control Features + ה + + + + Inputs... + + + + + automatically selected + נבחר אוטומאטית + + + + Insufficient funds! + אין מספיק כספים! + + + + Quantity: + כמות: + + + + + 0 + + + + + Bytes: + בייטים: + + + + Amount: + כמות: + + + + + + + 0.00 BC + + + + + Priority: + קדימות: + + + + medium + + + + + Fee: + תשלום: + + + + Low Output: + + + + + no + + + + + After Fee: + לאחר עמלה: + + + + Change + + + + + custom change address + + + + + Send to multiple recipients at once + שלח למספר מקבלים בו-זמנית + + + + Add &Recipient + הוסף מקבל + + + + Remove all transaction fields + + + + + Clear &All + נקה הכל + + + + Balance: + יתרה: + + + + 123.456 BC + + + + + Confirm the send action + אשר את פעולת השליחה + + + + S&end + שלח + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Copy quantity + העתק כמות + + + + Copy amount + העתק כמות + + + + Copy fee + העתק מחיר + + + + Copy after fee + + + + + Copy bytes + + + + + Copy priority + העתק קדימות + + + + Copy low output + + + + + Copy change + + + + + <b>%1</b> to %2 (%3) + + + + + Confirm send coins + אשר שליחת מטבעות + + + + Are you sure you want to send %1? + + + + + and + + + + + The recipient address is not valid, please recheck. + כתובת המקבל אינה תקינה, אנא בדוק שנית. + + + + The amount to pay must be larger than 0. + הכמות לשלם חייבת להיות גדולה מ-0. + + + + The amount exceeds your balance. + הכמות עולה על המאזן שלך. + + + + The total exceeds your balance when the %1 transaction fee is included. + הכמות הכוללת, ובכללה עמלת פעולה בסך %1, עולה על המאזן שלך. + + + + Duplicate address found, can only send to each address once per send operation. + כתובת כפולה נמצאה, ניתן לשלוח לכל כתובת רק פעם אחת בכל פעולת שליחה. + + + + Error: Transaction creation failed. + + + + + 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. + + + + + WARNING: Invalid Arepacoin address + + + + + (no label) + (ללא תוית) + + + + WARNING: unknown change address + + + + + SendCoinsEntry + + + Form + + + + + A&mount: + כ&מות: + + + + Pay &To: + שלם &ל: + + + + + Enter a label for this address to add it to your address book + הכנס תוית לכתובת הזאת כדי להכניס לפנקס הכתובות + + + + &Label: + ת&וית: + + + + The address to send the payment to (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Choose address from address book + + + + + Alt+A + Alt+A + + + + Paste address from clipboard + הדבר כתובת מהלוח + + + + Alt+P + Alt+P + + + + Remove this recipient + + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + SignVerifyMessageDialog + + + Signatures - Sign / Verify a Message + חתימות - חתום או אמת הודעה + + + + + &Sign Message + חתום על הו&דעה + + + + You can sign messages with your addresses to prove you own them. Be careful not to sign anything vague, as phishing attacks may try to trick you into signing your identity over to them. Only sign fully-detailed statements you agree to. + אתה יכול לחתום על הודעות עם הכתובות שלך כדי להוכיח שהן בבעלותך. היזהר לא לחתום על משהו מעורפל, שכן התקפות פישינג עשויות לגרום לך בעורמה למסור את זהותך. חתום רק על אמרות מפורטות לחלוטין שאתה מסכים עימן. + + + + The address to sign the message with (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + + Choose an address from the address book + + + + + + Alt+A + Alt+A + + + + Paste address from clipboard + הדבק כתובת מהלוח + + + + Alt+P + Alt+P + + + + Enter the message you want to sign here + הכנס כאן את ההודעה שעליך ברצונך לחתום + + + + Copy the current signature to the system clipboard + העתק את החתימה הנוכחית ללוח המערכת + + + + Sign the message to prove you own this Arepacoin address + + + + + Reset all sign message fields + אפס את כל שדות החתימה על הודעה + + + + + Clear &All + נקה הכל + + + + + &Verify Message + אמת הודעה + + + + Enter the signing address, message (ensure you copy line breaks, spaces, tabs, etc. exactly) and signature below to verify the message. Be careful not to read more into the signature than what is in the signed message itself, to avoid being tricked by a man-in-the-middle attack. + הכנס למטה את הכתובת החותמת, ההודעה (ודא שאתה מעתיק מעברי שורה, רווחים, טאבים וכו' באופן מדויק) והחתימה כדי לאמת את ההודעה. היזהר לא לפרש את החתימה כיותר ממה שמופיע בהודעה החתומה בעצמה, כדי להימנע מליפול קורבן למתקפת איש-באמצע. + + + + The address the message was signed with (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Verify the message to ensure it was signed with the specified Arepacoin address + + + + + Reset all verify message fields + אפס את כל שדות אימות הודעה + + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Click "Sign Message" to generate signature + לחץ "חתום על ההודעה" כדי לחולל חתימה + + + + Enter Arepacoin signature + + + + + + The entered address is invalid. + הכתובת שהוכנסה אינה תקינה. + + + + + + + Please check the address and try again. + אנא בדוק את הכתובת ונסה שנית. + + + + + The entered address does not refer to a key. + הכתובת שהוכנסה אינה מתייחסת למפתח. + + + + Wallet unlock was cancelled. + פתיחת הארנק בוטלה. + + + + Private key for the entered address is not available. + המפתח הפרטי עבור הכתובת שהוכנסה אינו זמין. + + + + Message signing failed. + החתימה על ההודעה נכשלה. + + + + Message signed. + ההודעה נחתמה. + + + + The signature could not be decoded. + לא ניתן לפענח את החתימה. + + + + + Please check the signature and try again. + אנא בדוק את החתימה ונסה שנית. + + + + The signature did not match the message digest. + החתימה לא תואמת את תקציר ההודעה. + + + + Message verification failed. + אימות ההודעה נכשל. + + + + Message verified. + ההודעה אומתה. + + + + TransactionDesc + + + Open until %1 + פתוח עד %1 + + + + Open for %n block(s) + + + + + conflicted + + + + + %1/offline + %1/מנותק + + + + %1/unconfirmed + %1/ממתין לאישור + + + + %1 confirmations + %1 אישורים + + + + Status + מצב + + + + , broadcast through %n node(s) + , הופץ דרך צומת אחד, הופץ דרך %n צמתים + + + + Date + תאריך + + + + Source + מקור + + + + Generated + נוצר + + + + + From + מאת + + + + + + To + אל + + + + + own address + כתובת עצמית + + + + label + תוית + + + + + + + + Credit + זיכוי + + + + matures in %n more block(s) + מבשיל בעוד בלוק אחדמבשיל בעוד %n בלוקים + + + + not accepted + לא התקבל + + + + + + + Debit + חיוב + + + + Transaction fee + עמלת פעולה + + + + Net amount + כמות נקיה + + + + Message + הודעה + + + + Comment + הערה + + + + Transaction ID + זיהוי פעולה + + + + Generated coins must mature 6 blocks before they can be spent. When you generated this block, it was broadcast to the network to be added to the block chain. If it fails to get into the chain, its state will change to "not accepted" and it won't be spendable. This may occasionally happen if another node generates a block within a few seconds of yours. + + + + + Debug information + מידע ניפוי + + + + Transaction + פעולה + + + + Inputs + קלטים + + + + Amount + כמות + + + + true + אמת + + + + false + שקר + + + + , has not been successfully broadcast yet + , טרם שודר בהצלחה + + + + unknown + לא ידוע + + + + TransactionDescDialog + + + Transaction details + פרטי הפעולה + + + + This pane shows a detailed description of the transaction + חלונית זו מציגה תיאור מפורט של הפעולה + + + + TransactionTableModel + + + Date + תאריך + + + + Type + סוג + + + + Address + כתובת + + + + Amount + כמות + + + + Open until %1 + פתוח עד %1 + + + + Confirmed (%1 confirmations) + מאושר (%1 אישורים) + + + + Open for %n more block(s) + פתח למשך בלוק %n יותרפתח למשך %n בלוקים נוספים + + + + Offline + + + + + Unconfirmed + + + + + Confirming (%1 of %2 recommended confirmations) + + + + + Conflicted + + + + + Immature (%1 confirmations, will be available after %2) + + + + + This block was not received by any other nodes and will probably not be accepted! + הבלוק הזה לא נקלט על ידי אף צומת אחר, וכנראה לא יתקבל! + + + + Generated but not accepted + נוצר אך לא התקבל + + + + Received with + התקבל עם + + + + Received from + התקבל מאת + + + + Sent to + נשלח ל + + + + Payment to yourself + תשלום לעצמך + + + + Mined + נכרה + + + + (n/a) + (n/a) + + + + Transaction status. Hover over this field to show number of confirmations. + מצב הפעולה. השהה את הסמן מעל שדה זה כדי לראות את מספר האישורים. + + + + Date and time that the transaction was received. + התאריך והשעה בה הפעולה הזאת התקבלה. + + + + Type of transaction. + סוג הפעולה. + + + + Destination address of transaction. + כתובת היעד של הפעולה. + + + + Amount removed from or added to balance. + הכמות שהתווספה או הוסרה מהיתרה. + + + + TransactionView + + + + All + הכל + + + + Today + היום + + + + This week + השבוע + + + + This month + החודש + + + + Last month + החודש שעבר + + + + This year + השנה + + + + Range... + טווח... + + + + Received with + התקבל עם + + + + Sent to + נשלח ל + + + + To yourself + לעצמך + + + + Mined + נכרה + + + + Other + אחר + + + + Enter address or label to search + הכנס כתובת או תוית לחפש + + + + Min amount + כמות מזערית + + + + Copy address + העתק כתובת + + + + Copy label + העתק תוית + + + + Copy amount + העתק כמות + + + + Copy transaction ID + העתק מזהה פעולה + + + + Edit label + ערוך תוית + + + + Show transaction details + הצג פרטי פעולה + + + + Export Transaction Data + + + + + Comma separated file (*.csv) + קובץ מופרד בפסיקים (*.csv) + + + + Confirmed + מאושר + + + + Date + תאריך + + + + Type + סוג + + + + Label + תוית + + + + Address + כתובת + + + + Amount + כמות + + + + ID + מזהה + + + + Error exporting + + + + + Could not write to file %1. + + + + + Range: + טווח: + + + + to + אל + + + + WalletModel + + + Sending... + + + + + bitcoin-core + + + Arepacoin version + + + + + Usage: + שימוש: + + + + Send command to -server or arepacoind + + + + + List commands + רשימת פקודות + + + + Get help for a command + קבל עזרה עבור פקודה + + + + Options: + אפשרויות: + + + + Specify configuration file (default: arepacoin.conf) + + + + + Specify pid file (default: arepacoind.pid) + + + + + Specify wallet file (within data directory) + + + + + Specify data directory + ציין תיקיית נתונים + + + + Set database cache size in megabytes (default: 25) + קבע את גודל המטמון של מסד הנתונים במגהבייט (ברירת מחדל: 25) + + + + Set database disk log size in megabytes (default: 100) + + + + + Listen for connections on <port> (default: 9853 or testnet: 19853) + + + + + Maintain at most <n> connections to peers (default: 125) + החזק לכל היותר <n> חיבורים לעמיתים (ברירת מחדל: 125) + + + + Connect to a node to retrieve peer addresses, and disconnect + התחבר לצומת כדי לדלות כתובות עמיתים, ואז התנתק + + + + Specify your own public address + ציין את הכתובת הפומבית שלך + + + + Bind to given address. Use [host]:port notation for IPv6 + + + + + Stake your coins to support network and gain reward (default: 1) + + + + + Threshold for disconnecting misbehaving peers (default: 100) + סף להתנתקות מעמיתים הנוהגים שלא כהלכה (ברירת מחדל: 100) + + + + Number of seconds to keep misbehaving peers from reconnecting (default: 86400) + מספר שניות למנוע מעמיתים הנוהגים שלא כהלכה מלהתחבר מחדש (ברירת מחדל: 86400) + + + + An error occurred while setting up the RPC port %u for listening on IPv4: %s + אירעה שגיאה בעת הגדרת פורט RPC %u להאזנה ב-IPv4: %s + + + + Detach block and address databases. Increases shutdown time (default: 0) + + + + + 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. + + + + + Error: This transaction requires a transaction fee of at least %s because of its amount, complexity, or use of recently received funds + + + + + Listen for JSON-RPC connections on <port> (default: 9852 or testnet: 19852) + + + + + Accept command line and JSON-RPC commands + קבל פקודות משורת הפקודה ו- JSON-RPC + + + + Error: Transaction creation failed + + + + + Error: Wallet locked, unable to create transaction + + + + + Importing blockchain data file. + + + + + Importing bootstrap blockchain data file. + + + + + Run in the background as a daemon and accept commands + רוץ ברקע כדימון וקבל פקודות + + + + Use the test network + השתמש ברשת הבדיקה + + + + Accept connections from outside (default: 1 if no -proxy or -connect) + קבל חיבורים מבחוץ (ברירת מחדל: 1 ללא -proxy או -connect) + + + + An error occurred while setting up the RPC port %u for listening on IPv6, falling back to IPv4: %s + אירעה שגיאה בעת הגדרת פורט RPC %u להאזנה ב-IPv6, נסוג ל-IPv4: %s + + + + Error initializing database environment %s! To recover, BACKUP THAT DIRECTORY, then remove everything from it except for wallet.dat. + + + + + Set maximum size of high-priority/low-fee transactions in bytes (default: 27000) + + + + + Warning: -paytxfee is set very high! This is the transaction fee you will pay if you send a transaction. + אזהרה: -paytxfee נקבע לערך מאד גבוה! זוהי עמלת הפעולה שתשלם אם אתה שולח פעולה. + + + + Warning: Please check that your computer's date and time are correct! If your clock is wrong Arepacoin will not work properly. + + + + + Warning: error reading wallet.dat! All keys read correctly, but transaction data or address book entries might be missing or incorrect. + אזהרה: שגיאה בקריאת wallet.dat! כל המתפחות נקראו באופן תקין, אך נתוני הפעולות או ספר הכתובות עלולים להיות חסרים או שגויים. + + + + Warning: wallet.dat corrupt, data salvaged! Original wallet.dat saved as wallet.{timestamp}.bak in %s; if your balance or transactions are incorrect you should restore from a backup. + אזהרה: קובץ wallet.dat מושחת, המידע חולץ! קובץ wallet.dat המקורח נשמר כ - wallet.{timestamp}.bak ב - %s; אם המאזן או הפעולות שגויים עליך לשחזר גיבוי. + + + + Attempt to recover private keys from a corrupt wallet.dat + נסה לשחזר מפתחות פרטיים מקובץ wallet.dat מושחת. + + + + Block creation options: + אפשרויות יצירת בלוק: + + + + Connect only to the specified node(s) + התחבר רק לצמתים המצוינים + + + + Discover own IP address (default: 1 when listening and no -externalip) + גלה את כתובת ה-IP העצמית (ברירת מחדל: 1 כשמאזינים וללא -externalip) + + + + Failed to listen on any port. Use -listen=0 if you want this. + האזנה נכשלה בכל פורט. השתמש ב- -listen=0 אם ברצונך בכך. + + + + Find peers using DNS lookup (default: 1) + + + + + Sync checkpoints policy (default: strict) + + + + + Invalid -tor address: '%s' + + + + + Invalid amount for -reservebalance=<amount> + + + + + Maximum per-connection receive buffer, <n>*1000 bytes (default: 5000) + חוצץ קבלה מירבי לכל חיבור, <n>*1000 בתים (ברירת מחדל: 5000) + + + + Maximum per-connection send buffer, <n>*1000 bytes (default: 1000) + חוצץ שליחה מירבי לכל חיבור, <n>*1000 בתים (ברירת מחדל: 1000) + + + + Only connect to nodes in network <net> (IPv4, IPv6 or Tor) + התחבר רק לצמתים ברשת <net> (IPv4, IPv6 או Tor) + + + + Output extra debugging information. Implies all other -debug* options + + + + + Output extra network debugging information + + + + + Prepend debug output with timestamp + + + + + SSL options: (see the Bitcoin Wiki for SSL setup instructions) + אפשרויות SSL: (ראה את הויקי של ביטקוין עבור הוראות הגדרת SSL) + + + + Select the version of socks proxy to use (4-5, default: 5) + + + + + Send trace/debug info to console instead of debug.log file + שלח מידע דיבאג ועקבה לקונסולה במקום לקובץ debug.log + + + + Send trace/debug info to debugger + + + + + Set maximum block size in bytes (default: 250000) + + + + + Set minimum block size in bytes (default: 0) + קבע את גודל הבלוק המינימלי בבתים (ברירת מחדל: 0) + + + + Shrink debug.log file on client startup (default: 1 when no -debug) + כווץ את קובץ debug.log בהפעלת הקליינט (ברירת מחדל: 1 ללא -debug) + + + + Specify connection timeout in milliseconds (default: 5000) + ציין הגבלת זמן לחיבור במילישניות (ברירת מחדל: 5000) + + + + Unable to sign checkpoint, wrong checkpointkey? + + + + + + Use UPnP to map the listening port (default: 0) + השתמש ב-UPnP כדי למפות את הפורט להאזנה (ברירת מחדל: 0) + + + + Use UPnP to map the listening port (default: 1 when listening) + השתמש ב-UPnP כדי למפות את הפורט להאזנה (ברירת מחדל: 1 בעת האזנה) + + + + Use proxy to reach tor hidden services (default: same as -proxy) + + + + + Username for JSON-RPC connections + שם משתמש לחיבורי JSON-RPC + + + + Verifying database integrity... + + + + + WARNING: syncronized checkpoint violation detected, but skipped! + + + + + Warning: Disk space is low! + + + + + Warning: This version is obsolete, upgrade required! + אזהרה: הגרסה הזאת מיושנת, יש צורך בשדרוג! + + + + wallet.dat corrupt, salvage failed + קובץ wallet.dat מושחת, החילוץ נכשל + + + + Password for JSON-RPC connections + סיסמה לחיבורי JSON-RPC + + + + %s, you must set a rpcpassword in the configuration file: + %s +It is recommended you use the following random password: +rpcuser=arepacoinrpc +rpcpassword=%s +(you do not need to remember this password) +The username and password MUST NOT be the same. +If the file does not exist, create it with owner-readable-only file permissions. +It is also recommended to set alertnotify so you are notified of problems; +for example: alertnotify=echo %%s | mail -s "Arepacoin Alert" admin@foo.com + + + + + + Find peers using internet relay chat (default: 0) + + + + + Sync time with other nodes. Disable if time on your system is precise e.g. syncing with NTP (default: 1) + + + + + When creating transactions, ignore inputs with value less than this (default: 0.01) + + + + + Allow JSON-RPC connections from specified IP address + אפשר חיבורי JSON-RPC מכתובת האינטרנט המצוינת + + + + Send commands to node running on <ip> (default: 127.0.0.1) + שלח פקודות לצומת ב-<ip> (ברירת מחדל: 127.0.0.1) + + + + Execute command when the best block changes (%s in cmd is replaced by block hash) + בצע פקודה זו כשהבלוק הטוב ביותר משתנה (%s בפקודה יוחלף בגיבוב הבלוק) + + + + Execute command when a wallet transaction changes (%s in cmd is replaced by TxID) + בצע פקודה כאשר פעולת ארנק משתנה (%s ב cmd יוחלף ב TxID) + + + + Require a confirmations for change (default: 0) + + + + + Enforce transaction scripts to use canonical PUSH operators (default: 1) + + + + + Execute command when a relevant alert is received (%s in cmd is replaced by message) + + + + + Upgrade wallet to latest format + שדרג את הארנק לפורמט העדכני + + + + Set key pool size to <n> (default: 100) + קבע את גודל המאגר ל -<n> (ברירת מחדל: 100) + + + + Rescan the block chain for missing wallet transactions + סרוק מחדש את שרשרת הבלוקים למציאת פעולות חסרות בארנק + + + + How many blocks to check at startup (default: 2500, 0 = all) + + + + + How thorough the block verification is (0-6, default: 1) + + + + + Imports blocks from external blk000?.dat file + + + + + Use OpenSSL (https) for JSON-RPC connections + השתמש ב-OpenSSL (https( עבור חיבורי JSON-RPC + + + + Server certificate file (default: server.cert) + קובץ תעודת שרת (ברירת מחדל: server.cert) + + + + Server private key (default: server.pem) + מפתח פרטי של השרת (ברירת מחדל: server.pem) + + + + Acceptable ciphers (default: TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH) + + + + + Error: Wallet unlocked for staking only, unable to create transaction. + + + + + WARNING: Invalid checkpoint found! Displayed transactions may not be correct! You may need to upgrade, or notify developers. + + + + + This help message + הודעת העזרה הזו + + + + Wallet %s resides outside data directory %s. + + + + + Cannot obtain a lock on data directory %s. Arepacoin is probably already running. + + + + + Arepacoin + + + + + Unable to bind to %s on this computer (bind returned error %d, %s) + לא מסוגל לקשור ל-%s במחשב זה (הקשירה החזירה שגיאה %d, %s) + + + + Connect through socks proxy + + + + + Allow DNS lookups for -addnode, -seednode and -connect + אפשר בדיקת DNS עבור -addnode, -seednode ו- -connect + + + + Loading addresses... + טוען כתובות... + + + + Error loading blkindex.dat + + + + + Error loading wallet.dat: Wallet corrupted + שגיאה בטעינת הקובץ wallet.dat: הארנק מושחת + + + + Error loading wallet.dat: Wallet requires newer version of Arepacoin + + + + + Wallet needed to be rewritten: restart Arepacoin to complete + + + + + Error loading wallet.dat + שגיאה בטעינת הקובץ wallet.dat + + + + Invalid -proxy address: '%s' + כתובת -proxy לא תקינה: '%s' + + + + Unknown network specified in -onlynet: '%s' + רשת לא ידועה צוינה ב- -onlynet: '%s' + + + + Unknown -socks proxy version requested: %i + התבקשה גרסת פרוקסי -socks לא ידועה: %i + + + + Cannot resolve -bind address: '%s' + לא מסוגל לפתור כתובת -bind: '%s' + + + + Cannot resolve -externalip address: '%s' + לא מסוגל לפתור כתובת -externalip: '%s' + + + + Invalid amount for -paytxfee=<amount>: '%s' + כמות לא תקינה עבור -paytxfee=<amount>: '%s' + + + + Error: could not start node + + + + + Sending... + + + + + Invalid amount + כמות לא תקינה + + + + Insufficient funds + אין מספיק כספים + + + + Loading block index... + טוען את אינדקס הבלוקים... + + + + Add a node to connect to and attempt to keep the connection open + הוסף צומת להתחברות ונסה לשמור את החיבור פתוח + + + + Unable to bind to %s on this computer. Arepacoin is probably already running. + + + + + Fee per KB to add to transactions you send + + + + + Invalid amount for -mininput=<amount>: '%s' + + + + + Loading wallet... + טוען ארנק... + + + + Cannot downgrade wallet + לא יכול להוריד דרגת הארנק + + + + Cannot initialize keypool + + + + + Cannot write default address + לא יכול לכתוב את כתובת ברירת המחדל + + + + Rescanning... + סורק מחדש... + + + + Done loading + טעינה הושלמה + + + + To use the %s option + להשתמש באפשרות %s + + + + Error + שגיאה + + + + You must set rpcpassword=<password> in the configuration file: +%s +If the file does not exist, create it with owner-readable-only file permissions. + עליך לקבוע rpcpassword=yourpassword בקובץ ההגדרות: +%s +אם הקובץ אינו קיים, צור אותו עם הרשאות קריאה לבעלים בלבד. + + + \ No newline at end of file diff --git a/src/qt/locale/bitcoin_hi_IN.ts b/src/qt/locale/bitcoin_hi_IN.ts new file mode 100755 index 0000000..936d530 --- /dev/null +++ b/src/qt/locale/bitcoin_hi_IN.ts @@ -0,0 +1,3280 @@ + + + AboutDialog + + + About Arepacoin + + + + + <b>Arepacoin</b> version + + + + + Copyright © 2009-2014 The Bitcoin developers +Copyright © 2012-2014 The NovaCoin developers +Copyright © 2014 The Arepacoin developers + + + + + +This is experimental software. + +Distributed under the MIT/X11 software license, see the accompanying file COPYING or http://www.opensource.org/licenses/mit-license.php. + +This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit (http://www.openssl.org/) and cryptographic software written by Eric Young (eay@cryptsoft.com) and UPnP software written by Thomas Bernard. + + + + + AddressBookPage + + + Address Book + + + + + Double-click to edit address or label + दो बार क्लिक करे पता या लेबल संपादन करने के लिए ! + + + + Create a new address + नया पता लिखिए ! + + + + Copy the currently selected address to the system clipboard + चुनिन्दा पते को सिस्टम क्लिपबोर्ड पर कापी करे ! + + + + &New Address + + + + + These are your Arepacoin addresses for receiving payments. You may want to give a different one to each sender so you can keep track of who is paying you. + + + + + &Copy Address + &पता कॉपी करे + + + + Show &QR Code + + + + + Sign a message to prove you own a Arepacoin address + + + + + Sign &Message + + + + + Delete the currently selected address from the list + + + + + Verify a message to ensure it was signed with a specified Arepacoin address + + + + + &Verify Message + + + + + &Delete + &मिटाए !! + + + + Copy &Label + &लेबल कॉपी करे + + + + &Edit + &एडिट + + + + Export Address Book Data + + + + + Comma separated file (*.csv) + Comma separated file (*.csv) + + + + Error exporting + + + + + Could not write to file %1. + + + + + AddressTableModel + + + Label + लेबल + + + + Address + पता + + + + (no label) + (कोई लेबल नही !) + + + + AskPassphraseDialog + + + Passphrase Dialog + + + + + Enter passphrase + पहचान शब्द/अक्षर डालिए ! + + + + New passphrase + नया पहचान शब्द/अक्षर डालिए ! + + + + Repeat new passphrase + दोबारा नया पहचान शब्द/अक्षर डालिए ! + + + + Serves to disable the trivial sendmoney when OS account compromised. Provides no real security. + + + + + For staking only + + + + + Enter the new passphrase to the wallet.<br/>Please use a passphrase of <b>10 or more random characters</b>, or <b>eight or more words</b>. + नया पहचान शब्द/अक्षर वॉलेट मे डालिए ! <br/> कृपा करके पहचान शब्द में <br> 10 से ज़्यादा अक्षॉरों का इस्तेमाल करे </b>,या <b>आठ या उससे से ज़्यादा शब्दो का इस्तेमाल करे</b> ! + + + + Encrypt wallet + एनक्रिप्ट वॉलेट ! + + + + This operation needs your wallet passphrase to unlock the wallet. + वॉलेट खोलने के आपका वॉलेट पहचान शब्द्‌/अक्षर चाईए ! + + + + Unlock wallet + वॉलेट खोलिए + + + + This operation needs your wallet passphrase to decrypt the wallet. + वॉलेट डीक्रिप्ट( विकोड) करने के लिए आपका वॉलेट पहचान शब्द्‌/अक्षर चाईए ! + + + + Decrypt wallet + डीक्रिप्ट वॉलेट + + + + Change passphrase + पहचान शब्द/अक्षर बदलिये ! + + + + Enter the old and new passphrase to the wallet. + कृपा करके पुराना एवं नया पहचान शब्द/अक्षर वॉलेट में डालिए ! + + + + Confirm wallet encryption + वॉलेट एनक्रिपशन को प्रमाणित कीजिए ! + + + + Warning: If you encrypt your wallet and lose your passphrase, you will <b>LOSE ALL OF YOUR COINS</b>! + + + + + Are you sure you wish to encrypt your wallet? + + + + + IMPORTANT: Any previous backups you have made of your wallet file should be replaced with the newly generated, encrypted wallet file. For security reasons, previous backups of the unencrypted wallet file will become useless as soon as you start using the new, encrypted wallet. + + + + + + Warning: The Caps Lock key is on! + + + + + + Wallet encrypted + वॉलेट एनक्रिप्ट हो गया ! + + + + Arepacoin will close now to finish the encryption process. Remember that encrypting your wallet cannot fully protect your coins from being stolen by malware infecting your computer. + + + + + + + + Wallet encryption failed + वॉलेट एनक्रिप्ट नही हुआ! + + + + Wallet encryption failed due to an internal error. Your wallet was not encrypted. + वॉलेट एनक्रिपशन नाकाम हो गया इंटर्नल एरर की वजह से! आपका वॉलेट एनक्रीपत नही हुआ है! + + + + + The supplied passphrases do not match. + आपके द्वारा डाले गये पहचान शब्द/अक्षर मिलते नही है ! + + + + Wallet unlock failed + वॉलेट का लॉक नही खुला ! + + + + + + The passphrase entered for the wallet decryption was incorrect. + वॉलेट डीक्रिप्ट करने के लिए जो पहचान शब्द/अक्षर डाले गये है वो सही नही है! + + + + Wallet decryption failed + वॉलेट का डीक्रिप्ट-ष्ण असफल ! + + + + Wallet passphrase was successfully changed. + + + + + BitcoinGUI + + + Sign &message... + + + + + Synchronizing with network... + नेटवर्क से समकालिक (मिल) रहा है ... + + + + &Overview + &विवरण + + + + Show general overview of wallet + वॉलेट का सामानया विवरण दिखाए ! + + + + &Transactions + & लेन-देन + + + + + Browse transaction history + देखिए पुराने लेन-देन के विवरण ! + + + + &Address Book + + + + + Edit the list of stored addresses and labels + + + + + &Receive coins + + + + + Show the list of addresses for receiving payments + + + + + &Send coins + + + + + E&xit + बाहर जायें + + + + Quit application + अप्लिकेशन से बाहर निकलना ! + + + + Show information about Arepacoin + + + + + About &Qt + + + + + Show information about Qt + + + + + &Options... + &विकल्प + + + + &Encrypt Wallet... + + + + + &Backup Wallet... + &बैकप वॉलेट + + + + &Change Passphrase... + + + + + ~%n block(s) remaining + + + + + Downloaded %1 of %2 blocks of transaction history (%3% done). + + + + + &Export... + + + + + Send coins to a Arepacoin address + + + + + Modify configuration options for Arepacoin + + + + + Export the data in the current tab to a file + + + + + Encrypt or decrypt wallet + + + + + Backup wallet to another location + + + + + Change the passphrase used for wallet encryption + पहचान शब्द/अक्षर जो वॉलेट एनक्रिपशन के लिए इस्तेमाल किया है उसे बदलिए! + + + + &Debug window + + + + + Open debugging and diagnostic console + + + + + &Verify message... + + + + + Arepacoin + + + + + Wallet + वॉलेट + + + + &About Arepacoin + + + + + &Show / Hide + + + + + Unlock wallet + + + + + &Lock Wallet + + + + + Lock wallet + + + + + &File + &फाइल + + + + &Settings + &सेट्टिंग्स + + + + &Help + &मदद + + + + Tabs toolbar + टैबस टूलबार + + + + Actions toolbar + + + + + + [testnet] + [टेस्टनेट] + + + + + Arepacoin client + + + + + %n active connection(s) to Arepacoin network + + + + + Downloaded %1 blocks of transaction history. + + + + + Staking.<br>Your weight is %1<br>Network weight is %2<br>Expected time to earn reward is %3 + + + + + Not staking because wallet is locked + + + + + Not staking because wallet is offline + + + + + Not staking because wallet is syncing + + + + + Not staking because you don't have mature coins + + + + + %n second(s) ago + + + + + &Unlock Wallet... + + + + + %n minute(s) ago + + + + + %n hour(s) ago + + + + + %n day(s) ago + + + + + Up to date + नवीनतम + + + + Catching up... + + + + + Last received block was generated %1. + + + + + This transaction is over the size limit. You can still send it for a fee of %1, which goes to the nodes that process your transaction and helps to support the network. Do you want to pay the fee? + + + + + Confirm transaction fee + + + + + Sent transaction + भेजी ट्रांजक्शन + + + + Incoming transaction + प्राप्त हुई ट्रांजक्शन + + + + Date: %1 +Amount: %2 +Type: %3 +Address: %4 + + तारीख: %1\n +राशि: %2\n +टाइप: %3\n +पता:%4\n + + + + + URI handling + + + + + + URI can not be parsed! This can be caused by an invalid Arepacoin address or malformed URI parameters. + + + + + Wallet is <b>encrypted</b> and currently <b>unlocked</b> + वॉलेट एन्क्रिप्टेड है तथा अभी लॉक्ड नहीं है + + + + Wallet is <b>encrypted</b> and currently <b>locked</b> + वॉलेट एन्क्रिप्टेड है तथा अभी लॉक्ड है + + + + Backup Wallet + + + + + Wallet Data (*.dat) + + + + + Backup Failed + + + + + There was an error trying to save the wallet data to the new location. + + + + + %n second(s) + + + + + %n minute(s) + + + + + %n hour(s) + %n घंटा%n घंटे + + + + %n day(s) + %n दिन%n दिनो + + + + Not staking + + + + + A fatal error occurred. Arepacoin can no longer continue safely and will quit. + + + + + ClientModel + + + Network Alert + + + + + CoinControlDialog + + + Coin Control + + + + + Quantity: + + + + + Bytes: + + + + + Amount: + राशि : + + + + Priority: + + + + + Fee: + + + + + Low Output: + + + + + no + + + + + After Fee: + + + + + Change: + + + + + (un)select all + + + + + Tree mode + + + + + List mode + + + + + Amount + राशि + + + + Label + + + + + Address + पता + + + + Date + taareek + + + + Confirmations + + + + + Confirmed + पक्का + + + + Priority + + + + + Copy address + पता कॉपी करे + + + + Copy label + लेबल कॉपी करे + + + + + Copy amount + कॉपी राशि + + + + Copy transaction ID + + + + + Copy quantity + + + + + Copy fee + + + + + Copy after fee + + + + + Copy bytes + + + + + Copy priority + + + + + Copy low output + + + + + Copy change + + + + + highest + + + + + high + + + + + medium-high + + + + + medium + + + + + low-medium + + + + + low + + + + + lowest + + + + + DUST + + + + + yes + + + + + This label turns red, if the transaction size is bigger than 10000 bytes. + + This means a fee of at least %1 per kb is required. + + Can vary +/- 1 Byte per input. + + + + + Transactions with higher priority get more likely into a block. + +This label turns red, if the priority is smaller than "medium". + + This means a fee of at least %1 per kb is required. + + + + + This label turns red, if any recipient receives an amount smaller than %1. + + This means a fee of at least %2 is required. + + Amounts below 0.546 times the minimum relay fee are shown as DUST. + + + + + This label turns red, if the change is smaller than %1. + + This means a fee of at least %2 is required. + + + + + + (no label) + (कोई लेबल नही !) + + + + change from %1 (%2) + + + + + (change) + + + + + EditAddressDialog + + + Edit Address + पता एडिट करना + + + + &Label + &लेबल + + + + The label associated with this address book entry + + + + + &Address + &पता + + + + The address associated with this address book entry. This can only be modified for sending addresses. + + + + + New receiving address + नया स्वीकार्य पता + + + + New sending address + नया भेजने वाला पता + + + + Edit receiving address + एडिट स्वीकार्य पता + + + + Edit sending address + एडिट भेजने वाला पता + + + + The entered address "%1" is already in the address book. + डाला गया पता "%1" एड्रेस बुक में पहले से ही मोजूद है| + + + + The entered address "%1" is not a valid Arepacoin address. + + + + + Could not unlock wallet. + वॉलेट को unlock नहीं किया जा सकता| + + + + New key generation failed. + नयी कुंजी का निर्माण असफल रहा| + + + + GUIUtil::HelpMessageBox + + + + Arepacoin-Qt + + + + + version + + + + + Usage: + + + + + command-line options + + + + + UI options + + + + + Set language, for example "de_DE" (default: system locale) + + + + + Start minimized + + + + + Show splash screen on startup (default: 1) + + + + + OptionsDialog + + + Options + विकल्प + + + + &Main + + + + + Optional transaction fee per kB that helps make sure your transactions are processed quickly. Most transactions are 1 kB. Fee 0.01 recommended. + + + + + Pay transaction &fee + + + + + Reserved amount does not participate in staking and is therefore spendable at any time. + + + + + Reserve + + + + + Automatically start Arepacoin after logging in to the system. + + + + + &Start Arepacoin on system login + + + + + Detach block and address databases at shutdown. This means they can be moved to another data directory, but it slows down shutdown. The wallet is always detached. + + + + + &Detach databases at shutdown + + + + + &Network + + + + + Automatically open the Arepacoin client port on the router. This only works when your router supports UPnP and it is enabled. + + + + + Map port using &UPnP + + + + + Connect to the Arepacoin network through a SOCKS proxy (e.g. when connecting through Tor). + + + + + &Connect through SOCKS proxy: + + + + + Proxy &IP: + + + + + IP address of the proxy (e.g. 127.0.0.1) + + + + + &Port: + + + + + Port of the proxy (e.g. 9050) + + + + + SOCKS &Version: + + + + + SOCKS version of the proxy (e.g. 5) + + + + + &Window + + + + + Show only a tray icon after minimizing the window. + + + + + &Minimize to the tray instead of the taskbar + + + + + Minimize instead of exit the application when the window is closed. When this option is enabled, the application will be closed only after selecting Quit in the menu. + + + + + M&inimize on close + + + + + &Display + + + + + User Interface &language: + + + + + The user interface language can be set here. This setting will take effect after restarting Arepacoin. + + + + + &Unit to show amounts in: + + + + + Choose the default subdivision unit to show in the interface and when sending coins. + + + + + Whether to show Arepacoin addresses in the transaction list or not. + + + + + &Display addresses in transaction list + + + + + Whether to show coin control features or not. + + + + + Display coin &control features (experts only!) + + + + + &OK + &ओके + + + + &Cancel + &कैन्सल + + + + &Apply + + + + + default + + + + + + Warning + + + + + + This setting will take effect after restarting Arepacoin. + + + + + The supplied proxy address is invalid. + + + + + OverviewPage + + + Form + फार्म + + + + + The displayed information may be out of date. Your wallet automatically synchronizes with the Arepacoin network after a connection is established, but this process has not completed yet. + + + + + Stake: + + + + + Unconfirmed: + + + + + Wallet + वॉलेट + + + + Spendable: + + + + + Your current spendable balance + + + + + Immature: + + + + + Mined balance that has not yet matured + + + + + Total: + + + + + Your current total balance + + + + + <b>Recent transactions</b> + <b>हाल का लेन-देन</b> + + + + Total of transactions that have yet to be confirmed, and do not yet count toward the current balance + + + + + Total of coins that was staked, and do not yet count toward the current balance + + + + + + out of sync + + + + + QRCodeDialog + + + QR Code Dialog + + + + + Request Payment + + + + + Amount: + + + + + Label: + + + + + Message: + + + + + &Save As... + + + + + Error encoding URI into QR Code. + + + + + The entered amount is invalid, please check. + + + + + Resulting URI too long, try to reduce the text for label / message. + + + + + Save QR Code + + + + + PNG Images (*.png) + + + + + RPCConsole + + + Client name + + + + + + + + + + + + + + N/A + लागू नही + + + + + Client version + + + + + &Information + + + + + Using OpenSSL version + + + + + Startup time + + + + + Network + + + + + Number of connections + + + + + On testnet + + + + + Block chain + + + + + Current number of blocks + + + + + Estimated total blocks + + + + + Last block time + + + + + &Open + + + + + Command-line options + + + + + Show the Arepacoin-Qt help message to get a list with possible Arepacoin command-line options. + + + + + &Show + + + + + &Console + + + + + Build date + + + + + Arepacoin - Debug window + + + + + Arepacoin Core + + + + + Debug log file + + + + + Open the Arepacoin debug log file from the current data directory. This can take a few seconds for large log files. + + + + + Clear console + + + + + Welcome to the Arepacoin RPC console. + + + + + Use up and down arrows to navigate history, and <b>Ctrl-L</b> to clear screen. + + + + + Type <b>help</b> for an overview of available commands. + + + + + SendCoinsDialog + + + + + + + + + + Send Coins + सिक्के भेजें| + + + + Coin Control Features + + + + + Inputs... + + + + + automatically selected + + + + + Insufficient funds! + + + + + Quantity: + + + + + + 0 + + + + + Bytes: + + + + + Amount: + राशि : + + + + + + + 0.00 BC + + + + + Priority: + + + + + medium + + + + + Fee: + + + + + Low Output: + + + + + no + + + + + After Fee: + + + + + Change + + + + + custom change address + + + + + Send to multiple recipients at once + एक साथ कई प्राप्तकर्ताओं को भेजें + + + + Add &Recipient + + + + + Remove all transaction fields + + + + + Clear &All + + + + + Balance: + बाकी रकम : + + + + 123.456 BC + + + + + Confirm the send action + भेजने की पुष्टि करें + + + + S&end + + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Copy quantity + + + + + Copy amount + कॉपी राशि + + + + Copy fee + + + + + Copy after fee + + + + + Copy bytes + + + + + Copy priority + + + + + Copy low output + + + + + Copy change + + + + + <b>%1</b> to %2 (%3) + + + + + Confirm send coins + सिक्के भेजने की पुष्टि करें + + + + Are you sure you want to send %1? + + + + + and + + + + + The recipient address is not valid, please recheck. + + + + + The amount to pay must be larger than 0. + भेजा गया अमाउंट शुन्य से अधिक होना चाहिए| + + + + The amount exceeds your balance. + + + + + The total exceeds your balance when the %1 transaction fee is included. + + + + + Duplicate address found, can only send to each address once per send operation. + + + + + Error: Transaction creation failed. + + + + + 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. + + + + + WARNING: Invalid Arepacoin address + + + + + (no label) + (कोई लेबल नही !) + + + + WARNING: unknown change address + + + + + SendCoinsEntry + + + Form + + + + + A&mount: + अमाउंट: + + + + Pay &To: + प्राप्तकर्ता: + + + + + Enter a label for this address to add it to your address book + आपकी एड्रेस बुक में इस एड्रेस के लिए एक लेबल लिखें + + + + &Label: + लेबल: + + + + The address to send the payment to (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Choose address from address book + + + + + Alt+A + Alt-A + + + + Paste address from clipboard + Clipboard से एड्रेस paste करें + + + + Alt+P + Alt-P + + + + Remove this recipient + + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + SignVerifyMessageDialog + + + Signatures - Sign / Verify a Message + + + + + + &Sign Message + + + + + You can sign messages with your addresses to prove you own them. Be careful not to sign anything vague, as phishing attacks may try to trick you into signing your identity over to them. Only sign fully-detailed statements you agree to. + + + + + The address to sign the message with (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + + Choose an address from the address book + + + + + + Alt+A + Alt-A + + + + Paste address from clipboard + Clipboard से एड्रेस paste करें + + + + Alt+P + Alt-P + + + + Enter the message you want to sign here + + + + + Copy the current signature to the system clipboard + + + + + Sign the message to prove you own this Arepacoin address + + + + + Reset all sign message fields + + + + + + Clear &All + + + + + + &Verify Message + + + + + Enter the signing address, message (ensure you copy line breaks, spaces, tabs, etc. exactly) and signature below to verify the message. Be careful not to read more into the signature than what is in the signed message itself, to avoid being tricked by a man-in-the-middle attack. + + + + + The address the message was signed with (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Verify the message to ensure it was signed with the specified Arepacoin address + + + + + Reset all verify message fields + + + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Click "Sign Message" to generate signature + + + + + Enter Arepacoin signature + + + + + + The entered address is invalid. + + + + + + + + Please check the address and try again. + + + + + + The entered address does not refer to a key. + + + + + Wallet unlock was cancelled. + + + + + Private key for the entered address is not available. + + + + + Message signing failed. + + + + + Message signed. + + + + + The signature could not be decoded. + + + + + + Please check the signature and try again. + + + + + The signature did not match the message digest. + + + + + Message verification failed. + + + + + Message verified. + + + + + TransactionDesc + + + Open until %1 + खुला है जबतक %1 + + + + Open for %n block(s) + + + + + conflicted + + + + + %1/offline + + + + + %1/unconfirmed + %1/अपुष्ट + + + + %1 confirmations + %1 पुष्टियाँ + + + + Status + + + + + , broadcast through %n node(s) + + + + + Date + taareek + + + + Source + + + + + Generated + + + + + + From + + + + + + + To + + + + + + own address + + + + + label + + + + + + + + + Credit + + + + + matures in %n more block(s) + + + + + not accepted + + + + + + + + Debit + + + + + Transaction fee + + + + + Net amount + + + + + Message + + + + + Comment + + + + + Transaction ID + + + + + Generated coins must mature 6 blocks before they can be spent. When you generated this block, it was broadcast to the network to be added to the block chain. If it fails to get into the chain, its state will change to "not accepted" and it won't be spendable. This may occasionally happen if another node generates a block within a few seconds of yours. + + + + + Debug information + + + + + Transaction + + + + + Inputs + + + + + Amount + राशि + + + + true + सही + + + + false + ग़लत + + + + , has not been successfully broadcast yet + , अभी तक सफलतापूर्वक प्रसारित नहीं किया गया है + + + + unknown + अज्ञात + + + + TransactionDescDialog + + + Transaction details + लेन-देन का विवरण + + + + This pane shows a detailed description of the transaction + ये खिड़की आपको लेन-देन का विस्तृत विवरण देगी ! + + + + TransactionTableModel + + + Date + taareek + + + + Type + टाइप + + + + Address + पता + + + + Amount + राशि + + + + Open until %1 + खुला है जबतक %1 + + + + Confirmed (%1 confirmations) + पक्के ( %1 पक्का करना) + + + + Open for %n more block(s) + + + + + Offline + + + + + Unconfirmed + + + + + Confirming (%1 of %2 recommended confirmations) + + + + + Conflicted + + + + + Immature (%1 confirmations, will be available after %2) + + + + + This block was not received by any other nodes and will probably not be accepted! + यह ब्लॉक किसी भी और नोड को मिला नही है ! शायद यह ब्लॉक कोई भी नोड स्वीकारे गा नही ! + + + + Generated but not accepted + जेनरेट किया गया किंतु स्वीकारा नही गया ! + + + + Received with + स्वीकारा गया + + + + Received from + स्वीकार्य ओर से + + + + Sent to + भेजा गया + + + + Payment to yourself + भेजा खुद को भुगतान + + + + Mined + माइंड + + + + (n/a) + (लागू नहीं) + + + + Transaction status. Hover over this field to show number of confirmations. + ट्रांसेक्शन स्तिथि| पुष्टियों की संख्या जानने के लिए इस जगह पर माउस लायें| + + + + Date and time that the transaction was received. + तारीख तथा समय जब ये ट्रांसेक्शन प्राप्त हुई थी| + + + + Type of transaction. + ट्रांसेक्शन का प्रकार| + + + + Destination address of transaction. + ट्रांसेक्शन की मंजिल का पता| + + + + Amount removed from or added to balance. + अमाउंट बैलेंस से निकला या जमा किया गया | + + + + TransactionView + + + + All + सभी + + + + Today + आज + + + + This week + इस हफ्ते + + + + This month + इस महीने + + + + Last month + पिछले महीने + + + + This year + इस साल + + + + Range... + विस्तार... + + + + Received with + स्वीकार करना + + + + Sent to + भेजा गया + + + + To yourself + अपनेआप को + + + + Mined + माइंड + + + + Other + अन्य + + + + Enter address or label to search + ढूँदने के लिए कृपा करके पता या लेबल टाइप करे ! + + + + Min amount + लघुत्तम राशि + + + + Copy address + पता कॉपी करे + + + + Copy label + लेबल कॉपी करे + + + + Copy amount + कॉपी राशि + + + + Copy transaction ID + + + + + Edit label + एडिट लेबल + + + + Show transaction details + + + + + Export Transaction Data + + + + + Comma separated file (*.csv) + Comma separated file (*.csv) + + + + Confirmed + पक्का + + + + Date + taareek + + + + Type + टाइप + + + + Label + लेबल + + + + Address + पता + + + + Amount + राशि + + + + ID + ID + + + + Error exporting + + + + + Could not write to file %1. + + + + + Range: + विस्तार: + + + + to + तक + + + + WalletModel + + + Sending... + + + + + bitcoin-core + + + Arepacoin version + + + + + Usage: + खपत : + + + + Send command to -server or arepacoind + + + + + List commands + commands की लिस्ट बनाएं + + + + Get help for a command + किसी command के लिए मदद लें + + + + Options: + विकल्प: + + + + Specify configuration file (default: arepacoin.conf) + + + + + Specify pid file (default: arepacoind.pid) + + + + + Specify wallet file (within data directory) + + + + + Specify data directory + डेटा डायरेक्टरी बताएं + + + + Set database cache size in megabytes (default: 25) + + + + + Set database disk log size in megabytes (default: 100) + + + + + Listen for connections on <port> (default: 9853 or testnet: 19853) + + + + + Maintain at most <n> connections to peers (default: 125) + + + + + Connect to a node to retrieve peer addresses, and disconnect + + + + + Specify your own public address + + + + + Bind to given address. Use [host]:port notation for IPv6 + + + + + Stake your coins to support network and gain reward (default: 1) + + + + + Threshold for disconnecting misbehaving peers (default: 100) + + + + + Number of seconds to keep misbehaving peers from reconnecting (default: 86400) + + + + + An error occurred while setting up the RPC port %u for listening on IPv4: %s + + + + + Detach block and address databases. Increases shutdown time (default: 0) + + + + + 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. + + + + + Error: This transaction requires a transaction fee of at least %s because of its amount, complexity, or use of recently received funds + + + + + Listen for JSON-RPC connections on <port> (default: 9852 or testnet: 19852) + + + + + Accept command line and JSON-RPC commands + + + + + Error: Transaction creation failed + + + + + Error: Wallet locked, unable to create transaction + + + + + Importing blockchain data file. + + + + + Importing bootstrap blockchain data file. + + + + + Run in the background as a daemon and accept commands + बैकग्राउंड में डेमॉन बन कर रन करे तथा कमांड्स स्वीकार करें + + + + Use the test network + टेस्ट नेटवर्क का इस्तेमाल करे + + + + Accept connections from outside (default: 1 if no -proxy or -connect) + + + + + An error occurred while setting up the RPC port %u for listening on IPv6, falling back to IPv4: %s + + + + + Error initializing database environment %s! To recover, BACKUP THAT DIRECTORY, then remove everything from it except for wallet.dat. + + + + + Set maximum size of high-priority/low-fee transactions in bytes (default: 27000) + + + + + Warning: -paytxfee is set very high! This is the transaction fee you will pay if you send a transaction. + + + + + Warning: Please check that your computer's date and time are correct! If your clock is wrong Arepacoin will not work properly. + + + + + Warning: error reading wallet.dat! All keys read correctly, but transaction data or address book entries might be missing or incorrect. + + + + + Warning: wallet.dat corrupt, data salvaged! Original wallet.dat saved as wallet.{timestamp}.bak in %s; if your balance or transactions are incorrect you should restore from a backup. + + + + + Attempt to recover private keys from a corrupt wallet.dat + + + + + Block creation options: + + + + + Connect only to the specified node(s) + + + + + Discover own IP address (default: 1 when listening and no -externalip) + + + + + Failed to listen on any port. Use -listen=0 if you want this. + + + + + Find peers using DNS lookup (default: 1) + + + + + Sync checkpoints policy (default: strict) + + + + + Invalid -tor address: '%s' + + + + + Invalid amount for -reservebalance=<amount> + + + + + Maximum per-connection receive buffer, <n>*1000 bytes (default: 5000) + + + + + Maximum per-connection send buffer, <n>*1000 bytes (default: 1000) + + + + + Only connect to nodes in network <net> (IPv4, IPv6 or Tor) + + + + + Output extra debugging information. Implies all other -debug* options + + + + + Output extra network debugging information + + + + + Prepend debug output with timestamp + + + + + SSL options: (see the Bitcoin Wiki for SSL setup instructions) + + + + + Select the version of socks proxy to use (4-5, default: 5) + + + + + Send trace/debug info to console instead of debug.log file + + + + + Send trace/debug info to debugger + + + + + Set maximum block size in bytes (default: 250000) + + + + + Set minimum block size in bytes (default: 0) + + + + + Shrink debug.log file on client startup (default: 1 when no -debug) + + + + + Specify connection timeout in milliseconds (default: 5000) + + + + + Unable to sign checkpoint, wrong checkpointkey? + + + + + + Use UPnP to map the listening port (default: 0) + + + + + Use UPnP to map the listening port (default: 1 when listening) + + + + + Use proxy to reach tor hidden services (default: same as -proxy) + + + + + Username for JSON-RPC connections + + + + + Verifying database integrity... + + + + + WARNING: syncronized checkpoint violation detected, but skipped! + + + + + Warning: Disk space is low! + + + + + Warning: This version is obsolete, upgrade required! + + + + + wallet.dat corrupt, salvage failed + + + + + Password for JSON-RPC connections + + + + + %s, you must set a rpcpassword in the configuration file: + %s +It is recommended you use the following random password: +rpcuser=arepacoinrpc +rpcpassword=%s +(you do not need to remember this password) +The username and password MUST NOT be the same. +If the file does not exist, create it with owner-readable-only file permissions. +It is also recommended to set alertnotify so you are notified of problems; +for example: alertnotify=echo %%s | mail -s "Arepacoin Alert" admin@foo.com + + + + + + Find peers using internet relay chat (default: 0) + + + + + Sync time with other nodes. Disable if time on your system is precise e.g. syncing with NTP (default: 1) + + + + + When creating transactions, ignore inputs with value less than this (default: 0.01) + + + + + Allow JSON-RPC connections from specified IP address + + + + + Send commands to node running on <ip> (default: 127.0.0.1) + + + + + Execute command when the best block changes (%s in cmd is replaced by block hash) + + + + + Execute command when a wallet transaction changes (%s in cmd is replaced by TxID) + + + + + Require a confirmations for change (default: 0) + + + + + Enforce transaction scripts to use canonical PUSH operators (default: 1) + + + + + Execute command when a relevant alert is received (%s in cmd is replaced by message) + + + + + Upgrade wallet to latest format + + + + + Set key pool size to <n> (default: 100) + + + + + Rescan the block chain for missing wallet transactions + + + + + How many blocks to check at startup (default: 2500, 0 = all) + + + + + How thorough the block verification is (0-6, default: 1) + + + + + Imports blocks from external blk000?.dat file + + + + + Use OpenSSL (https) for JSON-RPC connections + + + + + Server certificate file (default: server.cert) + + + + + Server private key (default: server.pem) + + + + + Acceptable ciphers (default: TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH) + + + + + Error: Wallet unlocked for staking only, unable to create transaction. + + + + + WARNING: Invalid checkpoint found! Displayed transactions may not be correct! You may need to upgrade, or notify developers. + + + + + This help message + + + + + Wallet %s resides outside data directory %s. + + + + + Cannot obtain a lock on data directory %s. Arepacoin is probably already running. + + + + + Arepacoin + + + + + Unable to bind to %s on this computer (bind returned error %d, %s) + + + + + Connect through socks proxy + + + + + Allow DNS lookups for -addnode, -seednode and -connect + + + + + Loading addresses... + पता पुस्तक आ रही है... + + + + Error loading blkindex.dat + + + + + Error loading wallet.dat: Wallet corrupted + + + + + Error loading wallet.dat: Wallet requires newer version of Arepacoin + + + + + Wallet needed to be rewritten: restart Arepacoin to complete + + + + + Error loading wallet.dat + + + + + Invalid -proxy address: '%s' + + + + + Unknown network specified in -onlynet: '%s' + + + + + Unknown -socks proxy version requested: %i + + + + + Cannot resolve -bind address: '%s' + + + + + Cannot resolve -externalip address: '%s' + + + + + Invalid amount for -paytxfee=<amount>: '%s' + + + + + Error: could not start node + + + + + Sending... + + + + + Invalid amount + राशि ग़लत है + + + + Insufficient funds + + + + + Loading block index... + ब्लॉक इंडेक्स आ रहा है... + + + + Add a node to connect to and attempt to keep the connection open + + + + + Unable to bind to %s on this computer. Arepacoin is probably already running. + + + + + Fee per KB to add to transactions you send + + + + + Invalid amount for -mininput=<amount>: '%s' + + + + + Loading wallet... + वॉलेट आ रहा है... + + + + Cannot downgrade wallet + + + + + Cannot initialize keypool + + + + + Cannot write default address + + + + + Rescanning... + रि-स्केनी-इंग... + + + + Done loading + लोड हो गया| + + + + To use the %s option + + + + + Error + भूल + + + + You must set rpcpassword=<password> in the configuration file: +%s +If the file does not exist, create it with owner-readable-only file permissions. + + + + \ No newline at end of file diff --git a/src/qt/locale/bitcoin_hr.ts b/src/qt/locale/bitcoin_hr.ts new file mode 100755 index 0000000..d09dc39 --- /dev/null +++ b/src/qt/locale/bitcoin_hr.ts @@ -0,0 +1,3279 @@ + + + AboutDialog + + + About Arepacoin + + + + + <b>Arepacoin</b> version + + + + + Copyright © 2009-2014 The Bitcoin developers +Copyright © 2012-2014 The NovaCoin developers +Copyright © 2014 The Arepacoin developers + + + + + +This is experimental software. + +Distributed under the MIT/X11 software license, see the accompanying file COPYING or http://www.opensource.org/licenses/mit-license.php. + +This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit (http://www.openssl.org/) and cryptographic software written by Eric Young (eay@cryptsoft.com) and UPnP software written by Thomas Bernard. + + + + + AddressBookPage + + + Address Book + + + + + Double-click to edit address or label + Dvostruki klik za uređivanje adrese ili oznake + + + + Create a new address + Dodajte novu adresu + + + + Copy the currently selected address to the system clipboard + Kopiraj trenutno odabranu adresu u međuspremnik + + + + &New Address + + + + + These are your Arepacoin addresses for receiving payments. You may want to give a different one to each sender so you can keep track of who is paying you. + + + + + &Copy Address + &Kopirati adresu + + + + Show &QR Code + + + + + Sign a message to prove you own a Arepacoin address + + + + + Sign &Message + + + + + Delete the currently selected address from the list + + + + + Verify a message to ensure it was signed with a specified Arepacoin address + + + + + &Verify Message + + + + + &Delete + &Brisanje + + + + Copy &Label + Kopirati &oznaku + + + + &Edit + &Izmjeniti + + + + Export Address Book Data + + + + + Comma separated file (*.csv) + Datoteka vrijednosti odvojenih zarezom (*. csv) + + + + Error exporting + + + + + Could not write to file %1. + + + + + AddressTableModel + + + Label + Oznaka + + + + Address + Adresa + + + + (no label) + (bez oznake) + + + + AskPassphraseDialog + + + Passphrase Dialog + + + + + Enter passphrase + Unesite lozinku + + + + New passphrase + Nova lozinka + + + + Repeat new passphrase + Ponovite novu lozinku + + + + Serves to disable the trivial sendmoney when OS account compromised. Provides no real security. + + + + + For staking only + + + + + Enter the new passphrase to the wallet.<br/>Please use a passphrase of <b>10 or more random characters</b>, or <b>eight or more words</b>. + Unesite novi lozinku za novčanik. <br/> Molimo Vas da koristite zaporku od <b>10 ili više slučajnih znakova,</b> ili <b>osam ili više riječi.</b> + + + + Encrypt wallet + Šifriranje novčanika + + + + This operation needs your wallet passphrase to unlock the wallet. + Ova operacija treba lozinku vašeg novčanika kako bi se novčanik otključao. + + + + Unlock wallet + Otključaj novčanik + + + + This operation needs your wallet passphrase to decrypt the wallet. + Ova operacija treba lozinku vašeg novčanika kako bi se novčanik dešifrirao. + + + + Decrypt wallet + Dešifriranje novčanika. + + + + Change passphrase + Promjena lozinke + + + + Enter the old and new passphrase to the wallet. + Unesite staru i novu lozinku za novčanik. + + + + Confirm wallet encryption + Potvrdi šifriranje novčanika + + + + Warning: If you encrypt your wallet and lose your passphrase, you will <b>LOSE ALL OF YOUR COINS</b>! + + + + + Are you sure you wish to encrypt your wallet? + Jeste li sigurni da želite šifrirati svoj novčanik? + + + + IMPORTANT: Any previous backups you have made of your wallet file should be replaced with the newly generated, encrypted wallet file. For security reasons, previous backups of the unencrypted wallet file will become useless as soon as you start using the new, encrypted wallet. + + + + + + Warning: The Caps Lock key is on! + Upozorenje: Tipka Caps Lock je uključena! + + + + + Wallet encrypted + Novčanik šifriran + + + + Arepacoin will close now to finish the encryption process. Remember that encrypting your wallet cannot fully protect your coins from being stolen by malware infecting your computer. + + + + + + + + Wallet encryption failed + Šifriranje novčanika nije uspjelo + + + + Wallet encryption failed due to an internal error. Your wallet was not encrypted. + Šifriranje novčanika nije uspjelo zbog interne pogreške. Vaš novčanik nije šifriran. + + + + + The supplied passphrases do not match. + Priložene lozinke se ne podudaraju. + + + + Wallet unlock failed + Otključavanje novčanika nije uspjelo + + + + + + The passphrase entered for the wallet decryption was incorrect. + Lozinka za dešifriranje novčanika nije točna. + + + + Wallet decryption failed + Dešifriranje novčanika nije uspjelo + + + + Wallet passphrase was successfully changed. + Lozinka novčanika je uspješno promijenjena. + + + + BitcoinGUI + + + Sign &message... + &Potpišite poruku... + + + + Synchronizing with network... + Usklađivanje s mrežom ... + + + + &Overview + &Pregled + + + + Show general overview of wallet + Prikaži opći pregled novčanika + + + + &Transactions + &Transakcije + + + + Browse transaction history + Pretraži povijest transakcija + + + + &Address Book + + + + + Edit the list of stored addresses and labels + + + + + &Receive coins + + + + + Show the list of addresses for receiving payments + + + + + &Send coins + + + + + E&xit + &Izlaz + + + + Quit application + Izlazak iz programa + + + + Show information about Arepacoin + + + + + About &Qt + Više o &Qt + + + + Show information about Qt + Prikaži informacije o Qt + + + + &Options... + &Postavke + + + + &Encrypt Wallet... + &Šifriraj novčanik... + + + + &Backup Wallet... + &Backup novčanika... + + + + &Change Passphrase... + &Promijena lozinke... + + + + ~%n block(s) remaining + + + + + Downloaded %1 of %2 blocks of transaction history (%3% done). + + + + + &Export... + + + + + Send coins to a Arepacoin address + + + + + Modify configuration options for Arepacoin + + + + + Export the data in the current tab to a file + + + + + Encrypt or decrypt wallet + + + + + Backup wallet to another location + Napravite sigurnosnu kopiju novčanika na drugoj lokaciji + + + + Change the passphrase used for wallet encryption + Promijenite lozinku za šifriranje novčanika + + + + &Debug window + + + + + Open debugging and diagnostic console + + + + + &Verify message... + &Potvrdite poruku... + + + + Arepacoin + + + + + Wallet + Novčanik + + + + &About Arepacoin + + + + + &Show / Hide + + + + + Unlock wallet + + + + + &Lock Wallet + + + + + Lock wallet + + + + + &File + &Datoteka + + + + &Settings + &Konfiguracija + + + + &Help + &Pomoć + + + + Tabs toolbar + Traka kartica + + + + Actions toolbar + + + + + + [testnet] + [testnet] + + + + + Arepacoin client + + + + + %n active connection(s) to Arepacoin network + + + + + Downloaded %1 blocks of transaction history. + + + + + Staking.<br>Your weight is %1<br>Network weight is %2<br>Expected time to earn reward is %3 + + + + + Not staking because wallet is locked + + + + + Not staking because wallet is offline + + + + + Not staking because wallet is syncing + + + + + Not staking because you don't have mature coins + + + + + %n second(s) ago + + + + + &Unlock Wallet... + + + + + %n minute(s) ago + + + + + %n hour(s) ago + + + + + %n day(s) ago + + + + + Up to date + Ažurno + + + + Catching up... + Ažuriranje... + + + + Last received block was generated %1. + + + + + This transaction is over the size limit. You can still send it for a fee of %1, which goes to the nodes that process your transaction and helps to support the network. Do you want to pay the fee? + + + + + Confirm transaction fee + + + + + Sent transaction + Poslana transakcija + + + + Incoming transaction + Dolazna transakcija + + + + Date: %1 +Amount: %2 +Type: %3 +Address: %4 + + Datum:%1 +Iznos:%2 +Tip:%3 +Adresa:%4 + + + + + + URI handling + + + + + + URI can not be parsed! This can be caused by an invalid Arepacoin address or malformed URI parameters. + + + + + Wallet is <b>encrypted</b> and currently <b>unlocked</b> + Novčanik je <b>šifriran</b> i trenutno <b>otključan</b> + + + + Wallet is <b>encrypted</b> and currently <b>locked</b> + Novčanik je <b>šifriran</b> i trenutno <b>zaključan</b> + + + + Backup Wallet + + + + + Wallet Data (*.dat) + + + + + Backup Failed + + + + + There was an error trying to save the wallet data to the new location. + + + + + %n second(s) + + + + + %n minute(s) + + + + + %n hour(s) + + + + + %n day(s) + + + + + Not staking + + + + + A fatal error occurred. Arepacoin can no longer continue safely and will quit. + + + + + ClientModel + + + Network Alert + + + + + CoinControlDialog + + + Coin Control + + + + + Quantity: + + + + + Bytes: + + + + + Amount: + Iznos: + + + + Priority: + + + + + Fee: + + + + + Low Output: + + + + + no + + + + + After Fee: + + + + + Change: + + + + + (un)select all + + + + + Tree mode + + + + + List mode + + + + + Amount + Iznos + + + + Label + + + + + Address + Adresa + + + + Date + Datum + + + + Confirmations + + + + + Confirmed + Potvrđeno + + + + Priority + + + + + Copy address + Kopirati adresu + + + + Copy label + Kopirati oznaku + + + + + Copy amount + Kopiraj iznos + + + + Copy transaction ID + + + + + Copy quantity + + + + + Copy fee + + + + + Copy after fee + + + + + Copy bytes + + + + + Copy priority + + + + + Copy low output + + + + + Copy change + + + + + highest + + + + + high + + + + + medium-high + + + + + medium + + + + + low-medium + + + + + low + + + + + lowest + + + + + DUST + + + + + yes + + + + + This label turns red, if the transaction size is bigger than 10000 bytes. + + This means a fee of at least %1 per kb is required. + + Can vary +/- 1 Byte per input. + + + + + Transactions with higher priority get more likely into a block. + +This label turns red, if the priority is smaller than "medium". + + This means a fee of at least %1 per kb is required. + + + + + This label turns red, if any recipient receives an amount smaller than %1. + + This means a fee of at least %2 is required. + + Amounts below 0.546 times the minimum relay fee are shown as DUST. + + + + + This label turns red, if the change is smaller than %1. + + This means a fee of at least %2 is required. + + + + + + (no label) + (bez oznake) + + + + change from %1 (%2) + + + + + (change) + + + + + EditAddressDialog + + + Edit Address + Izmjeni adresu + + + + &Label + &Oznaka + + + + The label associated with this address book entry + + + + + &Address + &Adresa + + + + The address associated with this address book entry. This can only be modified for sending addresses. + + + + + New receiving address + Nova adresa za primanje + + + + New sending address + Nova adresa za slanje + + + + Edit receiving address + Uredi adresu za primanje + + + + Edit sending address + Uredi adresu za slanje + + + + The entered address "%1" is already in the address book. + Upisana adresa "%1" je već u adresaru. + + + + The entered address "%1" is not a valid Arepacoin address. + + + + + Could not unlock wallet. + Ne mogu otključati novčanik. + + + + New key generation failed. + Stvaranje novog ključa nije uspjelo. + + + + GUIUtil::HelpMessageBox + + + + Arepacoin-Qt + + + + + version + + + + + Usage: + + + + + command-line options + + + + + UI options + + + + + Set language, for example "de_DE" (default: system locale) + + + + + Start minimized + + + + + Show splash screen on startup (default: 1) + + + + + OptionsDialog + + + Options + Postavke + + + + &Main + &Glavno + + + + Optional transaction fee per kB that helps make sure your transactions are processed quickly. Most transactions are 1 kB. Fee 0.01 recommended. + + + + + Pay transaction &fee + Plati &naknadu za transakciju + + + + Reserved amount does not participate in staking and is therefore spendable at any time. + + + + + Reserve + + + + + Automatically start Arepacoin after logging in to the system. + + + + + &Start Arepacoin on system login + + + + + Detach block and address databases at shutdown. This means they can be moved to another data directory, but it slows down shutdown. The wallet is always detached. + + + + + &Detach databases at shutdown + + + + + &Network + &Mreža + + + + Automatically open the Arepacoin client port on the router. This only works when your router supports UPnP and it is enabled. + + + + + Map port using &UPnP + Mapiraj port koristeći &UPnP + + + + Connect to the Arepacoin network through a SOCKS proxy (e.g. when connecting through Tor). + + + + + &Connect through SOCKS proxy: + + + + + Proxy &IP: + Proxy &IP: + + + + IP address of the proxy (e.g. 127.0.0.1) + + + + + &Port: + + + + + Port of the proxy (e.g. 9050) + Port od proxy-a (npr. 9050) + + + + SOCKS &Version: + SOCKS &Verzija: + + + + SOCKS version of the proxy (e.g. 5) + + + + + &Window + &Prozor + + + + Show only a tray icon after minimizing the window. + Prikaži samo ikonu u sistemskoj traci nakon minimiziranja prozora + + + + &Minimize to the tray instead of the taskbar + &Minimiziraj u sistemsku traku umjesto u traku programa + + + + Minimize instead of exit the application when the window is closed. When this option is enabled, the application will be closed only after selecting Quit in the menu. + Minimizirati umjesto izaći iz aplikacije kada je prozor zatvoren. Kada je ova opcija omogućena, aplikacija će biti zatvorena tek nakon odabira Izlaz u izborniku. + + + + M&inimize on close + M&inimiziraj kod zatvaranja + + + + &Display + &Prikaz + + + + User Interface &language: + + + + + The user interface language can be set here. This setting will take effect after restarting Arepacoin. + + + + + &Unit to show amounts in: + &Jedinica za prikazivanje iznosa: + + + + Choose the default subdivision unit to show in the interface and when sending coins. + Izaberite željeni najmanji dio bitcoina koji će biti prikazan u sučelju i koji će se koristiti za plaćanje. + + + + Whether to show Arepacoin addresses in the transaction list or not. + + + + + &Display addresses in transaction list + &Prikaži adrese u popisu transakcija + + + + Whether to show coin control features or not. + + + + + Display coin &control features (experts only!) + + + + + &OK + &U redu + + + + &Cancel + &Odustani + + + + &Apply + + + + + default + standardne vrijednosti + + + + + Warning + + + + + + This setting will take effect after restarting Arepacoin. + + + + + The supplied proxy address is invalid. + + + + + OverviewPage + + + Form + Oblik + + + + + The displayed information may be out of date. Your wallet automatically synchronizes with the Arepacoin network after a connection is established, but this process has not completed yet. + + + + + Stake: + + + + + Unconfirmed: + + + + + Wallet + Novčanik + + + + Spendable: + + + + + Your current spendable balance + + + + + Immature: + + + + + Mined balance that has not yet matured + + + + + Total: + Ukupno: + + + + Your current total balance + + + + + <b>Recent transactions</b> + <b>Nedavne transakcije</b> + + + + Total of transactions that have yet to be confirmed, and do not yet count toward the current balance + + + + + Total of coins that was staked, and do not yet count toward the current balance + + + + + + out of sync + + + + + QRCodeDialog + + + QR Code Dialog + + + + + Request Payment + + + + + Amount: + + + + + Label: + + + + + Message: + + + + + &Save As... + + + + + Error encoding URI into QR Code. + + + + + The entered amount is invalid, please check. + + + + + Resulting URI too long, try to reduce the text for label / message. + + + + + Save QR Code + + + + + PNG Images (*.png) + + + + + RPCConsole + + + Client name + Ime klijenta + + + + + + + + + + + + + N/A + N/A + + + + Client version + Verzija klijenta + + + + &Information + &Informacija + + + + Using OpenSSL version + Koristim OpenSSL verziju + + + + Startup time + + + + + Network + Mreža + + + + Number of connections + Broj konekcija + + + + On testnet + + + + + Block chain + Lanac blokova + + + + Current number of blocks + Trenutni broj blokova + + + + Estimated total blocks + Procjenjeni ukupni broj blokova + + + + Last block time + Posljednje vrijeme bloka + + + + &Open + &Otvori + + + + Command-line options + + + + + Show the Arepacoin-Qt help message to get a list with possible Arepacoin command-line options. + + + + + &Show + + + + + &Console + &Konzola + + + + Build date + + + + + Arepacoin - Debug window + + + + + Arepacoin Core + + + + + Debug log file + + + + + Open the Arepacoin debug log file from the current data directory. This can take a few seconds for large log files. + + + + + Clear console + Očisti konzolu + + + + Welcome to the Arepacoin RPC console. + + + + + Use up and down arrows to navigate history, and <b>Ctrl-L</b> to clear screen. + + + + + Type <b>help</b> for an overview of available commands. + + + + + SendCoinsDialog + + + + + + + + + + Send Coins + Slanje novca + + + + Coin Control Features + + + + + Inputs... + + + + + automatically selected + + + + + Insufficient funds! + + + + + Quantity: + + + + + + 0 + + + + + Bytes: + + + + + Amount: + Iznos: + + + + + + + 0.00 BC + + + + + Priority: + + + + + medium + + + + + Fee: + + + + + Low Output: + + + + + no + + + + + After Fee: + + + + + Change + + + + + custom change address + + + + + Send to multiple recipients at once + Pošalji k nekoliko primatelja odjednom + + + + Add &Recipient + &Dodaj primatelja + + + + Remove all transaction fields + + + + + Clear &All + Obriši &sve + + + + Balance: + Stanje: + + + + 123.456 BC + + + + + Confirm the send action + Potvrdi akciju slanja + + + + S&end + &Pošalji + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Copy quantity + + + + + Copy amount + Kopiraj iznos + + + + Copy fee + + + + + Copy after fee + + + + + Copy bytes + + + + + Copy priority + + + + + Copy low output + + + + + Copy change + + + + + <b>%1</b> to %2 (%3) + + + + + Confirm send coins + Potvrdi slanje novca + + + + Are you sure you want to send %1? + + + + + and + + + + + The recipient address is not valid, please recheck. + Adresa primatelja je nevaljala, molimo provjerite je ponovo. + + + + The amount to pay must be larger than 0. + Iznos mora biti veći od 0. + + + + The amount exceeds your balance. + Iznos je veći od stanja računa. + + + + The total exceeds your balance when the %1 transaction fee is included. + Iznos je veći od stanja računa kad se doda naknada za transakcije od %1. + + + + Duplicate address found, can only send to each address once per send operation. + Pronašli smo adresu koja se ponavlja. U svakom plaćanju program može svaku adresu koristiti samo jedanput. + + + + Error: Transaction creation failed. + + + + + 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. + + + + + WARNING: Invalid Arepacoin address + + + + + (no label) + (bez oznake) + + + + WARNING: unknown change address + + + + + SendCoinsEntry + + + Form + + + + + A&mount: + &Iznos: + + + + Pay &To: + &Primatelj plaćanja: + + + + + Enter a label for this address to add it to your address book + Unesite oznaku za ovu adresu kako bi ju dodali u vaš adresar + + + + &Label: + &Oznaka: + + + + The address to send the payment to (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Choose address from address book + + + + + Alt+A + Alt+A + + + + Paste address from clipboard + Zalijepi adresu iz međuspremnika + + + + Alt+P + Alt+P + + + + Remove this recipient + + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + SignVerifyMessageDialog + + + Signatures - Sign / Verify a Message + + + + + + &Sign Message + &Potpišite poruku + + + + You can sign messages with your addresses to prove you own them. Be careful not to sign anything vague, as phishing attacks may try to trick you into signing your identity over to them. Only sign fully-detailed statements you agree to. + Možete potpisati poruke sa svojom adresom kako bi dokazali da ih posjedujete. Budite oprezni da ne potpisujete ništa mutno, jer bi vas phishing napadi mogli na prevaru natjerati da prepišete svoj identitet njima. Potpisujte samo detaljno objašnjene izjave sa kojima se slažete. + + + + The address to sign the message with (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + + Choose an address from the address book + + + + + + Alt+A + Alt+A + + + + Paste address from clipboard + Zalijepi adresu iz međuspremnika + + + + Alt+P + Alt+P + + + + Enter the message you want to sign here + Upišite poruku koju želite potpisati ovdje + + + + Copy the current signature to the system clipboard + + + + + Sign the message to prove you own this Arepacoin address + + + + + Reset all sign message fields + + + + + + Clear &All + Obriši &sve + + + + + &Verify Message + &Potvrdite poruku + + + + Enter the signing address, message (ensure you copy line breaks, spaces, tabs, etc. exactly) and signature below to verify the message. Be careful not to read more into the signature than what is in the signed message itself, to avoid being tricked by a man-in-the-middle attack. + + + + + The address the message was signed with (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Verify the message to ensure it was signed with the specified Arepacoin address + + + + + Reset all verify message fields + + + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Click "Sign Message" to generate signature + + + + + Enter Arepacoin signature + + + + + + The entered address is invalid. + + + + + + + + Please check the address and try again. + + + + + + The entered address does not refer to a key. + + + + + Wallet unlock was cancelled. + Otključavanje novčanika je otkazano. + + + + Private key for the entered address is not available. + + + + + Message signing failed. + + + + + Message signed. + Poruka je potpisana. + + + + The signature could not be decoded. + + + + + + Please check the signature and try again. + + + + + The signature did not match the message digest. + + + + + Message verification failed. + + + + + Message verified. + + + + + TransactionDesc + + + Open until %1 + Otvoren do %1 + + + + Open for %n block(s) + + + + + conflicted + + + + + %1/offline + %1 nije dostupan + + + + %1/unconfirmed + %1/nepotvrđeno + + + + %1 confirmations + %1 potvrda + + + + Status + Status + + + + , broadcast through %n node(s) + + + + + Date + Datum + + + + Source + Izvor + + + + Generated + Generiran + + + + + From + Od + + + + + + To + Za + + + + + own address + vlastita adresa + + + + label + oznaka + + + + + + + + Credit + Uplaćeno + + + + matures in %n more block(s) + + + + + not accepted + Nije prihvaćeno + + + + + + + Debit + Zaduženje + + + + Transaction fee + Naknada za transakciju + + + + Net amount + Neto iznos + + + + Message + Poruka + + + + Comment + Komentar + + + + Transaction ID + ID transakcije + + + + Generated coins must mature 6 blocks before they can be spent. When you generated this block, it was broadcast to the network to be added to the block chain. If it fails to get into the chain, its state will change to "not accepted" and it won't be spendable. This may occasionally happen if another node generates a block within a few seconds of yours. + + + + + Debug information + + + + + Transaction + Transakcija + + + + Inputs + Unosi + + + + Amount + Iznos + + + + true + + + + + false + + + + + , has not been successfully broadcast yet + , još nije bio uspješno emitiran + + + + unknown + nepoznato + + + + TransactionDescDialog + + + Transaction details + Detalji transakcije + + + + This pane shows a detailed description of the transaction + Ova panela prikazuje detaljni opis transakcije + + + + TransactionTableModel + + + Date + Datum + + + + Type + Tip + + + + Address + Adresa + + + + Amount + Iznos + + + + Open until %1 + Otvoren do %1 + + + + Confirmed (%1 confirmations) + Potvrđen (%1 potvrda) + + + + Open for %n more block(s) + + + + + Offline + + + + + Unconfirmed + + + + + Confirming (%1 of %2 recommended confirmations) + + + + + Conflicted + + + + + Immature (%1 confirmations, will be available after %2) + + + + + This block was not received by any other nodes and will probably not be accepted! + Generirano - Upozorenje: ovaj blok nije bio primljen od strane bilo kojeg drugog noda i vjerojatno neće biti prihvaćen! + + + + Generated but not accepted + Generirano, ali nije prihvaćeno + + + + Received with + Primljeno s + + + + Received from + Primljeno od + + + + Sent to + Poslano za + + + + Payment to yourself + Plaćanje samom sebi + + + + Mined + Rudareno + + + + (n/a) + (n/d) + + + + Transaction status. Hover over this field to show number of confirmations. + Status transakcije + + + + Date and time that the transaction was received. + Datum i vrijeme kad je transakcija primljena + + + + Type of transaction. + Vrsta transakcije. + + + + Destination address of transaction. + Odredište transakcije + + + + Amount removed from or added to balance. + Iznos odbijen od ili dodan k saldu. + + + + TransactionView + + + + All + Sve + + + + Today + Danas + + + + This week + Ovaj tjedan + + + + This month + Ovaj mjesec + + + + Last month + Prošli mjesec + + + + This year + Ove godine + + + + Range... + Raspon... + + + + Received with + Primljeno s + + + + Sent to + Poslano za + + + + To yourself + Tebi + + + + Mined + Rudareno + + + + Other + Ostalo + + + + Enter address or label to search + Unesite adresu ili oznaku za pretraživanje + + + + Min amount + Min iznos + + + + Copy address + Kopirati adresu + + + + Copy label + Kopirati oznaku + + + + Copy amount + Kopiraj iznos + + + + Copy transaction ID + + + + + Edit label + Izmjeniti oznaku + + + + Show transaction details + + + + + Export Transaction Data + + + + + Comma separated file (*.csv) + Datoteka podataka odvojenih zarezima (*.csv) + + + + Confirmed + Potvrđeno + + + + Date + Datum + + + + Type + Tip + + + + Label + Oznaka + + + + Address + Adresa + + + + Amount + Iznos + + + + ID + ID + + + + Error exporting + + + + + Could not write to file %1. + + + + + Range: + Raspon: + + + + to + za + + + + WalletModel + + + Sending... + + + + + bitcoin-core + + + Arepacoin version + + + + + Usage: + Upotreba: + + + + Send command to -server or arepacoind + + + + + List commands + Prikaži komande + + + + Get help for a command + Potraži pomoć za komandu + + + + Options: + Postavke: + + + + Specify configuration file (default: arepacoin.conf) + + + + + Specify pid file (default: arepacoind.pid) + + + + + Specify wallet file (within data directory) + + + + + Specify data directory + Odredi direktorij za datoteke + + + + Set database cache size in megabytes (default: 25) + Postavi cache za bazu podataka u MB (zadano:25) + + + + Set database disk log size in megabytes (default: 100) + + + + + Listen for connections on <port> (default: 9853 or testnet: 19853) + + + + + Maintain at most <n> connections to peers (default: 125) + Održavaj najviše <n> veza sa članovima (default: 125) + + + + Connect to a node to retrieve peer addresses, and disconnect + + + + + Specify your own public address + + + + + Bind to given address. Use [host]:port notation for IPv6 + + + + + Stake your coins to support network and gain reward (default: 1) + + + + + Threshold for disconnecting misbehaving peers (default: 100) + Prag za odspajanje članova koji se čudno ponašaju (default: 100) + + + + Number of seconds to keep misbehaving peers from reconnecting (default: 86400) + Broj sekundi koliko se članovima koji se čudno ponašaju neće dopustiti da se opet spoje (default: 86400) + + + + An error occurred while setting up the RPC port %u for listening on IPv4: %s + + + + + Detach block and address databases. Increases shutdown time (default: 0) + + + + + 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. + + + + + Error: This transaction requires a transaction fee of at least %s because of its amount, complexity, or use of recently received funds + + + + + Listen for JSON-RPC connections on <port> (default: 9852 or testnet: 19852) + + + + + Accept command line and JSON-RPC commands + Prihvati komande iz tekst moda i JSON-RPC + + + + Error: Transaction creation failed + + + + + Error: Wallet locked, unable to create transaction + + + + + Importing blockchain data file. + + + + + Importing bootstrap blockchain data file. + + + + + Run in the background as a daemon and accept commands + Izvršavaj u pozadini kao uslužnik i prihvaćaj komande + + + + Use the test network + Koristi test mrežu + + + + Accept connections from outside (default: 1 if no -proxy or -connect) + + + + + An error occurred while setting up the RPC port %u for listening on IPv6, falling back to IPv4: %s + + + + + Error initializing database environment %s! To recover, BACKUP THAT DIRECTORY, then remove everything from it except for wallet.dat. + + + + + Set maximum size of high-priority/low-fee transactions in bytes (default: 27000) + + + + + Warning: -paytxfee is set very high! This is the transaction fee you will pay if you send a transaction. + Upozorenje: -paytxfee je podešen na preveliki iznos. To je iznos koji ćete platiti za obradu transakcije. + + + + Warning: Please check that your computer's date and time are correct! If your clock is wrong Arepacoin will not work properly. + + + + + Warning: error reading wallet.dat! All keys read correctly, but transaction data or address book entries might be missing or incorrect. + + + + + Warning: wallet.dat corrupt, data salvaged! Original wallet.dat saved as wallet.{timestamp}.bak in %s; if your balance or transactions are incorrect you should restore from a backup. + + + + + Attempt to recover private keys from a corrupt wallet.dat + + + + + Block creation options: + Opcije za kreiranje bloka: + + + + Connect only to the specified node(s) + Poveži se samo sa određenim nodom + + + + Discover own IP address (default: 1 when listening and no -externalip) + + + + + Failed to listen on any port. Use -listen=0 if you want this. + + + + + Find peers using DNS lookup (default: 1) + + + + + Sync checkpoints policy (default: strict) + + + + + Invalid -tor address: '%s' + + + + + Invalid amount for -reservebalance=<amount> + + + + + Maximum per-connection receive buffer, <n>*1000 bytes (default: 5000) + + + + + Maximum per-connection send buffer, <n>*1000 bytes (default: 1000) + + + + + Only connect to nodes in network <net> (IPv4, IPv6 or Tor) + + + + + Output extra debugging information. Implies all other -debug* options + + + + + Output extra network debugging information + + + + + Prepend debug output with timestamp + + + + + SSL options: (see the Bitcoin Wiki for SSL setup instructions) + SSL postavke: (za detalje o podešavanju SSL opcija vidi Bitcoin Wiki) + + + + Select the version of socks proxy to use (4-5, default: 5) + + + + + Send trace/debug info to console instead of debug.log file + Šalji trace/debug informacije na konzolu umjesto u debug.log datoteku + + + + Send trace/debug info to debugger + + + + + Set maximum block size in bytes (default: 250000) + + + + + Set minimum block size in bytes (default: 0) + Podesite minimalnu veličinu bloka u bajtovima (default: 0) + + + + Shrink debug.log file on client startup (default: 1 when no -debug) + + + + + Specify connection timeout in milliseconds (default: 5000) + Odredi vremenski prozor za spajanje na mrežu u milisekundama (ugrađeni izbor: 5000) + + + + Unable to sign checkpoint, wrong checkpointkey? + + + + + + Use UPnP to map the listening port (default: 0) + Pokušaj koristiti UPnP da otvoriš port za uslugu (default: 0) + + + + Use UPnP to map the listening port (default: 1 when listening) + Pokušaj koristiti UPnP da otvoriš port za uslugu (default: 1 when listening) + + + + Use proxy to reach tor hidden services (default: same as -proxy) + + + + + Username for JSON-RPC connections + Korisničko ime za JSON-RPC veze + + + + Verifying database integrity... + + + + + WARNING: syncronized checkpoint violation detected, but skipped! + + + + + Warning: Disk space is low! + + + + + Warning: This version is obsolete, upgrade required! + + + + + wallet.dat corrupt, salvage failed + + + + + Password for JSON-RPC connections + Lozinka za JSON-RPC veze + + + + %s, you must set a rpcpassword in the configuration file: + %s +It is recommended you use the following random password: +rpcuser=arepacoinrpc +rpcpassword=%s +(you do not need to remember this password) +The username and password MUST NOT be the same. +If the file does not exist, create it with owner-readable-only file permissions. +It is also recommended to set alertnotify so you are notified of problems; +for example: alertnotify=echo %%s | mail -s "Arepacoin Alert" admin@foo.com + + + + + + Find peers using internet relay chat (default: 0) + + + + + Sync time with other nodes. Disable if time on your system is precise e.g. syncing with NTP (default: 1) + + + + + When creating transactions, ignore inputs with value less than this (default: 0.01) + + + + + Allow JSON-RPC connections from specified IP address + Dozvoli JSON-RPC povezivanje s određene IP adrese + + + + Send commands to node running on <ip> (default: 127.0.0.1) + Pošalji komande nodu na adresi <ip> (ugrađeni izbor: 127.0.0.1) + + + + Execute command when the best block changes (%s in cmd is replaced by block hash) + Izvršite naredbu kada se najbolji blok promjeni (%s u cmd je zamjenjen sa block hash) + + + + Execute command when a wallet transaction changes (%s in cmd is replaced by TxID) + + + + + Require a confirmations for change (default: 0) + + + + + Enforce transaction scripts to use canonical PUSH operators (default: 1) + + + + + Execute command when a relevant alert is received (%s in cmd is replaced by message) + + + + + Upgrade wallet to latest format + Nadogradite novčanik u posljednji format. + + + + Set key pool size to <n> (default: 100) + Podesi memorijski prostor za ključeve na <n> (ugrađeni izbor: 100) + + + + Rescan the block chain for missing wallet transactions + Ponovno pretraži lanac blokova za transakcije koje nedostaju + + + + How many blocks to check at startup (default: 2500, 0 = all) + + + + + How thorough the block verification is (0-6, default: 1) + + + + + Imports blocks from external blk000?.dat file + + + + + Use OpenSSL (https) for JSON-RPC connections + Koristi OpenSSL (https) za JSON-RPC povezivanje + + + + Server certificate file (default: server.cert) + Uslužnikov SSL certifikat (ugrađeni izbor: server.cert) + + + + Server private key (default: server.pem) + Uslužnikov privatni ključ (ugrađeni izbor: server.pem) + + + + Acceptable ciphers (default: TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH) + + + + + Error: Wallet unlocked for staking only, unable to create transaction. + + + + + WARNING: Invalid checkpoint found! Displayed transactions may not be correct! You may need to upgrade, or notify developers. + + + + + This help message + Ova poruka za pomoć + + + + Wallet %s resides outside data directory %s. + + + + + Cannot obtain a lock on data directory %s. Arepacoin is probably already running. + + + + + Arepacoin + + + + + Unable to bind to %s on this computer (bind returned error %d, %s) + Program ne može koristiti %s na ovom računalu (bind returned error %d, %s) + + + + Connect through socks proxy + + + + + Allow DNS lookups for -addnode, -seednode and -connect + Dozvoli DNS upite za dodavanje nodova i povezivanje + + + + Loading addresses... + Učitavanje adresa... + + + + Error loading blkindex.dat + + + + + Error loading wallet.dat: Wallet corrupted + Greška kod učitavanja wallet.dat: Novčanik pokvaren + + + + Error loading wallet.dat: Wallet requires newer version of Arepacoin + + + + + Wallet needed to be rewritten: restart Arepacoin to complete + + + + + Error loading wallet.dat + Greška kod učitavanja wallet.dat + + + + Invalid -proxy address: '%s' + Nevaljala -proxy adresa: '%s' + + + + Unknown network specified in -onlynet: '%s' + + + + + Unknown -socks proxy version requested: %i + + + + + Cannot resolve -bind address: '%s' + + + + + Cannot resolve -externalip address: '%s' + + + + + Invalid amount for -paytxfee=<amount>: '%s' + Nevaljali iznos za opciju -paytxfee=<amount>: '%s' + + + + Error: could not start node + + + + + Sending... + + + + + Invalid amount + Nevaljali iznos za opciju + + + + Insufficient funds + Nedovoljna sredstva + + + + Loading block index... + Učitavanje indeksa blokova... + + + + Add a node to connect to and attempt to keep the connection open + Unesite nod s kojim se želite spojiti and attempt to keep the connection open + + + + Unable to bind to %s on this computer. Arepacoin is probably already running. + + + + + Fee per KB to add to transactions you send + + + + + Invalid amount for -mininput=<amount>: '%s' + + + + + Loading wallet... + Učitavanje novčanika... + + + + Cannot downgrade wallet + Nije moguće novčanik vratiti na prijašnju verziju. + + + + Cannot initialize keypool + + + + + Cannot write default address + Nije moguće upisati zadanu adresu. + + + + Rescanning... + Rescaniranje + + + + Done loading + Učitavanje gotovo + + + + To use the %s option + + + + + Error + Greška + + + + You must set rpcpassword=<password> in the configuration file: +%s +If the file does not exist, create it with owner-readable-only file permissions. + + + + \ No newline at end of file diff --git a/src/qt/locale/bitcoin_hu.ts b/src/qt/locale/bitcoin_hu.ts new file mode 100755 index 0000000..272fa40 --- /dev/null +++ b/src/qt/locale/bitcoin_hu.ts @@ -0,0 +1,3303 @@ + + + AboutDialog + + + About Arepacoin + A Arepacoin-ról + + + + <b>Arepacoin</b> version + <b>Arepacoin</b> verzió + + + + Copyright © 2009-2014 The Bitcoin developers +Copyright © 2012-2014 The NovaCoin developers +Copyright © 2014 The Arepacoin developers + + + + + +This is experimental software. + +Distributed under the MIT/X11 software license, see the accompanying file COPYING or http://www.opensource.org/licenses/mit-license.php. + +This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit (http://www.openssl.org/) and cryptographic software written by Eric Young (eay@cryptsoft.com) and UPnP software written by Thomas Bernard. + +Ez egy kísérleti program. +MIT/X11 szoftverlicenc alatt kiadva, lásd a mellékelt COPYING fájlt vagy a http://www.opensource.org/licenses/mit-license.php weboldalt. + +Ez a termék tartalmaz az OpenSSL Project által az OpenSSL Toolkit-hez (http://www.openssl.org/) fejlesztett szoftvert; kriptográfiai szoftvert, melyet Eric Young (eay@cryptsoft.com) írt; és Thomas Bernard által írt UPnP szoftvert. + + + + AddressBookPage + + + Address Book + Címjegyzék + + + + Double-click to edit address or label + Kattints duplán a cím vagy címke szerkesztéséhez + + + + Create a new address + Új cím létrehozása + + + + Copy the currently selected address to the system clipboard + A kiválasztott cím másolása a vágólapra + + + + &New Address + &Új Cím + + + + These are your Arepacoin addresses for receiving payments. You may want to give a different one to each sender so you can keep track of who is paying you. + Ezek a Arepacoin-címeid a fizetések fogadásához. Érdemes minden küldőnek egy külön címet létrehozni, hogy könnyebben követhesd személyenként a tranzakciókat. + + + + &Copy Address + &Cím Másolása + + + + Show &QR Code + &QR Kód Mutatása + + + + Sign a message to prove you own a Arepacoin address + Írj alá egy üzenetet, hogy bizonyíthasd egy Arepacoin-cím birtoklását + + + + Sign &Message + &Üzenet Aláírása + + + + Delete the currently selected address from the list + A kiválasztott cím törlése a listáról + + + + Verify a message to ensure it was signed with a specified Arepacoin address + Hitelesíts egy üzenetet ahhoz, hogy bebizonyosodjon Arepacoin-cím alapján a feladó kiléte + + + + &Verify Message + Üzenet &Hitelesítése + + + + &Delete + &Törlés + + + + Copy &Label + Címke &Másolása + + + + &Edit + Sz&erkesztés + + + + Export Address Book Data + Címjegyzék Exportálása + + + + Comma separated file (*.csv) + Vesszővel elválasztott fájl (*.csv) + + + + Error exporting + Hiba exportálás + + + + Could not write to file %1. + Nem lehetett írni a fájlt a következő helyen: %1. + + + + AddressTableModel + + + Label + Címke + + + + Address + Cím + + + + (no label) + (nincs címke) + + + + AskPassphraseDialog + + + Passphrase Dialog + Kulcsszó Párbeszédablak + + + + Enter passphrase + Add meg a jelszót + + + + New passphrase + Új jelszó + + + + Repeat new passphrase + Új jelszó ismét + + + + Serves to disable the trivial sendmoney when OS account compromised. Provides no real security. + Triviálisan a sendmoney parancs letiltására szolgál, amennyiben az OS felhasználója kompromittálódik. Nem ad valós biztonságot. + + + + For staking only + Csak kamatoztatásra + + + + Enter the new passphrase to the wallet.<br/>Please use a passphrase of <b>10 or more random characters</b>, or <b>eight or more words</b>. + Írd be az új jelszót a tárcához.<br/>Használj <b>legalább 10 véletlenszerű karaktert</b>, vagy <b>legalább nyolc szót</b>. + + + + Encrypt wallet + Tárca kódolása + + + + This operation needs your wallet passphrase to unlock the wallet. + Ez a művelet a tárcád jelszavának megadását igényli annak megnyitásához. + + + + Unlock wallet + Tárca feloldása + + + + This operation needs your wallet passphrase to decrypt the wallet. + Ez a művelet a tárcád jelszavának megadását igényli annak dekódolásához. + + + + Decrypt wallet + Tárca dekódolása + + + + Change passphrase + Jelszó megváltoztatása + + + + Enter the old and new passphrase to the wallet. + Írd be a tárca régi és új jelszavát. + + + + Confirm wallet encryption + Biztosan kódolni akarod a tárcát? + + + + Warning: If you encrypt your wallet and lose your passphrase, you will <b>LOSE ALL OF YOUR COINS</b>! + Figyelmeztetés: Ha kódolod a tárcád és elveszíted annak jelszavát, el fogod <b>VESZÍTENI AZ ÖSSZES ÉRMÉDET</b>! + + + + Are you sure you wish to encrypt your wallet? + Biztosan kódolni akarod a tárcát? + + + + IMPORTANT: Any previous backups you have made of your wallet file should be replaced with the newly generated, encrypted wallet file. For security reasons, previous backups of the unencrypted wallet file will become useless as soon as you start using the new, encrypted wallet. + FONTOS: A pénztárca-fájl korábbi mentéseit ezzel az új, titkosított pénztárca-fájllal kell helyettesíteni. Biztonsági okokból a pénztárca-fájl korábbi titkosítás nélküli mentései haszontalanná válnak amint elkezdi használni az új, titkosított pénztárcát. + + + + + Warning: The Caps Lock key is on! + + + + + + Wallet encrypted + Tárca kódolva + + + + Arepacoin will close now to finish the encryption process. Remember that encrypting your wallet cannot fully protect your coins from being stolen by malware infecting your computer. + + + + + + + + Wallet encryption failed + Tárca kódolása sikertelen. + + + + Wallet encryption failed due to an internal error. Your wallet was not encrypted. + Tárca kódolása belső hiba miatt sikertelen. A tárcád nem lett kódolva. + + + + + The supplied passphrases do not match. + A megadott jelszavak nem egyeznek. + + + + Wallet unlock failed + Tárca megnyitása sikertelen + + + + + + The passphrase entered for the wallet decryption was incorrect. + Hibás jelszó. + + + + Wallet decryption failed + Dekódolás sikertelen. + + + + Wallet passphrase was successfully changed. + Jelszó megváltoztatva. + + + + BitcoinGUI + + + Sign &message... + Üzenet aláírása... + + + + Synchronizing with network... + Szinkronizálás a hálózattal... + + + + &Overview + &Áttekintés + + + + Show general overview of wallet + Tárca általános áttekintése + + + + &Transactions + &Tranzakciók + + + + Browse transaction history + Tranzakciótörténet megtekintése + + + + &Address Book + + + + + Edit the list of stored addresses and labels + + + + + &Receive coins + + + + + Show the list of addresses for receiving payments + + + + + &Send coins + + + + + E&xit + &Kilépés + + + + Quit application + Kilépés + + + + Show information about Arepacoin + + + + + About &Qt + A &Qt-ról + + + + Show information about Qt + Információk a Qt ról + + + + &Options... + &Opciók... + + + + &Encrypt Wallet... + Tárca &kódolása... + + + + &Backup Wallet... + &Bisztonsági másolat készítése a Tárcáról + + + + &Change Passphrase... + Jelszó &megváltoztatása... + + + + ~%n block(s) remaining + + + + + Downloaded %1 of %2 blocks of transaction history (%3% done). + + + + + &Export... + + + + + Send coins to a Arepacoin address + + + + + Modify configuration options for Arepacoin + + + + + Export the data in the current tab to a file + + + + + Encrypt or decrypt wallet + + + + + Backup wallet to another location + Biztonsági másolat készítése a Tárcáról egy másik helyre + + + + Change the passphrase used for wallet encryption + Tárcakódoló jelszó megváltoztatása + + + + &Debug window + &Debug ablak + + + + Open debugging and diagnostic console + Hibakereső és diagnosztikai konzol megnyitása + + + + &Verify message... + Üzenet &valódiságának ellenőrzése + + + + Arepacoin + + + + + Wallet + Tárca + + + + &About Arepacoin + + + + + &Show / Hide + &Mutat / Elrejt + + + + Unlock wallet + + + + + &Lock Wallet + + + + + Lock wallet + + + + + &File + &Fájl + + + + &Settings + &Beállítások + + + + &Help + &Súgó + + + + Tabs toolbar + Fül eszköztár + + + + Actions toolbar + + + + + + [testnet] + [teszthálózat] + + + + + Arepacoin client + + + + + %n active connection(s) to Arepacoin network + + + + + Downloaded %1 blocks of transaction history. + + + + + Staking.<br>Your weight is %1<br>Network weight is %2<br>Expected time to earn reward is %3 + + + + + Not staking because wallet is locked + + + + + Not staking because wallet is offline + + + + + Not staking because wallet is syncing + + + + + Not staking because you don't have mature coins + + + + + %n second(s) ago + + + + + &Unlock Wallet... + + + + + %n minute(s) ago + + + + + %n hour(s) ago + + + + + %n day(s) ago + + + + + Up to date + Naprakész + + + + Catching up... + Frissítés... + + + + Last received block was generated %1. + + + + + This transaction is over the size limit. You can still send it for a fee of %1, which goes to the nodes that process your transaction and helps to support the network. Do you want to pay the fee? + + + + + Confirm transaction fee + + + + + Sent transaction + Tranzakció elküldve. + + + + Incoming transaction + Beérkező tranzakció + + + + Date: %1 +Amount: %2 +Type: %3 +Address: %4 + + Dátum: %1 +Összeg: %2 +Típus: %3 +Cím: %4 + + + + + + URI handling + + + + + + URI can not be parsed! This can be caused by an invalid Arepacoin address or malformed URI parameters. + + + + + Wallet is <b>encrypted</b> and currently <b>unlocked</b> + Tárca <b>kódolva</b> és jelenleg <b>nyitva</b>. + + + + Wallet is <b>encrypted</b> and currently <b>locked</b> + Tárca <b>kódolva</b> és jelenleg <b>zárva</b>. + + + + Backup Wallet + + + + + Wallet Data (*.dat) + + + + + Backup Failed + + + + + There was an error trying to save the wallet data to the new location. + + + + + %n second(s) + + + + + %n minute(s) + + + + + %n hour(s) + + + + + %n day(s) + + + + + Not staking + + + + + A fatal error occurred. Arepacoin can no longer continue safely and will quit. + + + + + ClientModel + + + Network Alert + Hálózati figyelmeztetés + + + + CoinControlDialog + + + Coin Control + + + + + Quantity: + + + + + Bytes: + + + + + Amount: + Összeg: + + + + Priority: + + + + + Fee: + + + + + Low Output: + + + + + no + + + + + After Fee: + + + + + Change: + + + + + (un)select all + + + + + Tree mode + + + + + List mode + + + + + Amount + Összeg + + + + Label + + + + + Address + Cím + + + + Date + Dátum + + + + Confirmations + + + + + Confirmed + Megerősítve + + + + Priority + + + + + Copy address + Cím másolása + + + + Copy label + Címke másolása + + + + + Copy amount + Összeg másolása + + + + Copy transaction ID + Tranzakcióazonosító másolása + + + + Copy quantity + + + + + Copy fee + + + + + Copy after fee + + + + + Copy bytes + + + + + Copy priority + + + + + Copy low output + + + + + Copy change + + + + + highest + + + + + high + + + + + medium-high + + + + + medium + + + + + low-medium + + + + + low + + + + + lowest + + + + + DUST + + + + + yes + + + + + This label turns red, if the transaction size is bigger than 10000 bytes. + + This means a fee of at least %1 per kb is required. + + Can vary +/- 1 Byte per input. + + + + + Transactions with higher priority get more likely into a block. + +This label turns red, if the priority is smaller than "medium". + + This means a fee of at least %1 per kb is required. + + + + + This label turns red, if any recipient receives an amount smaller than %1. + + This means a fee of at least %2 is required. + + Amounts below 0.546 times the minimum relay fee are shown as DUST. + + + + + This label turns red, if the change is smaller than %1. + + This means a fee of at least %2 is required. + + + + + + (no label) + (nincs címke) + + + + change from %1 (%2) + + + + + (change) + + + + + EditAddressDialog + + + Edit Address + Cím szerkesztése + + + + &Label + Cím&ke + + + + The label associated with this address book entry + + + + + &Address + &Cím + + + + The address associated with this address book entry. This can only be modified for sending addresses. + + + + + New receiving address + Új fogadó cím + + + + New sending address + Új küldő cím + + + + Edit receiving address + Fogadó cím szerkesztése + + + + Edit sending address + Küldő cím szerkesztése + + + + The entered address "%1" is already in the address book. + A megadott "%1" cím már szerepel a címjegyzékben. + + + + The entered address "%1" is not a valid Arepacoin address. + + + + + Could not unlock wallet. + Tárca feloldása sikertelen + + + + New key generation failed. + Új kulcs generálása sikertelen + + + + GUIUtil::HelpMessageBox + + + + Arepacoin-Qt + + + + + version + + + + + Usage: + + + + + command-line options + + + + + UI options + + + + + Set language, for example "de_DE" (default: system locale) + + + + + Start minimized + + + + + Show splash screen on startup (default: 1) + + + + + OptionsDialog + + + Options + Opciók + + + + &Main + &Fő + + + + Optional transaction fee per kB that helps make sure your transactions are processed quickly. Most transactions are 1 kB. Fee 0.01 recommended. + + + + + Pay transaction &fee + Tranzakciós &díj fizetése + + + + Reserved amount does not participate in staking and is therefore spendable at any time. + + + + + Reserve + + + + + Automatically start Arepacoin after logging in to the system. + + + + + &Start Arepacoin on system login + + + + + Detach block and address databases at shutdown. This means they can be moved to another data directory, but it slows down shutdown. The wallet is always detached. + + + + + &Detach databases at shutdown + + + + + &Network + &Hálózat + + + + Automatically open the Arepacoin client port on the router. This only works when your router supports UPnP and it is enabled. + + + + + Map port using &UPnP + &UPnP port-feltérképezés + + + + Connect to the Arepacoin network through a SOCKS proxy (e.g. when connecting through Tor). + + + + + &Connect through SOCKS proxy: + + + + + Proxy &IP: + Proxy &IP: + + + + IP address of the proxy (e.g. 127.0.0.1) + + + + + &Port: + &Port: + + + + Port of the proxy (e.g. 9050) + Proxy portja (pl.: 9050) + + + + SOCKS &Version: + SOCKS &Verzió: + + + + SOCKS version of the proxy (e.g. 5) + A proxy SOCKS verziója (pl. 5) + + + + &Window + &Ablak + + + + Show only a tray icon after minimizing the window. + Kicsinyítés után csak eszköztár-ikont mutass + + + + &Minimize to the tray instead of the taskbar + &Kicsinyítés a tálcára az eszköztár helyett + + + + Minimize instead of exit the application when the window is closed. When this option is enabled, the application will be closed only after selecting Quit in the menu. + Az alkalmazásból való kilépés helyett az eszköztárba kicsinyíti az alkalmazást az ablak bezárásakor. Ez esetben az alkalmazás csak a Kilépés menüponttal zárható be. + + + + M&inimize on close + K&icsinyítés záráskor + + + + &Display + &Megjelenítés + + + + User Interface &language: + Felhasználófelület nye&lve: + + + + The user interface language can be set here. This setting will take effect after restarting Arepacoin. + + + + + &Unit to show amounts in: + &Mértékegység: + + + + Choose the default subdivision unit to show in the interface and when sending coins. + Válaszd ki az interfészen és érmék küldésekor megjelenítendő alapértelmezett alegységet. + + + + Whether to show Arepacoin addresses in the transaction list or not. + + + + + &Display addresses in transaction list + &Címek megjelenítése a tranzakciólistában + + + + Whether to show coin control features or not. + + + + + Display coin &control features (experts only!) + + + + + &OK + &OK + + + + &Cancel + Megszakítás + + + + &Apply + + + + + default + alapértelmezett + + + + + Warning + + + + + + This setting will take effect after restarting Arepacoin. + + + + + The supplied proxy address is invalid. + A megadott proxy cím nem érvényes. + + + + OverviewPage + + + Form + Űrlap + + + + + The displayed information may be out of date. Your wallet automatically synchronizes with the Arepacoin network after a connection is established, but this process has not completed yet. + + + + + Stake: + + + + + Unconfirmed: + + + + + Wallet + Tárca + + + + Spendable: + + + + + Your current spendable balance + Jelenlegi egyenleg + + + + Immature: + Éretlen: + + + + Mined balance that has not yet matured + Bányászott egyenleg amely még nem érett be. + + + + Total: + Összesen: + + + + Your current total balance + Aktuális egyenleged + + + + <b>Recent transactions</b> + <b>Legutóbbi tranzakciók</b> + + + + Total of transactions that have yet to be confirmed, and do not yet count toward the current balance + + + + + Total of coins that was staked, and do not yet count toward the current balance + + + + + + out of sync + Nincs szinkronban. + + + + QRCodeDialog + + + QR Code Dialog + + + + + Request Payment + + + + + Amount: + + + + + Label: + + + + + Message: + + + + + &Save As... + + + + + Error encoding URI into QR Code. + + + + + The entered amount is invalid, please check. + + + + + Resulting URI too long, try to reduce the text for label / message. + + + + + Save QR Code + + + + + PNG Images (*.png) + + + + + RPCConsole + + + Client name + Kliens néve + + + + + + + + + + + + + N/A + Nem elérhető + + + + Client version + Kliens verzió + + + + &Information + &Információ + + + + Using OpenSSL version + Használt OpenSSL verzió + + + + Startup time + Bekapcsolás ideje + + + + Network + Hálózat + + + + Number of connections + Kapcsolatok száma + + + + On testnet + + + + + Block chain + Blokklánc + + + + Current number of blocks + Aktuális blokkok száma + + + + Estimated total blocks + Becsült összes blokk + + + + Last block time + Utolsó blokk ideje + + + + &Open + &Megnyitás + + + + Command-line options + + + + + Show the Arepacoin-Qt help message to get a list with possible Arepacoin command-line options. + + + + + &Show + + + + + &Console + &Konzol + + + + Build date + Fordítás dátuma + + + + Arepacoin - Debug window + + + + + Arepacoin Core + + + + + Debug log file + Debug naplófájl + + + + Open the Arepacoin debug log file from the current data directory. This can take a few seconds for large log files. + + + + + Clear console + Konzol törlése + + + + Welcome to the Arepacoin RPC console. + + + + + Use up and down arrows to navigate history, and <b>Ctrl-L</b> to clear screen. + Navigálhat a fel és le nyilakkal, és <b>Ctrl-L</b> -vel törölheti a képernyőt. + + + + Type <b>help</b> for an overview of available commands. + Írd be azt, hogy <b>help</b> az elérhető parancsok áttekintéséhez. + + + + SendCoinsDialog + + + + + + + + + + Send Coins + Érmék küldése + + + + Coin Control Features + + + + + Inputs... + + + + + automatically selected + + + + + Insufficient funds! + + + + + Quantity: + + + + + + 0 + + + + + Bytes: + + + + + Amount: + Összeg: + + + + + + + 0.00 BC + + + + + Priority: + + + + + medium + + + + + Fee: + + + + + Low Output: + + + + + no + + + + + After Fee: + + + + + Change + + + + + custom change address + + + + + Send to multiple recipients at once + Küldés több címzettnek egyszerre + + + + Add &Recipient + &Címzett hozzáadása + + + + Remove all transaction fields + + + + + Clear &All + Mindent &töröl + + + + Balance: + Egyenleg: + + + + 123.456 BC + + + + + Confirm the send action + Küldés megerősítése + + + + S&end + &Küldés + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Copy quantity + + + + + Copy amount + Összeg másolása + + + + Copy fee + + + + + Copy after fee + + + + + Copy bytes + + + + + Copy priority + + + + + Copy low output + + + + + Copy change + + + + + <b>%1</b> to %2 (%3) + + + + + Confirm send coins + Küldés megerősítése + + + + Are you sure you want to send %1? + + + + + and + + + + + The recipient address is not valid, please recheck. + A címzett címe érvénytelen, kérlek, ellenőrizd. + + + + The amount to pay must be larger than 0. + A fizetendő összegnek nagyobbnak kell lennie 0-nál. + + + + The amount exceeds your balance. + Nincs ennyi bitcoin az egyenlegeden. + + + + The total exceeds your balance when the %1 transaction fee is included. + A küldeni kívánt összeg és a %1 tranzakciós díj együtt meghaladja az egyenlegeden rendelkezésedre álló összeget. + + + + Duplicate address found, can only send to each address once per send operation. + Többször szerepel ugyanaz a cím. Egy küldési műveletben egy címre csak egyszer lehet küldeni. + + + + Error: Transaction creation failed. + + + + + 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. + + + + + WARNING: Invalid Arepacoin address + + + + + (no label) + (nincs címke) + + + + WARNING: unknown change address + + + + + SendCoinsEntry + + + Form + + + + + A&mount: + Összeg: + + + + Pay &To: + Címzett: + + + + + Enter a label for this address to add it to your address book + Milyen címkével kerüljön be ez a cím a címtáradba? + + + + + &Label: + Címke: + + + + The address to send the payment to (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Choose address from address book + + + + + Alt+A + Alt+A + + + + Paste address from clipboard + Cím beillesztése a vágólapról + + + + Alt+P + Alt+P + + + + Remove this recipient + + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + SignVerifyMessageDialog + + + Signatures - Sign / Verify a Message + + + + + + &Sign Message + Üzenet aláírása... + + + + You can sign messages with your addresses to prove you own them. Be careful not to sign anything vague, as phishing attacks may try to trick you into signing your identity over to them. Only sign fully-detailed statements you agree to. + Aláírhat a címeivel üzeneteket, amivel bizonyíthatja, hogy a címek az önéi. Vigyázzon, hogy ne írjon alá semmi félreérthetőt, mivel a phising támadásokkal megpróbálhatják becsapni, hogy az azonosságát átírja másokra. Csak olyan részletes állításokat írjon alá, amivel egyetért. + + + + The address to sign the message with (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + + Choose an address from the address book + + + + + + Alt+A + Alt+A + + + + Paste address from clipboard + Cím beillesztése a vágólapról + + + + Alt+P + Alt+P + + + + Enter the message you want to sign here + Ide írja az aláírandó üzenetet + + + + Copy the current signature to the system clipboard + A jelenleg kiválasztott aláírás másolása a rendszer-vágólapra + + + + Sign the message to prove you own this Arepacoin address + + + + + Reset all sign message fields + + + + + + Clear &All + Mindent &töröl + + + + + &Verify Message + Üzenet ellenőrzése + + + + Enter the signing address, message (ensure you copy line breaks, spaces, tabs, etc. exactly) and signature below to verify the message. Be careful not to read more into the signature than what is in the signed message itself, to avoid being tricked by a man-in-the-middle attack. + Írja be az aláírás címét, az üzenetet (ügyelve arra, hogy az új-sor, szóköz, tab, stb. karaktereket is pontosan) és az aláírást az üzenet ellenőrzéséhez. Ügyeljen arra, ne gondoljon többet az aláírásról, mint amennyi az aláírt szövegben ténylegesen áll, hogy elkerülje a köztes-ember (man-in-the-middle) támadást. + + + + The address the message was signed with (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Verify the message to ensure it was signed with the specified Arepacoin address + + + + + Reset all verify message fields + + + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Click "Sign Message" to generate signature + + + + + Enter Arepacoin signature + + + + + + The entered address is invalid. + A megadott cím nem érvényes. + + + + + + + Please check the address and try again. + Ellenőrizze a címet és próbálja meg újra. + + + + + The entered address does not refer to a key. + + + + + Wallet unlock was cancelled. + + + + + Private key for the entered address is not available. + + + + + Message signing failed. + Üzenet aláírása nem sikerült. + + + + Message signed. + Üzenet aláírva. + + + + The signature could not be decoded. + Az aláírást nem sikerült dekódolni. + + + + + Please check the signature and try again. + Ellenőrizd az aláírást és próbáld újra. + + + + The signature did not match the message digest. + + + + + Message verification failed. + Az üzenet ellenőrzése nem sikerült. + + + + Message verified. + Üzenet ellenőrizve. + + + + TransactionDesc + + + Open until %1 + Megnyitva %1-ig + + + + Open for %n block(s) + + + + + conflicted + + + + + %1/offline + + + + + %1/unconfirmed + %1/megerősítetlen + + + + %1 confirmations + %1 megerősítés + + + + Status + Állapot + + + + , broadcast through %n node(s) + + + + + Date + Dátum + + + + Source + + + + + Generated + Legenerálva + + + + + From + Űrlap + + + + + + To + Címzett + + + + + own address + saját cím + + + + label + címke + + + + + + + + Credit + Jóváírás + + + + matures in %n more block(s) + + + + + not accepted + elutasítva + + + + + + + Debit + Terhelés + + + + Transaction fee + Tranzakciós díj + + + + Net amount + Nettó összeg + + + + Message + Üzenet + + + + Comment + Megjegyzés + + + + Transaction ID + Tranzakcióazonosító + + + + Generated coins must mature 6 blocks before they can be spent. When you generated this block, it was broadcast to the network to be added to the block chain. If it fails to get into the chain, its state will change to "not accepted" and it won't be spendable. This may occasionally happen if another node generates a block within a few seconds of yours. + + + + + Debug information + Debug információ + + + + Transaction + Tranzakció + + + + Inputs + Bemenetek + + + + Amount + Összeg + + + + true + igaz + + + + false + hamis + + + + , has not been successfully broadcast yet + , még nem sikerült elküldeni. + + + + unknown + ismeretlen + + + + TransactionDescDialog + + + Transaction details + Tranzakció részletei + + + + This pane shows a detailed description of the transaction + Ez a mező a tranzakció részleteit mutatja + + + + TransactionTableModel + + + Date + Dátum + + + + Type + Típus + + + + Address + Cím + + + + Amount + Összeg + + + + Open until %1 + %1-ig megnyitva + + + + Confirmed (%1 confirmations) + Megerősítve (%1 megerősítés) + + + + Open for %n more block(s) + + + + + Offline + + + + + Unconfirmed + + + + + Confirming (%1 of %2 recommended confirmations) + + + + + Conflicted + + + + + Immature (%1 confirmations, will be available after %2) + + + + + This block was not received by any other nodes and will probably not be accepted! + Ezt a blokkot egyetlen másik csomópont sem kapta meg, így valószínűleg nem lesz elfogadva! + + + + Generated but not accepted + Legenerálva, de még el nem fogadva. + + + + Received with + Erre a címre + + + + Received from + Erről az + + + + Sent to + Erre a címre + + + + Payment to yourself + Magadnak kifizetve + + + + Mined + Kibányászva + + + + (n/a) + (nincs) + + + + Transaction status. Hover over this field to show number of confirmations. + Tranzakció állapota. Húzd ide a kurzort, hogy lásd a megerősítések számát. + + + + Date and time that the transaction was received. + Tranzakció fogadásának dátuma és időpontja. + + + + Type of transaction. + Tranzakció típusa. + + + + Destination address of transaction. + A tranzakció címzettjének címe. + + + + Amount removed from or added to balance. + Az egyenleghez jóváírt vagy ráterhelt összeg. + + + + TransactionView + + + + All + Mind + + + + Today + Mai + + + + This week + Ezen a héten + + + + This month + Ebben a hónapban + + + + Last month + Múlt hónapban + + + + This year + Ebben az évben + + + + Range... + Tartomány ... + + + + Received with + Erre a címre + + + + Sent to + Erre a címre + + + + To yourself + Magadnak + + + + Mined + Kibányászva + + + + Other + Más + + + + Enter address or label to search + Írd be a keresendő címet vagy címkét + + + + Min amount + Minimális összeg + + + + Copy address + Cím másolása + + + + Copy label + Címke másolása + + + + Copy amount + Összeg másolása + + + + Copy transaction ID + Tranzakcióazonosító másolása + + + + Edit label + Címke szerkesztése + + + + Show transaction details + Tranzakciós részletek megjelenítése + + + + Export Transaction Data + + + + + Comma separated file (*.csv) + Vesszővel elválasztott fájl (*.csv) + + + + Confirmed + Megerősítve + + + + Date + Dátum + + + + Type + Típus + + + + Label + Címke + + + + Address + Cím + + + + Amount + Összeg + + + + ID + Azonosító + + + + Error exporting + + + + + Could not write to file %1. + + + + + Range: + Tartomány: + + + + to + meddig + + + + WalletModel + + + Sending... + + + + + bitcoin-core + + + Arepacoin version + + + + + Usage: + Használat: + + + + Send command to -server or arepacoind + + + + + List commands + Parancsok kilistázása + + + + + Get help for a command + Segítség egy parancsról + + + + + Options: + Opciók + + + + + Specify configuration file (default: arepacoin.conf) + + + + + Specify pid file (default: arepacoind.pid) + + + + + Specify wallet file (within data directory) + + + + + Specify data directory + Adatkönyvtár + + + + + Set database cache size in megabytes (default: 25) + Az adatbázis gyorsítótár mérete megabájtban (alapértelmezés: 25) + + + + Set database disk log size in megabytes (default: 100) + + + + + Listen for connections on <port> (default: 9853 or testnet: 19853) + + + + + Maintain at most <n> connections to peers (default: 125) + Maximálisan <n> számú kapcsolat fenntartása a peerekkel (alapértelmezés: 125) + + + + Connect to a node to retrieve peer addresses, and disconnect + Kapcsolódás egy csomóponthoz a peerek címeinek megszerzése miatt, majd szétkapcsolás + + + + Specify your own public address + Adja meg az Ön saját nyilvános címét + + + + Bind to given address. Use [host]:port notation for IPv6 + + + + + Stake your coins to support network and gain reward (default: 1) + + + + + Threshold for disconnecting misbehaving peers (default: 100) + Helytelenül viselkedő peerek leválasztási határértéke (alapértelmezés: 100) + + + + Number of seconds to keep misbehaving peers from reconnecting (default: 86400) + Helytelenül viselkedő peerek kizárási ideje másodpercben (alapértelmezés: 86400) + + + + An error occurred while setting up the RPC port %u for listening on IPv4: %s + + + + + Detach block and address databases. Increases shutdown time (default: 0) + + + + + 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. + + + + + Error: This transaction requires a transaction fee of at least %s because of its amount, complexity, or use of recently received funds + + + + + Listen for JSON-RPC connections on <port> (default: 9852 or testnet: 19852) + + + + + Accept command line and JSON-RPC commands + Parancssoros és JSON-RPC parancsok elfogadása + + + + + Error: Transaction creation failed + + + + + Error: Wallet locked, unable to create transaction + + + + + Importing blockchain data file. + + + + + Importing bootstrap blockchain data file. + + + + + Run in the background as a daemon and accept commands + Háttérben futtatás daemonként és parancsok elfogadása + + + + + Use the test network + Teszthálózat használata + + + + + Accept connections from outside (default: 1 if no -proxy or -connect) + + + + + An error occurred while setting up the RPC port %u for listening on IPv6, falling back to IPv4: %s + + + + + Error initializing database environment %s! To recover, BACKUP THAT DIRECTORY, then remove everything from it except for wallet.dat. + + + + + Set maximum size of high-priority/low-fee transactions in bytes (default: 27000) + + + + + Warning: -paytxfee is set very high! This is the transaction fee you will pay if you send a transaction. + Figyelem: a -paytxfee nagyon magas. Ennyi tranzakciós díjat fogsz fizetni, ha elküldöd a tranzakciót. + + + + Warning: Please check that your computer's date and time are correct! If your clock is wrong Arepacoin will not work properly. + + + + + Warning: error reading wallet.dat! All keys read correctly, but transaction data or address book entries might be missing or incorrect. + + + + + Warning: wallet.dat corrupt, data salvaged! Original wallet.dat saved as wallet.{timestamp}.bak in %s; if your balance or transactions are incorrect you should restore from a backup. + + + + + Attempt to recover private keys from a corrupt wallet.dat + + + + + Block creation options: + + + + + Connect only to the specified node(s) + Csatlakozás csak a megadott csomóponthoz + + + + Discover own IP address (default: 1 when listening and no -externalip) + + + + + Failed to listen on any port. Use -listen=0 if you want this. + Egyik hálózati porton sem sikerül hallgatni. Használja a -listen=0 kapcsolót, ha ezt szeretné. + + + + Find peers using DNS lookup (default: 1) + + + + + Sync checkpoints policy (default: strict) + + + + + Invalid -tor address: '%s' + + + + + Invalid amount for -reservebalance=<amount> + + + + + Maximum per-connection receive buffer, <n>*1000 bytes (default: 5000) + + + + + Maximum per-connection send buffer, <n>*1000 bytes (default: 1000) + + + + + Only connect to nodes in network <net> (IPv4, IPv6 or Tor) + + + + + Output extra debugging information. Implies all other -debug* options + + + + + Output extra network debugging information + + + + + Prepend debug output with timestamp + + + + + SSL options: (see the Bitcoin Wiki for SSL setup instructions) + SSL-opciók: (lásd a Bitcoin Wiki SSL-beállítási instrukcióit) + + + + Select the version of socks proxy to use (4-5, default: 5) + + + + + Send trace/debug info to console instead of debug.log file + trace/debug információ küldése a konzolra a debog.log fájl helyett + + + + Send trace/debug info to debugger + + + + + Set maximum block size in bytes (default: 250000) + + + + + Set minimum block size in bytes (default: 0) + + + + + Shrink debug.log file on client startup (default: 1 when no -debug) + + + + + Specify connection timeout in milliseconds (default: 5000) + Csatlakozás időkerete milliszekundumban (alapértelmezett: 5000) + + + + Unable to sign checkpoint, wrong checkpointkey? + + + + + + Use UPnP to map the listening port (default: 0) + UPnP-használat engedélyezése a figyelő port feltérképezésénél (default: 0) + + + + Use UPnP to map the listening port (default: 1 when listening) + UPnP-használat engedélyezése a figyelő port feltérképezésénél (default: 1 when listening) + + + + Use proxy to reach tor hidden services (default: same as -proxy) + + + + + Username for JSON-RPC connections + Felhasználói név JSON-RPC csatlakozásokhoz + + + + + Verifying database integrity... + + + + + WARNING: syncronized checkpoint violation detected, but skipped! + + + + + Warning: Disk space is low! + + + + + Warning: This version is obsolete, upgrade required! + + + + + wallet.dat corrupt, salvage failed + + + + + Password for JSON-RPC connections + Jelszó JSON-RPC csatlakozásokhoz + + + + + %s, you must set a rpcpassword in the configuration file: + %s +It is recommended you use the following random password: +rpcuser=arepacoinrpc +rpcpassword=%s +(you do not need to remember this password) +The username and password MUST NOT be the same. +If the file does not exist, create it with owner-readable-only file permissions. +It is also recommended to set alertnotify so you are notified of problems; +for example: alertnotify=echo %%s | mail -s "Arepacoin Alert" admin@foo.com + + + + + + Find peers using internet relay chat (default: 0) + + + + + Sync time with other nodes. Disable if time on your system is precise e.g. syncing with NTP (default: 1) + + + + + When creating transactions, ignore inputs with value less than this (default: 0.01) + + + + + Allow JSON-RPC connections from specified IP address + JSON-RPC csatlakozások engedélyezése meghatározott IP-címről + + + + + Send commands to node running on <ip> (default: 127.0.0.1) + Parancsok küldése <ip> címen működő csomóponthoz (alapértelmezett: 127.0.0.1) + + + + + Execute command when the best block changes (%s in cmd is replaced by block hash) + Parancs, amit akkor hajt végre, amikor a legjobb blokk megváltozik (%s a cmd-ban lecserélődik a blokk hash-re) + + + + Execute command when a wallet transaction changes (%s in cmd is replaced by TxID) + Parancs, amit akkor hajt végre, amikor egy tárca-tranzakció megváltozik (%s a parancsban lecserélődik a blokk TxID-re) + + + + Require a confirmations for change (default: 0) + + + + + Enforce transaction scripts to use canonical PUSH operators (default: 1) + + + + + Execute command when a relevant alert is received (%s in cmd is replaced by message) + + + + + Upgrade wallet to latest format + A Tárca frissítése a legfrissebb formátumra + + + + Set key pool size to <n> (default: 100) + Kulcskarika mérete <n> (alapértelmezett: 100) + + + + + Rescan the block chain for missing wallet transactions + Blokklánc újraszkennelése hiányzó tárca-tranzakciók után + + + + + How many blocks to check at startup (default: 2500, 0 = all) + + + + + How thorough the block verification is (0-6, default: 1) + + + + + Imports blocks from external blk000?.dat file + + + + + Use OpenSSL (https) for JSON-RPC connections + OpenSSL (https) használata JSON-RPC csatalkozásokhoz + + + + + Server certificate file (default: server.cert) + Szervertanúsítvány-fájl (alapértelmezett: server.cert) + + + + + Server private key (default: server.pem) + Szerver titkos kulcsa (alapértelmezett: server.pem) + + + + + Acceptable ciphers (default: TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH) + + + + + Error: Wallet unlocked for staking only, unable to create transaction. + + + + + WARNING: Invalid checkpoint found! Displayed transactions may not be correct! You may need to upgrade, or notify developers. + + + + + This help message + Ez a súgó-üzenet + + + + + Wallet %s resides outside data directory %s. + + + + + Cannot obtain a lock on data directory %s. Arepacoin is probably already running. + + + + + Arepacoin + + + + + Unable to bind to %s on this computer (bind returned error %d, %s) + A %s nem elérhető ezen a gépen (bind returned error %d, %s) + + + + Connect through socks proxy + + + + + Allow DNS lookups for -addnode, -seednode and -connect + DNS-kikeresés engedélyezése az addnode-nál és a connect-nél + + + + Loading addresses... + Címek betöltése... + + + + Error loading blkindex.dat + + + + + Error loading wallet.dat: Wallet corrupted + Hiba a wallet.dat betöltése közben: meghibásodott tárca + + + + Error loading wallet.dat: Wallet requires newer version of Arepacoin + + + + + Wallet needed to be rewritten: restart Arepacoin to complete + + + + + Error loading wallet.dat + Hiba az wallet.dat betöltése közben + + + + Invalid -proxy address: '%s' + Érvénytelen -proxy cím: '%s' + + + + Unknown network specified in -onlynet: '%s' + Ismeretlen hálózat lett megadva -onlynet: '%s' + + + + Unknown -socks proxy version requested: %i + Ismeretlen -socks proxy kérése: %i + + + + Cannot resolve -bind address: '%s' + Csatlakozási cím (-bind address) feloldása nem sikerült: '%s' + + + + Cannot resolve -externalip address: '%s' + Külső cím (-externalip address) feloldása nem sikerült: '%s' + + + + Invalid amount for -paytxfee=<amount>: '%s' + Étvénytelen -paytxfee=<összeg> összeg: '%s' + + + + Error: could not start node + + + + + Sending... + + + + + Invalid amount + Étvénytelen összeg + + + + Insufficient funds + Nincs elég bitcoinod. + + + + Loading block index... + Blokkindex betöltése... + + + + Add a node to connect to and attempt to keep the connection open + Elérendő csomópont megadása and attempt to keep the connection open + + + + Unable to bind to %s on this computer. Arepacoin is probably already running. + + + + + Fee per KB to add to transactions you send + + + + + Invalid amount for -mininput=<amount>: '%s' + + + + + Loading wallet... + Tárca betöltése... + + + + Cannot downgrade wallet + Nem sikerült a Tárca visszaállítása a korábbi verzióra + + + + Cannot initialize keypool + + + + + Cannot write default address + Nem sikerült az alapértelmezett címet írni. + + + + Rescanning... + Újraszkennelés... + + + + Done loading + Betöltés befejezve. + + + + To use the %s option + Használd a %s opciót + + + + Error + Hiba + + + + You must set rpcpassword=<password> in the configuration file: +%s +If the file does not exist, create it with owner-readable-only file permissions. + Be kell állítani rpcpassword=<password> a konfigurációs fájlban +%s +Ha a fájl nem létezik, hozd létre 'csak a felhasználó által olvasható' fájl engedéllyel + + + \ No newline at end of file diff --git a/src/qt/locale/bitcoin_id_ID.ts b/src/qt/locale/bitcoin_id_ID.ts new file mode 100755 index 0000000..9af9350 --- /dev/null +++ b/src/qt/locale/bitcoin_id_ID.ts @@ -0,0 +1,3283 @@ + + + AboutDialog + + + About Arepacoin + Tentang Arepacoin + + + + <b>Arepacoin</b> version + <b>Arepacoin</b> versi + + + + Copyright © 2009-2014 The Bitcoin developers +Copyright © 2012-2014 The NovaCoin developers +Copyright © 2014 The Arepacoin developers + Copyright © 2009-2014 para pengembang Bitcoin +Copyright © 2012-2014 para pengembang NovaCoin +Copyright © 2014 para pengembang Arepacoin + + + + +This is experimental software. + +Distributed under the MIT/X11 software license, see the accompanying file COPYING or http://www.opensource.org/licenses/mit-license.php. + +This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit (http://www.openssl.org/) and cryptographic software written by Eric Young (eay@cryptsoft.com) and UPnP software written by Thomas Bernard. + + + + + AddressBookPage + + + Address Book + Buku Alamat + + + + Double-click to edit address or label + Klik dua-kali untuk mengubah alamat atau label + + + + Create a new address + Buat alamat baru + + + + Copy the currently selected address to the system clipboard + Salin alamat yang dipilih ke clipboard + + + + &New Address + &Alamat Baru + + + + These are your Arepacoin addresses for receiving payments. You may want to give a different one to each sender so you can keep track of who is paying you. + Ini adalah alamat Arepacoin Anda untuk menerima pembayaran. Anda dapat memberikan alamat yang berbeda untuk setiap pengirim, sehingga Anda dapat melacak siapa yang membayar Anda. + + + + &Copy Address + &Salin Alamat + + + + Show &QR Code + Unjukkan &Kode QR + + + + Sign a message to prove you own a Arepacoin address + Masukan pesan untuk membuktikan bahwa anda telah mempunyai adress Arepacoin + + + + Sign &Message + Sign & Pesan + + + + Delete the currently selected address from the list + Menghapus alamat yang saat ini dipilih dari daftar yang tersedia + + + + Verify a message to ensure it was signed with a specified Arepacoin address + + + + + &Verify Message + + + + + &Delete + &Hapus + + + + Copy &Label + Salin &Label + + + + &Edit + &Ubah + + + + Export Address Book Data + + + + + Comma separated file (*.csv) + File CSV (*.csv) + + + + Error exporting + + + + + Could not write to file %1. + Penulisan data ke file gagal %1 + + + + AddressTableModel + + + Label + Label + + + + Address + Alamat + + + + (no label) + (tidak ada label) + + + + AskPassphraseDialog + + + Passphrase Dialog + Dialog Kata kunci + + + + Enter passphrase + Masukkan kata kunci + + + + New passphrase + Kata kunci baru + + + + Repeat new passphrase + Ulangi kata kunci baru + + + + Serves to disable the trivial sendmoney when OS account compromised. Provides no real security. + + + + + For staking only + Hanya untuk staking + + + + Enter the new passphrase to the wallet.<br/>Please use a passphrase of <b>10 or more random characters</b>, or <b>eight or more words</b>. + Masukkan kata kunci baru ke dompet.<br/>Mohon gunakan kata kunci dengan <b>10 karakter atau lebih dengan acak</b>, atau <b>delapan kata atau lebih</b>. + + + + Encrypt wallet + Meng-enkripsikan dompet + + + + This operation needs your wallet passphrase to unlock the wallet. + Operasi ini memerlukan kata kunci dompet Anda untuk membuka dompet ini. + + + + Unlock wallet + Buka dompet + + + + This operation needs your wallet passphrase to decrypt the wallet. + Operasi ini memerlukan kata kunci dompet Anda untuk mendekripsi dompet ini. + + + + Decrypt wallet + Men-dekripsikan dompet + + + + Change passphrase + Ubah kata kunci + + + + Enter the old and new passphrase to the wallet. + Masukkan kata kunci lama dan baru ke dompet ini. + + + + Confirm wallet encryption + Menkonfirmasi enkripsi dompet + + + + Warning: If you encrypt your wallet and lose your passphrase, you will <b>LOSE ALL OF YOUR COINS</b>! + + + + + Are you sure you wish to encrypt your wallet? + Apakah Anda yakin untuk mengenkripsi dompet Anda? + + + + IMPORTANT: Any previous backups you have made of your wallet file should be replaced with the newly generated, encrypted wallet file. For security reasons, previous backups of the unencrypted wallet file will become useless as soon as you start using the new, encrypted wallet. + + + + + + Warning: The Caps Lock key is on! + Peringatan: tombol Caps Lock aktif! + + + + + Wallet encrypted + Dompet terenkripsi + + + + Arepacoin will close now to finish the encryption process. Remember that encrypting your wallet cannot fully protect your coins from being stolen by malware infecting your computer. + Arepacoin akan ditutup untuk menyelesaikan proses enkripsi. Ingat bahwa dompet Anda tidak bisa di lindungi dengan enkripsi sepenuhny dari pencurian melalui infeksi malware di komputer Anda. + + + + + + + Wallet encryption failed + Enkripsi dompet gagal + + + + Wallet encryption failed due to an internal error. Your wallet was not encrypted. + Enkripsi dompet gagal karena kesalahan internal. Dompet Anda tidak dienkripsi. + + + + + The supplied passphrases do not match. + Kata kunci yang dimasukkan tidak cocok. + + + + Wallet unlock failed + Gagal buka dompet + + + + + + The passphrase entered for the wallet decryption was incorrect. + Kata kunci yang dimasukkan untuk dekripsi dompet tidak cocok. + + + + Wallet decryption failed + Dekripsi dompet gagal + + + + Wallet passphrase was successfully changed. + Passphrase dompet telah berhasil diubah. + + + + BitcoinGUI + + + Sign &message... + Pesan &penanda... + + + + Synchronizing with network... + Sinkronisasi dengan jaringan... + + + + &Overview + &Kilasan + + + + Show general overview of wallet + Tampilkan kilasan umum dari dompet + + + + &Transactions + &Transaksi + + + + Browse transaction history + Jelajah sejarah transaksi + + + + &Address Book + &Buku Alamat + + + + Edit the list of stored addresses and labels + Mengedit daftar alamat-alamat dan label + + + + &Receive coins + &Menerima koin + + + + Show the list of addresses for receiving payments + Tampilkan daftar alamat untuk menerima pembayaran + + + + &Send coins + &Kirim koin + + + + E&xit + K&eluar + + + + Quit application + Keluar dari aplikasi + + + + Show information about Arepacoin + Tunjukkan informasi tentang Arepacoin + + + + About &Qt + Mengenai &Qt + + + + Show information about Qt + Tampilkan informasi mengenai Qt + + + + &Options... + &Pilihan... + + + + &Encrypt Wallet... + %Enkripsi Dompet... + + + + &Backup Wallet... + &Cadangkan Dompet... + + + + &Change Passphrase... + &Ubah Kata Kunci... + + + + ~%n block(s) remaining + ~%n blok yang tersisah + + + + Downloaded %1 of %2 blocks of transaction history (%3% done). + %1 dari %2 telah diunduh, blok dari sejarah transaksi (%3% selesai). + + + + &Export... + &Ekspor... + + + + Send coins to a Arepacoin address + Kirim koin ke alamat Arepacoin + + + + Modify configuration options for Arepacoin + Memodifikasi opsi aturan untuk Arepacoin + + + + Export the data in the current tab to a file + Mengekspor data dari tab saat ini ke dalam file + + + + Encrypt or decrypt wallet + Mengenkripsi atau mendekripsi dompet + + + + Backup wallet to another location + Cadangkan dompet ke lokasi lain + + + + Change the passphrase used for wallet encryption + Ubah kata kunci yang digunakan untuk enkripsi dompet + + + + &Debug window + &Jendela Debug + + + + Open debugging and diagnostic console + Buka konsol debug dan diagnosa + + + + &Verify message... + &Verifikasi pesan... + + + + Arepacoin + Arepacoin (CoinHitam) + + + + Wallet + Dompet + + + + &About Arepacoin + &Tentang Arepacoin + + + + &Show / Hide + &Tunjukkan / Sembunyikan + + + + Unlock wallet + Buka Dompet + + + + &Lock Wallet + &Kunci Dompet + + + + Lock wallet + Kunci dompet + + + + &File + &Berkas + + + + &Settings + &Pengaturan + + + + &Help + &Bantuan + + + + Tabs toolbar + Baris tab + + + + Actions toolbar + Baris tab + + + + + [testnet] + [testnet] + + + + + Arepacoin client + Klien Arepacoin + + + + %n active connection(s) to Arepacoin network + + + + + Downloaded %1 blocks of transaction history. + + + + + Staking.<br>Your weight is %1<br>Network weight is %2<br>Expected time to earn reward is %3 + + + + + Not staking because wallet is locked + + + + + Not staking because wallet is offline + + + + + Not staking because wallet is syncing + + + + + Not staking because you don't have mature coins + + + + + %n second(s) ago + + + + + &Unlock Wallet... + &Buka Dompet + + + + %n minute(s) ago + %n menit yang lalu + + + + %n hour(s) ago + %n jam yang lalu + + + + %n day(s) ago + %n hari yang lalu + + + + Up to date + Terbaru + + + + Catching up... + Menyusul... + + + + Last received block was generated %1. + + + + + This transaction is over the size limit. You can still send it for a fee of %1, which goes to the nodes that process your transaction and helps to support the network. Do you want to pay the fee? + + + + + Confirm transaction fee + + + + + Sent transaction + Transaksi terkirim + + + + Incoming transaction + Transaksi diterima + + + + Date: %1 +Amount: %2 +Type: %3 +Address: %4 + + Tanggal: %1 +Jumlah: %2 +Jenis: %3 +Alamat: %4 + + + + + + URI handling + + + + + + URI can not be parsed! This can be caused by an invalid Arepacoin address or malformed URI parameters. + + + + + Wallet is <b>encrypted</b> and currently <b>unlocked</b> + Dompet saat ini <b>terenkripsi</b> dan <b>terbuka</b> + + + + Wallet is <b>encrypted</b> and currently <b>locked</b> + Dompet saat ini <b>terenkripsi</b> dan <b>terkunci</b> + + + + Backup Wallet + + + + + Wallet Data (*.dat) + + + + + Backup Failed + Back-up Gagal + + + + There was an error trying to save the wallet data to the new location. + + + + + %n second(s) + %n detik + + + + %n minute(s) + %n menit + + + + %n hour(s) + %n jam + + + + %n day(s) + %n hari + + + + Not staking + Lagi tidak staking + + + + A fatal error occurred. Arepacoin can no longer continue safely and will quit. + + + + + ClientModel + + + Network Alert + Notifikasi Jaringan + + + + CoinControlDialog + + + Coin Control + + + + + Quantity: + Jumlah: + + + + Bytes: + Bytes: + + + + Amount: + Jumlah: + + + + Priority: + Prioritas: + + + + Fee: + Biaya: + + + + Low Output: + + + + + no + tidak + + + + After Fee: + Setelah biaya: + + + + Change: + Perubahan: + + + + (un)select all + + + + + Tree mode + + + + + List mode + mode Daftar + + + + Amount + Jumlah + + + + Label + Label + + + + Address + Alamat + + + + Date + Tanggal + + + + Confirmations + + + + + Confirmed + Terkonfirmasi + + + + Priority + Prioritas + + + + Copy address + Salin alamat + + + + Copy label + Salin label + + + + + Copy amount + Salin jumlah + + + + Copy transaction ID + + + + + Copy quantity + Salikan jumlah + + + + Copy fee + Salinkan Biaya + + + + Copy after fee + Salinkan setelah biaya + + + + Copy bytes + Salinkan bytes + + + + Copy priority + Salinkan prioritas + + + + Copy low output + Salinkan output rendah + + + + Copy change + Salinkan perubahan + + + + highest + tertinggi + + + + high + tinggi + + + + medium-high + menengah-tinggi + + + + medium + menengah + + + + low-medium + rendah-menengah + + + + low + rendah + + + + lowest + terendah + + + + DUST + DUST + + + + yes + ya + + + + This label turns red, if the transaction size is bigger than 10000 bytes. + + This means a fee of at least %1 per kb is required. + + Can vary +/- 1 Byte per input. + + + + + Transactions with higher priority get more likely into a block. + +This label turns red, if the priority is smaller than "medium". + + This means a fee of at least %1 per kb is required. + + + + + This label turns red, if any recipient receives an amount smaller than %1. + + This means a fee of at least %2 is required. + + Amounts below 0.546 times the minimum relay fee are shown as DUST. + + + + + This label turns red, if the change is smaller than %1. + + This means a fee of at least %2 is required. + + + + + + (no label) + (tidak ada label) + + + + change from %1 (%2) + perubahan dari %1 (%2) + + + + (change) + (perubahan) + + + + EditAddressDialog + + + Edit Address + Ubah Alamat + + + + &Label + &Label + + + + The label associated with this address book entry + + + + + &Address + &Alamat + + + + The address associated with this address book entry. This can only be modified for sending addresses. + + + + + New receiving address + Alamat menerima baru + + + + New sending address + Alamat mengirim baru + + + + Edit receiving address + Ubah alamat menerima + + + + Edit sending address + Ubah alamat mengirim + + + + The entered address "%1" is already in the address book. + Alamat yang dimasukkan "%1" sudah ada di dalam buku alamat. + + + + The entered address "%1" is not a valid Arepacoin address. + + + + + Could not unlock wallet. + Tidak dapat membuka dompet. + + + + New key generation failed. + Pembuatan kunci baru gagal. + + + + GUIUtil::HelpMessageBox + + + + Arepacoin-Qt + Arepacoin-Qt + + + + version + versi + + + + Usage: + Penggunaan: + + + + command-line options + + + + + UI options + + + + + Set language, for example "de_DE" (default: system locale) + + + + + Start minimized + + + + + Show splash screen on startup (default: 1) + + + + + OptionsDialog + + + Options + Pilihan + + + + &Main + &Utama + + + + Optional transaction fee per kB that helps make sure your transactions are processed quickly. Most transactions are 1 kB. Fee 0.01 recommended. + + + + + Pay transaction &fee + Bayar &biaya transaksi + + + + Reserved amount does not participate in staking and is therefore spendable at any time. + + + + + Reserve + + + + + Automatically start Arepacoin after logging in to the system. + + + + + &Start Arepacoin on system login + + + + + Detach block and address databases at shutdown. This means they can be moved to another data directory, but it slows down shutdown. The wallet is always detached. + + + + + &Detach databases at shutdown + + + + + &Network + &Jaringan + + + + Automatically open the Arepacoin client port on the router. This only works when your router supports UPnP and it is enabled. + + + + + Map port using &UPnP + Petakan port dengan &UPnP + + + + Connect to the Arepacoin network through a SOCKS proxy (e.g. when connecting through Tor). + + + + + &Connect through SOCKS proxy: + + + + + Proxy &IP: + IP Proxy: + + + + IP address of the proxy (e.g. 127.0.0.1) + + + + + &Port: + &Port: + + + + Port of the proxy (e.g. 9050) + Port proxy (cth. 9050) + + + + SOCKS &Version: + Versi &SOCKS: + + + + SOCKS version of the proxy (e.g. 5) + Versi SOCKS proxy (cth. 5) + + + + &Window + &Jendela + + + + Show only a tray icon after minimizing the window. + Hanya tampilkan ikon tray setelah meminilisasi jendela + + + + &Minimize to the tray instead of the taskbar + &Meminilisasi ke tray daripada taskbar + + + + Minimize instead of exit the application when the window is closed. When this option is enabled, the application will be closed only after selecting Quit in the menu. + + + + + M&inimize on close + M&eminilisasi saat tutup + + + + &Display + &Tampilan + + + + User Interface &language: + &Bahasa Antarmuka Pengguna: + + + + The user interface language can be set here. This setting will take effect after restarting Arepacoin. + + + + + &Unit to show amounts in: + &Unit untuk menunjukkan jumlah: + + + + Choose the default subdivision unit to show in the interface and when sending coins. + + + + + Whether to show Arepacoin addresses in the transaction list or not. + + + + + &Display addresses in transaction list + &Tampilkan alamat dalam daftar transaksi + + + + Whether to show coin control features or not. + + + + + Display coin &control features (experts only!) + + + + + &OK + &YA + + + + &Cancel + &Batal + + + + &Apply + + + + + default + standar + + + + + Warning + Peringatan + + + + + This setting will take effect after restarting Arepacoin. + + + + + The supplied proxy address is invalid. + Alamat proxy yang diisi tidak valid. + + + + OverviewPage + + + Form + Formulir + + + + + The displayed information may be out of date. Your wallet automatically synchronizes with the Arepacoin network after a connection is established, but this process has not completed yet. + + + + + Stake: + Stake: + + + + Unconfirmed: + + + + + Wallet + Dompet + + + + Spendable: + + + + + Your current spendable balance + + + + + Immature: + + + + + Mined balance that has not yet matured + + + + + Total: + Total: + + + + Your current total balance + Total saldo anda saat ini + + + + <b>Recent transactions</b> + <b>Transaksi sebelumnya</b> + + + + Total of transactions that have yet to be confirmed, and do not yet count toward the current balance + + + + + Total of coins that was staked, and do not yet count toward the current balance + + + + + + out of sync + tidak tersinkron + + + + QRCodeDialog + + + QR Code Dialog + + + + + Request Payment + Permintaan Pembayaran + + + + Amount: + Jumlah: + + + + Label: + Label: + + + + Message: + Pesan: + + + + &Save As... + &Simpan Sebagai... + + + + Error encoding URI into QR Code. + + + + + The entered amount is invalid, please check. + + + + + Resulting URI too long, try to reduce the text for label / message. + + + + + Save QR Code + Simpan Code QR + + + + PNG Images (*.png) + Gambar PNG (*.png) + + + + RPCConsole + + + Client name + Nama Klien + + + + + + + + + + + + + N/A + T/S + + + + Client version + Versi Klien + + + + &Information + &Informasi + + + + Using OpenSSL version + Menggunakan versi OpenSSL + + + + Startup time + Waktu nyala + + + + Network + Jaringan + + + + Number of connections + Jumlah hubungan + + + + On testnet + + + + + Block chain + Rantai blok + + + + Current number of blocks + Jumlah blok terkini + + + + Estimated total blocks + Perkiraan blok total + + + + Last block time + Waktu blok terakhir + + + + &Open + &Buka + + + + Command-line options + + + + + Show the Arepacoin-Qt help message to get a list with possible Arepacoin command-line options. + + + + + &Show + &Tunjukkan + + + + &Console + &Konsol + + + + Build date + Tanggal pembuatan + + + + Arepacoin - Debug window + + + + + Arepacoin Core + Inti Arepacoin + + + + Debug log file + + + + + Open the Arepacoin debug log file from the current data directory. This can take a few seconds for large log files. + + + + + Clear console + Bersihkan konsol + + + + Welcome to the Arepacoin RPC console. + + + + + Use up and down arrows to navigate history, and <b>Ctrl-L</b> to clear screen. + Gunakan panah keatas dan kebawah untuk menampilkan sejarah, dan <b>Ctrl-L</b> untuk bersihkan layar. + + + + Type <b>help</b> for an overview of available commands. + Ketik <b>help</b> untuk menampilkan perintah tersedia. + + + + SendCoinsDialog + + + + + + + + + + Send Coins + Kirim Koin + + + + Coin Control Features + + + + + Inputs... + + + + + automatically selected + + + + + Insufficient funds! + Jumlah dana dibutuhkan tidak mencukupi! + + + + Quantity: + Jumlah: + + + + + 0 + 0 + + + + Bytes: + Bytes: + + + + Amount: + Jumlah: + + + + + + + 0.00 BC + 123.456 BC {0.00 ?} + + + + Priority: + Prioritas: + + + + medium + menengah + + + + Fee: + Biaya: + + + + Low Output: + Output Rendah: + + + + no + tidak + + + + After Fee: + Setelah Biaya: + + + + Change + Perubahan + + + + custom change address + + + + + Send to multiple recipients at once + Kirim ke beberapa penerima sekaligus + + + + Add &Recipient + + + + + Remove all transaction fields + + + + + Clear &All + Hapus %Semua + + + + Balance: + Saldo: + + + + 123.456 BC + + + + + Confirm the send action + Konfirmasi aksi pengiriman + + + + S&end + + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Copy quantity + + + + + Copy amount + Salin jumlah + + + + Copy fee + + + + + Copy after fee + + + + + Copy bytes + + + + + Copy priority + + + + + Copy low output + + + + + Copy change + + + + + <b>%1</b> to %2 (%3) + + + + + Confirm send coins + Konfirmasi pengiriman koin + + + + Are you sure you want to send %1? + + + + + and + + + + + The recipient address is not valid, please recheck. + + + + + The amount to pay must be larger than 0. + Jumlah yang dibayar harus lebih besar dari 0. + + + + The amount exceeds your balance. + Jumlah melebihi saldo Anda. + + + + The total exceeds your balance when the %1 transaction fee is included. + Kelebihan total saldo Anda ketika biaya transaksi %1 ditambahkan. + + + + Duplicate address found, can only send to each address once per send operation. + Ditemukan alamat ganda, hanya dapat mengirim ke tiap alamat sekali per operasi pengiriman. + + + + Error: Transaction creation failed. + + + + + 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. + + + + + WARNING: Invalid Arepacoin address + + + + + (no label) + (tidak ada label) + + + + WARNING: unknown change address + + + + + SendCoinsEntry + + + Form + + + + + A&mount: + J&umlah: + + + + Pay &To: + Kirim &Ke: + + + + + Enter a label for this address to add it to your address book + Masukkan label bagi alamat ini untuk menambahkannya ke buku alamat Anda + + + + &Label: + &Label: + + + + The address to send the payment to (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Choose address from address book + + + + + Alt+A + Alt+J + + + + Paste address from clipboard + Tempel alamat dari salinan + + + + Alt+P + Alt+B + + + + Remove this recipient + + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + SignVerifyMessageDialog + + + Signatures - Sign / Verify a Message + + + + + + &Sign Message + + + + + You can sign messages with your addresses to prove you own them. Be careful not to sign anything vague, as phishing attacks may try to trick you into signing your identity over to them. Only sign fully-detailed statements you agree to. + + + + + The address to sign the message with (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + + Choose an address from the address book + + + + + + Alt+A + Alt+J + + + + Paste address from clipboard + Tempel alamat dari salinan + + + + Alt+P + Alt+B + + + + Enter the message you want to sign here + + + + + Copy the current signature to the system clipboard + + + + + Sign the message to prove you own this Arepacoin address + + + + + Reset all sign message fields + + + + + + Clear &All + Hapus %Semua + + + + + &Verify Message + + + + + Enter the signing address, message (ensure you copy line breaks, spaces, tabs, etc. exactly) and signature below to verify the message. Be careful not to read more into the signature than what is in the signed message itself, to avoid being tricked by a man-in-the-middle attack. + + + + + The address the message was signed with (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Verify the message to ensure it was signed with the specified Arepacoin address + + + + + Reset all verify message fields + + + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Click "Sign Message" to generate signature + + + + + Enter Arepacoin signature + + + + + + The entered address is invalid. + Alamat yang dimasukkan tidak sesuai. + + + + + + + Please check the address and try again. + Silahkan periksa alamat dan coba lagi. + + + + + The entered address does not refer to a key. + + + + + Wallet unlock was cancelled. + + + + + Private key for the entered address is not available. + + + + + Message signing failed. + + + + + Message signed. + + + + + The signature could not be decoded. + + + + + + Please check the signature and try again. + + + + + The signature did not match the message digest. + + + + + Message verification failed. + + + + + Message verified. + + + + + TransactionDesc + + + Open until %1 + Buka hingga %1 + + + + Open for %n block(s) + + + + + conflicted + + + + + %1/offline + + + + + %1/unconfirmed + %1/tidak terkonfirmasi + + + + %1 confirmations + %1 konfirmasi + + + + Status + Status + + + + , broadcast through %n node(s) + + + + + Date + Tanggal + + + + Source + + + + + Generated + + + + + + From + Dari + + + + + + To + Untuk + + + + + own address + + + + + label + + + + + + + + + Credit + + + + + matures in %n more block(s) + + + + + not accepted + + + + + + + + Debit + + + + + Transaction fee + + + + + Net amount + + + + + Message + Pesan: + + + + Comment + + + + + Transaction ID + + + + + Generated coins must mature 6 blocks before they can be spent. When you generated this block, it was broadcast to the network to be added to the block chain. If it fails to get into the chain, its state will change to "not accepted" and it won't be spendable. This may occasionally happen if another node generates a block within a few seconds of yours. + + + + + Debug information + + + + + Transaction + Transaksi + + + + Inputs + + + + + Amount + Jumlah + + + + true + + + + + false + + + + + , has not been successfully broadcast yet + , belum berhasil disiarkan + + + + unknown + tidak diketahui + + + + TransactionDescDialog + + + Transaction details + Rincian transaksi + + + + This pane shows a detailed description of the transaction + Jendela ini menampilkan deskripsi rinci dari transaksi tersebut + + + + TransactionTableModel + + + Date + Tanggal + + + + Type + Jenis + + + + Address + Alamat + + + + Amount + Jumlah + + + + Open until %1 + Buka hingga %1 + + + + Confirmed (%1 confirmations) + Terkonfirmasi (%1 konfirmasi) + + + + Open for %n more block(s) + + + + + Offline + + + + + Unconfirmed + + + + + Confirming (%1 of %2 recommended confirmations) + + + + + Conflicted + + + + + Immature (%1 confirmations, will be available after %2) + + + + + This block was not received by any other nodes and will probably not be accepted! + Blok ini tidak diterima oleh node lainnya dan kemungkinan tidak akan diterima! + + + + Generated but not accepted + Terbuat tetapi tidak diterima + + + + Received with + Diterima dengan + + + + Received from + Diterima dari + + + + Sent to + Terkirim ke + + + + Payment to yourself + Pembayaran ke Anda sendiri + + + + Mined + Tertambang + + + + (n/a) + (t/s) + + + + Transaction status. Hover over this field to show number of confirmations. + Status transaksi. Arahkan ke bagian ini untuk menampilkan jumlah konfrimasi. + + + + Date and time that the transaction was received. + Tanggal dan waktu transaksi tersebut diterima. + + + + Type of transaction. + Jenis transaksi. + + + + Destination address of transaction. + Alamat tujuan dari transaksi. + + + + Amount removed from or added to balance. + Jumlah terbuang dari atau ditambahkan ke saldo. + + + + TransactionView + + + + All + Semua + + + + Today + Hari ini + + + + This week + Minggu ini + + + + This month + Bulan ini + + + + Last month + Bulan kemarin + + + + This year + Tahun ini + + + + Range... + Jarak... + + + + Received with + DIterima dengan + + + + Sent to + Terkirim ke + + + + To yourself + Ke Anda sendiri + + + + Mined + Ditambang + + + + Other + Lainnya + + + + Enter address or label to search + Masukkan alamat atau label untuk mencari + + + + Min amount + Jumlah min + + + + Copy address + Salin alamat + + + + Copy label + Salin label + + + + Copy amount + Salin jumlah + + + + Copy transaction ID + + + + + Edit label + Ubah label + + + + Show transaction details + Tampilkan rincian transaksi + + + + Export Transaction Data + + + + + Comma separated file (*.csv) + Berkas CSV (*.csv) + + + + Confirmed + Terkonfirmasi + + + + Date + Tanggal + + + + Type + Jenis + + + + Label + Label + + + + Address + Alamat + + + + Amount + Jumlah + + + + ID + ID + + + + Error exporting + + + + + Could not write to file %1. + + + + + Range: + Jarak: + + + + to + ke + + + + WalletModel + + + Sending... + + + + + bitcoin-core + + + Arepacoin version + + + + + Usage: + Penggunaan: + + + + Send command to -server or arepacoind + + + + + List commands + Daftar perintah + + + + Get help for a command + Dapatkan bantuan untuk perintah + + + + Options: + Pilihan: + + + + Specify configuration file (default: arepacoin.conf) + + + + + Specify pid file (default: arepacoind.pid) + + + + + Specify wallet file (within data directory) + + + + + Specify data directory + Tentukan direktori data + + + + Set database cache size in megabytes (default: 25) + Atur ukuran tembolok dalam megabyte (standar: 25) + + + + Set database disk log size in megabytes (default: 100) + + + + + Listen for connections on <port> (default: 9853 or testnet: 19853) + + + + + Maintain at most <n> connections to peers (default: 125) + Mengatur hubungan paling banyak <n> ke peer (standar: 125) + + + + Connect to a node to retrieve peer addresses, and disconnect + Hubungkan ke node untuk menerima alamat peer, dan putuskan + + + + Specify your own public address + Tentukan alamat publik Anda sendiri + + + + Bind to given address. Use [host]:port notation for IPv6 + + + + + Stake your coins to support network and gain reward (default: 1) + + + + + Threshold for disconnecting misbehaving peers (default: 100) + Batas untuk memutuskan peer buruk (standar: 100) + + + + Number of seconds to keep misbehaving peers from reconnecting (default: 86400) + Jumlah kedua untuk menjaga peer buruk dari hubung-ulang (standar: 86400) + + + + An error occurred while setting up the RPC port %u for listening on IPv4: %s + + + + + Detach block and address databases. Increases shutdown time (default: 0) + + + + + 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. + + + + + Error: This transaction requires a transaction fee of at least %s because of its amount, complexity, or use of recently received funds + + + + + Listen for JSON-RPC connections on <port> (default: 9852 or testnet: 19852) + + + + + Accept command line and JSON-RPC commands + Menerima perintah baris perintah dan JSON-RPC + + + + Error: Transaction creation failed + + + + + Error: Wallet locked, unable to create transaction + + + + + Importing blockchain data file. + + + + + Importing bootstrap blockchain data file. + + + + + Run in the background as a daemon and accept commands + Berjalan dibelakang sebagai daemin dan menerima perintah + + + + Use the test network + Gunakan jaringan uji + + + + Accept connections from outside (default: 1 if no -proxy or -connect) + + + + + An error occurred while setting up the RPC port %u for listening on IPv6, falling back to IPv4: %s + + + + + Error initializing database environment %s! To recover, BACKUP THAT DIRECTORY, then remove everything from it except for wallet.dat. + + + + + Set maximum size of high-priority/low-fee transactions in bytes (default: 27000) + + + + + Warning: -paytxfee is set very high! This is the transaction fee you will pay if you send a transaction. + + + + + Warning: Please check that your computer's date and time are correct! If your clock is wrong Arepacoin will not work properly. + + + + + Warning: error reading wallet.dat! All keys read correctly, but transaction data or address book entries might be missing or incorrect. + + + + + Warning: wallet.dat corrupt, data salvaged! Original wallet.dat saved as wallet.{timestamp}.bak in %s; if your balance or transactions are incorrect you should restore from a backup. + + + + + Attempt to recover private keys from a corrupt wallet.dat + + + + + Block creation options: + + + + + Connect only to the specified node(s) + + + + + Discover own IP address (default: 1 when listening and no -externalip) + + + + + Failed to listen on any port. Use -listen=0 if you want this. + + + + + Find peers using DNS lookup (default: 1) + + + + + Sync checkpoints policy (default: strict) + + + + + Invalid -tor address: '%s' + + + + + Invalid amount for -reservebalance=<amount> + + + + + Maximum per-connection receive buffer, <n>*1000 bytes (default: 5000) + + + + + Maximum per-connection send buffer, <n>*1000 bytes (default: 1000) + + + + + Only connect to nodes in network <net> (IPv4, IPv6 or Tor) + + + + + Output extra debugging information. Implies all other -debug* options + + + + + Output extra network debugging information + + + + + Prepend debug output with timestamp + + + + + SSL options: (see the Bitcoin Wiki for SSL setup instructions) + + + + + Select the version of socks proxy to use (4-5, default: 5) + + + + + Send trace/debug info to console instead of debug.log file + Kirim info lacak/debug ke konsol sebaliknya dari berkas debug.log + + + + Send trace/debug info to debugger + + + + + Set maximum block size in bytes (default: 250000) + + + + + Set minimum block size in bytes (default: 0) + + + + + Shrink debug.log file on client startup (default: 1 when no -debug) + + + + + Specify connection timeout in milliseconds (default: 5000) + + + + + Unable to sign checkpoint, wrong checkpointkey? + + + + + + Use UPnP to map the listening port (default: 0) + + + + + Use UPnP to map the listening port (default: 1 when listening) + + + + + Use proxy to reach tor hidden services (default: same as -proxy) + + + + + Username for JSON-RPC connections + Nama pengguna untuk hubungan JSON-RPC + + + + Verifying database integrity... + + + + + WARNING: syncronized checkpoint violation detected, but skipped! + + + + + Warning: Disk space is low! + + + + + Warning: This version is obsolete, upgrade required! + + + + + wallet.dat corrupt, salvage failed + + + + + Password for JSON-RPC connections + Kata sandi untuk hubungan JSON-RPC + + + + %s, you must set a rpcpassword in the configuration file: + %s +It is recommended you use the following random password: +rpcuser=arepacoinrpc +rpcpassword=%s +(you do not need to remember this password) +The username and password MUST NOT be the same. +If the file does not exist, create it with owner-readable-only file permissions. +It is also recommended to set alertnotify so you are notified of problems; +for example: alertnotify=echo %%s | mail -s "Arepacoin Alert" admin@foo.com + + + + + + Find peers using internet relay chat (default: 0) + + + + + Sync time with other nodes. Disable if time on your system is precise e.g. syncing with NTP (default: 1) + + + + + When creating transactions, ignore inputs with value less than this (default: 0.01) + + + + + Allow JSON-RPC connections from specified IP address + Izinkan hubungan JSON-RPC dari alamat IP yang ditentukan + + + + Send commands to node running on <ip> (default: 127.0.0.1) + Kirim perintah ke node berjalan pada <ip> (standar: 127.0.0.1) + + + + Execute command when the best block changes (%s in cmd is replaced by block hash) + Menjalankan perintah ketika perubahan blok terbaik (%s dalam cmd digantikan oleh hash blok) + + + + Execute command when a wallet transaction changes (%s in cmd is replaced by TxID) + + + + + Require a confirmations for change (default: 0) + + + + + Enforce transaction scripts to use canonical PUSH operators (default: 1) + + + + + Execute command when a relevant alert is received (%s in cmd is replaced by message) + + + + + Upgrade wallet to latest format + Perbarui dompet ke format terbaru + + + + Set key pool size to <n> (default: 100) + Kirim ukuran kolam kunci ke <n> (standar: 100) + + + + Rescan the block chain for missing wallet transactions + Pindai ulang rantai-blok untuk transaksi dompet yang hilang + + + + How many blocks to check at startup (default: 2500, 0 = all) + + + + + How thorough the block verification is (0-6, default: 1) + + + + + Imports blocks from external blk000?.dat file + + + + + Use OpenSSL (https) for JSON-RPC connections + Gunakan OpenSSL (https) untuk hubungan JSON-RPC + + + + Server certificate file (default: server.cert) + Berkas sertifikat server (standar: server.cert) + + + + Server private key (default: server.pem) + Kunci pribadi server (standar: server.pem) + + + + Acceptable ciphers (default: TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH) + + + + + Error: Wallet unlocked for staking only, unable to create transaction. + Eror: Dompet hanya di-buka hanya untuk staking, transaksi gagal dilaksanakan + + + + WARNING: Invalid checkpoint found! Displayed transactions may not be correct! You may need to upgrade, or notify developers. + + + + + This help message + Pesan bantuan ini + + + + Wallet %s resides outside data directory %s. + + + + + Cannot obtain a lock on data directory %s. Arepacoin is probably already running. + + + + + Arepacoin + Arepacoin + + + + Unable to bind to %s on this computer (bind returned error %d, %s) + Tidak dapat mengikat ke %s dengan komputer ini (ikatan gagal %d, %s) + + + + Connect through socks proxy + + + + + Allow DNS lookups for -addnode, -seednode and -connect + Izinkan peninjauan DNS untuk -addnote, -seednode dan -connect + + + + Loading addresses... + Memuat alamat... + + + + Error loading blkindex.dat + + + + + Error loading wallet.dat: Wallet corrupted + Gagal memuat wallet.dat: Dompet rusak + + + + Error loading wallet.dat: Wallet requires newer version of Arepacoin + + + + + Wallet needed to be rewritten: restart Arepacoin to complete + + + + + Error loading wallet.dat + Gagal memuat wallet.dat + + + + Invalid -proxy address: '%s' + Alamat -proxy salah: '%s' + + + + Unknown network specified in -onlynet: '%s' + Jaringan tidak diketahui yang ditentukan dalam -onlynet: '%s' + + + + Unknown -socks proxy version requested: %i + Diminta versi proxy -socks tidak diketahui: %i + + + + Cannot resolve -bind address: '%s' + Tidak dapat menyelesaikan alamat -bind: '%s' + + + + Cannot resolve -externalip address: '%s' + Tidak dapat menyelesaikan alamat -externalip: '%s' + + + + Invalid amount for -paytxfee=<amount>: '%s' + Jumlah salah untuk -paytxfee=<amount>: '%s' + + + + Error: could not start node + + + + + Sending... + Mengirim... + + + + Invalid amount + Jumlah salah + + + + Insufficient funds + Saldo tidak mencukupi + + + + Loading block index... + Memuat indeks blok... + + + + Add a node to connect to and attempt to keep the connection open + Tambahkan node untuk dihubungkan dan upaya untuk menjaga hubungan tetap terbuka + + + + Unable to bind to %s on this computer. Arepacoin is probably already running. + + + + + Fee per KB to add to transactions you send + + + + + Invalid amount for -mininput=<amount>: '%s' + + + + + Loading wallet... + Memuat dompet... + + + + Cannot downgrade wallet + Tidak dapat menurunkan versi dompet + + + + Cannot initialize keypool + initialisasi keypool gagal + + + + Cannot write default address + Tidak dapat menyimpan alamat standar + + + + Rescanning... + Memindai ulang... + + + + Done loading + Memuat selesai + + + + To use the %s option + Gunakan pilihan %s + + + + Error + Gagal + + + + You must set rpcpassword=<password> in the configuration file: +%s +If the file does not exist, create it with owner-readable-only file permissions. + Anda harus mengatur rpcpassword=<kata sandi> dalam berkas konfigurasi: +%s +Jika berkas tidak ada, buatlah dengan permisi berkas hanya-dapat-dibaca-oleh-pemilik. + + + \ No newline at end of file diff --git a/src/qt/locale/bitcoin_it.ts b/src/qt/locale/bitcoin_it.ts new file mode 100755 index 0000000..996e40f --- /dev/null +++ b/src/qt/locale/bitcoin_it.ts @@ -0,0 +1,3299 @@ + + + AboutDialog + + + About Arepacoin + + + + + <b>Arepacoin</b> version + + + + + Copyright © 2009-2014 The Bitcoin developers +Copyright © 2012-2014 The NovaCoin developers +Copyright © 2014 The Arepacoin developers + + + + + +This is experimental software. + +Distributed under the MIT/X11 software license, see the accompanying file COPYING or http://www.opensource.org/licenses/mit-license.php. + +This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit (http://www.openssl.org/) and cryptographic software written by Eric Young (eay@cryptsoft.com) and UPnP software written by Thomas Bernard. + +Questo è un software sperimentale. + +Distribuito sotto la licenza software MIT/X11, vedi il file COPYING incluso oppure su http://www.opensource.org/licenses/mit-license.php. + +Questo prodotto include software sviluppato dal progetto OpenSSL per l'uso del Toolkit OpenSSL (http://www.openssl.org/), software crittografico scritto da Eric Young (eay@cryptsoft.com) e software UPnP scritto da Thomas Bernard. + + + + AddressBookPage + + + Address Book + + + + + Double-click to edit address or label + Fai doppio click per modificare o cancellare l'etichetta + + + + Create a new address + Crea un nuovo indirizzo + + + + Copy the currently selected address to the system clipboard + Copia l'indirizzo attualmente selezionato nella clipboard + + + + &New Address + + + + + These are your Arepacoin addresses for receiving payments. You may want to give a different one to each sender so you can keep track of who is paying you. + + + + + &Copy Address + &Copia l'indirizzo + + + + Show &QR Code + + + + + Sign a message to prove you own a Arepacoin address + + + + + Sign &Message + + + + + Delete the currently selected address from the list + Cancella l'indirizzo attualmente selezionato dalla lista + + + + Verify a message to ensure it was signed with a specified Arepacoin address + + + + + &Verify Message + + + + + &Delete + &Cancella + + + + Copy &Label + Copia &l'etichetta + + + + &Edit + &Modifica + + + + Export Address Book Data + + + + + Comma separated file (*.csv) + Testo CSV (*.csv) + + + + Error exporting + + + + + Could not write to file %1. + + + + + AddressTableModel + + + Label + Etichetta + + + + Address + Indirizzo + + + + (no label) + (nessuna etichetta) + + + + AskPassphraseDialog + + + Passphrase Dialog + Finestra passphrase + + + + Enter passphrase + Inserisci la passphrase + + + + New passphrase + Nuova passphrase + + + + Repeat new passphrase + Ripeti la passphrase + + + + Serves to disable the trivial sendmoney when OS account compromised. Provides no real security. + + + + + For staking only + + + + + Enter the new passphrase to the wallet.<br/>Please use a passphrase of <b>10 or more random characters</b>, or <b>eight or more words</b>. + Inserisci la passphrase per il portamonete.<br/>Per piacere usare unapassphrase di <b>10 o più caratteri casuali</b>, o <b>otto o più parole</b>. + + + + Encrypt wallet + Cifra il portamonete + + + + This operation needs your wallet passphrase to unlock the wallet. + Quest'operazione necessita della passphrase per sbloccare il portamonete. + + + + Unlock wallet + Sblocca il portamonete + + + + This operation needs your wallet passphrase to decrypt the wallet. + Quest'operazione necessita della passphrase per decifrare il portamonete, + + + + Decrypt wallet + Decifra il portamonete + + + + Change passphrase + Cambia la passphrase + + + + Enter the old and new passphrase to the wallet. + Inserisci la vecchia e la nuova passphrase per il portamonete. + + + + Confirm wallet encryption + Conferma la cifratura del portamonete + + + + Warning: If you encrypt your wallet and lose your passphrase, you will <b>LOSE ALL OF YOUR COINS</b>! + + + + + Are you sure you wish to encrypt your wallet? + Si è sicuri di voler cifrare il portamonete? + + + + IMPORTANT: Any previous backups you have made of your wallet file should be replaced with the newly generated, encrypted wallet file. For security reasons, previous backups of the unencrypted wallet file will become useless as soon as you start using the new, encrypted wallet. + IMPORTANTE: qualsiasi backup del portafoglio effettuato precedentemente dovrebbe essere sostituito con il file del portafoglio criptato appena generato. Per ragioni di sicurezza, i backup precedenti del file del portafoglio non criptato diventeranno inservibili non appena si inizi ad usare il nuovo portafoglio criptato. + + + + + Warning: The Caps Lock key is on! + Attenzione: tasto Blocco maiuscole attivo. + + + + + Wallet encrypted + Portamonete cifrato + + + + Arepacoin will close now to finish the encryption process. Remember that encrypting your wallet cannot fully protect your coins from being stolen by malware infecting your computer. + + + + + + + + Wallet encryption failed + Cifratura del portamonete fallita + + + + Wallet encryption failed due to an internal error. Your wallet was not encrypted. + Cifratura del portamonete fallita a causa di un errore interno. Il portamonete non è stato cifrato. + + + + + The supplied passphrases do not match. + Le passphrase inserite non corrispondono. + + + + Wallet unlock failed + Sblocco del portamonete fallito + + + + + + The passphrase entered for the wallet decryption was incorrect. + La passphrase inserita per la decifrazione del portamonete è errata. + + + + Wallet decryption failed + Decifrazione del portamonete fallita + + + + Wallet passphrase was successfully changed. + Passphrase del portamonete modificata con successo. + + + + BitcoinGUI + + + Sign &message... + Firma il &messaggio... + + + + Synchronizing with network... + Sto sincronizzando con la rete... + + + + &Overview + &Sintesi + + + + Show general overview of wallet + Mostra lo stato generale del portamonete + + + + &Transactions + &Transazioni + + + + Browse transaction history + Cerca nelle transazioni + + + + &Address Book + + + + + Edit the list of stored addresses and labels + + + + + &Receive coins + + + + + Show the list of addresses for receiving payments + + + + + &Send coins + + + + + E&xit + &Esci + + + + Quit application + Chiudi applicazione + + + + Show information about Arepacoin + + + + + About &Qt + Informazioni su &Qt + + + + Show information about Qt + Mostra informazioni su Qt + + + + &Options... + &Opzioni... + + + + &Encrypt Wallet... + &Cifra il portamonete... + + + + &Backup Wallet... + &Backup Portamonete... + + + + &Change Passphrase... + &Cambia la passphrase... + + + + ~%n block(s) remaining + + + + + Downloaded %1 of %2 blocks of transaction history (%3% done). + + + + + &Export... + + + + + Send coins to a Arepacoin address + + + + + Modify configuration options for Arepacoin + + + + + Export the data in the current tab to a file + + + + + Encrypt or decrypt wallet + + + + + Backup wallet to another location + Backup portamonete in un'altra locazione + + + + Change the passphrase used for wallet encryption + Cambia la passphrase per la cifratura del portamonete + + + + &Debug window + Finestra &Debug + + + + Open debugging and diagnostic console + Apri la console di degugging e diagnostica + + + + &Verify message... + &Verifica messaggio... + + + + Arepacoin + + + + + Wallet + Portamonete + + + + &About Arepacoin + + + + + &Show / Hide + &Mostra/Nascondi + + + + Unlock wallet + + + + + &Lock Wallet + + + + + Lock wallet + + + + + &File + &File + + + + &Settings + &Impostazioni + + + + &Help + &Aiuto + + + + Tabs toolbar + Barra degli strumenti "Tabs" + + + + Actions toolbar + + + + + + [testnet] + [testnet] + + + + + Arepacoin client + + + + + %n active connection(s) to Arepacoin network + + + + + Downloaded %1 blocks of transaction history. + + + + + Staking.<br>Your weight is %1<br>Network weight is %2<br>Expected time to earn reward is %3 + + + + + Not staking because wallet is locked + + + + + Not staking because wallet is offline + + + + + Not staking because wallet is syncing + + + + + Not staking because you don't have mature coins + + + + + %n second(s) ago + + + + + &Unlock Wallet... + + + + + %n minute(s) ago + + + + + %n hour(s) ago + + + + + %n day(s) ago + + + + + Up to date + Aggiornato + + + + Catching up... + In aggiornamento... + + + + Last received block was generated %1. + + + + + This transaction is over the size limit. You can still send it for a fee of %1, which goes to the nodes that process your transaction and helps to support the network. Do you want to pay the fee? + + + + + Confirm transaction fee + + + + + Sent transaction + Transazione inviata + + + + Incoming transaction + Transazione ricevuta + + + + Date: %1 +Amount: %2 +Type: %3 +Address: %4 + + Data: %1 +Quantità: %2 +Tipo: %3 +Indirizzo: %4 + + + + + + + URI handling + + + + + + URI can not be parsed! This can be caused by an invalid Arepacoin address or malformed URI parameters. + + + + + Wallet is <b>encrypted</b> and currently <b>unlocked</b> + Il portamonete è <b>cifrato</b> e attualmente <b>sbloccato</b> + + + + Wallet is <b>encrypted</b> and currently <b>locked</b> + Il portamonete è <b>cifrato</b> e attualmente <b>bloccato</b> + + + + Backup Wallet + + + + + Wallet Data (*.dat) + + + + + Backup Failed + + + + + There was an error trying to save the wallet data to the new location. + + + + + %n second(s) + + + + + %n minute(s) + + + + + %n hour(s) + %n ora%n ore + + + + %n day(s) + %n giorno%n giorni + + + + Not staking + + + + + A fatal error occurred. Arepacoin can no longer continue safely and will quit. + + + + + ClientModel + + + Network Alert + Avviso di rete + + + + CoinControlDialog + + + Coin Control + + + + + Quantity: + Quantità: + + + + Bytes: + Byte: + + + + Amount: + Importo: + + + + Priority: + Priorità: + + + + Fee: + Commissione: + + + + Low Output: + Low Output: + + + + no + no + + + + After Fee: + Dopo Commissione: + + + + Change: + Resto: + + + + (un)select all + (de)seleziona tutto + + + + Tree mode + Modalità Albero + + + + List mode + Modalità Lista + + + + Amount + Importo + + + + Label + + + + + Address + Indirizzo + + + + Date + Data + + + + Confirmations + Conferme: + + + + Confirmed + Confermato + + + + Priority + Priorità + + + + Copy address + Copia l'indirizzo + + + + Copy label + Copia l'etichetta + + + + + Copy amount + Copia l'importo + + + + Copy transaction ID + Copia l'ID transazione + + + + Copy quantity + Copia quantità + + + + Copy fee + Copia commissione + + + + Copy after fee + Copia dopo commissione + + + + Copy bytes + Copia byte + + + + Copy priority + Copia priorità + + + + Copy low output + Copia low output + + + + Copy change + Copia resto + + + + highest + massima + + + + high + alta + + + + medium-high + medio-alta + + + + medium + media + + + + low-medium + medio-bassa + + + + low + bassa + + + + lowest + infima + + + + DUST + + + + + yes + si + + + + This label turns red, if the transaction size is bigger than 10000 bytes. + + This means a fee of at least %1 per kb is required. + + Can vary +/- 1 Byte per input. + + + + + Transactions with higher priority get more likely into a block. + +This label turns red, if the priority is smaller than "medium". + + This means a fee of at least %1 per kb is required. + + + + + This label turns red, if any recipient receives an amount smaller than %1. + + This means a fee of at least %2 is required. + + Amounts below 0.546 times the minimum relay fee are shown as DUST. + + + + + This label turns red, if the change is smaller than %1. + + This means a fee of at least %2 is required. + + + + + + (no label) + (nessuna etichetta) + + + + change from %1 (%2) + resto da %1 (%2) + + + + (change) + (resto) + + + + EditAddressDialog + + + Edit Address + Modifica l'indirizzo + + + + &Label + &Etichetta + + + + The label associated with this address book entry + + + + + &Address + &Indirizzo + + + + The address associated with this address book entry. This can only be modified for sending addresses. + + + + + New receiving address + Nuovo indirizzo di ricezione + + + + New sending address + Nuovo indirizzo d'invio + + + + Edit receiving address + Modifica indirizzo di ricezione + + + + Edit sending address + Modifica indirizzo d'invio + + + + The entered address "%1" is already in the address book. + L'indirizzo inserito "%1" è già in rubrica. + + + + The entered address "%1" is not a valid Arepacoin address. + + + + + Could not unlock wallet. + Impossibile sbloccare il portamonete. + + + + New key generation failed. + Generazione della nuova chiave non riuscita. + + + + GUIUtil::HelpMessageBox + + + + Arepacoin-Qt + + + + + version + + + + + Usage: + + + + + command-line options + + + + + UI options + + + + + Set language, for example "de_DE" (default: system locale) + + + + + Start minimized + + + + + Show splash screen on startup (default: 1) + + + + + OptionsDialog + + + Options + Opzioni + + + + &Main + &Principale + + + + Optional transaction fee per kB that helps make sure your transactions are processed quickly. Most transactions are 1 kB. Fee 0.01 recommended. + + + + + Pay transaction &fee + Paga la &commissione + + + + Reserved amount does not participate in staking and is therefore spendable at any time. + + + + + Reserve + + + + + Automatically start Arepacoin after logging in to the system. + + + + + &Start Arepacoin on system login + + + + + Detach block and address databases at shutdown. This means they can be moved to another data directory, but it slows down shutdown. The wallet is always detached. + + + + + &Detach databases at shutdown + + + + + &Network + Rete + + + + Automatically open the Arepacoin client port on the router. This only works when your router supports UPnP and it is enabled. + + + + + Map port using &UPnP + Mappa le porte tramite l'&UPnP + + + + Connect to the Arepacoin network through a SOCKS proxy (e.g. when connecting through Tor). + + + + + &Connect through SOCKS proxy: + + + + + Proxy &IP: + &IP del proxy: + + + + IP address of the proxy (e.g. 127.0.0.1) + + + + + &Port: + &Porta: + + + + Port of the proxy (e.g. 9050) + Porta del proxy (es. 9050) + + + + SOCKS &Version: + SOCKS &Version: + + + + SOCKS version of the proxy (e.g. 5) + Versione SOCKS del proxy (es. 5) + + + + &Window + &Finestra + + + + Show only a tray icon after minimizing the window. + Mostra solo un'icona nel tray quando si minimizza la finestra + + + + &Minimize to the tray instead of the taskbar + &Minimizza sul tray invece che sulla barra delle applicazioni + + + + Minimize instead of exit the application when the window is closed. When this option is enabled, the application will be closed only after selecting Quit in the menu. + Riduci ad icona, invece di uscire dall'applicazione quando la finestra viene chiusa. Quando questa opzione è attivata, l'applicazione verrà chiusa solo dopo aver selezionato Esci nel menu. + + + + M&inimize on close + M&inimizza alla chiusura + + + + &Display + &Mostra + + + + User Interface &language: + &Lingua Interfaccia Utente: + + + + The user interface language can be set here. This setting will take effect after restarting Arepacoin. + + + + + &Unit to show amounts in: + &Unità di misura degli importi in: + + + + Choose the default subdivision unit to show in the interface and when sending coins. + Scegli l'unità di suddivisione predefinita per l'interfaccia e per l'invio di monete + + + + Whether to show Arepacoin addresses in the transaction list or not. + + + + + &Display addresses in transaction list + &Mostra gli indirizzi nella lista delle transazioni + + + + Whether to show coin control features or not. + Mostrare/non mostrare le funzionalita' di controllo della moneta. + + + + Display coin &control features (experts only!) + + + + + &OK + &OK + + + + &Cancel + &Cancella + + + + &Apply + + + + + default + predefinito + + + + + Warning + + + + + + This setting will take effect after restarting Arepacoin. + + + + + The supplied proxy address is invalid. + L'indirizzo proxy che hai fornito è invalido. + + + + OverviewPage + + + Form + Modulo + + + + + The displayed information may be out of date. Your wallet automatically synchronizes with the Arepacoin network after a connection is established, but this process has not completed yet. + + + + + Stake: + + + + + Unconfirmed: + + + + + Wallet + Portamonete + + + + Spendable: + + + + + Your current spendable balance + Saldo spendibile attuale + + + + Immature: + Immaturo: + + + + Mined balance that has not yet matured + Importo scavato che non è ancora maturato + + + + Total: + Totale: + + + + Your current total balance + Saldo totale attuale + + + + <b>Recent transactions</b> + <b>Transazioni recenti</b> + + + + Total of transactions that have yet to be confirmed, and do not yet count toward the current balance + + + + + Total of coins that was staked, and do not yet count toward the current balance + + + + + + out of sync + fuori sincrono + + + + QRCodeDialog + + + QR Code Dialog + + + + + Request Payment + + + + + Amount: + + + + + Label: + + + + + Message: + + + + + &Save As... + + + + + Error encoding URI into QR Code. + + + + + The entered amount is invalid, please check. + + + + + Resulting URI too long, try to reduce the text for label / message. + + + + + Save QR Code + + + + + PNG Images (*.png) + + + + + RPCConsole + + + Client name + Nome del client + + + + + + + + + + + + + N/A + N/D + + + + Client version + Versione client + + + + &Information + &Informazione + + + + Using OpenSSL version + Versione OpenSSL in uso + + + + Startup time + Tempo di avvio + + + + Network + Rete + + + + Number of connections + Numero connessioni + + + + On testnet + + + + + Block chain + Block chain + + + + Current number of blocks + Numero attuale di blocchi + + + + Estimated total blocks + Numero totale stimato di blocchi + + + + Last block time + Ora dell blocco piu recente + + + + &Open + &Apri + + + + Command-line options + + + + + Show the Arepacoin-Qt help message to get a list with possible Arepacoin command-line options. + + + + + &Show + + + + + &Console + &Console + + + + Build date + Data di creazione + + + + Arepacoin - Debug window + + + + + Arepacoin Core + + + + + Debug log file + File log del Debug + + + + Open the Arepacoin debug log file from the current data directory. This can take a few seconds for large log files. + + + + + Clear console + Svuota console + + + + Welcome to the Arepacoin RPC console. + + + + + Use up and down arrows to navigate history, and <b>Ctrl-L</b> to clear screen. + Usa le frecce direzionali per navigare la cronologia, and <b>Ctrl-L</b> per cancellarla. + + + + Type <b>help</b> for an overview of available commands. + Scrivi <b>help</b> per un riassunto dei comandi disponibili + + + + SendCoinsDialog + + + + + + + + + + Send Coins + Spedisci Bitcoin + + + + Coin Control Features + Funzionalità di Coin Control + + + + Inputs... + Input... + + + + automatically selected + selezionato automaticamente + + + + Insufficient funds! + Fondi insufficienti! + + + + Quantity: + Quantità: + + + + + 0 + + + + + Bytes: + Byte: + + + + Amount: + Importo: + + + + + + + 0.00 BC + + + + + Priority: + Priorità: + + + + medium + + + + + Fee: + Commissione: + + + + Low Output: + Low Output: + + + + no + + + + + After Fee: + Dopo Commissione: + + + + Change + + + + + custom change address + + + + + Send to multiple recipients at once + Spedisci a diversi beneficiari in una volta sola + + + + Add &Recipient + &Aggiungi beneficiario + + + + Remove all transaction fields + + + + + Clear &All + Cancella &tutto + + + + Balance: + Saldo: + + + + 123.456 BC + + + + + Confirm the send action + Conferma la spedizione + + + + S&end + &Spedisci + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Copy quantity + Copia quantità + + + + Copy amount + Copia l'importo + + + + Copy fee + Copia commissione + + + + Copy after fee + Copia dopo commissione + + + + Copy bytes + Copia byte + + + + Copy priority + Copia priorità + + + + Copy low output + Copia low output + + + + Copy change + Copia resto + + + + <b>%1</b> to %2 (%3) + + + + + Confirm send coins + Conferma la spedizione di bitcoin + + + + Are you sure you want to send %1? + + + + + and + + + + + The recipient address is not valid, please recheck. + L'indirizzo del beneficiario non è valido, per cortesia controlla. + + + + The amount to pay must be larger than 0. + L'importo da pagare dev'essere maggiore di 0. + + + + The amount exceeds your balance. + L'importo è superiore al saldo attuale + + + + The total exceeds your balance when the %1 transaction fee is included. + Il totale è superiore al saldo attuale includendo la commissione %1. + + + + Duplicate address found, can only send to each address once per send operation. + Trovato un indirizzo doppio, si può spedire solo una volta a ciascun indirizzo in una singola operazione. + + + + Error: Transaction creation failed. + + + + + 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. + + + + + WARNING: Invalid Arepacoin address + + + + + (no label) + (nessuna etichetta) + + + + WARNING: unknown change address + + + + + SendCoinsEntry + + + Form + + + + + A&mount: + &Importo: + + + + Pay &To: + Paga &a: + + + + + Enter a label for this address to add it to your address book + Inserisci un'etichetta per questo indirizzo, per aggiungerlo nella rubrica + + + + &Label: + &Etichetta + + + + The address to send the payment to (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Choose address from address book + + + + + Alt+A + Alt+A + + + + Paste address from clipboard + Incollare l'indirizzo dagli appunti + + + + Alt+P + Alt+P + + + + Remove this recipient + + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + SignVerifyMessageDialog + + + Signatures - Sign / Verify a Message + Firme - Firma / Verifica un messaggio + + + + + &Sign Message + &Firma il messaggio + + + + You can sign messages with your addresses to prove you own them. Be careful not to sign anything vague, as phishing attacks may try to trick you into signing your identity over to them. Only sign fully-detailed statements you agree to. + Puoi firmare messeggi con i tuoi indirizzi per dimostrare che sono tuoi. Fai attenzione a non firmare niente di vago, visto che gli attacchi di phishing potrebbero cercare di spingerti a mettere la tua firma su di loro. Firma solo dichiarazioni completamente dettagliate con cui sei d'accordo. + + + + The address to sign the message with (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + + Choose an address from the address book + + + + + + Alt+A + Alt+A + + + + Paste address from clipboard + Incollare l'indirizzo dagli appunti + + + + Alt+P + Alt+P + + + + Enter the message you want to sign here + Inserisci qui il messaggio che vuoi firmare + + + + Copy the current signature to the system clipboard + Copia la firma corrente nella clipboard + + + + Sign the message to prove you own this Arepacoin address + + + + + Reset all sign message fields + Reimposta tutti i campi della firma + + + + + Clear &All + Cancella &tutto + + + + + &Verify Message + &Verifica Messaggio + + + + Enter the signing address, message (ensure you copy line breaks, spaces, tabs, etc. exactly) and signature below to verify the message. Be careful not to read more into the signature than what is in the signed message itself, to avoid being tricked by a man-in-the-middle attack. + Inserisci l'indirizzo per la firma, il messaggio (verifica di copiare esattamente anche i ritorni a capo, gli spazi, le tabulazioni, etc) e la firma qui sotto, per verificare il messaggio. Verifica che il contenuto della firma non sia più grande di quello del messaggio per evitare attacchi di tipo man-in-the-middle. + + + + The address the message was signed with (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Verify the message to ensure it was signed with the specified Arepacoin address + + + + + Reset all verify message fields + Reimposta tutti i campi della verifica messaggio + + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Click "Sign Message" to generate signature + Clicca "Firma il messaggio" per ottenere la firma + + + + Enter Arepacoin signature + + + + + + The entered address is invalid. + L'indirizzo inserito non è valido. + + + + + + + Please check the address and try again. + Per favore controlla l'indirizzo e prova ancora + + + + + The entered address does not refer to a key. + L'indirizzo bitcoin inserito non è associato a nessuna chiave. + + + + Wallet unlock was cancelled. + Sblocco del portafoglio annullato. + + + + Private key for the entered address is not available. + La chiave privata per l'indirizzo inserito non è disponibile. + + + + Message signing failed. + Firma messaggio fallita. + + + + Message signed. + Messaggio firmato. + + + + The signature could not be decoded. + Non è stato possibile decodificare la firma. + + + + + Please check the signature and try again. + Per favore controlla la firma e prova ancora. + + + + The signature did not match the message digest. + La firma non corrisponde al sunto del messaggio. + + + + Message verification failed. + Verifica messaggio fallita. + + + + Message verified. + Messaggio verificato. + + + + TransactionDesc + + + Open until %1 + Aperto fino a %1 + + + + Open for %n block(s) + + + + + conflicted + in conflitto + + + + %1/offline + %1/offline + + + + %1/unconfirmed + %1/non confermato + + + + %1 confirmations + %1 conferme + + + + Status + Stato + + + + , broadcast through %n node(s) + , trasmesso attraverso %n nodo, trasmesso attraverso %n nodi + + + + Date + Data + + + + Source + Sorgente + + + + Generated + Generato + + + + + From + Da + + + + + + To + A + + + + + own address + proprio indirizzo + + + + label + etichetta + + + + + + + + Credit + Credito + + + + matures in %n more block(s) + matura in %n ulteriore bloccomatura in altri %n blocchi + + + + not accepted + non accettate + + + + + + + Debit + Debito + + + + Transaction fee + Commissione transazione + + + + Net amount + Importo netto + + + + Message + Messaggio + + + + Comment + Commento + + + + Transaction ID + ID della transazione + + + + Generated coins must mature 6 blocks before they can be spent. When you generated this block, it was broadcast to the network to be added to the block chain. If it fails to get into the chain, its state will change to "not accepted" and it won't be spendable. This may occasionally happen if another node generates a block within a few seconds of yours. + + + + + Debug information + Informazione di debug + + + + Transaction + Transazione + + + + Inputs + Input + + + + Amount + Importo + + + + true + vero + + + + false + falso + + + + , has not been successfully broadcast yet + , non è stato ancora trasmesso con successo + + + + unknown + sconosciuto + + + + TransactionDescDialog + + + Transaction details + Dettagli sulla transazione + + + + This pane shows a detailed description of the transaction + Questo pannello mostra una descrizione dettagliata della transazione + + + + TransactionTableModel + + + Date + Data + + + + Type + Tipo + + + + Address + Indirizzo + + + + Amount + Importo + + + + Open until %1 + Aperto fino a %1 + + + + Confirmed (%1 confirmations) + Confermato (%1 conferme) + + + + Open for %n more block(s) + Aperto per %n altro bloccoAperto per altri %n blocchi + + + + Offline + Offline + + + + Unconfirmed + Non confermato: + + + + Confirming (%1 of %2 recommended confirmations) + In conferma (%1 di %2 conferme raccomandate) + + + + Conflicted + In conflitto + + + + Immature (%1 confirmations, will be available after %2) + Immaturo (%1 conferme, sarà disponibile fra %2) + + + + This block was not received by any other nodes and will probably not be accepted! + Questo blocco non è stato ricevuto da altri nodi e probabilmente non sarà accettato! + + + + Generated but not accepted + Generati, ma non accettati + + + + Received with + Ricevuto tramite + + + + Received from + Ricevuto da + + + + Sent to + Spedito a + + + + Payment to yourself + Pagamento a te stesso + + + + Mined + Ottenuto dal mining + + + + (n/a) + (N / a) + + + + Transaction status. Hover over this field to show number of confirmations. + Stato della transazione. Passare con il mouse su questo campo per vedere il numero di conferme. + + + + Date and time that the transaction was received. + Data e ora in cui la transazione è stata ricevuta. + + + + Type of transaction. + Tipo di transazione. + + + + Destination address of transaction. + Indirizzo di destinazione della transazione. + + + + Amount removed from or added to balance. + Importo rimosso o aggiunto al saldo. + + + + TransactionView + + + + All + Tutti + + + + Today + Oggi + + + + This week + Questa settimana + + + + This month + Questo mese + + + + Last month + Il mese scorso + + + + This year + Quest'anno + + + + Range... + Intervallo... + + + + Received with + Ricevuto tramite + + + + Sent to + Spedito a + + + + To yourself + A te + + + + Mined + Ottenuto dal mining + + + + Other + Altro + + + + Enter address or label to search + Inserisci un indirizzo o un'etichetta da cercare + + + + Min amount + Importo minimo + + + + Copy address + Copia l'indirizzo + + + + Copy label + Copia l'etichetta + + + + Copy amount + Copia l'importo + + + + Copy transaction ID + Copia l'ID transazione + + + + Edit label + Modifica l'etichetta + + + + Show transaction details + Mostra i dettagli della transazione + + + + Export Transaction Data + + + + + Comma separated file (*.csv) + Testo CSV (*.csv) + + + + Confirmed + Confermato + + + + Date + Data + + + + Type + Tipo + + + + Label + Etichetta + + + + Address + Indirizzo + + + + Amount + Importo + + + + ID + ID + + + + Error exporting + + + + + Could not write to file %1. + + + + + Range: + Intervallo: + + + + to + a + + + + WalletModel + + + Sending... + + + + + bitcoin-core + + + Arepacoin version + + + + + Usage: + Utilizzo: + + + + Send command to -server or arepacoind + + + + + List commands + Lista comandi + + + + + Get help for a command + Aiuto su un comando + + + + + Options: + Opzioni: + + + + + Specify configuration file (default: arepacoin.conf) + + + + + Specify pid file (default: arepacoind.pid) + + + + + Specify wallet file (within data directory) + Specifica il file portafoglio (nella cartella dati) + + + + Specify data directory + Specifica la cartella dati + + + + + Set database cache size in megabytes (default: 25) + Imposta la dimensione cache del database in megabyte (predefinita: 25) + + + + Set database disk log size in megabytes (default: 100) + + + + + Listen for connections on <port> (default: 9853 or testnet: 19853) + + + + + Maintain at most <n> connections to peers (default: 125) + Mantieni al massimo <n> connessioni ai peer (predefinite: 125) + + + + Connect to a node to retrieve peer addresses, and disconnect + Connessione ad un nodo per ricevere l'indirizzo del peer, e disconnessione + + + + Specify your own public address + Specifica il tuo indirizzo pubblico + + + + Bind to given address. Use [host]:port notation for IPv6 + + + + + Stake your coins to support network and gain reward (default: 1) + + + + + Threshold for disconnecting misbehaving peers (default: 100) + Soglia di disconnessione dei peer di cattiva qualità (predefinita: 100) + + + + Number of seconds to keep misbehaving peers from reconnecting (default: 86400) + Numero di secondi di sospensione che i peer di cattiva qualità devono trascorrere prima di riconnettersi (predefiniti: 86400) + + + + An error occurred while setting up the RPC port %u for listening on IPv4: %s + Errore riscontrato durante l'impostazione della porta RPC %u per l'ascolto su IPv4: %s + + + + Detach block and address databases. Increases shutdown time (default: 0) + + + + + 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. + + + + + Error: This transaction requires a transaction fee of at least %s because of its amount, complexity, or use of recently received funds + + + + + Listen for JSON-RPC connections on <port> (default: 9852 or testnet: 19852) + + + + + Accept command line and JSON-RPC commands + Accetta da linea di comando e da comandi JSON-RPC + + + + + Error: Transaction creation failed + + + + + Error: Wallet locked, unable to create transaction + + + + + Importing blockchain data file. + + + + + Importing bootstrap blockchain data file. + + + + + Run in the background as a daemon and accept commands + Esegui in background come demone e accetta i comandi + + + + + Use the test network + Utilizza la rete di prova + + + + + Accept connections from outside (default: 1 if no -proxy or -connect) + Accetta connessioni dall'esterno (predefinito: 1 se no -proxy o -connect) + + + + An error occurred while setting up the RPC port %u for listening on IPv6, falling back to IPv4: %s + Errore riscontrato durante l'impostazione della porta RPC %u per l'ascolto su IPv6, tornando su IPv4: %s + + + + Error initializing database environment %s! To recover, BACKUP THAT DIRECTORY, then remove everything from it except for wallet.dat. + + + + + Set maximum size of high-priority/low-fee transactions in bytes (default: 27000) + + + + + Warning: -paytxfee is set very high! This is the transaction fee you will pay if you send a transaction. + Attenzione: -paytxfee è molto alta. Questa è la commissione che si paga quando si invia una transazione. + + + + Warning: Please check that your computer's date and time are correct! If your clock is wrong Arepacoin will not work properly. + + + + + Warning: error reading wallet.dat! All keys read correctly, but transaction data or address book entries might be missing or incorrect. + Attenzione: errore di lettura di wallet.dat! Tutte le chiave lette correttamente, ma i dati delle transazioni o le voci in rubrica potrebbero mancare o non essere corretti. + + + + Warning: wallet.dat corrupt, data salvaged! Original wallet.dat saved as wallet.{timestamp}.bak in %s; if your balance or transactions are incorrect you should restore from a backup. + Attenzione: wallet.dat corrotto, dati salvati! Il wallet.dat originale salvato come wallet.{timestamp}.bak in %s; se il tuo bilancio o le transazioni non sono corrette dovresti ripristinare da un backup. + + + + Attempt to recover private keys from a corrupt wallet.dat + Tenta di recuperare le chiavi private da un wallet.dat corrotto + + + + Block creation options: + Opzioni creazione blocco: + + + + Connect only to the specified node(s) + Connetti solo al nodo specificato + + + + Discover own IP address (default: 1 when listening and no -externalip) + Scopri proprio indirizzo IP (predefinito: 1 se in ascolto e no -externalip) + + + + Failed to listen on any port. Use -listen=0 if you want this. + Impossibile mettersi in ascolto su una porta. Usa -listen=0 se vuoi usare questa opzione. + + + + Find peers using DNS lookup (default: 1) + + + + + Sync checkpoints policy (default: strict) + + + + + Invalid -tor address: '%s' + + + + + Invalid amount for -reservebalance=<amount> + + + + + Maximum per-connection receive buffer, <n>*1000 bytes (default: 5000) + Buffer di ricezione massimo per connessione, <n>*1000 byte (predefinito: 5000) + + + + Maximum per-connection send buffer, <n>*1000 bytes (default: 1000) + Buffer di invio massimo per connessione, <n>*1000 byte (predefinito: 1000) + + + + Only connect to nodes in network <net> (IPv4, IPv6 or Tor) + Connetti solo a nodi nella rete <net> (IPv4, IPv6 o Tor) + + + + Output extra debugging information. Implies all other -debug* options + + + + + Output extra network debugging information + + + + + Prepend debug output with timestamp + + + + + SSL options: (see the Bitcoin Wiki for SSL setup instructions) + Opzioni SSL: (vedi il wiki di Bitcoin per le istruzioni di configurazione SSL) + + + + Select the version of socks proxy to use (4-5, default: 5) + + + + + Send trace/debug info to console instead of debug.log file + Invia le informazioni di trace/debug alla console invece che al file debug.log + + + + Send trace/debug info to debugger + + + + + Set maximum block size in bytes (default: 250000) + + + + + Set minimum block size in bytes (default: 0) + Imposta dimensione minima del blocco in bytes (predefinita: 0) + + + + Shrink debug.log file on client startup (default: 1 when no -debug) + Riduci il file debug.log all'avvio del client (predefinito: 1 se non impostato -debug) + + + + Specify connection timeout in milliseconds (default: 5000) + Specifica il timeout di connessione in millisecondi (predefinito: 5000) + + + + Unable to sign checkpoint, wrong checkpointkey? + + + + + + Use UPnP to map the listening port (default: 0) + Usa UPnP per mappare la porta in ascolto (predefinito: 0) + + + + Use UPnP to map the listening port (default: 1 when listening) + Usa UPnP per mappare la porta in ascolto (predefinito: 1 when listening) + + + + Use proxy to reach tor hidden services (default: same as -proxy) + + + + + Username for JSON-RPC connections + Nome utente per connessioni JSON-RPC + + + + + Verifying database integrity... + + + + + WARNING: syncronized checkpoint violation detected, but skipped! + + + + + Warning: Disk space is low! + + + + + Warning: This version is obsolete, upgrade required! + Attenzione: questa versione è obsoleta, aggiornamento necessario! + + + + wallet.dat corrupt, salvage failed + wallet.dat corrotto, salvataggio fallito + + + + Password for JSON-RPC connections + Password per connessioni JSON-RPC + + + + + %s, you must set a rpcpassword in the configuration file: + %s +It is recommended you use the following random password: +rpcuser=arepacoinrpc +rpcpassword=%s +(you do not need to remember this password) +The username and password MUST NOT be the same. +If the file does not exist, create it with owner-readable-only file permissions. +It is also recommended to set alertnotify so you are notified of problems; +for example: alertnotify=echo %%s | mail -s "Arepacoin Alert" admin@foo.com + + + + + + Find peers using internet relay chat (default: 0) + + + + + Sync time with other nodes. Disable if time on your system is precise e.g. syncing with NTP (default: 1) + + + + + When creating transactions, ignore inputs with value less than this (default: 0.01) + + + + + Allow JSON-RPC connections from specified IP address + Consenti connessioni JSON-RPC dall'indirizzo IP specificato + + + + + Send commands to node running on <ip> (default: 127.0.0.1) + Inviare comandi al nodo in esecuzione su <ip> (predefinito: 127.0.0.1) + + + + Execute command when the best block changes (%s in cmd is replaced by block hash) + Esegui il comando quando il miglior block cambia(%s nel cmd è sostituito dall'hash del blocco) + + + + Execute command when a wallet transaction changes (%s in cmd is replaced by TxID) + Esegui comando quando una transazione del portafoglio cambia (%s in cmd è sostituito da TxID) + + + + Require a confirmations for change (default: 0) + + + + + Enforce transaction scripts to use canonical PUSH operators (default: 1) + + + + + Execute command when a relevant alert is received (%s in cmd is replaced by message) + + + + + Upgrade wallet to latest format + Aggiorna il wallet all'ultimo formato + + + + Set key pool size to <n> (default: 100) + Impostare la quantità di chiavi di riserva a <n> (predefinita: 100) + + + + Rescan the block chain for missing wallet transactions + Ripeti analisi della catena dei blocchi per cercare le transazioni mancanti dal portamonete + + + + + How many blocks to check at startup (default: 2500, 0 = all) + + + + + How thorough the block verification is (0-6, default: 1) + + + + + Imports blocks from external blk000?.dat file + + + + + Use OpenSSL (https) for JSON-RPC connections + Utilizzare OpenSSL (https) per le connessioni JSON-RPC + + + + + Server certificate file (default: server.cert) + File certificato del server (predefinito: server.cert) + + + + Server private key (default: server.pem) + Chiave privata del server (predefinito: server.pem) + + + + Acceptable ciphers (default: TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH) + + + + + Error: Wallet unlocked for staking only, unable to create transaction. + + + + + WARNING: Invalid checkpoint found! Displayed transactions may not be correct! You may need to upgrade, or notify developers. + + + + + This help message + Questo messaggio di aiuto + + + + + Wallet %s resides outside data directory %s. + + + + + Cannot obtain a lock on data directory %s. Arepacoin is probably already running. + + + + + Arepacoin + + + + + Unable to bind to %s on this computer (bind returned error %d, %s) + Impossibile collegarsi alla %s su questo computer (bind returned error %d, %s) + + + + Connect through socks proxy + + + + + Allow DNS lookups for -addnode, -seednode and -connect + Consenti ricerche DNS per aggiungere nodi e collegare + + + + + Loading addresses... + Caricamento indirizzi... + + + + Error loading blkindex.dat + + + + + Error loading wallet.dat: Wallet corrupted + Errore caricamento wallet.dat: Wallet corrotto + + + + Error loading wallet.dat: Wallet requires newer version of Arepacoin + + + + + Wallet needed to be rewritten: restart Arepacoin to complete + + + + + Error loading wallet.dat + Errore caricamento wallet.dat + + + + Invalid -proxy address: '%s' + Indirizzo -proxy non valido: '%s' + + + + Unknown network specified in -onlynet: '%s' + Rete sconosciuta specificata in -onlynet: '%s' + + + + Unknown -socks proxy version requested: %i + Versione -socks proxy sconosciuta richiesta: %i + + + + Cannot resolve -bind address: '%s' + Impossibile risolvere -bind address: '%s' + + + + Cannot resolve -externalip address: '%s' + Impossibile risolvere indirizzo -externalip: '%s' + + + + Invalid amount for -paytxfee=<amount>: '%s' + Importo non valido per -paytxfee=<amount>: '%s' + + + + Error: could not start node + + + + + Sending... + + + + + Invalid amount + Importo non valido + + + + Insufficient funds + Fondi insufficienti + + + + Loading block index... + Caricamento dell'indice del blocco... + + + + Add a node to connect to and attempt to keep the connection open + Elérendő csomópont megadása and attempt to keep the connection open + + + + Unable to bind to %s on this computer. Arepacoin is probably already running. + + + + + Fee per KB to add to transactions you send + + + + + Invalid amount for -mininput=<amount>: '%s' + + + + + Loading wallet... + Caricamento portamonete... + + + + Cannot downgrade wallet + Non è possibile retrocedere il wallet + + + + Cannot initialize keypool + + + + + Cannot write default address + Non è possibile scrivere l'indirizzo predefinito + + + + Rescanning... + Ripetere la scansione... + + + + Done loading + Caricamento completato + + + + To use the %s option + Per usare la opzione %s + + + + Error + Errore + + + + You must set rpcpassword=<password> in the configuration file: +%s +If the file does not exist, create it with owner-readable-only file permissions. + Devi settare rpcpassword=<password> nel file di configurazione: %s Se il file non esiste, crealo con i permessi di amministratore + + + \ No newline at end of file diff --git a/src/qt/locale/bitcoin_ja.ts b/src/qt/locale/bitcoin_ja.ts new file mode 100755 index 0000000..87d2472 --- /dev/null +++ b/src/qt/locale/bitcoin_ja.ts @@ -0,0 +1,3312 @@ + + + AboutDialog + + + About Arepacoin + ブラックコインについて + + + + <b>Arepacoin</b> version + <b>ブラックコイン</b>バージョン + + + + Copyright © 2009-2014 The Bitcoin developers +Copyright © 2012-2014 The NovaCoin developers +Copyright © 2014 The Arepacoin developers + コピーライト © 2009-2014 The Bitcoin developers +コピーライト © 2012-2014 The NovaCoin developers +コピーライト © 2014 The Arepacoin developers + + + + +This is experimental software. + +Distributed under the MIT/X11 software license, see the accompanying file COPYING or http://www.opensource.org/licenses/mit-license.php. + +This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit (http://www.openssl.org/) and cryptographic software written by Eric Young (eay@cryptsoft.com) and UPnP software written by Thomas Bernard. + +これは実験的なソフトウェアです。 + +MIT/X11 ソフトウェア ライセンスの下で配布されています。詳しくは添付の COPYING ファイルやhttp://www.opensource.org/licenses/mit-license.php を参照してください。 + +この製品は OpenSSL Toolkit (http://www.openssl.org/) に用いられる Eric Young (eay@cryptsoft.com) が開発した暗号化ソフトウェアと Thomas Bernard が開発した UPnP ソフトウェアを含んでいます。 + + + + AddressBookPage + + + Address Book + アドレス帳 + + + + Double-click to edit address or label + アドレスまたはラベルを編集するにはダブルクリック + + + + Create a new address + 新規アドレスの作成 + + + + Copy the currently selected address to the system clipboard + 現在選択されているアドレスをシステムのクリップボードにコピーする + + + + &New Address + 新しいアドレス + + + + These are your Arepacoin addresses for receiving payments. You may want to give a different one to each sender so you can keep track of who is paying you. + これは支払いを受けるためのブラックコインのアドレス。支払い管理をするのため、各送信者へ、それぞれのアドレスを伝えたほうがいいです。 + + + + &Copy Address + アドレスをコピー (&C) + + + + Show &QR Code + QRコードを表す + + + + Sign a message to prove you own a Arepacoin address + 所有権の証明するためのメサッジを署名する。 + + + + Sign &Message + メサッジを署名する。 + + + + Delete the currently selected address from the list + 選択されたアドレスを一覧から削除する + + + + Verify a message to ensure it was signed with a specified Arepacoin address + 受け取ったメッセージの署名を確保のため、メッセージを確認する。 + + + + &Verify Message + メッセージを確認する。 + + + + &Delete + 削除 + + + + Copy &Label + ラベルをコピー (&L) + + + + &Edit + 編集 (&E) + + + + Export Address Book Data + アドレス帳のデータを書き出す + + + + Comma separated file (*.csv) + CSVファイル (*.csv) + + + + Error exporting + エラーを書き出す + + + + Could not write to file %1. + ファイルを書き込めなかった。%1 + + + + AddressTableModel + + + Label + ラベル + + + + Address + アドレス + + + + (no label) + (ラベル無し) + + + + AskPassphraseDialog + + + Passphrase Dialog + パスフレーズ ダイアログ + + + + Enter passphrase + パスフレーズを入力 + + + + New passphrase + 新しいパスフレーズ + + + + Repeat new passphrase + 新しいパスフレーズをもう一度 + + + + Serves to disable the trivial sendmoney when OS account compromised. Provides no real security. + ユーザアカウントはハッキングされたばい、瑣末のsendmoney無効にする。機密保護には効果はない。 + + + + For staking only + 賭けるのみ + + + + Enter the new passphrase to the wallet.<br/>Please use a passphrase of <b>10 or more random characters</b>, or <b>eight or more words</b>. + ウォレットの新しいパスフレーズを入力してください。<br/><b>8個以上の単語か10個以上のランダムな文字</b>を使ってください。 + + + + Encrypt wallet + ウォレットを暗号化する + + + + This operation needs your wallet passphrase to unlock the wallet. + この操作はウォレットをアンロックするためにパスフレーズが必要です。 + + + + Unlock wallet + ウォレットをアンロックする + + + + This operation needs your wallet passphrase to decrypt the wallet. + この操作はウォレットの暗号化解除のためにパスフレーズが必要です。 + + + + Decrypt wallet + ウォレットの暗号化を解除する + + + + Change passphrase + パスフレーズの変更 + + + + Enter the old and new passphrase to the wallet. + 新旧両方のパスフレーズを入力してください。 + + + + Confirm wallet encryption + ウォレットの暗号化を確認する + + + + Warning: If you encrypt your wallet and lose your passphrase, you will <b>LOSE ALL OF YOUR COINS</b>! + ご注意:暗号化したウォレットのパスワードを忘れたばい、b>すべてのコインを失う</b>! + + + + Are you sure you wish to encrypt your wallet? + ウォレットを暗号化、よろしいですか? + + + + IMPORTANT: Any previous backups you have made of your wallet file should be replaced with the newly generated, encrypted wallet file. For security reasons, previous backups of the unencrypted wallet file will become useless as soon as you start using the new, encrypted wallet. + 重要: 過去のウォレット ファイルのバックアップは、暗号化された新しいウォレット ファイルに取り替える必要があります。セキュリティ上の理由により、暗号化された新しいウォレットを使い始めると、暗号化されていないウォレット ファイルのバックアップはすぐに使えなくなります。 + + + + + Warning: The Caps Lock key is on! + 警告: Caps Lock キーがオンになっています! + + + + + Wallet encrypted + ウォレットは暗号化されました + + + + Arepacoin will close now to finish the encryption process. Remember that encrypting your wallet cannot fully protect your coins from being stolen by malware infecting your computer. + ただいま、暗号化手順を完成するため、ブラックコインQTは閉じます。尚、ウォレットを暗号化をされたにしても、PCのウイルスから盗難防止の報償できないことを、ご理解をお願い足します。 + + + + + + + Wallet encryption failed + ウォレットの暗号化に失敗しました + + + + Wallet encryption failed due to an internal error. Your wallet was not encrypted. + 内部エラーによりウォレットの暗号化が失敗しました。ウォレットは暗号化されませんでした。 + + + + + The supplied passphrases do not match. + パスフレーズが同じではありません。 + + + + Wallet unlock failed + ウォレットのアンロックに失敗しました + + + + + + The passphrase entered for the wallet decryption was incorrect. + ウォレットの暗号化解除のパスフレーズが正しくありません。 + + + + Wallet decryption failed + ウォレットの暗号化解除に失敗しました + + + + Wallet passphrase was successfully changed. + ウォレットのパスフレーズの変更が成功しました。 + + + + BitcoinGUI + + + Sign &message... + メッセージの署名... (&m) + + + + Synchronizing with network... + ネットワークに同期中…… + + + + &Overview + 概要(&O) + + + + Show general overview of wallet + ウォレットの概要を見る + + + + &Transactions + 処理(&T) + + + + Browse transaction history + 処理履歴を閲覧 + + + + &Address Book + アドレス帳 + + + + Edit the list of stored addresses and labels + 保存されたアドレスとラベルの編集 + + + + &Receive coins + コインを受け取る + + + + Show the list of addresses for receiving payments + 支払いを受けるためのアドレスリストを表示 + + + + &Send coins + コインを送る + + + + E&xit + 終了(&E) + + + + Quit application + アプリケーションを終了 + + + + Show information about Arepacoin + ブラックコインの情報を表示 + + + + About &Qt + Qt について(&Q) + + + + Show information about Qt + Qt の情報を表示 + + + + &Options... + オプション... (&O) + + + + &Encrypt Wallet... + ウォレットの暗号化... (&E) + + + + &Backup Wallet... + ウォレットのバックアップ... (&B) + + + + &Change Passphrase... + パスフレーズの変更... (&C) + + + + ~%n block(s) remaining + ~%n ブロックが残っている + + + + Downloaded %1 of %2 blocks of transaction history (%3% done). + 処理の履歴の%1 / %2 ブロックをダウンロードしました。(%3% 完成) + + + + &Export... + (&E)書き出す... + + + + Send coins to a Arepacoin address + ブラックコインアドレスへコインを送る + + + + Modify configuration options for Arepacoin + ブラックコインの設定を変化する + + + + Export the data in the current tab to a file + 現在のタブのデータをファイルへ書き出す + + + + Encrypt or decrypt wallet + ウォレットを暗号化か暗号化を解除する + + + + Backup wallet to another location + ウォレットを他の場所にバックアップ + + + + Change the passphrase used for wallet encryption + ウォレット暗号化用パスフレーズの変更 + + + + &Debug window + デバッグ ウインドウ (&D) + + + + Open debugging and diagnostic console + デバッグと診断コンソールを開く + + + + &Verify message... + メッセージの検証... (&V) + + + + Arepacoin + ブラックコイン + + + + Wallet + ウォレット + + + + &About Arepacoin + ブラックコインについて + + + + &Show / Hide + 見る/隠す (&S) + + + + Unlock wallet + ウォレットをアンロックする + + + + &Lock Wallet + (&L)ウォレットをロックする + + + + Lock wallet + ウォレットをロックする + + + + &File + ファイル(&F) + + + + &Settings + 設定(&S) + + + + &Help + ヘルプ(&H) + + + + Tabs toolbar + タブツールバー + + + + Actions toolbar + 活動ツールバー + + + + + [testnet] + [testnet] + + + + + Arepacoin client + ブラックコインクライアントソフトウェア + + + + %n active connection(s) to Arepacoin network + ブラックコインネットワークへの%n アクティブな接続 + + + + Downloaded %1 blocks of transaction history. + 処理履歴の%1ブロックをダウンロードしました。 + + + + Staking.<br>Your weight is %1<br>Network weight is %2<br>Expected time to earn reward is %3 + 賭けている。<br>重さは%1<br>ネットワークの重さは%2<br>報酬をもらう時間の推測は%3 + + + + Not staking because wallet is locked + ウォレットをロックされたため、賭けていません + + + + Not staking because wallet is offline + ウォレットはオフラインで、賭けていません + + + + Not staking because wallet is syncing + ウォレットは同期最中ため、賭けていません。 + + + + Not staking because you don't have mature coins + コインはまだ成長できていないため、賭けていません。 + + + + %n second(s) ago + %n 秒前 + + + + &Unlock Wallet... + &ウォレットをアンロック... + + + + %n minute(s) ago + %n 分前 + + + + %n hour(s) ago + %n 時間前 + + + + %n day(s) ago + %n 日間前 + + + + Up to date + バージョンは最新です + + + + Catching up... + 追跡中... + + + + Last received block was generated %1. + 最新ブロックは%1に生成されました。 + + + + This transaction is over the size limit. You can still send it for a fee of %1, which goes to the nodes that process your transaction and helps to support the network. Do you want to pay the fee? + この処理は大きさの制限を超えている。%1料金を払ったばい、通信可能性です。料金は手続きをするノードへ支払って、ネットワークのサッポートになります。料金を払いますか。 + + + + Confirm transaction fee + 処理手数料を確認する + + + + Sent transaction + 送金処理 + + + + Incoming transaction + 着金処理 + + + + Date: %1 +Amount: %2 +Type: %3 +Address: %4 + + 日付: %1 +総額: %2 +種類: %3 +アドレス: %4 + + + + + URI handling + URIの取り扱い + + + + + URI can not be parsed! This can be caused by an invalid Arepacoin address or malformed URI parameters. + URIのパーズができませんでした!。原因は無効なブラックコインアドレスか不正なURIパラメータ。 + + + + Wallet is <b>encrypted</b> and currently <b>unlocked</b> + ウォレットは<b>暗号化されて、アンロックされています</b> + + + + Wallet is <b>encrypted</b> and currently <b>locked</b> + ウォレットは<b>暗号化されて、ロックされています</b> + + + + Backup Wallet + ウォレットのバックアップ + + + + Wallet Data (*.dat) + ウォレットのデータ (*.dat) + + + + Backup Failed + バックアップは失敗しました + + + + There was an error trying to save the wallet data to the new location. + ウォレットのデータが新しい場所へ保存するにはエラーになりました。 + + + + %n second(s) + %n 秒 + + + + %n minute(s) + %n 分 + + + + %n hour(s) + %n 時間 + + + + %n day(s) + %n 日間 + + + + Not staking + 賭けていません + + + + A fatal error occurred. Arepacoin can no longer continue safely and will quit. + 致命的エラー。安全に続きができないため、バラックコインQTは閉じます。 + + + + ClientModel + + + Network Alert + ネットワーク警告 + + + + CoinControlDialog + + + Coin Control + コインのコントロール + + + + Quantity: + 数量: + + + + Bytes: + バイト + + + + Amount: + 総額: + + + + Priority: + 優先: + + + + Fee: + 料金: + + + + Low Output: + アウトプット低い: + + + + no + いいえ + + + + After Fee: + 料金の後 + + + + Change: + お釣り: + + + + (un)select all + すべてを選択か選択を解除 + + + + Tree mode + 木モード + + + + List mode + リストモード + + + + Amount + 総額 + + + + Label + レベル + + + + Address + アドレス + + + + Date + 日付 + + + + Confirmations + 検証済みの数 + + + + Confirmed + 検証済 + + + + Priority + 優先 + + + + Copy address + アドレスをコピー + + + + Copy label + ラベルをコピー + + + + + Copy amount + 総額のコピー + + + + Copy transaction ID + 処理のIDをコピー + + + + Copy quantity + 数量をコピー + + + + Copy fee + 料金をコピー + + + + Copy after fee + 料金の後をコピー + + + + Copy bytes + バイトをコピー + + + + Copy priority + 優先をコピー + + + + Copy low output + アウトプット低いをコピー + + + + Copy change + お釣りをコピー + + + + highest + 最高 + + + + high + 高い + + + + medium-high + 中高 + + + + medium + + + + + low-medium + 中低 + + + + low + 低い + + + + lowest + 最低 + + + + DUST + ほこり + + + + yes + はい + + + + This label turns red, if the transaction size is bigger than 10000 bytes. + + This means a fee of at least %1 per kb is required. + + Can vary +/- 1 Byte per input. + このラベルが赤くなったら、処理の大きさは10000バイトより大きいです。 + +少なくとも%1 KBあたりの料金は必要となります。 + +入力データによって、料金の+/-1 バイトが可能です。 + + + + Transactions with higher priority get more likely into a block. + +This label turns red, if the priority is smaller than "medium". + + This means a fee of at least %1 per kb is required. + 高い優先ありの処理の方はブロックに書き込み可能性が高い。 + +このラベルは優先の設定は中より低いです。 + +少なくとも%1 KBあたりの料金は必要となります。 + + + + This label turns red, if any recipient receives an amount smaller than %1. + + This means a fee of at least %2 is required. + + Amounts below 0.546 times the minimum relay fee are shown as DUST. + 任意の受信者は%1より少ない額をもらったばい、このラベルは赤くなる。 + +少なくとも%2の料金は必要となります。 + +最小なリレー料金 x 0.546より下の額は、ほこりになります。 + + + + This label turns red, if the change is smaller than %1. + + This means a fee of at least %2 is required. + このラベルが赤くなたら、お釣りは%1より少ない。 + +少なくとも%2の料金は必要となります。 + + + + + (no label) + (ラベル無し) + + + + change from %1 (%2) + %1 (%2)からお釣り + + + + (change) + (お釣り) + + + + EditAddressDialog + + + Edit Address + アドレスの編集 + + + + &Label + ラベル(&L) + + + + The label associated with this address book entry + このアドレス帳の入力のラベル + + + + &Address + アドレス帳 (&A) + + + + The address associated with this address book entry. This can only be modified for sending addresses. + このアドレス帳の入力のアドレス。通信アドレスした変更ができない。 + + + + New receiving address + 新しい受信アドレス + + + + New sending address + 新しい送信アドレス + + + + Edit receiving address + 受信アドレスを編集 + + + + Edit sending address + 送信アドレスを編集 + + + + The entered address "%1" is already in the address book. + 入力されたアドレス "%1" は既にアドレス帳にあります。 + + + + The entered address "%1" is not a valid Arepacoin address. + 入力されたアドレス "%1" 、有効なブラックコインアドレスではない。 + + + + Could not unlock wallet. + ウォレットをアンロックできませんでした。 + + + + New key generation failed. + 新しいキーの生成に失敗しました。 + + + + GUIUtil::HelpMessageBox + + + + Arepacoin-Qt + ブラックコインQT + + + + version + バージョン + + + + Usage: + 使用法 + + + + command-line options + コマンドラインのオプション + + + + UI options + UIのオプション + + + + Set language, for example "de_DE" (default: system locale) + 言語の設定、例: "de_DE" (デフォルト:システムのロケール) + + + + Start minimized + 最小化でスタート + + + + Show splash screen on startup (default: 1) + スタートでスプラッシュスクリーンを表示(デフォルト:1) + + + + OptionsDialog + + + Options + 設定 + + + + &Main + メイン (&M) + + + + Optional transaction fee per kB that helps make sure your transactions are processed quickly. Most transactions are 1 kB. Fee 0.01 recommended. + 手続きを早めるためのオプショナル料金。だいたいの処理は1KB。料金の0.01が勧めです。 + + + + Pay transaction &fee + 支払う取引手数料 (&f) + + + + Reserved amount does not participate in staking and is therefore spendable at any time. + 貯金は賭ける参加しないため、いつでも支出できる。 + + + + Reserve + 貯金 + + + + Automatically start Arepacoin after logging in to the system. + システムのログイン次第、自動的にブラックコインをスタート。 + + + + &Start Arepacoin on system login + システムログイン次第、ブラックコインをスタート + + + + Detach block and address databases at shutdown. This means they can be moved to another data directory, but it slows down shutdown. The wallet is always detached. + シャットダウンするとき、ブロックとアドレスのデータベースを切り離す。すると、別のディレクトリへ移動できますが、シャットダウンは少し遅れます。ウォレットはいつも切り離します。 + + + + &Detach databases at shutdown + シャットダウンするとき、データベースを切り離す + + + + &Network + ネットワーク (&N) + + + + Automatically open the Arepacoin client port on the router. This only works when your router supports UPnP and it is enabled. + 自動的にルーターでブラックコインクライエントソフトウェアのポートを開く。ルーターはUPnPのサポートあり、UPnPを有効にするならできる。 + + + + Map port using &UPnP + UPnP を使ってポートを割り当てる (&U) + + + + Connect to the Arepacoin network through a SOCKS proxy (e.g. when connecting through Tor). + ブラックコインのネットワークへSOCKSプロキシで接続する(例:TORで接続するばい) + + + + &Connect through SOCKS proxy: + SOCKSプロキシで接続する + + + + Proxy &IP: + プロキシの IP (&I) : + + + + IP address of the proxy (e.g. 127.0.0.1) + プロキシのIPアドレス (例:127.0.0.1) + + + + &Port: + ポート (&P) : + + + + Port of the proxy (e.g. 9050) + プロキシのポート番号 (例 9050) + + + + SOCKS &Version: + SOCKS バージョン (&V) : + + + + SOCKS version of the proxy (e.g. 5) + SOCKS プロキシのバージョン (例 5) + + + + &Window + ウインドウ (&W) + + + + Show only a tray icon after minimizing the window. + ウインドウを最小化したあとトレイ アイコンだけを表示する。 + + + + &Minimize to the tray instead of the taskbar + タスクバーの代わりにトレイに最小化 (&M) + + + + Minimize instead of exit the application when the window is closed. When this option is enabled, the application will be closed only after selecting Quit in the menu. + ウインドウが閉じられる時アプリケーションを終了せずに最小化します。このオプションが有効な時にアプリケーションを終了するにはメニューから終了を選択します。 + + + + M&inimize on close + 閉じる時に最小化 (&i) + + + + &Display + 表示 (&D) + + + + User Interface &language: + ユーザインターフェースの言語 (&l) : + + + + The user interface language can be set here. This setting will take effect after restarting Arepacoin. + ユーザのインターフェースの言語の設定です。リスタートの後、有効します。 + + + + &Unit to show amounts in: + 額を表示する単位 (&U) : + + + + Choose the default subdivision unit to show in the interface and when sending coins. + インターフェース上の表示とコインの送信で使用する単位を選択します。 + + + + Whether to show Arepacoin addresses in the transaction list or not. + 処理の歴史でブラックコインのアドレスを表示する/しない。 + + + + &Display addresses in transaction list + 処理の履歴にアドレスを表示 (&D) + + + + Whether to show coin control features or not. + コインコントロールを表示する/しない。 + + + + Display coin &control features (experts only!) + コインコントロールの設定を表示する(有識者のみ!) + + + + &OK + &OK + + + + &Cancel + キャンセル (&C) + + + + &Apply + 適用する + + + + default + 初期値 + + + + + Warning + 警告 + + + + + This setting will take effect after restarting Arepacoin. + この設定はブラックコインをリスタートした後に有効する。 + + + + The supplied proxy address is invalid. + プロキシアドレスが無効です。 + + + + OverviewPage + + + Form + フォーム + + + + + The displayed information may be out of date. Your wallet automatically synchronizes with the Arepacoin network after a connection is established, but this process has not completed yet. + 表示されている情報は時間遅れている。接続したら、ウォレットは自動的にブラックコインネットワークと同期しますが過程は完了してません。 + + + + Stake: + 賭け金: + + + + Unconfirmed: + 未検証: + + + + Wallet + ウォレット + + + + Spendable: + 支出可能: + + + + Your current spendable balance + あなたの利用可能残高 + + + + Immature: + 未完成: + + + + Mined balance that has not yet matured + 完成していない採掘された残高 + + + + Total: + 合計: + + + + Your current total balance + あなたの現在の残高 + + + + <b>Recent transactions</b> + <b>最近の処理</b> + + + + Total of transactions that have yet to be confirmed, and do not yet count toward the current balance + 未確認の合計で、まだ現在の残高に含まれていない。 + + + + Total of coins that was staked, and do not yet count toward the current balance + 賭けているコインの合計で、まだ現在の残高に含まれていない。 + + + + + out of sync + 同期していない + + + + QRCodeDialog + + + QR Code Dialog + QRコードのダイアログ + + + + Request Payment + 支払いを要請する + + + + Amount: + 総額: + + + + Label: + レベル + + + + Message: + メッセージ: + + + + &Save As... + &S名前を付けて保存... + + + + Error encoding URI into QR Code. + URIからQRコードにエンコードするエラー。 + + + + The entered amount is invalid, please check. + 入力された額は無効です。確認してください。 + + + + Resulting URI too long, try to reduce the text for label / message. + URIは長過ぎて、ラベル文字の長さを短くしてください。 + + + + Save QR Code + QRコードを保存 + + + + PNG Images (*.png) + PNG イメージ (*.png) + + + + RPCConsole + + + Client name + クライアント名 + + + + + + + + + + + + + N/A + N/A + + + + Client version + クライアントのバージョン + + + + &Information + 情報 (&I) + + + + Using OpenSSL version + 使用中の OpenSSL のバージョン + + + + Startup time + 起動した日時 + + + + Network + ネットワーク + + + + Number of connections + 接続数 + + + + On testnet + testnetで + + + + Block chain + ブロック チェーン + + + + Current number of blocks + 現在のブロック数 + + + + Estimated total blocks + 推定総ブロック数 + + + + Last block time + 最終ブロックの日時 + + + + &Open + 開く (&O) + + + + Command-line options + コマンドラインのオプション + + + + Show the Arepacoin-Qt help message to get a list with possible Arepacoin command-line options. + ブラックコインQTのコマンドラインのヘルプ情報を表示する。 + + + + &Show + (&S)表示 + + + + &Console + コンソール (&C) + + + + Build date + ビルドの日付 + + + + Arepacoin - Debug window + ブラックコイン:デバッグウインドウ + + + + Arepacoin Core + ブラックコインコア + + + + Debug log file + デバッグ用ログファイル + + + + Open the Arepacoin debug log file from the current data directory. This can take a few seconds for large log files. + 現行のディレクトリからデバッグログファイルを開く。大きなファイルのばい、少し時間かかる。 + + + + Clear console + コンソールをクリア + + + + Welcome to the Arepacoin RPC console. + ブラックコインRPCコンソールへようこそ。 + + + + Use up and down arrows to navigate history, and <b>Ctrl-L</b> to clear screen. + 上下の矢印で履歴をたどれます。 <b>Ctrl-L</b> でスクリーンを消去できます。 + + + + Type <b>help</b> for an overview of available commands. + 使用可能なコマンドを見るには <b>help</b> と入力します。 + + + + SendCoinsDialog + + + + + + + + + + Send Coins + コインを送る + + + + Coin Control Features + コインのコントロールの設定 + + + + Inputs... + 入力... + + + + automatically selected + 自動的に選択 + + + + Insufficient funds! + 資金不足! + + + + Quantity: + 数量: + + + + + 0 + 0 + + + + Bytes: + バイト + + + + Amount: + 総額: + + + + + + + 0.00 BC + 123.456 BC {0.00 ?} + + + + Priority: + 優先: + + + + medium + + + + + Fee: + 料金: + + + + Low Output: + アウトプット低い: + + + + no + いいえ + + + + After Fee: + 料金の後 + + + + Change + お釣り: + + + + custom change address + カスタムのお釣りのアドレス + + + + Send to multiple recipients at once + 一度に複数の人に送る + + + + Add &Recipient + 受取人を追加 (&R) + + + + Remove all transaction fields + 全分の処理欄を削除する + + + + Clear &All + すべてクリア (&A) + + + + Balance: + 残高: + + + + 123.456 BC + 123.456 BC + + + + Confirm the send action + 送る操作を確認する + + + + S&end + 送る (&e) + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + ブラックコインアドレスの入力 (例;AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + Copy quantity + 数量をコピー + + + + Copy amount + 総額のコピー + + + + Copy fee + 料金をコピー + + + + Copy after fee + 料金の後をコピー + + + + Copy bytes + バイトをコピー + + + + Copy priority + 優先をコピー + + + + Copy low output + アウトプット低いをコピー + + + + Copy change + お釣りをコピー + + + + <b>%1</b> to %2 (%3) + <b>%1</b> から %2 (%3)に + + + + Confirm send coins + コインを送る確認 + + + + Are you sure you want to send %1? + %1送付、よろしいですか? + + + + and + + + + + The recipient address is not valid, please recheck. + 受取人のアドレスが不正です。再確認してください。 + + + + The amount to pay must be larger than 0. + 支払額は0より大きくないといけません。 + + + + The amount exceeds your balance. + 額が残高を超えています。 + + + + The total exceeds your balance when the %1 transaction fee is included. + %1 の処理手数料を含めると額が残高を超えています。 + + + + Duplicate address found, can only send to each address once per send operation. + 重複しているアドレスが見つかりました。1回の送信で同じアドレスに送ることは出来ません。 + + + + Error: Transaction creation failed. + エラー:処理を失敗しました。 + + + + 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. + エラー:処理は拒否されました。ウォレットのコインをすでに費やした可能性で、wallet.datのコピーで費やしたが、現行のwallet.datとはアップデートされていない。 + + + + WARNING: Invalid Arepacoin address + 警告:無効なブラックコインアドレス + + + + (no label) + (ラベル無し) + + + + WARNING: unknown change address + 警告:不明なお釣りのアドレス + + + + SendCoinsEntry + + + Form + フォーム + + + + A&mount: + 金額(&A): + + + + Pay &To: + 送り先(&T): + + + + + Enter a label for this address to add it to your address book + アドレス帳に追加するには、このアドレスのラベルを入力します + + + + &Label: + ラベル(&L): + + + + The address to send the payment to (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + 支払いへ送るアドレス (例:AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + Choose address from address book + アドレス帳からアドレスを選択する + + + + Alt+A + Alt+A + + + + Paste address from clipboard + クリップボードからアドレスを貼付ける + + + + Alt+P + Alt+P + + + + Remove this recipient + この受信者を外す + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + ブラックコインアドレスの入力 (例;AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + SignVerifyMessageDialog + + + Signatures - Sign / Verify a Message + 署名 - メッセージの署名/検証 + + + + + &Sign Message + メッセージの署名 (&S) + + + + You can sign messages with your addresses to prove you own them. Be careful not to sign anything vague, as phishing attacks may try to trick you into signing your identity over to them. Only sign fully-detailed statements you agree to. + あなた自身を立証するためにあなたのアドレスでメッセージに署名することができます。フィッシング攻撃によってあなたを騙して署名を譲渡させようとするかもしれないので、不明確なものは絶対に署名しないように注意してください。あなたが同意する完全に詳細な声明にだけ署名してください。 + + + + The address to sign the message with (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + メッセージの署名するアドレス(例:AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Choose an address from the address book + アドレス帳からアドレスを選ぶ + + + + + Alt+A + Alt+A + + + + Paste address from clipboard + クリップボードからアドレスを貼付ける + + + + Alt+P + Alt+P + + + + Enter the message you want to sign here + ここにあなたが署名するメッセージを入力します + + + + Copy the current signature to the system clipboard + 現在の署名をシステムのクリップボードにコピーする + + + + Sign the message to prove you own this Arepacoin address + 所有権の証明するためこのメサッジを署名する + + + + Reset all sign message fields + メッセージ署名の内容をすべて消去します + + + + + Clear &All + すべてクリア (&A) + + + + + &Verify Message + メッセージの検証 (&V) + + + + Enter the signing address, message (ensure you copy line breaks, spaces, tabs, etc. exactly) and signature below to verify the message. Be careful not to read more into the signature than what is in the signed message itself, to avoid being tricked by a man-in-the-middle attack. + メッセージを検証するために、署名するアドレスとメッセージ(改行、スペース、タブなどを正確にコピーしてください)、そして署名を入力します。中間者攻撃によってだまされることを避けるために、署名されたメッセージそのものよりも、署名を読み取られないように注意してください。 + + + + The address the message was signed with (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + メッセージの署名するアドレス(例:AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + Verify the message to ensure it was signed with the specified Arepacoin address + 受け取ったメッセージの署名を確保のため、メッセージを確認する。 + + + + Reset all verify message fields + 入力項目の内容をすべて消去します + + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + ブラックコインのアドレスを入力(例:AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + Click "Sign Message" to generate signature + 署名を作成するには"メッセージの署名"をクリック + + + + Enter Arepacoin signature + ブラックコインのデジタル署名を入力 + + + + + The entered address is invalid. + 不正なアドレスが入力されました。 + + + + + + + Please check the address and try again. + アドレスを確かめてからもう一度試してください。 + + + + + The entered address does not refer to a key. + 入力されたアドレスに関連するキーがありません。 + + + + Wallet unlock was cancelled. + ウォレットのアンロックはキャンセルされました。 + + + + Private key for the entered address is not available. + 入力されたアドレスのプライベート キーが無効です。 + + + + Message signing failed. + メッセージの署名に失敗しました。 + + + + Message signed. + メッセージに署名しました。 + + + + The signature could not be decoded. + 署名がデコードできません。 + + + + + Please check the signature and try again. + 署名を確認してからもう一度試してください。 + + + + The signature did not match the message digest. + 署名はメッセージ ダイジェストと一致しませんでした。 + + + + Message verification failed. + メッセージの検証に失敗しました。 + + + + Message verified. + メッセージは検証されました。 + + + + TransactionDesc + + + Open until %1 + ユニット %1 を開く + + + + Open for %n block(s) + %n ブロックに開いている + + + + conflicted + 相違 + + + + %1/offline + %1/オフライン + + + + %1/unconfirmed + %1/未検証 + + + + %1 confirmations + %1 確認 + + + + Status + ステータス + + + + , broadcast through %n node(s) + %n ノードにブロードキャスト + + + + Date + 日付 + + + + Source + ソース + + + + Generated + 生成された + + + + + From + 送信 + + + + + + To + 受信 + + + + + own address + 自分のアドレス + + + + label + ラベル + + + + + + + + Credit + クレジット + + + + matures in %n more block(s) + %n 以上のブロックが満期 + + + + not accepted + 承認されなかった + + + + + + + Debit + 引き落とし額 + + + + Transaction fee + 処理の手数料 + + + + Net amount + 正味金額 + + + + Message + メッセージ + + + + Comment + コメント + + + + Transaction ID + 処理のID + + + + Generated coins must mature 6 blocks before they can be spent. When you generated this block, it was broadcast to the network to be added to the block chain. If it fails to get into the chain, its state will change to "not accepted" and it won't be spendable. This may occasionally happen if another node generates a block within a few seconds of yours. + コインを費やす前に発現されたコインは6ブロック間成熟しなければなりません。このブロックを発現させたときに、ブロックチェインに足すためにネットワークへ放送しました。ブロックチェインに追加失敗したばい、レベルは「受け入られていない」に変わって、費やせられない状況になります。自分のノードと他のノードと同時に新しいブロックを発現させたときに、時折に起こること。 + + + + Debug information + デバッグ情報 + + + + Transaction + 処理 + + + + Inputs + 入力 + + + + Amount + 総額 + + + + true + 正しい + + + + false + 正しくない + + + + , has not been successfully broadcast yet + まだブロードキャストが成功していません + + + + unknown + 未確認 + + + + TransactionDescDialog + + + Transaction details + 処理の詳細 + + + + This pane shows a detailed description of the transaction + ここでは処理の詳細を表示しています + + + + TransactionTableModel + + + Date + 日付 + + + + Type + タイプ + + + + Address + Helbidea + + + + Amount + 総額 + + + + Open until %1 + ユニット %1 を開く + + + + Confirmed (%1 confirmations) + 検証されました (%1 検証済み) + + + + Open for %n more block(s) + %n 以上のブロックを開く + + + + Offline + オフライン + + + + Unconfirmed + 未検証 + + + + Confirming (%1 of %2 recommended confirmations) + 検証最中 (%1 / %2 の進めている検証済み) + + + + Conflicted + 相違 + + + + Immature (%1 confirmations, will be available after %2) + 未熟 (%1 検証,%2の後可用ができる) + + + + This block was not received by any other nodes and will probably not be accepted! + このブロックは他のどのノードによっても受け取られないで、多分受け入れられないでしょう! + + + + Generated but not accepted + 生成されましたが承認されませんでした + + + + Received with + 受信元 + + + + Received from + 送り主 + + + + Sent to + 送り先 + + + + Payment to yourself + 自分自身への支払い + + + + Mined + 発掘した + + + + (n/a) + (n/a) + + + + Transaction status. Hover over this field to show number of confirmations. + 処理の状況。この欄の上にカーソルを置くと検証の数を表示します。 + + + + Date and time that the transaction was received. + 処理を受信した日時。 + + + + Type of transaction. + 処理の種類。 + + + + Destination address of transaction. + 処理の宛先アドレス。 + + + + Amount removed from or added to balance. + 残高に追加または削除された総額。 + + + + TransactionView + + + + All + すべて + + + + Today + 今日 + + + + This week + 今週 + + + + This month + 今月 + + + + Last month + 先月 + + + + This year + 今年 + + + + Range... + 期間... + + + + Received with + 送り主 + + + + Sent to + 送り先 + + + + To yourself + 自分自身 + + + + Mined + 発掘した + + + + Other + その他 + + + + Enter address or label to search + 検索するアドレスまたはラベルを入力 + + + + Min amount + 最小の額 + + + + Copy address + アドレスをコピーする + + + + Copy label + ラベルをコピーする + + + + Copy amount + 総額のコピー + + + + Copy transaction ID + 処理IDをコピー + + + + Edit label + ラベルの編集 + + + + Show transaction details + 処理の詳細を表示 + + + + Export Transaction Data + 処理のデータを書き出す + + + + Comma separated file (*.csv) + テキスト CSV (*.csv) + + + + Confirmed + 検証済み + + + + Date + 日付 + + + + Type + タイプ + + + + Label + ラベル + + + + Address + Helbidea + + + + Amount + 総額 + + + + ID + ID + + + + Error exporting + エラーを書き出す + + + + Could not write to file %1. + ファイルを書き込めなかった。%1 + + + + Range: + 期間: + + + + to + から + + + + WalletModel + + + Sending... + 通信中... + + + + bitcoin-core + + + Arepacoin version + ブラックコインバージョン + + + + Usage: + 使用法: + + + + Send command to -server or arepacoind + -server か arepacoindへコマンドを送る。 + + + + List commands + コマンド一覧 + + + + Get help for a command + コマンドのヘルプ + + + + Options: + オプション: + + + + Specify configuration file (default: arepacoin.conf) + 設定ファイルを特定する (デファルト: arepacoin.conf) + + + + Specify pid file (default: arepacoind.pid) + pid ファイルを特定する (デフォルト: arepacoind.pid) + + + + Specify wallet file (within data directory) + ウォレットのファイルを指定 (データ・ディレクトリの中に) + + + + Specify data directory + データ ディレクトリの指定 + + + + Set database cache size in megabytes (default: 25) + データベースのキャッシュサイズをメガバイトで設定 (初期値: 25) + + + + Set database disk log size in megabytes (default: 100) + メガバイトでのデータベースのログザイズの大きさの設定(デファルト:100) + + + + Listen for connections on <port> (default: 9853 or testnet: 19853) + <port> で 接続をリスン (デフォルト: 9853かtestnet は 19853) + + + + Maintain at most <n> connections to peers (default: 125) + ピアの最大接続数 (初期値: 125) + + + + Connect to a node to retrieve peer addresses, and disconnect + ピア アドレスを取得するためにノードに接続し、そして切断します + + + + Specify your own public address + あなた自身のパブリックなアドレスを指定 + + + + Bind to given address. Use [host]:port notation for IPv6 + アドレスに結ぶ。IPv6のばい、[host]:port 表記法を使ってください。 + + + + Stake your coins to support network and gain reward (default: 1) + 褒奨金をもらうためと、ブラックコインネットワークをサッポートするために、コインを賭ける(デファルト:1) + + + + Threshold for disconnecting misbehaving peers (default: 100) + 不正なピアを切断するためのしきい値 (初期値: 100) + + + + Number of seconds to keep misbehaving peers from reconnecting (default: 86400) + 不正なピアを再接続するまでの秒数 (初期値: 86400) + + + + An error occurred while setting up the RPC port %u for listening on IPv4: %s + IPv4 でリスンする RPC ポート %u の設定中にエラーが発生しました: %s + + + + Detach block and address databases. Increases shutdown time (default: 0) + ブロックとアドレスのデータベースを切り離す。この設定はシャットダウンの時間を伸ばさせます。(デファルト:0) + + + + 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. + エラー:処理は拒否されました。ウォレットのコインをすでに費やした可能性で、wallet.datのコピーで費やしたが、現行のwallet.datとはアップデートされていない。 + + + + Error: This transaction requires a transaction fee of at least %s because of its amount, complexity, or use of recently received funds + エラー:額,複雑,最近もらった資金、どれかの理由で処理は少なくとも %sの料金が必要です。 + + + + Listen for JSON-RPC connections on <port> (default: 9852 or testnet: 19852) + <port> で JSON-RPC 接続をリスン (デフォルト: 9852かtestnet は 19852) + + + + Accept command line and JSON-RPC commands + コマンドラインと JSON-RPC コマンドを許可 + + + + Error: Transaction creation failed + エラー:処理を失敗しました。 + + + + Error: Wallet locked, unable to create transaction + エラー:ウォレットはロックされたために、処理を作られなかった。 + + + + Importing blockchain data file. + ブロックチェインのファイルを読み込んでいる。 + + + + Importing bootstrap blockchain data file. + ブートストラップなブロックチェインのファイルを読み込んでいる。 + + + + Run in the background as a daemon and accept commands + デーモンとしてバックグランドで実行しコマンドを許可 + + + + Use the test network + テストのためのネットワークを使用 + + + + Accept connections from outside (default: 1 if no -proxy or -connect) + 外部からの接続を許可 (初期値: -proxy または -connect を使用していない場合は1) + + + + An error occurred while setting up the RPC port %u for listening on IPv6, falling back to IPv4: %s + IPv6 でリスンする RPC ポート %u の設定中にエラーが発生したので IPv4 に切り替えます: %s + + + + Error initializing database environment %s! To recover, BACKUP THAT DIRECTORY, then remove everything from it except for wallet.dat. + データベース%sを初期化するにエラーになりました。直すためにディレクトリをバックアップして、そしてwallet.dat意外のファイルを取り除いてください。 + + + + Set maximum size of high-priority/low-fee transactions in bytes (default: 27000) + バイトで、最優先、低料金の処理の最大サイズの設定(デファルト:27000) + + + + Warning: -paytxfee is set very high! This is the transaction fee you will pay if you send a transaction. + 警告: -paytxfee が非常に高く設定されています! これは処理を送信する場合に支払う取引手数料です。 + + + + Warning: Please check that your computer's date and time are correct! If your clock is wrong Arepacoin will not work properly. +  警告:コンピュータの日付と時間を調べてください。時間ずらしかったばい、ブラックコイン QTは正しく行動しない。 + + + + Warning: error reading wallet.dat! All keys read correctly, but transaction data or address book entries might be missing or incorrect. + 警告: wallet.dat の読み込みエラー! すべてのキーは正しく読み取れますが、処理のデータやアドレス帳のエントリが失われたか、正しくない可能性があります。 + + + + Warning: wallet.dat corrupt, data salvaged! Original wallet.dat saved as wallet.{timestamp}.bak in %s; if your balance or transactions are incorrect you should restore from a backup. + 警告: wallet.dat のデータはの汚染で、でデータを復旧しました! オリジナルの wallet.dat は wallet.{timestamp}.bak として %s に保存されました; もしもあなたの残高や処理が正しくないばい、バックアップから復元してください。 + + + + Attempt to recover private keys from a corrupt wallet.dat + 壊れた wallet.dat から秘密鍵を復旧することを試す + + + + Block creation options: + ブロック作成オプション: + + + + Connect only to the specified node(s) + 指定したノードだけに接続 + + + + Discover own IP address (default: 1 when listening and no -externalip) + 自分の IP アドレスを発見 (初期値: リスン中と -externalip を使用していない場合は1) + + + + Failed to listen on any port. Use -listen=0 if you want this. + ポートのリスンに失敗しました。必要であれば -listen=0 を使用してください。 + + + + Find peers using DNS lookup (default: 1) + DNSルックアップでピーアを探す(デファルト:1) + + + + Sync checkpoints policy (default: strict) + 同期チェックポイント方針(デファルト:厳しい) + + + + Invalid -tor address: '%s' + 無効なTORアドレス: '%s' + + + + Invalid amount for -reservebalance=<amount> + -reservebalance=<amount>の額は無効です + + + + Maximum per-connection receive buffer, <n>*1000 bytes (default: 5000) + 接続毎の最大受信バッファ <n>*1000 バイト (初期値: 5000) + + + + Maximum per-connection send buffer, <n>*1000 bytes (default: 1000) + 接続毎の最大送信バッファ <n>*1000 バイト (初期値: 1000) + + + + Only connect to nodes in network <net> (IPv4, IPv6 or Tor) + <net> (IPv4, IPv6, Tor) ネットワーク内のノードだけに接続する + + + + Output extra debugging information. Implies all other -debug* options + 余分なデバッグ情報を出力する。この設定はすべてのdebug* の設定を有効にする。 + + + + Output extra network debugging information + 余分なネットワークのデバッグ情報を出力する + + + + Prepend debug output with timestamp + デバッグのアウトプットはタイムスタンプで先頭に追加する + + + + SSL options: (see the Bitcoin Wiki for SSL setup instructions) + SSL オプション: (SSLのセットアップ手順は Bitcoin Wiki をご覧下さい) + + + + Select the version of socks proxy to use (4-5, default: 5) + SOCKSプロクシーのバージョンを選択する (4-5、 デファルト: 5) + + + + Send trace/debug info to console instead of debug.log file + トレース/デバッグ情報を debug.log ファイルの代わりにコンソールへ送る + + + + Send trace/debug info to debugger + デバッガへ追跡とデバッグ情報を送る。 + + + + Set maximum block size in bytes (default: 250000) + 最大ブロックサイズをバイトで設定 (初期値: 250000) + + + + Set minimum block size in bytes (default: 0) + 最小ブロックサイズをバイトで設定 (初期値: 0) + + + + Shrink debug.log file on client startup (default: 1 when no -debug) + クライアント起動時に debug.log ファイルを縮小 (初期値: -debug オプションを指定しない場合は1) + + + + Specify connection timeout in milliseconds (default: 5000) + 接続のタイムアウトをミリセコンドで指定 (初期値: 5000) + + + + Unable to sign checkpoint, wrong checkpointkey? + + チェックポイントを署名できません。checkpointkeyは違いますか。 + + + + + Use UPnP to map the listening port (default: 0) + リスン ポートの割当に UPnP を使用 (初期値: 0) + + + + Use UPnP to map the listening port (default: 1 when listening) + リスン ポートの割当に UPnP を使用 (初期値: リスン中は1) + + + + Use proxy to reach tor hidden services (default: same as -proxy) + プロクシーでTORヒドゥンサービス(TOR Hidden Services)を接続する(デファルト:-proxyと同じ) + + + + Username for JSON-RPC connections + JSON-RPC 接続のユーザー名 + + + + Verifying database integrity... + データベースの保全性を確認最中... + + + + WARNING: syncronized checkpoint violation detected, but skipped! + 警告:シンクロナイズドチェックポイント違反を検出したが、チェックポイントを飛ばした。 + + + + Warning: Disk space is low! + 警告:ディスクの空き領域は少ない! + + + + Warning: This version is obsolete, upgrade required! + 警告: このバージョンは古いのでアップグレードが必要です! + + + + wallet.dat corrupt, salvage failed + wallet.dat が壊れ、復旧に失敗しました + + + + Password for JSON-RPC connections + JSON-RPC 接続のパスワード + + + + %s, you must set a rpcpassword in the configuration file: + %s +It is recommended you use the following random password: +rpcuser=arepacoinrpc +rpcpassword=%s +(you do not need to remember this password) +The username and password MUST NOT be the same. +If the file does not exist, create it with owner-readable-only file permissions. +It is also recommended to set alertnotify so you are notified of problems; +for example: alertnotify=echo %%s | mail -s "Arepacoin Alert" admin@foo.com + + %s, 設定ファイル:%sでrpcpasswordのパスワードを入力しなければならい + +このランダムパスワードのおすすめです: +rpcuser=arepacoinrpc +rpcpassword=%s +(このパサワードを覚えなくても大丈夫です) +ユーザ名とパスワードは同じであってはなりません。 +ファイルは存在しないばいは、所有者が読み取り可能な専用のファイルを作成してください。 +問題のことを知らせるために、alertnotifyの設定を有効にしたほうがいいです。 +例:alertnotify=echo %%s | mail -s "ブラックコイン警告" admin@foo.com + + + + + Find peers using internet relay chat (default: 0) + インターネットリレーチャット(IRC)でピアアを探す。(デファルト:1 {0}?) + + + + Sync time with other nodes. Disable if time on your system is precise e.g. syncing with NTP (default: 1) + 他のノードと時刻の同期する。確な時刻のコンピューターのばい、無効する。例:NTP同期設定有効ある(デファルト:1) + + + + When creating transactions, ignore inputs with value less than this (default: 0.01) + 処理を作ると、この額より少ない数字を無視する (デファルト:0.01) + + + + Allow JSON-RPC connections from specified IP address + 指定した IP アドレスからの JSON-RPC 接続を許可 + + + + Send commands to node running on <ip> (default: 127.0.0.1) + <ip> (初期値: 127.0.0.1) で実行中のノードにコマンドを送信 + + + + Execute command when the best block changes (%s in cmd is replaced by block hash) + 最良のブロックに変更する際にコマンドを実行 (cmd の %s はブロック ハッシュに置換される) + + + + Execute command when a wallet transaction changes (%s in cmd is replaced by TxID) + ウォレットの処理を変更する際にコマンドを実行 (cmd の %s は TxID に置換される) + + + + Require a confirmations for change (default: 0) + 変更するために、確認を必要とする (デファルト:0) + + + + Enforce transaction scripts to use canonical PUSH operators (default: 1) + 処理のスクリプトコマンドで標準的なPUSHオペレータを施行する(デファルト:1) + + + + Execute command when a relevant alert is received (%s in cmd is replaced by message) + 関連した警告をもらったら、コマンドを実行する (cmdの中で%sにメッセージを交換される) + + + + Upgrade wallet to latest format + ウォレットを最新のフォーマットにアップグレード + + + + Set key pool size to <n> (default: 100) + key pool のサイズを <n> (初期値: 100) にセット + + + + Rescan the block chain for missing wallet transactions + 失ったウォレットの処理のブロック チェーンを再スキャン + + + + How many blocks to check at startup (default: 2500, 0 = all) + スタートのときに、いくつのブロックを調べます (デファルト:2500、 0 = すべて ) + + + + How thorough the block verification is (0-6, default: 1) + ブロック検証の徹底の程度 (0-6 、デファルト:1) + + + + Imports blocks from external blk000?.dat file + 外部 blk000?.dat ファイルからブロックを読み込む。 + + + + Use OpenSSL (https) for JSON-RPC connections + JSON-RPC 接続に OpenSSL (https) を使用 + + + + Server certificate file (default: server.cert) + サーバ証明書ファイル (初期値: server.cert) + + + + Server private key (default: server.pem) + サーバの秘密鍵 (初期値: server.pem) + + + + Acceptable ciphers (default: TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH) + 許容可能な暗号 (デフォルト: TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH) + + + + Error: Wallet unlocked for staking only, unable to create transaction. + エラー:アンロックされたウォレットは賭けるためだけで、処理を作られない。 + + + + WARNING: Invalid checkpoint found! Displayed transactions may not be correct! You may need to upgrade, or notify developers. + 警告:無効なチェックポイントを見つかりました!表示された処理は正しくない可能性がある!アップグレードするか、デベロッパーに報告する必要があります。 + + + + This help message + このヘルプ メッセージ + + + + Wallet %s resides outside data directory %s. + %sウォレットはディレクトリ%sの外にあります。 + + + + Cannot obtain a lock on data directory %s. Arepacoin is probably already running. + %sディレクトリにをロックオンできない。ブラックコインQTは、もう発行してるでしょう。 + + + + Arepacoin + ブラックコイン + + + + Unable to bind to %s on this computer (bind returned error %d, %s) + このコンピュータの %s にバインドすることができません (バインドが返したエラーは %d, %s) + + + + Connect through socks proxy + SOCKSプロキシで接続する + + + + Allow DNS lookups for -addnode, -seednode and -connect + -addnode, -seednode と -connect で DNS ルックアップを許可する + + + + Loading addresses... + アドレスを読み込んでいます... + + + + Error loading blkindex.dat + blkindex.dat 読み込みエラー + + + + Error loading wallet.dat: Wallet corrupted + wallet.dat 読み込みエラー: ウォレットが壊れました + + + + Error loading wallet.dat: Wallet requires newer version of Arepacoin + wallet.dat 読み込みエラー:  ブラックコインQTの最新バージョンが必要です + + + + Wallet needed to be rewritten: restart Arepacoin to complete + ウォレットのデータをリライトしなければならい:ブラックコインQTをリスタートしてください + + + + Error loading wallet.dat + wallet.dat 読み込みエラー + + + + Invalid -proxy address: '%s' + 無効な -proxy アドレス: '%s' + + + + Unknown network specified in -onlynet: '%s' + -onlynet で指定された '%s' は未知のネットワークです + + + + Unknown -socks proxy version requested: %i + -socks で指定された %i は未知のバージョンです + + + + Cannot resolve -bind address: '%s' + -bind のアドレス '%s' を解決できません + + + + Cannot resolve -externalip address: '%s' + -externalip のアドレス '%s' を解決できません + + + + Invalid amount for -paytxfee=<amount>: '%s' + -paytxfee=<amount> の額 '%s' が無効です + + + + Error: could not start node + エラー:ノードの開始ができなった + + + + Sending... + 通信中... + + + + Invalid amount + 無効な総額 + + + + Insufficient funds + 残高不足 + + + + Loading block index... + ブロック インデックスを読み込んでいます... + + + + Add a node to connect to and attempt to keep the connection open + 接続するノードを追加し接続を持続するように試します + + + + Unable to bind to %s on this computer. Arepacoin is probably already running. + このコンピューターで%sに結ぶことができなかった。ブラックコインQTは、もう発行してるでしょう。 + + + + Fee per KB to add to transactions you send + 送る処理を足して、KBあたりの料金 + + + + Invalid amount for -mininput=<amount>: '%s' + -mininput=<amount>: '%s'の額は無効です + + + + Loading wallet... + ウォレットを読み込んでいます... + + + + Cannot downgrade wallet + ウォレットのダウングレードはできません + + + + Cannot initialize keypool + キースペースをイニシャライズをする + + + + Cannot write default address + 初期値のアドレスを書き込むことができません + + + + Rescanning... + 再スキャン中... + + + + Done loading + 読み込み完了 + + + + To use the %s option + %s オプションを使うには + + + + Error + エラー + + + + You must set rpcpassword=<password> in the configuration file: +%s +If the file does not exist, create it with owner-readable-only file permissions. + rpcpassword=<password> を設定ファイルでセットしてください: +%s +ファイルが無い場合は、オーナーだけが読み取れる権限でファイルを作成してください。 + + + \ No newline at end of file diff --git a/src/qt/locale/bitcoin_ka.ts b/src/qt/locale/bitcoin_ka.ts new file mode 100755 index 0000000..cfa1c6e --- /dev/null +++ b/src/qt/locale/bitcoin_ka.ts @@ -0,0 +1,3286 @@ + + + AboutDialog + + + About Arepacoin + + + + + <b>Arepacoin</b> version + + + + + Copyright © 2009-2014 The Bitcoin developers +Copyright © 2012-2014 The NovaCoin developers +Copyright © 2014 The Arepacoin developers + + + + + +This is experimental software. + +Distributed under the MIT/X11 software license, see the accompanying file COPYING or http://www.opensource.org/licenses/mit-license.php. + +This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit (http://www.openssl.org/) and cryptographic software written by Eric Young (eay@cryptsoft.com) and UPnP software written by Thomas Bernard. + +პროგრამა ექსპერიმენტულია. + +ვრცელდება MIT/X11 ლიცენზიით, იხილე თანდართული ფაილი COPYING ან http://www.opensource.org/licenses/mit-license.php. + +პროდუქტი შეიცავს OpenSSL პროექტის ფარგლებში შემუშავებულ პროგრამულ უზრუნველყოფას OpenSSL Toolkit-ში გამოყენებისათვის (http://www.openssl.org/), კრიპტოგრაფიულ პროგრამას, ავტორი ერიქ იანგი (Eric Young, eay@cryptsoft.com) და UPnP-პროგრამას, ავტორი თომას ბერნარდი (Thomas Bernard). + + + + AddressBookPage + + + Address Book + + + + + Double-click to edit address or label + დააკლიკეთ ორჯერ მისამართის ან ნიშნულის შესაცვლელად + + + + Create a new address + ახალი მისამართის შექმნა + + + + Copy the currently selected address to the system clipboard + მონიშნული მისამართის კოპირება სისტემურ კლიპბორდში + + + + &New Address + + + + + These are your Arepacoin addresses for receiving payments. You may want to give a different one to each sender so you can keep track of who is paying you. + + + + + &Copy Address + &მისამართის კოპირება + + + + Show &QR Code + + + + + Sign a message to prove you own a Arepacoin address + + + + + Sign &Message + + + + + Delete the currently selected address from the list + მონიშნული მისამართის წაშლა სიიდან + + + + Verify a message to ensure it was signed with a specified Arepacoin address + + + + + &Verify Message + + + + + &Delete + &წაშლა + + + + Copy &Label + ნიშნუ&ლის კოპირება + + + + &Edit + რ&ედაქტირება + + + + Export Address Book Data + + + + + Comma separated file (*.csv) + CSV-ფაილი (*.csv) + + + + Error exporting + + + + + Could not write to file %1. + + + + + AddressTableModel + + + Label + ნიშნული + + + + Address + მისამართი + + + + (no label) + (არ არის ნიშნული) + + + + AskPassphraseDialog + + + Passphrase Dialog + ფრაზა-პაროლის დიალოგი + + + + Enter passphrase + შეიყვანეთ ფრაზა-პაროლი + + + + New passphrase + ახალი ფრაზა-პაროლი + + + + Repeat new passphrase + გაიმეორეთ ახალი ფრაზა-პაროლი + + + + Serves to disable the trivial sendmoney when OS account compromised. Provides no real security. + + + + + For staking only + + + + + Enter the new passphrase to the wallet.<br/>Please use a passphrase of <b>10 or more random characters</b>, or <b>eight or more words</b>. + შეიყვანეთ საფულის ახალი ფრაზა-პაროლი.<br/>ფრაზა-პაროლი შეადგინეთ <b>არანაკლებ 10 შემთხვევითი სიმბოლოსაგან</b>, ან <b>რვა და მეტი სიტყვისაგან</b>. + + + + Encrypt wallet + საფულის დაშიფრვა + + + + This operation needs your wallet passphrase to unlock the wallet. + ეს ოპერაცია მოითხოვს თქვენი საფულის ფრაზა-პაროლს საფულის განსაბლოკად. + + + + Unlock wallet + საფულის განბლოკვა + + + + This operation needs your wallet passphrase to decrypt the wallet. + ეს ოპერაცია მოითხოვს თქვენი საფულის ფრაზა-პაროლს საფულის გასაშიფრად. + + + + Decrypt wallet + საფულის გაშიფრვა + + + + Change passphrase + ფრაზა-პაროლის შეცვლა + + + + Enter the old and new passphrase to the wallet. + შეიყვანეთ საფულის ძველი და ახალი ფრაზა-პაროლი. + + + + Confirm wallet encryption + დაადასტურეთ საფულის დაშიფრვა + + + + Warning: If you encrypt your wallet and lose your passphrase, you will <b>LOSE ALL OF YOUR COINS</b>! + + + + + Are you sure you wish to encrypt your wallet? + დარწმუნებული ხართ, რომ გინდათ საფულის დაშიფრვა? + + + + IMPORTANT: Any previous backups you have made of your wallet file should be replaced with the newly generated, encrypted wallet file. For security reasons, previous backups of the unencrypted wallet file will become useless as soon as you start using the new, encrypted wallet. + მნიშვნელოვანია: თქვენი საფულის ყველა ადრინდელი არქივი შეიცვლება ახლადგენერირებული დაშიფრული საფულის ფაილით. უსაფრთხოების მოსაზრებებით დაუშიფრავი საფულის ძველი არქივები ძალას დაკარგავს, როგორც კი დაიწყებთ ახალი, დაშიფრული საფულის გამოყენებას. + + + + + Warning: The Caps Lock key is on! + ყურადღება: ჩართულია Caps Lock რეჟიმი! + + + + + Wallet encrypted + საფულე დაშიფრულია + + + + Arepacoin will close now to finish the encryption process. Remember that encrypting your wallet cannot fully protect your coins from being stolen by malware infecting your computer. + + + + + + + + Wallet encryption failed + ვერ მოხერხდა საფულის დაშიფრვა + + + + Wallet encryption failed due to an internal error. Your wallet was not encrypted. + საფულის დაშიფრვა ვერ მოხერხდა სისტემაში შეცდომის გამო. თქვენი საფულე არ არის დაშფრული. + + + + + The supplied passphrases do not match. + ფრაზა-პაროლები არ ემთხვევა ერთმანეთს. + + + + Wallet unlock failed + საფულის განბლოკვა ვერ მოხერხდა + + + + + + The passphrase entered for the wallet decryption was incorrect. + საფულის განშიფრვის ფრაზა-პაროლი არაწორია + + + + Wallet decryption failed + საფულის განშიფრვა ვერ მოხერხდა + + + + Wallet passphrase was successfully changed. + საფულის ფრაზა-პაროლი შეცვლილია. + + + + BitcoinGUI + + + Sign &message... + ხელ&მოწერა + + + + Synchronizing with network... + ქსელთან სინქრონიზება... + + + + &Overview + მიმ&ოხილვა + + + + Show general overview of wallet + საფულის ზოგადი მიმოხილვა + + + + &Transactions + &ტრანსაქციები + + + + Browse transaction history + ტრანსაქციების ისტორიის დათვალიერება + + + + &Address Book + + + + + Edit the list of stored addresses and labels + + + + + &Receive coins + + + + + Show the list of addresses for receiving payments + + + + + &Send coins + + + + + E&xit + &გასვლა + + + + Quit application + გასვლა + + + + Show information about Arepacoin + + + + + About &Qt + &Qt-ს შესახებ + + + + Show information about Qt + ინფორმაცია Qt-ს შესახებ + + + + &Options... + &ოპციები + + + + &Encrypt Wallet... + საფულის &დაშიფრვა + + + + &Backup Wallet... + საფულის &არქივირება + + + + &Change Passphrase... + ფრაზა-პაროლის შე&ცვლა + + + + ~%n block(s) remaining + + + + + Downloaded %1 of %2 blocks of transaction history (%3% done). + + + + + &Export... + + + + + Send coins to a Arepacoin address + + + + + Modify configuration options for Arepacoin + + + + + Export the data in the current tab to a file + + + + + Encrypt or decrypt wallet + + + + + Backup wallet to another location + საფულის არქივირება სხვა ადგილზე + + + + Change the passphrase used for wallet encryption + საფულის დაშიფრვის ფრაზა-პაროლის შეცვლა + + + + &Debug window + და&ხვეწის ფანჯარა + + + + Open debugging and diagnostic console + დახვეწისა და გიაგნოსტიკის კონსოლის გაშვება + + + + &Verify message... + &ვერიფიკაცია + + + + Arepacoin + + + + + Wallet + საფულე + + + + &About Arepacoin + + + + + &Show / Hide + &ჩვენება/დაფარვა + + + + Unlock wallet + + + + + &Lock Wallet + + + + + Lock wallet + + + + + &File + &ფაილი + + + + &Settings + &პარამეტრები + + + + &Help + &დახმარება + + + + Tabs toolbar + ბარათების პანელი + + + + Actions toolbar + + + + + + [testnet] + [testnet] + + + + + Arepacoin client + + + + + %n active connection(s) to Arepacoin network + + + + + Downloaded %1 blocks of transaction history. + + + + + Staking.<br>Your weight is %1<br>Network weight is %2<br>Expected time to earn reward is %3 + + + + + Not staking because wallet is locked + + + + + Not staking because wallet is offline + + + + + Not staking because wallet is syncing + + + + + Not staking because you don't have mature coins + + + + + %n second(s) ago + + + + + &Unlock Wallet... + + + + + %n minute(s) ago + + + + + %n hour(s) ago + + + + + %n day(s) ago + + + + + Up to date + განახლებულია + + + + Catching up... + ჩართვა... + + + + Last received block was generated %1. + + + + + This transaction is over the size limit. You can still send it for a fee of %1, which goes to the nodes that process your transaction and helps to support the network. Do you want to pay the fee? + + + + + Confirm transaction fee + + + + + Sent transaction + გაგზავნილი ტრანსაქციები + + + + Incoming transaction + მიღებული ტრანსაქციები + + + + Date: %1 +Amount: %2 +Type: %3 +Address: %4 + + თარიღი: %1 +თანხა: %2 +ტიპი: %3 +მისამართი: %4 + + + + + + URI handling + + + + + + URI can not be parsed! This can be caused by an invalid Arepacoin address or malformed URI parameters. + + + + + Wallet is <b>encrypted</b> and currently <b>unlocked</b> + საფულე <b>დაშიფრულია</b> და ამჟამად <b>განბლოკილია</b> + + + + Wallet is <b>encrypted</b> and currently <b>locked</b> + საფულე <b>დაშიფრულია</b> და ამჟამად <b>დაბლოკილია</b> + + + + Backup Wallet + + + + + Wallet Data (*.dat) + + + + + Backup Failed + + + + + There was an error trying to save the wallet data to the new location. + + + + + %n second(s) + + + + + %n minute(s) + + + + + %n hour(s) + + + + + %n day(s) + + + + + Not staking + + + + + A fatal error occurred. Arepacoin can no longer continue safely and will quit. + + + + + ClientModel + + + Network Alert + ქსელური განგაში + + + + CoinControlDialog + + + Coin Control + + + + + Quantity: + რაოდენობა: + + + + Bytes: + ბაიტები: + + + + Amount: + თანხა: + + + + Priority: + პრიორიტეტი: + + + + Fee: + საკომისიო: + + + + Low Output: + ქვედა ზღვარი: + + + + no + არა + + + + After Fee: + დამატებითი საკომისიო: + + + + Change: + ხურდა: + + + + (un)select all + ყველას მონიშვნა/(მოხსნა) + + + + Tree mode + განტოტვილი + + + + List mode + სია + + + + Amount + რაოდენობა + + + + Label + + + + + Address + მისამართი + + + + Date + თარიღი + + + + Confirmations + დადასტურება + + + + Confirmed + დადასტურებულია + + + + Priority + პრიორიტეტი + + + + Copy address + მისამართის კოპირება + + + + Copy label + ნიშნულის კოპირება + + + + + Copy amount + თანხის კოპირება + + + + Copy transaction ID + ტრანსაქციის ID-ს კოპირება + + + + Copy quantity + რაოდენობის კოპირება + + + + Copy fee + საკომისიოს კოპირება + + + + Copy after fee + დამატებითი საკომისიოს კოპირება + + + + Copy bytes + ბაიტების კოპირება + + + + Copy priority + პრიორიტეტის კოპირება + + + + Copy low output + ქვედა ზღვრის კოპირება + + + + Copy change + ხურდის კოპირება + + + + highest + უმაღლესი + + + + high + მაღალი + + + + medium-high + საშუალოზე მაღალი + + + + medium + საშუალო + + + + low-medium + საშუალოზე დაბალი + + + + low + დაბალი + + + + lowest + უდაბლესი + + + + DUST + + + + + yes + კი + + + + This label turns red, if the transaction size is bigger than 10000 bytes. + + This means a fee of at least %1 per kb is required. + + Can vary +/- 1 Byte per input. + + + + + Transactions with higher priority get more likely into a block. + +This label turns red, if the priority is smaller than "medium". + + This means a fee of at least %1 per kb is required. + + + + + This label turns red, if any recipient receives an amount smaller than %1. + + This means a fee of at least %2 is required. + + Amounts below 0.546 times the minimum relay fee are shown as DUST. + + + + + This label turns red, if the change is smaller than %1. + + This means a fee of at least %2 is required. + + + + + + (no label) + (არ არის ნიშნული) + + + + change from %1 (%2) + ხურდა %1-დან (%2) + + + + (change) + (ხურდა) + + + + EditAddressDialog + + + Edit Address + მისამართის შეცვლა + + + + &Label + ნიშნუ&ლი + + + + The label associated with this address book entry + + + + + &Address + მის&ამართი + + + + The address associated with this address book entry. This can only be modified for sending addresses. + + + + + New receiving address + ახალი მიღების მისამართი + + + + New sending address + ახალი გაგზავნის მისამართი + + + + Edit receiving address + მიღების მისამართის შეცვლა + + + + Edit sending address + გაგზავნის მისამართის შეცვლა + + + + The entered address "%1" is already in the address book. + მისამართი "%1" უკვე არის მისამართების წიგნში. + + + + The entered address "%1" is not a valid Arepacoin address. + + + + + Could not unlock wallet. + საფულის განბლოკვა ვერ მოხერხდა. + + + + New key generation failed. + ახალი გასაღების გენერირება ვერ მოხერხდა + + + + GUIUtil::HelpMessageBox + + + + Arepacoin-Qt + + + + + version + + + + + Usage: + + + + + command-line options + + + + + UI options + + + + + Set language, for example "de_DE" (default: system locale) + + + + + Start minimized + + + + + Show splash screen on startup (default: 1) + + + + + OptionsDialog + + + Options + ოპციები + + + + &Main + &მთავარი + + + + Optional transaction fee per kB that helps make sure your transactions are processed quickly. Most transactions are 1 kB. Fee 0.01 recommended. + + + + + Pay transaction &fee + ტრანსაქციის სა&ფასურის გადახდა + + + + Reserved amount does not participate in staking and is therefore spendable at any time. + + + + + Reserve + + + + + Automatically start Arepacoin after logging in to the system. + + + + + &Start Arepacoin on system login + + + + + Detach block and address databases at shutdown. This means they can be moved to another data directory, but it slows down shutdown. The wallet is always detached. + + + + + &Detach databases at shutdown + + + + + &Network + &ქსელი + + + + Automatically open the Arepacoin client port on the router. This only works when your router supports UPnP and it is enabled. + + + + + Map port using &UPnP + პორტის გადამისამართება &UPnP-ით + + + + Connect to the Arepacoin network through a SOCKS proxy (e.g. when connecting through Tor). + + + + + &Connect through SOCKS proxy: + + + + + Proxy &IP: + პროქსის &IP: + + + + IP address of the proxy (e.g. 127.0.0.1) + + + + + &Port: + &პორტი + + + + Port of the proxy (e.g. 9050) + პროქსის პორტი (მაგ.: 9050) + + + + SOCKS &Version: + SOCKS &ვერსია: + + + + SOCKS version of the proxy (e.g. 5) + პროქსის SOCKS-ვერსია (მაგ.: 5) + + + + &Window + &ფანჯარა + + + + Show only a tray icon after minimizing the window. + ფანჯრის მინიმიზებისას მხოლოდ იკონა სისტემურ ზონაში + + + + &Minimize to the tray instead of the taskbar + &მინიმიზება სისტემურ ზონაში პროგრამების პანელის ნაცვლად + + + + Minimize instead of exit the application when the window is closed. When this option is enabled, the application will be closed only after selecting Quit in the menu. + პროგრამის მინიმიზება ფანჯრის დახურვისას. ოპციის ჩართვის შემდეგ პროგრამის დახურვა შესაძლებელი იქნება მხოლოდ მენიუდან - პუნქტი "გასვლა". + + + + M&inimize on close + მ&ინიმიზება დახურვისას + + + + &Display + &ჩვენება + + + + User Interface &language: + სამომხმარებ&ლო ენა: + + + + The user interface language can be set here. This setting will take effect after restarting Arepacoin. + + + + + &Unit to show amounts in: + ერთეუ&ლი: + + + + Choose the default subdivision unit to show in the interface and when sending coins. + აირჩიეთ გასაგზავნი თანხის ნაგულისხმევი ერთეული. + + + + Whether to show Arepacoin addresses in the transaction list or not. + + + + + &Display addresses in transaction list + მისამართების &ჩვენება სიაში + + + + Whether to show coin control features or not. + ვაჩვენოთ თუ არა მონეტების მართვის პარამეტრები. + + + + Display coin &control features (experts only!) + + + + + &OK + &OK + + + + &Cancel + &გაუქმება + + + + &Apply + + + + + default + ნაგულისხმევი + + + + + Warning + + + + + + This setting will take effect after restarting Arepacoin. + + + + + The supplied proxy address is invalid. + პროქსის მისამართი არასწორია. + + + + OverviewPage + + + Form + ფორმა + + + + + The displayed information may be out of date. Your wallet automatically synchronizes with the Arepacoin network after a connection is established, but this process has not completed yet. + + + + + Stake: + + + + + Unconfirmed: + დაუდასტურებელია: + + + + Wallet + საფულე + + + + Spendable: + + + + + Your current spendable balance + თქვენი ხელმისაწვდომი ნაშთი + + + + Immature: + მოუმზადებელია: + + + + Mined balance that has not yet matured + მოპოვებული თანხა, რომელიც ჯერ არ არის მზადყოფნაში + + + + Total: + სულ: + + + + Your current total balance + თქვენი სრული მიმდინარე ბალანსი + + + + <b>Recent transactions</b> + <b>ბოლო ტრანსაქციები</b> + + + + Total of transactions that have yet to be confirmed, and do not yet count toward the current balance + + + + + Total of coins that was staked, and do not yet count toward the current balance + + + + + + out of sync + არ არის სინქრონიზებული + + + + QRCodeDialog + + + QR Code Dialog + + + + + Request Payment + + + + + Amount: + + + + + Label: + + + + + Message: + + + + + &Save As... + + + + + Error encoding URI into QR Code. + + + + + The entered amount is invalid, please check. + + + + + Resulting URI too long, try to reduce the text for label / message. + + + + + Save QR Code + + + + + PNG Images (*.png) + + + + + RPCConsole + + + Client name + კლიენტი + + + + + + + + + + + + + N/A + მიუწვდ. + + + + Client version + კლიენტის ვერსია + + + + &Information + &ინფორმაცია + + + + Using OpenSSL version + OpenSSL-ის ვერსია + + + + Startup time + სტარტის დრო + + + + Network + ქსელი + + + + Number of connections + შეერთებების რაოდენობა + + + + On testnet + + + + + Block chain + ბლოკთა ჯაჭვი + + + + Current number of blocks + ბლოკების მიმდინარე რაოდენობა + + + + Estimated total blocks + ბლოკების სავარაუდო რაოდენობა + + + + Last block time + ბოლო ბლოკის დრო + + + + &Open + &შექმნა + + + + Command-line options + + + + + Show the Arepacoin-Qt help message to get a list with possible Arepacoin command-line options. + + + + + &Show + + + + + &Console + &კონსოლი + + + + Build date + შექმნის დრო + + + + Arepacoin - Debug window + + + + + Arepacoin Core + + + + + Debug log file + დახვეწის ლოგ-ფაილი + + + + Open the Arepacoin debug log file from the current data directory. This can take a few seconds for large log files. + + + + + Clear console + კონსოლის გასუფთავება + + + + Welcome to the Arepacoin RPC console. + + + + + Use up and down arrows to navigate history, and <b>Ctrl-L</b> to clear screen. + კლავიშები "ზევით" და "ქვევით" - ისტორიაში მოძრაობა, <b>Ctrl-L</b> - ეკრანის გასუფთავება. + + + + Type <b>help</b> for an overview of available commands. + აკრიფეთ <b>help</b> ფაშვებული ბრძანებების სანახავად. + + + + SendCoinsDialog + + + + + + + + + + Send Coins + მონეტების გაგზავნა + + + + Coin Control Features + მონეტების კონტროლის პარამეტრები + + + + Inputs... + ხარჯები... + + + + automatically selected + არჩეულია ავტომატურად + + + + Insufficient funds! + არ არის საკმარისი თანხა! + + + + Quantity: + რაოდენობა: + + + + + 0 + + + + + Bytes: + ბაიტები: + + + + Amount: + თანხა: + + + + + + + 0.00 BC + + + + + Priority: + პრიორიტეტი: + + + + medium + + + + + Fee: + საკომისიო: + + + + Low Output: + ქვედა ზღვარი: + + + + no + + + + + After Fee: + დამატებითი საკომისიო: + + + + Change + + + + + custom change address + + + + + Send to multiple recipients at once + გაგზავნა რამდენიმე რეციპიენტთან ერთდროულად + + + + Add &Recipient + &რეციპიენტის დამატება + + + + Remove all transaction fields + + + + + Clear &All + გ&ასუფთავება + + + + Balance: + ბალანსი: + + + + 123.456 BC + + + + + Confirm the send action + გაგზავნის დადასტურება + + + + S&end + გაგ&ზავნა + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Copy quantity + რაოდენობის კოპირება + + + + Copy amount + თანხის კოპირება + + + + Copy fee + საკომისიოს კოპირება + + + + Copy after fee + დამატებითი საკომისიოს კოპირება + + + + Copy bytes + ბაიტების კოპირება + + + + Copy priority + პრიორიტეტის კოპირება + + + + Copy low output + ქვედა ზღვრის კოპირება + + + + Copy change + ხურდის კოპირება + + + + <b>%1</b> to %2 (%3) + + + + + Confirm send coins + მონეტების გაგზავნის დადასტურება + + + + Are you sure you want to send %1? + + + + + and + + + + + The recipient address is not valid, please recheck. + მიმღების მისამართი არასწორია, შეამოწმეთ. + + + + The amount to pay must be larger than 0. + გადახდის მოცულობა 0-ზე მეტი უნდა იყოს + + + + The amount exceeds your balance. + თანხა აღემატება თქვენს ბალანსს + + + + The total exceeds your balance when the %1 transaction fee is included. + საკომისიო 1%-ის დამატების შემდეგ თანხა აჭარბებს თქვენს ბალანსს + + + + Duplicate address found, can only send to each address once per send operation. + მისამართები დუბლირებულია, დაშვებულია ერთ ჯერზე თითო მისამართზე ერთხელ გაგზავნა. + + + + Error: Transaction creation failed. + + + + + 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. + + + + + WARNING: Invalid Arepacoin address + + + + + (no label) + (არ არის ნიშნული) + + + + WARNING: unknown change address + + + + + SendCoinsEntry + + + Form + + + + + A&mount: + &რაოდენობა + + + + Pay &To: + ადრესა&ტი: + + + + + Enter a label for this address to add it to your address book + შეიყვანეთ ამ მისამართის ნიშნული მისამართების წიგნში დასამატებლად + + + + &Label: + ნიშნუ&ლი: + + + + The address to send the payment to (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Choose address from address book + + + + + Alt+A + Alt+A + + + + Paste address from clipboard + მისამართის ჩასმა კლიპბორდიდან + + + + Alt+P + Alt+P + + + + Remove this recipient + + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + SignVerifyMessageDialog + + + Signatures - Sign / Verify a Message + ხელმოწერები - მესიჯის ხელმოწერა/ვერიფიკაცია + + + + + &Sign Message + მე&სიჯის ხელმოწერა + + + + You can sign messages with your addresses to prove you own them. Be careful not to sign anything vague, as phishing attacks may try to trick you into signing your identity over to them. Only sign fully-detailed statements you agree to. + ხელმოწერით თქვენ ადასტურებთ, რომ მესიჯი თქვენია. ფრთხილად - არ მოაწეროთ ხელი რაიმე საეჭვოს: ფიშინგური ხრიკებით შეიძლება ის თქვენს მესიჯად გაასაღონ. მოაწერეთ ხელი მხოლოდ იმას, რასაც ყველა წვრილმანში ეთანხმებით. + + + + The address to sign the message with (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + + Choose an address from the address book + + + + + + Alt+A + Alt+A + + + + Paste address from clipboard + მისამართის ჩასმა კლიპბორდიდან + + + + Alt+P + Alt+P + + + + Enter the message you want to sign here + აკრიფეთ ხელმოსაწერი მესიჯი + + + + Copy the current signature to the system clipboard + მიმდინარე ხელმოწერის კოპირება კლიპბორდში + + + + Sign the message to prove you own this Arepacoin address + + + + + Reset all sign message fields + ხელმოწერის ყველა ველის წაშლა + + + + + Clear &All + გ&ასუფთავება + + + + + &Verify Message + მესიჯის &ვერიფიკაცია + + + + Enter the signing address, message (ensure you copy line breaks, spaces, tabs, etc. exactly) and signature below to verify the message. Be careful not to read more into the signature than what is in the signed message itself, to avoid being tricked by a man-in-the-middle attack. + შეიყვანეთ ხელმოწერის მისამართი, მესიჯი (დაუკვირდით, რომ ზუსტად იყოს კოპირებული სტრიქონის გადატანები, ჰარები, ტაბულაციები და სხვ) და ხელმოწერა მესიჯის ვერიფიკაციისათვის. მიაქციეთ ყურადღება, რომ რაიმე ზედმეტი არ გაგყვეთ კოპირებისას, რათა არ გახდეთ "man-in-the-middle" შეტევის ობიექტი. + + + + The address the message was signed with (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Verify the message to ensure it was signed with the specified Arepacoin address + + + + + Reset all verify message fields + ვერიფიკაციის ყველა ველის წაშლა + + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Click "Sign Message" to generate signature + ხელმოწერის გენერირებისათვის დააჭირეთ "მესიჯის ხელმოწერა"-ს + + + + Enter Arepacoin signature + + + + + + The entered address is invalid. + შეყვანილი მისამართი არასწორია. + + + + + + + Please check the address and try again. + შეამოწმეთ მისამართი და სცადეთ ხელახლა. + + + + + The entered address does not refer to a key. + შეყვანილი მისამართი არ არის კავშირში გასაღებთან. + + + + Wallet unlock was cancelled. + საფულის განბლოკვა შეწყვეტილია. + + + + Private key for the entered address is not available. + ამ მისამართისათვის პირადი გასაღები მიუწვდომელია. + + + + Message signing failed. + ვერ მოხერხდა მესიჯის ხელმოწერა. + + + + Message signed. + მესიჯი ხელმოწერილია. + + + + The signature could not be decoded. + ხელმოწერის დეკოდირება ვერ ხერხდება. + + + + + Please check the signature and try again. + შეამოწმეთ ხელმოწერა და სცადეთ ხელახლა. + + + + The signature did not match the message digest. + ხელმოწერა არ შეესაბამება მესიჯის დაიჯესტს. + + + + Message verification failed. + მესიჯის ვერიფიკაცია ვერ მოხერხდა. + + + + Message verified. + მესიჯი ვერიფიცირებულია. + + + + TransactionDesc + + + Open until %1 + ღია იქნება სანამ %1 + + + + Open for %n block(s) + + + + + conflicted + + + + + %1/offline + %1/გათიშულია + + + + %1/unconfirmed + %1/დაუდასტურებელია + + + + %1 confirmations + %1 დადასტურებულია + + + + Status + სტატუსი + + + + , broadcast through %n node(s) + + + + + Date + თარიღი + + + + Source + წყარო + + + + Generated + გენერირებულია + + + + + From + გამგზავნი + + + + + + To + მიმღები + + + + + own address + საკუთარი მისამართი + + + + label + ნიშნული + + + + + + + + Credit + კრედიტი + + + + matures in %n more block(s) + + + + + not accepted + უარყოფილია + + + + + + + Debit + დებიტი + + + + Transaction fee + ტრანსაქციის საფასური - საკომისიო + + + + Net amount + სუფთა თანხა + + + + Message + მესიჯი + + + + Comment + შენიშვნა + + + + Transaction ID + ტრანსაქციის ID + + + + Generated coins must mature 6 blocks before they can be spent. When you generated this block, it was broadcast to the network to be added to the block chain. If it fails to get into the chain, its state will change to "not accepted" and it won't be spendable. This may occasionally happen if another node generates a block within a few seconds of yours. + + + + + Debug information + დახვეწის ინფორმაცია + + + + Transaction + ტრანსაქცია + + + + Inputs + ხარჯები + + + + Amount + თანხა + + + + true + ჭეშმარიტი + + + + false + მცდარი + + + + , has not been successfully broadcast yet + , დაგზავნა არ არის წარმატებით დასრულებული + + + + unknown + უცნობია + + + + TransactionDescDialog + + + Transaction details + ტრანსაქციის დეტალები + + + + This pane shows a detailed description of the transaction + ტრანსაქციის დაწვრილებითი აღწერილობა + + + + TransactionTableModel + + + Date + თარიღი + + + + Type + ტიპი + + + + Address + მისამართი + + + + Amount + რაოდენობა + + + + Open until %1 + ღია იქნება სანამ %1 + + + + Confirmed (%1 confirmations) + დადასტურებულია (%1დასტური) + + + + Open for %n more block(s) + + + + + Offline + + + + + Unconfirmed + + + + + Confirming (%1 of %2 recommended confirmations) + + + + + Conflicted + + + + + Immature (%1 confirmations, will be available after %2) + არ არის მომწიფებული (%1 დასტური, საჭიროა სულ %2) + + + + This block was not received by any other nodes and will probably not be accepted! + ეს ბლოკი არ არის მიღებული არცერთი კვანძის მიერ და სავარაუდოდ უარყოფილია! + + + + Generated but not accepted + გენერირებულია, მაგრამ უარყოფილია + + + + Received with + მიღებულია + + + + Received from + გამომგზავნი + + + + Sent to + გაგზავნილია ადრესატთან + + + + Payment to yourself + გადახდილია საკუთარი თავისათვის + + + + Mined + მოპოვებულია + + + + (n/a) + (მიუწვდ.) + + + + Transaction status. Hover over this field to show number of confirmations. + ტრანსაქციის სტატუსი. ველზე კურსორის შეყვანისას გამოჩნდება დასტურების რაოდენობა. + + + + Date and time that the transaction was received. + ტრანსაქციის მიღების თარიღი და დრო. + + + + Type of transaction. + ტრანსაქციის ტიპი. + + + + Destination address of transaction. + ტრანსაქიის დანიშნულების მისამართი. + + + + Amount removed from or added to balance. + ბალანსიდან მოხსნილი ან დამატებული თანხა. + + + + TransactionView + + + + All + ყველა + + + + Today + დღეს + + + + This week + ამ კვირის + + + + This month + ამ თვის + + + + Last month + ბოლო თვის + + + + This year + ამ წლის + + + + Range... + შუალედი... + + + + Received with + შემოსულია + + + + Sent to + გაგზავნილია + + + + To yourself + საკუთარი თავისათვის + + + + Mined + მოპოვებულია + + + + Other + სხვა + + + + Enter address or label to search + შეიყვანეთ საძებნი მისამართი ან ნიშნული + + + + Min amount + მინ. თანხა + + + + Copy address + მისამართის კოპირება + + + + Copy label + ნიშნულის კოპირება + + + + Copy amount + თანხის კოპირება + + + + Copy transaction ID + ტრანსაქციის ID-ს კოპირება + + + + Edit label + ნიშნულის რედაქტირება + + + + Show transaction details + ტრანსაქციის დეტალების ჩვენება + + + + Export Transaction Data + + + + + Comma separated file (*.csv) + CSV-ფაილი (*.csv) + + + + Confirmed + დადასტურებულია + + + + Date + თარიღი + + + + Type + ტიპი + + + + Label + ნიშნული + + + + Address + მისამართი + + + + Amount + თანხა + + + + ID + ID + + + + Error exporting + + + + + Could not write to file %1. + + + + + Range: + შუალედი: + + + + to + - + + + + WalletModel + + + Sending... + + + + + bitcoin-core + + + Arepacoin version + + + + + Usage: + გამოყენება: + + + + Send command to -server or arepacoind + + + + + List commands + ბრძანებები + + + + Get help for a command + ბრძანების აღწერილობა + + + + Options: + ოპციები: + + + + Specify configuration file (default: arepacoin.conf) + + + + + Specify pid file (default: arepacoind.pid) + + + + + Specify wallet file (within data directory) + მიუთითეთ საფულის ფაილი (კატალოგში) + + + + Specify data directory + მიუთითეთ მონაცემთა კატალოგი + + + + Set database cache size in megabytes (default: 25) + მონაცემთა ბაზის ქეშის ზომა მეგაბაიტებში (ნაგულისხმევია 25) + + + + Set database disk log size in megabytes (default: 100) + + + + + Listen for connections on <port> (default: 9853 or testnet: 19853) + + + + + Maintain at most <n> connections to peers (default: 125) + არაუმეტეს <n> შეერთებისა პირებზე (ნაგულისხმევი: 125) + + + + Connect to a node to retrieve peer addresses, and disconnect + მიერთება კვანძთან, პირების მისამართების მიღება და გათიშვა + + + + Specify your own public address + მიუთითეთ თქვენი საჯარო მისამართი + + + + Bind to given address. Use [host]:port notation for IPv6 + + + + + Stake your coins to support network and gain reward (default: 1) + + + + + Threshold for disconnecting misbehaving peers (default: 100) + არასწორად მოქმედი პირების გათიშვის ზღვარი (ნაგულისხმევი:100) + + + + Number of seconds to keep misbehaving peers from reconnecting (default: 86400) + არასწორად მოქმედი პირების ბლოკირების დრო წამებში (ნაგულისხმევი: 86400) + + + + An error occurred while setting up the RPC port %u for listening on IPv4: %s + შეცდომა %u RPC-პორტის მიყურადების ჩართვისას IPv4 მისამართზე: %s + + + + Detach block and address databases. Increases shutdown time (default: 0) + + + + + 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. + + + + + Error: This transaction requires a transaction fee of at least %s because of its amount, complexity, or use of recently received funds + + + + + Listen for JSON-RPC connections on <port> (default: 9852 or testnet: 19852) + + + + + Accept command line and JSON-RPC commands + საკომანდო სტრიქონისა და JSON-RPC-კომამდების ნებართვა + + + + Error: Transaction creation failed + + + + + Error: Wallet locked, unable to create transaction + + + + + Importing blockchain data file. + + + + + Importing bootstrap blockchain data file. + + + + + Run in the background as a daemon and accept commands + რეზიდენტულად გაშვება და კომანდების მიღება + + + + Use the test network + სატესტო ქსელის გამოყენება + + + + Accept connections from outside (default: 1 if no -proxy or -connect) + გარედან შეერთებების დაშვება (ნაგულისხმევი: 1 თუ არ გამოიყენება -proxy ან -connect) + + + + An error occurred while setting up the RPC port %u for listening on IPv6, falling back to IPv4: %s + შეცდომა %u RPC-პორტის მიყურადების ჩართვისას IPv6 მისამართზე, ვბრუნდებით IPv4-ზე : %s + + + + Error initializing database environment %s! To recover, BACKUP THAT DIRECTORY, then remove everything from it except for wallet.dat. + + + + + Set maximum size of high-priority/low-fee transactions in bytes (default: 27000) + + + + + Warning: -paytxfee is set very high! This is the transaction fee you will pay if you send a transaction. + ყურადღება: ძალიან მაღალია -paytxfee - საკომისო, რომელსაც თქვენ გადაიხდით ამ ტრანსაქციის გაგზავნის საფასურად. + + + + Warning: Please check that your computer's date and time are correct! If your clock is wrong Arepacoin will not work properly. + + + + + Warning: error reading wallet.dat! All keys read correctly, but transaction data or address book entries might be missing or incorrect. + ყურადღება: არ იკითხება wallet.dat! ყველა გასაღები წაკითხულია, მაგრამ გამორჩენილი ან არასწორია ტრანსაქციის თარიღი ან ჩანაწერები მისამართების წიგნში. + + + + Warning: wallet.dat corrupt, data salvaged! Original wallet.dat saved as wallet.{timestamp}.bak in %s; if your balance or transactions are incorrect you should restore from a backup. + ყურადღება: wallet.dat დაზიანებულია! ორიგინალური wallet.dat შენახულია როგორც wallet.{timestamp}.bak %s-ში; თუ შეამჩნიეთ უზუსტობა ნაშთში ან ტრანსაქციებში, აღადგინეთ არქივიდან. + + + + Attempt to recover private keys from a corrupt wallet.dat + პირადი გასაღებების აღდგენის მცდელობა wallet.dat-იდან + + + + Block creation options: + ბლოკის შექმნის ოპციები: + + + + Connect only to the specified node(s) + შეერთება მხოლოდ მითითებულ კვანძ(ებ)თან + + + + Discover own IP address (default: 1 when listening and no -externalip) + საკუთარი IP-მისამართის განსაზღვრა (ნაგულისხმევი: 1 თუ ჩართულია მიყურადება და არ გამოიყენება -externalip) + + + + Failed to listen on any port. Use -listen=0 if you want this. + ვერ ხერხდება პორტების მიყურადება. თუ გსურთ, გამოიყენეთ -listen=0. + + + + Find peers using DNS lookup (default: 1) + + + + + Sync checkpoints policy (default: strict) + + + + + Invalid -tor address: '%s' + + + + + Invalid amount for -reservebalance=<amount> + + + + + Maximum per-connection receive buffer, <n>*1000 bytes (default: 5000) + მიღების ბუფერის მაქსიმალური ზომა შეერთებაზე, <n>*1000 ბაიტი (ნაგულისხმევი: 5000) + + + + Maximum per-connection send buffer, <n>*1000 bytes (default: 1000) + გაგზავნის ბუფერის მაქსიმალური ზომა შეერთებაზე, <n>*1000 ბაიტი (ნაგულისხმევი: 5000) + + + + Only connect to nodes in network <net> (IPv4, IPv6 or Tor) + შეერთება მხოლოდ <net> ქსელის კვანძებთან (IPv4, IPv6 ან Tor) + + + + Output extra debugging information. Implies all other -debug* options + + + + + Output extra network debugging information + + + + + Prepend debug output with timestamp + + + + + SSL options: (see the Bitcoin Wiki for SSL setup instructions) + SSL ოპციები: (იხილე Bitcoin Wiki-ში SSL-ს მოწყობის ინსტრუქციები) + + + + Select the version of socks proxy to use (4-5, default: 5) + + + + + Send trace/debug info to console instead of debug.log file + ტრასირების/დახვეწის ინფოს გაგზავნა კონსოლზე debug.log ფაილის ნაცვლად + + + + Send trace/debug info to debugger + + + + + Set maximum block size in bytes (default: 250000) + + + + + Set minimum block size in bytes (default: 0) + დააყენეთ ბლოკის მინიმალური ზომა ბაიტებში (ნაგულისხმევი: 0) + + + + Shrink debug.log file on client startup (default: 1 when no -debug) + debug.log ფაილის შეკუმშვა გაშვებისას (ნაგულისხმევია: 1 როცა არ აყენია -debug) + + + + Specify connection timeout in milliseconds (default: 5000) + მიუთითეთ შეერთების ტაიმაუტი მილიწამებში (ნაგულისხმევი: 5000) + + + + Unable to sign checkpoint, wrong checkpointkey? + + + + + + Use UPnP to map the listening port (default: 0) + გამოიყენეთ UPnP მისაყურადებელი პორტის გადასამისამართებლად (ნაგულისხმევი: 0) + + + + Use UPnP to map the listening port (default: 1 when listening) + გამოიყენეთ UPnP მისაყურადებელი პორტის გადასამისამართებლად (ნაგულისხმევი: 1 როცა ჩართულია მიყურადება) + + + + Use proxy to reach tor hidden services (default: same as -proxy) + + + + + Username for JSON-RPC connections + მომხმარებლის სახელი JSON-RPC-შეერთებისათვის + + + + Verifying database integrity... + + + + + WARNING: syncronized checkpoint violation detected, but skipped! + + + + + Warning: Disk space is low! + + + + + Warning: This version is obsolete, upgrade required! + ყურადღება: ვერსია მოძველებულია, საჭიროა განახლება! + + + + wallet.dat corrupt, salvage failed + wallet.dat დაზიანებულია, აღდგენა ვერ მოხერხდა + + + + Password for JSON-RPC connections + პაროლი JSON-RPC-შეერთებისათვის + + + + %s, you must set a rpcpassword in the configuration file: + %s +It is recommended you use the following random password: +rpcuser=arepacoinrpc +rpcpassword=%s +(you do not need to remember this password) +The username and password MUST NOT be the same. +If the file does not exist, create it with owner-readable-only file permissions. +It is also recommended to set alertnotify so you are notified of problems; +for example: alertnotify=echo %%s | mail -s "Arepacoin Alert" admin@foo.com + + + + + + Find peers using internet relay chat (default: 0) + + + + + Sync time with other nodes. Disable if time on your system is precise e.g. syncing with NTP (default: 1) + + + + + When creating transactions, ignore inputs with value less than this (default: 0.01) + + + + + Allow JSON-RPC connections from specified IP address + JSON-RPC-შეერთების ნებართვა მითითებული IP მისამართიდან + + + + Send commands to node running on <ip> (default: 127.0.0.1) + კომანდის გაგზავნა კვანძისათვის, რომელიც გაშვებულია მისამართზე <ip> (ნაგულისხმევი: 127.0.0.1) + + + + Execute command when the best block changes (%s in cmd is replaced by block hash) + კომანდის შესრულება უკეთესი ბლოკის გამოჩენისას (%s კომანდაში ჩანაცვლდება ბლოკის ჰეშით) + + + + Execute command when a wallet transaction changes (%s in cmd is replaced by TxID) + კომანდის შესრულება საფულის ტრანსაქციის ცვლილებისას (%s კომანდაში ჩანაცვლდება TxID-ით) + + + + Require a confirmations for change (default: 0) + + + + + Enforce transaction scripts to use canonical PUSH operators (default: 1) + + + + + Execute command when a relevant alert is received (%s in cmd is replaced by message) + + + + + Upgrade wallet to latest format + საფულის ფორმატის განახლება + + + + Set key pool size to <n> (default: 100) + გასაღების პულის ზომა იქნება <n> (ნაგულისხმევი: 100) + + + + Rescan the block chain for missing wallet transactions + ბლოკების ჯაჭვის გადამოწმება საფულეში გამორჩენილ ტრანსაქციებზე + + + + How many blocks to check at startup (default: 2500, 0 = all) + + + + + How thorough the block verification is (0-6, default: 1) + + + + + Imports blocks from external blk000?.dat file + + + + + Use OpenSSL (https) for JSON-RPC connections + OpenSSL-ის (https) გამოყენება JSON-RPC-შეერთებებისათვის + + + + Server certificate file (default: server.cert) + სერვერის სერტიფიკატის ფაილი (ნაგულისხმევი: server.cert) + + + + Server private key (default: server.pem) + სერვერის პირადი გასაღები (ნაგულისხმევი: server.pem) + + + + Acceptable ciphers (default: TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH) + + + + + Error: Wallet unlocked for staking only, unable to create transaction. + + + + + WARNING: Invalid checkpoint found! Displayed transactions may not be correct! You may need to upgrade, or notify developers. + + + + + This help message + ეს ტექსტი + + + + Wallet %s resides outside data directory %s. + + + + + Cannot obtain a lock on data directory %s. Arepacoin is probably already running. + + + + + Arepacoin + + + + + Unable to bind to %s on this computer (bind returned error %d, %s) + ვერ ხერხდება მიბმა %s-თან ამ კომპიუტერზე (მიღებულია შეცდომა %d, %s) + + + + Connect through socks proxy + + + + + Allow DNS lookups for -addnode, -seednode and -connect + DNS-ძებნის დაშვება -addnode, -seednode და -connect-სათვის + + + + Loading addresses... + მისამართების ჩატვირთვა... + + + + Error loading blkindex.dat + + + + + Error loading wallet.dat: Wallet corrupted + არ იტვირთება wallet.dat: საფულე დაზიანებულია + + + + Error loading wallet.dat: Wallet requires newer version of Arepacoin + + + + + Wallet needed to be rewritten: restart Arepacoin to complete + + + + + Error loading wallet.dat + არ იტვირთება wallet.dat + + + + Invalid -proxy address: '%s' + არასწორია მისამართი -proxy: '%s' + + + + Unknown network specified in -onlynet: '%s' + -onlynet-ში მითითებულია უცნობი ქსელი: '%s' + + + + Unknown -socks proxy version requested: %i + მოთხოვნილია -socks პროქსის უცნობი ვერსია: %i + + + + Cannot resolve -bind address: '%s' + ვერ ხერხდება -bind მისამართის გარკვევა: '%s' + + + + Cannot resolve -externalip address: '%s' + ვერ ხერხდება -externalip მისამართის გარკვევა: '%s' + + + + Invalid amount for -paytxfee=<amount>: '%s' + დაუშვებელი მნიშვნელობა -paytxfee=<amount>: '%s' + + + + Error: could not start node + + + + + Sending... + + + + + Invalid amount + დაუშვებელი თანხა + + + + Insufficient funds + არ არის საკმარისი თანხა + + + + Loading block index... + ბლოკების ინდექსის ჩატვირთვა... + + + + Add a node to connect to and attempt to keep the connection open + მისაერთებელი კვანძის დამატება და მიერთების შეძლებისდაგვარად შენარჩუნება + + + + Unable to bind to %s on this computer. Arepacoin is probably already running. + + + + + Fee per KB to add to transactions you send + + + + + Invalid amount for -mininput=<amount>: '%s' + + + + + Loading wallet... + საფულის ჩატვირთვა... + + + + Cannot downgrade wallet + საფულის ძველ ვერსიაზე გადაყვანა შეუძლებელია + + + + Cannot initialize keypool + + + + + Cannot write default address + ვერ ხერხდება ნაგულისხმევი მისამართის ჩაწერა + + + + Rescanning... + სკანირება... + + + + Done loading + ჩატვირთვა დასრულებულია + + + + To use the %s option + %s ოპციის გამოსაყენებლად + + + + Error + შეცდომა + + + + You must set rpcpassword=<password> in the configuration file: +%s +If the file does not exist, create it with owner-readable-only file permissions. + უნდა დააყენოთ rpcpassword=<password> საკონფიგურაციო ფაილში: +%s +თუ ეს ფაილი არ არსებობს, შექმენით იგი უფლებებით owner-readable-only. + + + \ No newline at end of file diff --git a/src/qt/locale/bitcoin_kk_KZ.ts b/src/qt/locale/bitcoin_kk_KZ.ts new file mode 100755 index 0000000..2586bb3 --- /dev/null +++ b/src/qt/locale/bitcoin_kk_KZ.ts @@ -0,0 +1,3275 @@ + + + AboutDialog + + + About Arepacoin + + + + + <b>Arepacoin</b> version + + + + + Copyright © 2009-2014 The Bitcoin developers +Copyright © 2012-2014 The NovaCoin developers +Copyright © 2014 The Arepacoin developers + + + + + +This is experimental software. + +Distributed under the MIT/X11 software license, see the accompanying file COPYING or http://www.opensource.org/licenses/mit-license.php. + +This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit (http://www.openssl.org/) and cryptographic software written by Eric Young (eay@cryptsoft.com) and UPnP software written by Thomas Bernard. + + + + + AddressBookPage + + + Address Book + + + + + Double-click to edit address or label + Адресті немесе белгіні өзгерту үшін екі рет шертіңіз + + + + Create a new address + Жаңа адрес енгізу + + + + Copy the currently selected address to the system clipboard + Таңдаған адресті тізімнен жою + + + + &New Address + + + + + These are your Arepacoin addresses for receiving payments. You may want to give a different one to each sender so you can keep track of who is paying you. + + + + + &Copy Address + + + + + Show &QR Code + + + + + Sign a message to prove you own a Arepacoin address + + + + + Sign &Message + + + + + Delete the currently selected address from the list + + + + + Verify a message to ensure it was signed with a specified Arepacoin address + + + + + &Verify Message + + + + + &Delete + Жою + + + + Copy &Label + + + + + &Edit + + + + + Export Address Book Data + + + + + Comma separated file (*.csv) + Үтірмен бөлінген текст (*.csv) + + + + Error exporting + + + + + Could not write to file %1. + + + + + AddressTableModel + + + Label + таңба + + + + Address + Адрес + + + + (no label) + (таңбасыз) + + + + AskPassphraseDialog + + + Passphrase Dialog + + + + + Enter passphrase + Құпия сөзді енгізу + + + + New passphrase + Жаңа құпия сөзі + + + + Repeat new passphrase + Жаңа құпия сөзді қайта енгізу + + + + Serves to disable the trivial sendmoney when OS account compromised. Provides no real security. + + + + + For staking only + + + + + Enter the new passphrase to the wallet.<br/>Please use a passphrase of <b>10 or more random characters</b>, or <b>eight or more words</b>. + Әмиянға жаңа қүпия сөзді енгізіңіз.<br/><b>10 немесе одан әрі кездейсоқ белгілерді</b>, әлде <b>сегіз немесе одан әрі сөздерді</b>құпия сөзіңізде пайдалану өтінеміз. + + + + Encrypt wallet + Әмиянді шифрлау + + + + This operation needs your wallet passphrase to unlock the wallet. + Бұл операциясы бойынша сіздің әмиянізді қоршаудан шығару үшін әмиянның құпия сөзі керек + + + + Unlock wallet + Әмиянізді қоршаудан шығару + + + + This operation needs your wallet passphrase to decrypt the wallet. + Бұл операциясы бойынша сіздің әмиянізді шифрлап тастау үшін әмиянның құпия сөзі керек + + + + Decrypt wallet + Әмиянізді шифрлап тастау + + + + Change passphrase + Құпия сөзді өзгерту + + + + Enter the old and new passphrase to the wallet. + + + + + Confirm wallet encryption + + + + + Warning: If you encrypt your wallet and lose your passphrase, you will <b>LOSE ALL OF YOUR COINS</b>! + + + + + Are you sure you wish to encrypt your wallet? + + + + + IMPORTANT: Any previous backups you have made of your wallet file should be replaced with the newly generated, encrypted wallet file. For security reasons, previous backups of the unencrypted wallet file will become useless as soon as you start using the new, encrypted wallet. + + + + + + Warning: The Caps Lock key is on! + + + + + + Wallet encrypted + + + + + Arepacoin will close now to finish the encryption process. Remember that encrypting your wallet cannot fully protect your coins from being stolen by malware infecting your computer. + + + + + + + + Wallet encryption failed + + + + + Wallet encryption failed due to an internal error. Your wallet was not encrypted. + + + + + + The supplied passphrases do not match. + + + + + Wallet unlock failed + + + + + + + The passphrase entered for the wallet decryption was incorrect. + + + + + Wallet decryption failed + + + + + Wallet passphrase was successfully changed. + + + + + BitcoinGUI + + + Sign &message... + + + + + Synchronizing with network... + + + + + &Overview + + + + + Show general overview of wallet + + + + + &Transactions + + + + + Browse transaction history + + + + + &Address Book + + + + + Edit the list of stored addresses and labels + + + + + &Receive coins + + + + + Show the list of addresses for receiving payments + + + + + &Send coins + + + + + E&xit + + + + + Quit application + + + + + Show information about Arepacoin + + + + + About &Qt + + + + + Show information about Qt + + + + + &Options... + + + + + &Encrypt Wallet... + + + + + &Backup Wallet... + + + + + &Change Passphrase... + + + + + ~%n block(s) remaining + + + + + Downloaded %1 of %2 blocks of transaction history (%3% done). + + + + + &Export... + + + + + Send coins to a Arepacoin address + + + + + Modify configuration options for Arepacoin + + + + + Export the data in the current tab to a file + + + + + Encrypt or decrypt wallet + + + + + Backup wallet to another location + + + + + Change the passphrase used for wallet encryption + + + + + &Debug window + + + + + Open debugging and diagnostic console + + + + + &Verify message... + + + + + Arepacoin + + + + + Wallet + + + + + &About Arepacoin + + + + + &Show / Hide + + + + + Unlock wallet + + + + + &Lock Wallet + + + + + Lock wallet + + + + + &File + + + + + &Settings + + + + + &Help + + + + + Tabs toolbar + + + + + Actions toolbar + + + + + + [testnet] + + + + + + Arepacoin client + + + + + %n active connection(s) to Arepacoin network + + + + + Downloaded %1 blocks of transaction history. + + + + + Staking.<br>Your weight is %1<br>Network weight is %2<br>Expected time to earn reward is %3 + + + + + Not staking because wallet is locked + + + + + Not staking because wallet is offline + + + + + Not staking because wallet is syncing + + + + + Not staking because you don't have mature coins + + + + + %n second(s) ago + + + + + &Unlock Wallet... + + + + + %n minute(s) ago + + + + + %n hour(s) ago + + + + + %n day(s) ago + + + + + Up to date + + + + + Catching up... + + + + + Last received block was generated %1. + + + + + This transaction is over the size limit. You can still send it for a fee of %1, which goes to the nodes that process your transaction and helps to support the network. Do you want to pay the fee? + + + + + Confirm transaction fee + + + + + Sent transaction + + + + + Incoming transaction + + + + + Date: %1 +Amount: %2 +Type: %3 +Address: %4 + + + + + + + URI handling + + + + + + URI can not be parsed! This can be caused by an invalid Arepacoin address or malformed URI parameters. + + + + + Wallet is <b>encrypted</b> and currently <b>unlocked</b> + + + + + Wallet is <b>encrypted</b> and currently <b>locked</b> + + + + + Backup Wallet + + + + + Wallet Data (*.dat) + + + + + Backup Failed + + + + + There was an error trying to save the wallet data to the new location. + + + + + %n second(s) + + + + + %n minute(s) + + + + + %n hour(s) + + + + + %n day(s) + + + + + Not staking + + + + + A fatal error occurred. Arepacoin can no longer continue safely and will quit. + + + + + ClientModel + + + Network Alert + + + + + CoinControlDialog + + + Coin Control + + + + + Quantity: + + + + + Bytes: + + + + + Amount: + + + + + Priority: + + + + + Fee: + + + + + Low Output: + + + + + no + + + + + After Fee: + + + + + Change: + + + + + (un)select all + + + + + Tree mode + + + + + List mode + + + + + Amount + + + + + Label + + + + + Address + Адрес + + + + Date + + + + + Confirmations + + + + + Confirmed + + + + + Priority + + + + + Copy address + + + + + Copy label + + + + + + Copy amount + + + + + Copy transaction ID + + + + + Copy quantity + + + + + Copy fee + + + + + Copy after fee + + + + + Copy bytes + + + + + Copy priority + + + + + Copy low output + + + + + Copy change + + + + + highest + + + + + high + + + + + medium-high + + + + + medium + + + + + low-medium + + + + + low + + + + + lowest + + + + + DUST + + + + + yes + + + + + This label turns red, if the transaction size is bigger than 10000 bytes. + + This means a fee of at least %1 per kb is required. + + Can vary +/- 1 Byte per input. + + + + + Transactions with higher priority get more likely into a block. + +This label turns red, if the priority is smaller than "medium". + + This means a fee of at least %1 per kb is required. + + + + + This label turns red, if any recipient receives an amount smaller than %1. + + This means a fee of at least %2 is required. + + Amounts below 0.546 times the minimum relay fee are shown as DUST. + + + + + This label turns red, if the change is smaller than %1. + + This means a fee of at least %2 is required. + + + + + + (no label) + (таңбасыз) + + + + change from %1 (%2) + + + + + (change) + + + + + EditAddressDialog + + + Edit Address + + + + + &Label + + + + + The label associated with this address book entry + + + + + &Address + + + + + The address associated with this address book entry. This can only be modified for sending addresses. + + + + + New receiving address + + + + + New sending address + + + + + Edit receiving address + + + + + Edit sending address + + + + + The entered address "%1" is already in the address book. + + + + + The entered address "%1" is not a valid Arepacoin address. + + + + + Could not unlock wallet. + + + + + New key generation failed. + + + + + GUIUtil::HelpMessageBox + + + + Arepacoin-Qt + + + + + version + + + + + Usage: + + + + + command-line options + + + + + UI options + + + + + Set language, for example "de_DE" (default: system locale) + + + + + Start minimized + + + + + Show splash screen on startup (default: 1) + + + + + OptionsDialog + + + Options + + + + + &Main + + + + + Optional transaction fee per kB that helps make sure your transactions are processed quickly. Most transactions are 1 kB. Fee 0.01 recommended. + + + + + Pay transaction &fee + + + + + Reserved amount does not participate in staking and is therefore spendable at any time. + + + + + Reserve + + + + + Automatically start Arepacoin after logging in to the system. + + + + + &Start Arepacoin on system login + + + + + Detach block and address databases at shutdown. This means they can be moved to another data directory, but it slows down shutdown. The wallet is always detached. + + + + + &Detach databases at shutdown + + + + + &Network + + + + + Automatically open the Arepacoin client port on the router. This only works when your router supports UPnP and it is enabled. + + + + + Map port using &UPnP + + + + + Connect to the Arepacoin network through a SOCKS proxy (e.g. when connecting through Tor). + + + + + &Connect through SOCKS proxy: + + + + + Proxy &IP: + + + + + IP address of the proxy (e.g. 127.0.0.1) + + + + + &Port: + + + + + Port of the proxy (e.g. 9050) + + + + + SOCKS &Version: + + + + + SOCKS version of the proxy (e.g. 5) + + + + + &Window + + + + + Show only a tray icon after minimizing the window. + + + + + &Minimize to the tray instead of the taskbar + + + + + Minimize instead of exit the application when the window is closed. When this option is enabled, the application will be closed only after selecting Quit in the menu. + + + + + M&inimize on close + + + + + &Display + + + + + User Interface &language: + + + + + The user interface language can be set here. This setting will take effect after restarting Arepacoin. + + + + + &Unit to show amounts in: + + + + + Choose the default subdivision unit to show in the interface and when sending coins. + + + + + Whether to show Arepacoin addresses in the transaction list or not. + + + + + &Display addresses in transaction list + + + + + Whether to show coin control features or not. + + + + + Display coin &control features (experts only!) + + + + + &OK + + + + + &Cancel + + + + + &Apply + + + + + default + + + + + + Warning + + + + + + This setting will take effect after restarting Arepacoin. + + + + + The supplied proxy address is invalid. + + + + + OverviewPage + + + Form + + + + + + The displayed information may be out of date. Your wallet automatically synchronizes with the Arepacoin network after a connection is established, but this process has not completed yet. + + + + + Stake: + + + + + Unconfirmed: + + + + + Wallet + + + + + Spendable: + + + + + Your current spendable balance + + + + + Immature: + + + + + Mined balance that has not yet matured + + + + + Total: + + + + + Your current total balance + + + + + <b>Recent transactions</b> + + + + + Total of transactions that have yet to be confirmed, and do not yet count toward the current balance + + + + + Total of coins that was staked, and do not yet count toward the current balance + + + + + + out of sync + + + + + QRCodeDialog + + + QR Code Dialog + + + + + Request Payment + + + + + Amount: + + + + + Label: + + + + + Message: + + + + + &Save As... + + + + + Error encoding URI into QR Code. + + + + + The entered amount is invalid, please check. + + + + + Resulting URI too long, try to reduce the text for label / message. + + + + + Save QR Code + + + + + PNG Images (*.png) + + + + + RPCConsole + + + Client name + + + + + + + + + + + + + + N/A + + + + + Client version + + + + + &Information + + + + + Using OpenSSL version + + + + + Startup time + + + + + Network + + + + + Number of connections + + + + + On testnet + + + + + Block chain + + + + + Current number of blocks + + + + + Estimated total blocks + + + + + Last block time + + + + + &Open + + + + + Command-line options + + + + + Show the Arepacoin-Qt help message to get a list with possible Arepacoin command-line options. + + + + + &Show + + + + + &Console + + + + + Build date + + + + + Arepacoin - Debug window + + + + + Arepacoin Core + + + + + Debug log file + + + + + Open the Arepacoin debug log file from the current data directory. This can take a few seconds for large log files. + + + + + Clear console + + + + + Welcome to the Arepacoin RPC console. + + + + + Use up and down arrows to navigate history, and <b>Ctrl-L</b> to clear screen. + + + + + Type <b>help</b> for an overview of available commands. + + + + + SendCoinsDialog + + + + + + + + + + Send Coins + + + + + Coin Control Features + + + + + Inputs... + + + + + automatically selected + + + + + Insufficient funds! + + + + + Quantity: + + + + + + 0 + + + + + Bytes: + + + + + Amount: + + + + + + + + 0.00 BC + + + + + Priority: + + + + + medium + + + + + Fee: + + + + + Low Output: + + + + + no + + + + + After Fee: + + + + + Change + + + + + custom change address + + + + + Send to multiple recipients at once + + + + + Add &Recipient + + + + + Remove all transaction fields + + + + + Clear &All + + + + + Balance: + + + + + 123.456 BC + + + + + Confirm the send action + + + + + S&end + + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Copy quantity + + + + + Copy amount + + + + + Copy fee + + + + + Copy after fee + + + + + Copy bytes + + + + + Copy priority + + + + + Copy low output + + + + + Copy change + + + + + <b>%1</b> to %2 (%3) + + + + + Confirm send coins + + + + + Are you sure you want to send %1? + + + + + and + + + + + The recipient address is not valid, please recheck. + + + + + The amount to pay must be larger than 0. + + + + + The amount exceeds your balance. + + + + + The total exceeds your balance when the %1 transaction fee is included. + + + + + Duplicate address found, can only send to each address once per send operation. + + + + + Error: Transaction creation failed. + + + + + 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. + + + + + WARNING: Invalid Arepacoin address + + + + + (no label) + (таңбасыз) + + + + WARNING: unknown change address + + + + + SendCoinsEntry + + + Form + + + + + A&mount: + + + + + Pay &To: + + + + + + Enter a label for this address to add it to your address book + + + + + &Label: + + + + + The address to send the payment to (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Choose address from address book + + + + + Alt+A + + + + + Paste address from clipboard + + + + + Alt+P + + + + + Remove this recipient + + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + SignVerifyMessageDialog + + + Signatures - Sign / Verify a Message + + + + + + &Sign Message + + + + + You can sign messages with your addresses to prove you own them. Be careful not to sign anything vague, as phishing attacks may try to trick you into signing your identity over to them. Only sign fully-detailed statements you agree to. + + + + + The address to sign the message with (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + + Choose an address from the address book + + + + + + Alt+A + + + + + Paste address from clipboard + + + + + Alt+P + + + + + Enter the message you want to sign here + + + + + Copy the current signature to the system clipboard + + + + + Sign the message to prove you own this Arepacoin address + + + + + Reset all sign message fields + + + + + + Clear &All + + + + + + &Verify Message + + + + + Enter the signing address, message (ensure you copy line breaks, spaces, tabs, etc. exactly) and signature below to verify the message. Be careful not to read more into the signature than what is in the signed message itself, to avoid being tricked by a man-in-the-middle attack. + + + + + The address the message was signed with (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Verify the message to ensure it was signed with the specified Arepacoin address + + + + + Reset all verify message fields + + + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Click "Sign Message" to generate signature + + + + + Enter Arepacoin signature + + + + + + The entered address is invalid. + + + + + + + + Please check the address and try again. + + + + + + The entered address does not refer to a key. + + + + + Wallet unlock was cancelled. + + + + + Private key for the entered address is not available. + + + + + Message signing failed. + + + + + Message signed. + + + + + The signature could not be decoded. + + + + + + Please check the signature and try again. + + + + + The signature did not match the message digest. + + + + + Message verification failed. + + + + + Message verified. + + + + + TransactionDesc + + + Open until %1 + + + + + Open for %n block(s) + + + + + conflicted + + + + + %1/offline + + + + + %1/unconfirmed + + + + + %1 confirmations + + + + + Status + + + + + , broadcast through %n node(s) + + + + + Date + + + + + Source + + + + + Generated + + + + + + From + + + + + + + To + + + + + + own address + + + + + label + + + + + + + + + Credit + + + + + matures in %n more block(s) + + + + + not accepted + + + + + + + + Debit + + + + + Transaction fee + + + + + Net amount + + + + + Message + + + + + Comment + + + + + Transaction ID + + + + + Generated coins must mature 6 blocks before they can be spent. When you generated this block, it was broadcast to the network to be added to the block chain. If it fails to get into the chain, its state will change to "not accepted" and it won't be spendable. This may occasionally happen if another node generates a block within a few seconds of yours. + + + + + Debug information + + + + + Transaction + + + + + Inputs + + + + + Amount + + + + + true + + + + + false + + + + + , has not been successfully broadcast yet + + + + + unknown + + + + + TransactionDescDialog + + + Transaction details + + + + + This pane shows a detailed description of the transaction + + + + + TransactionTableModel + + + Date + + + + + Type + + + + + Address + Адрес + + + + Amount + + + + + Open until %1 + + + + + Confirmed (%1 confirmations) + + + + + Open for %n more block(s) + + + + + Offline + + + + + Unconfirmed + + + + + Confirming (%1 of %2 recommended confirmations) + + + + + Conflicted + + + + + Immature (%1 confirmations, will be available after %2) + + + + + This block was not received by any other nodes and will probably not be accepted! + + + + + Generated but not accepted + + + + + Received with + + + + + Received from + + + + + Sent to + + + + + Payment to yourself + + + + + Mined + + + + + (n/a) + + + + + Transaction status. Hover over this field to show number of confirmations. + + + + + Date and time that the transaction was received. + + + + + Type of transaction. + + + + + Destination address of transaction. + + + + + Amount removed from or added to balance. + + + + + TransactionView + + + + All + + + + + Today + + + + + This week + + + + + This month + + + + + Last month + + + + + This year + + + + + Range... + + + + + Received with + + + + + Sent to + + + + + To yourself + + + + + Mined + + + + + Other + + + + + Enter address or label to search + + + + + Min amount + + + + + Copy address + + + + + Copy label + + + + + Copy amount + + + + + Copy transaction ID + + + + + Edit label + + + + + Show transaction details + + + + + Export Transaction Data + + + + + Comma separated file (*.csv) + Үтірмен бөлінген файл (*.csv) + + + + Confirmed + + + + + Date + + + + + Type + + + + + Label + таңба + + + + Address + Адрес + + + + Amount + + + + + ID + + + + + Error exporting + + + + + Could not write to file %1. + + + + + Range: + + + + + to + + + + + WalletModel + + + Sending... + + + + + bitcoin-core + + + Arepacoin version + + + + + Usage: + + + + + Send command to -server or arepacoind + + + + + List commands + + + + + Get help for a command + + + + + Options: + + + + + Specify configuration file (default: arepacoin.conf) + + + + + Specify pid file (default: arepacoind.pid) + + + + + Specify wallet file (within data directory) + + + + + Specify data directory + + + + + Set database cache size in megabytes (default: 25) + + + + + Set database disk log size in megabytes (default: 100) + + + + + Listen for connections on <port> (default: 9853 or testnet: 19853) + + + + + Maintain at most <n> connections to peers (default: 125) + + + + + Connect to a node to retrieve peer addresses, and disconnect + + + + + Specify your own public address + + + + + Bind to given address. Use [host]:port notation for IPv6 + + + + + Stake your coins to support network and gain reward (default: 1) + + + + + Threshold for disconnecting misbehaving peers (default: 100) + + + + + Number of seconds to keep misbehaving peers from reconnecting (default: 86400) + + + + + An error occurred while setting up the RPC port %u for listening on IPv4: %s + + + + + Detach block and address databases. Increases shutdown time (default: 0) + + + + + 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. + + + + + Error: This transaction requires a transaction fee of at least %s because of its amount, complexity, or use of recently received funds + + + + + Listen for JSON-RPC connections on <port> (default: 9852 or testnet: 19852) + + + + + Accept command line and JSON-RPC commands + + + + + Error: Transaction creation failed + + + + + Error: Wallet locked, unable to create transaction + + + + + Importing blockchain data file. + + + + + Importing bootstrap blockchain data file. + + + + + Run in the background as a daemon and accept commands + + + + + Use the test network + + + + + Accept connections from outside (default: 1 if no -proxy or -connect) + + + + + An error occurred while setting up the RPC port %u for listening on IPv6, falling back to IPv4: %s + + + + + Error initializing database environment %s! To recover, BACKUP THAT DIRECTORY, then remove everything from it except for wallet.dat. + + + + + Set maximum size of high-priority/low-fee transactions in bytes (default: 27000) + + + + + Warning: -paytxfee is set very high! This is the transaction fee you will pay if you send a transaction. + + + + + Warning: Please check that your computer's date and time are correct! If your clock is wrong Arepacoin will not work properly. + + + + + Warning: error reading wallet.dat! All keys read correctly, but transaction data or address book entries might be missing or incorrect. + + + + + Warning: wallet.dat corrupt, data salvaged! Original wallet.dat saved as wallet.{timestamp}.bak in %s; if your balance or transactions are incorrect you should restore from a backup. + + + + + Attempt to recover private keys from a corrupt wallet.dat + + + + + Block creation options: + + + + + Connect only to the specified node(s) + + + + + Discover own IP address (default: 1 when listening and no -externalip) + + + + + Failed to listen on any port. Use -listen=0 if you want this. + + + + + Find peers using DNS lookup (default: 1) + + + + + Sync checkpoints policy (default: strict) + + + + + Invalid -tor address: '%s' + + + + + Invalid amount for -reservebalance=<amount> + + + + + Maximum per-connection receive buffer, <n>*1000 bytes (default: 5000) + + + + + Maximum per-connection send buffer, <n>*1000 bytes (default: 1000) + + + + + Only connect to nodes in network <net> (IPv4, IPv6 or Tor) + + + + + Output extra debugging information. Implies all other -debug* options + + + + + Output extra network debugging information + + + + + Prepend debug output with timestamp + + + + + SSL options: (see the Bitcoin Wiki for SSL setup instructions) + + + + + Select the version of socks proxy to use (4-5, default: 5) + + + + + Send trace/debug info to console instead of debug.log file + + + + + Send trace/debug info to debugger + + + + + Set maximum block size in bytes (default: 250000) + + + + + Set minimum block size in bytes (default: 0) + + + + + Shrink debug.log file on client startup (default: 1 when no -debug) + + + + + Specify connection timeout in milliseconds (default: 5000) + + + + + Unable to sign checkpoint, wrong checkpointkey? + + + + + + Use UPnP to map the listening port (default: 0) + + + + + Use UPnP to map the listening port (default: 1 when listening) + + + + + Use proxy to reach tor hidden services (default: same as -proxy) + + + + + Username for JSON-RPC connections + + + + + Verifying database integrity... + + + + + WARNING: syncronized checkpoint violation detected, but skipped! + + + + + Warning: Disk space is low! + + + + + Warning: This version is obsolete, upgrade required! + + + + + wallet.dat corrupt, salvage failed + + + + + Password for JSON-RPC connections + + + + + %s, you must set a rpcpassword in the configuration file: + %s +It is recommended you use the following random password: +rpcuser=arepacoinrpc +rpcpassword=%s +(you do not need to remember this password) +The username and password MUST NOT be the same. +If the file does not exist, create it with owner-readable-only file permissions. +It is also recommended to set alertnotify so you are notified of problems; +for example: alertnotify=echo %%s | mail -s "Arepacoin Alert" admin@foo.com + + + + + + Find peers using internet relay chat (default: 0) + + + + + Sync time with other nodes. Disable if time on your system is precise e.g. syncing with NTP (default: 1) + + + + + When creating transactions, ignore inputs with value less than this (default: 0.01) + + + + + Allow JSON-RPC connections from specified IP address + + + + + Send commands to node running on <ip> (default: 127.0.0.1) + + + + + Execute command when the best block changes (%s in cmd is replaced by block hash) + + + + + Execute command when a wallet transaction changes (%s in cmd is replaced by TxID) + + + + + Require a confirmations for change (default: 0) + + + + + Enforce transaction scripts to use canonical PUSH operators (default: 1) + + + + + Execute command when a relevant alert is received (%s in cmd is replaced by message) + + + + + Upgrade wallet to latest format + + + + + Set key pool size to <n> (default: 100) + + + + + Rescan the block chain for missing wallet transactions + + + + + How many blocks to check at startup (default: 2500, 0 = all) + + + + + How thorough the block verification is (0-6, default: 1) + + + + + Imports blocks from external blk000?.dat file + + + + + Use OpenSSL (https) for JSON-RPC connections + + + + + Server certificate file (default: server.cert) + + + + + Server private key (default: server.pem) + + + + + Acceptable ciphers (default: TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH) + + + + + Error: Wallet unlocked for staking only, unable to create transaction. + + + + + WARNING: Invalid checkpoint found! Displayed transactions may not be correct! You may need to upgrade, or notify developers. + + + + + This help message + + + + + Wallet %s resides outside data directory %s. + + + + + Cannot obtain a lock on data directory %s. Arepacoin is probably already running. + + + + + Arepacoin + + + + + Unable to bind to %s on this computer (bind returned error %d, %s) + + + + + Connect through socks proxy + + + + + Allow DNS lookups for -addnode, -seednode and -connect + + + + + Loading addresses... + + + + + Error loading blkindex.dat + + + + + Error loading wallet.dat: Wallet corrupted + + + + + Error loading wallet.dat: Wallet requires newer version of Arepacoin + + + + + Wallet needed to be rewritten: restart Arepacoin to complete + + + + + Error loading wallet.dat + + + + + Invalid -proxy address: '%s' + + + + + Unknown network specified in -onlynet: '%s' + + + + + Unknown -socks proxy version requested: %i + + + + + Cannot resolve -bind address: '%s' + + + + + Cannot resolve -externalip address: '%s' + + + + + Invalid amount for -paytxfee=<amount>: '%s' + + + + + Error: could not start node + + + + + Sending... + + + + + Invalid amount + + + + + Insufficient funds + + + + + Loading block index... + + + + + Add a node to connect to and attempt to keep the connection open + + + + + Unable to bind to %s on this computer. Arepacoin is probably already running. + + + + + Fee per KB to add to transactions you send + + + + + Invalid amount for -mininput=<amount>: '%s' + + + + + Loading wallet... + + + + + Cannot downgrade wallet + + + + + Cannot initialize keypool + + + + + Cannot write default address + + + + + Rescanning... + + + + + Done loading + + + + + To use the %s option + + + + + Error + + + + + You must set rpcpassword=<password> in the configuration file: +%s +If the file does not exist, create it with owner-readable-only file permissions. + + + + \ No newline at end of file diff --git a/src/qt/locale/bitcoin_ko_KR.ts b/src/qt/locale/bitcoin_ko_KR.ts new file mode 100755 index 0000000..f523fdc --- /dev/null +++ b/src/qt/locale/bitcoin_ko_KR.ts @@ -0,0 +1,3286 @@ + + + AboutDialog + + + About Arepacoin + + + + + <b>Arepacoin</b> version + + + + + Copyright © 2009-2014 The Bitcoin developers +Copyright © 2012-2014 The NovaCoin developers +Copyright © 2014 The Arepacoin developers + + + + + +This is experimental software. + +Distributed under the MIT/X11 software license, see the accompanying file COPYING or http://www.opensource.org/licenses/mit-license.php. + +This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit (http://www.openssl.org/) and cryptographic software written by Eric Young (eay@cryptsoft.com) and UPnP software written by Thomas Bernard. + +이 프로그램은 시험용입니다. + +MIT/X11 프로그램 라이선스에 따라 배포합니다. COPYING 또는 http://www.opensource.org/licenses/mit-license.php를 참조하십시오. + +이 프로그램에는 OpenSSL 툴킷(http://www.openssl.org) 사용 목적으로 개발한 OpenSSL 프로젝트를 포함하고 있으며, 암호화 프로그램은 Eric Young(eay@cryptsoft.com)이, UPnP 프로그램은 Thomas Bernard가 작성했습니다. + + + + AddressBookPage + + + Address Book + + + + + Double-click to edit address or label + 주소 또는 표를 편집하기 위해 더블클릭 하시오 + + + + Create a new address + 새 주소 만들기 + + + + Copy the currently selected address to the system clipboard + 현재 선택한 주소를 시스템 클립보드로 복사하기 + + + + &New Address + + + + + These are your Arepacoin addresses for receiving payments. You may want to give a different one to each sender so you can keep track of who is paying you. + + + + + &Copy Address + 계좌 복사(&C) + + + + Show &QR Code + + + + + Sign a message to prove you own a Arepacoin address + + + + + Sign &Message + + + + + Delete the currently selected address from the list + 현재 목록에 선택한 주소 삭제 + + + + Verify a message to ensure it was signed with a specified Arepacoin address + + + + + &Verify Message + + + + + &Delete + &삭제 + + + + Copy &Label + 표 복사 + + + + &Edit + 편집& + + + + Export Address Book Data + + + + + Comma separated file (*.csv) + 각각의 파일에 쉼표하기(*.csv) + + + + Error exporting + + + + + Could not write to file %1. + + + + + AddressTableModel + + + Label + + + + + Address + 주소 + + + + (no label) + (표 없음) + + + + AskPassphraseDialog + + + Passphrase Dialog + 암호문 대화상자 + + + + Enter passphrase + 암호 입력하기 + + + + New passphrase + 새로운 암호 + + + + Repeat new passphrase + 새 암호 반복 + + + + Serves to disable the trivial sendmoney when OS account compromised. Provides no real security. + + + + + For staking only + + + + + Enter the new passphrase to the wallet.<br/>Please use a passphrase of <b>10 or more random characters</b>, or <b>eight or more words</b>. + 새로운 암호를 지갑에 입력. 8자보다 많은 단어를 입력하거나 10 자보다 많은 여러 종류를 암호에 사용하세요. + + + + Encrypt wallet + 지갑 암호화 + + + + This operation needs your wallet passphrase to unlock the wallet. + 이 작업은 지갑을 열기위해 사용자의 지갑의 암호가 필요합니다. + + + + Unlock wallet + 지갑 열기 + + + + This operation needs your wallet passphrase to decrypt the wallet. + 이 작업은 지갑을 해독하기 위해 사용자의 지갑 암호가 필요합니다. + + + + Decrypt wallet + 지갑 해독 + + + + Change passphrase + 암호 변경 + + + + Enter the old and new passphrase to the wallet. + 지갑의 예전 암호와 새로운 암호를 입력 + + + + Confirm wallet encryption + 지갑의 암호화를 확정 + + + + Warning: If you encrypt your wallet and lose your passphrase, you will <b>LOSE ALL OF YOUR COINS</b>! + + + + + Are you sure you wish to encrypt your wallet? + 지갑 암호화를 허용하시겠습니까? + + + + IMPORTANT: Any previous backups you have made of your wallet file should be replaced with the newly generated, encrypted wallet file. For security reasons, previous backups of the unencrypted wallet file will become useless as soon as you start using the new, encrypted wallet. + + + + + + Warning: The Caps Lock key is on! + 경고: 캡스록 키가 켜져있습니다! + + + + + Wallet encrypted + 지갑 암호화 완료 + + + + Arepacoin will close now to finish the encryption process. Remember that encrypting your wallet cannot fully protect your coins from being stolen by malware infecting your computer. + + + + + + + + Wallet encryption failed + 지갑 암호화 실패 + + + + Wallet encryption failed due to an internal error. Your wallet was not encrypted. + 지갑 암호화는 내부 에러로 인해 실패했습니다. 당신의 지갑은 암호화 되지 않았습니다. + + + + + The supplied passphrases do not match. + 지정한 암호가 일치하지 않습니다. + + + + Wallet unlock failed + 지갑 열기를 실패하였습니다. + + + + + + The passphrase entered for the wallet decryption was incorrect. + 지갑 해독을 위한 암호가 틀렸습니다. + + + + Wallet decryption failed + 지갑 해독에 실패하였습니다. + + + + Wallet passphrase was successfully changed. + 지갑 비밀번호가 성공적으로 변경되었습니다 + + + + BitcoinGUI + + + Sign &message... + 메시지 서명&... + + + + Synchronizing with network... + 네트워크와 동기화중... + + + + &Overview + &개요 + + + + Show general overview of wallet + 지갑의 일반적 개요를 보여 줍니다. + + + + &Transactions + &거래 + + + + Browse transaction history + 거래내역을 검색합니다. + + + + &Address Book + + + + + Edit the list of stored addresses and labels + + + + + &Receive coins + + + + + Show the list of addresses for receiving payments + + + + + &Send coins + + + + + E&xit + 나가기(&X) + + + + Quit application + 적용 중단 + + + + Show information about Arepacoin + + + + + About &Qt + Qt 정보(&Q) + + + + Show information about Qt + Qt 정보를 표시합니다 + + + + &Options... + &옵션 + + + + &Encrypt Wallet... + 지갑 암호화&... + + + + &Backup Wallet... + 지갑 백업&... + + + + &Change Passphrase... + 암호문 변경&... + + + + ~%n block(s) remaining + + + + + Downloaded %1 of %2 blocks of transaction history (%3% done). + + + + + &Export... + + + + + Send coins to a Arepacoin address + + + + + Modify configuration options for Arepacoin + + + + + Export the data in the current tab to a file + + + + + Encrypt or decrypt wallet + + + + + Backup wallet to another location + 지갑을 다른장소에 백업 + + + + Change the passphrase used for wallet encryption + 지갑 암호화에 사용되는 암호를 변경합니다 + + + + &Debug window + 디버그 창& + + + + Open debugging and diagnostic console + 디버깅 및 진단 콘솔을 엽니다 + + + + &Verify message... + 메시지 확인&... + + + + Arepacoin + + + + + Wallet + 지갑 + + + + &About Arepacoin + + + + + &Show / Hide + 보이기/숨기기(&S) + + + + Unlock wallet + + + + + &Lock Wallet + + + + + Lock wallet + + + + + &File + &파일 + + + + &Settings + &설정 + + + + &Help + &도움말 + + + + Tabs toolbar + 툴바 색인표 + + + + Actions toolbar + + + + + + [testnet] + [테스트넷] + + + + + Arepacoin client + + + + + %n active connection(s) to Arepacoin network + + + + + Downloaded %1 blocks of transaction history. + + + + + Staking.<br>Your weight is %1<br>Network weight is %2<br>Expected time to earn reward is %3 + + + + + Not staking because wallet is locked + + + + + Not staking because wallet is offline + + + + + Not staking because wallet is syncing + + + + + Not staking because you don't have mature coins + + + + + %n second(s) ago + + + + + &Unlock Wallet... + + + + + %n minute(s) ago + + + + + %n hour(s) ago + + + + + %n day(s) ago + + + + + Up to date + 현재까지 + + + + Catching up... + 따라잡기... + + + + Last received block was generated %1. + + + + + This transaction is over the size limit. You can still send it for a fee of %1, which goes to the nodes that process your transaction and helps to support the network. Do you want to pay the fee? + + + + + Confirm transaction fee + + + + + Sent transaction + 거래 보내기 + + + + Incoming transaction + 거래 들어오는 중 + + + + Date: %1 +Amount: %2 +Type: %3 +Address: %4 + + 날짜: %1 +거래액: %2 +형식: %3 +주소: %4 + + + + + + URI handling + + + + + + URI can not be parsed! This can be caused by an invalid Arepacoin address or malformed URI parameters. + + + + + Wallet is <b>encrypted</b> and currently <b>unlocked</b> + 지갑이 암호화 되었고 현재 차단해제 되었습니다 + + + + Wallet is <b>encrypted</b> and currently <b>locked</b> + 지갑이 암호화 되었고 현재 잠겨져 있습니다 + + + + Backup Wallet + + + + + Wallet Data (*.dat) + + + + + Backup Failed + + + + + There was an error trying to save the wallet data to the new location. + + + + + %n second(s) + + + + + %n minute(s) + + + + + %n hour(s) + 시간 + + + + %n day(s) + + + + + Not staking + + + + + A fatal error occurred. Arepacoin can no longer continue safely and will quit. + + + + + ClientModel + + + Network Alert + 네트워크 경고 + + + + CoinControlDialog + + + Coin Control + + + + + Quantity: + 수량: + + + + Bytes: + Bytes: + + + + Amount: + 거래량 + + + + Priority: + 우선도: + + + + Fee: + 수수료: + + + + Low Output: + + + + + no + 아니요 + + + + After Fee: + 수수료 이후: + + + + Change: + + + + + (un)select all + + + + + Tree mode + 트리 모드 + + + + List mode + 리스트 모드 + + + + Amount + 거래량 + + + + Label + + + + + Address + 주소 + + + + Date + 날짜 + + + + Confirmations + 확인 + + + + Confirmed + 확인됨 + + + + Priority + 우선도 + + + + Copy address + 주소 복사하기 + + + + Copy label + 라벨 복사하기 + + + + + Copy amount + 거래액 복사 + + + + Copy transaction ID + 송금 ID 복사 + + + + Copy quantity + 수량 복사 + + + + Copy fee + 수수료 복사 + + + + Copy after fee + 수수료 이후 복사 + + + + Copy bytes + bytes를 복사 + + + + Copy priority + 우선도 복사 + + + + Copy low output + + + + + Copy change + + + + + highest + 최상 + + + + high + + + + + medium-high + 중상 + + + + medium + + + + + low-medium + 중하 + + + + low + + + + + lowest + + + + + DUST + + + + + yes + + + + + This label turns red, if the transaction size is bigger than 10000 bytes. + + This means a fee of at least %1 per kb is required. + + Can vary +/- 1 Byte per input. + + + + + Transactions with higher priority get more likely into a block. + +This label turns red, if the priority is smaller than "medium". + + This means a fee of at least %1 per kb is required. + + + + + This label turns red, if any recipient receives an amount smaller than %1. + + This means a fee of at least %2 is required. + + Amounts below 0.546 times the minimum relay fee are shown as DUST. + + + + + This label turns red, if the change is smaller than %1. + + This means a fee of at least %2 is required. + + + + + + (no label) + (표 없슴) + + + + change from %1 (%2) + ~로부터 변경 %1 (%2) + + + + (change) + + + + + EditAddressDialog + + + Edit Address + 주소 편집 + + + + &Label + &표 + + + + The label associated with this address book entry + + + + + &Address + &주소 + + + + The address associated with this address book entry. This can only be modified for sending addresses. + + + + + New receiving address + 새로 받는 주소 + + + + New sending address + 새로 보내는 주소 + + + + Edit receiving address + 받는 주소 편집 + + + + Edit sending address + 보내는 주소 편집 + + + + The entered address "%1" is already in the address book. + 입력된 주소는"%1" 이미 주소록에 있습니다. + + + + The entered address "%1" is not a valid Arepacoin address. + + + + + Could not unlock wallet. + 지갑을 열 수 없습니다. + + + + New key generation failed. + 새로운 키 생성이 실패하였습니다 + + + + GUIUtil::HelpMessageBox + + + + Arepacoin-Qt + + + + + version + + + + + Usage: + + + + + command-line options + + + + + UI options + + + + + Set language, for example "de_DE" (default: system locale) + + + + + Start minimized + + + + + Show splash screen on startup (default: 1) + + + + + OptionsDialog + + + Options + 선택들 + + + + &Main + 메인(&M) + + + + Optional transaction fee per kB that helps make sure your transactions are processed quickly. Most transactions are 1 kB. Fee 0.01 recommended. + + + + + Pay transaction &fee + 송금 수수료(&F) + + + + Reserved amount does not participate in staking and is therefore spendable at any time. + + + + + Reserve + + + + + Automatically start Arepacoin after logging in to the system. + + + + + &Start Arepacoin on system login + + + + + Detach block and address databases at shutdown. This means they can be moved to another data directory, but it slows down shutdown. The wallet is always detached. + + + + + &Detach databases at shutdown + + + + + &Network + 네트워크(&N) + + + + Automatically open the Arepacoin client port on the router. This only works when your router supports UPnP and it is enabled. + + + + + Map port using &UPnP + 사용중인 UPnP 포트 매핑(&U) + + + + Connect to the Arepacoin network through a SOCKS proxy (e.g. when connecting through Tor). + + + + + &Connect through SOCKS proxy: + + + + + Proxy &IP: + 프록시 IP(&I): + + + + IP address of the proxy (e.g. 127.0.0.1) + + + + + &Port: + 포트(&P): + + + + Port of the proxy (e.g. 9050) + 프록시의 포트번호입니다(예: 9050) + + + + SOCKS &Version: + SOCKS 버전(&V): + + + + SOCKS version of the proxy (e.g. 5) + 프록시의 SOCKS 버전입니다(예: 5) + + + + &Window + 창(&W) + + + + Show only a tray icon after minimizing the window. + 창을 최소화 하면 트레이에 아이콘만 표시합니다. + + + + &Minimize to the tray instead of the taskbar + 작업 표시줄 대신 트레이로 최소화(&M) + + + + Minimize instead of exit the application when the window is closed. When this option is enabled, the application will be closed only after selecting Quit in the menu. + 창을 닫으면 프로그램에서 나가지 않고 최소화합니다. 이 옵션을 활성화하면, 프로그램은 메뉴에서 나가기를 선택한 후에만 닫힙니다. + + + + M&inimize on close + 닫을때 최소화(&I) + + + + &Display + 표시(&D) + + + + User Interface &language: + 사용자 인터페이스 언어(&L): + + + + The user interface language can be set here. This setting will take effect after restarting Arepacoin. + + + + + &Unit to show amounts in: + 거래액을 표시할 단위(&U): + + + + Choose the default subdivision unit to show in the interface and when sending coins. + 인터페이스에 표시하고 코인을 보낼때 사용할 기본 최소화 단위를 선택하십시오. + + + + Whether to show Arepacoin addresses in the transaction list or not. + + + + + &Display addresses in transaction list + 송금 목록에 주소 표시(&D) + + + + Whether to show coin control features or not. + + + + + Display coin &control features (experts only!) + + + + + &OK + 확인(&O) + + + + &Cancel + 취소(&C) + + + + &Apply + + + + + default + 기본값 + + + + + Warning + + + + + + This setting will take effect after restarting Arepacoin. + + + + + The supplied proxy address is invalid. + 지정한 프록시 주소가 잘못되었습니다. + + + + OverviewPage + + + Form + 유형 + + + + + The displayed information may be out of date. Your wallet automatically synchronizes with the Arepacoin network after a connection is established, but this process has not completed yet. + + + + + Stake: + + + + + Unconfirmed: + + + + + Wallet + 지갑 + + + + Spendable: + + + + + Your current spendable balance + 당신의 현재 사용 가능한 잔액 + + + + Immature: + 아직 사용 불가능: + + + + Mined balance that has not yet matured + 아직 사용 가능하지 않은 채굴된 잔액 + + + + Total: + 총액: + + + + Your current total balance + 당신의 현재 총액 + + + + <b>Recent transactions</b> + <b>최근 거래내역</b> + + + + Total of transactions that have yet to be confirmed, and do not yet count toward the current balance + + + + + Total of coins that was staked, and do not yet count toward the current balance + + + + + + out of sync + 오래됨 + + + + QRCodeDialog + + + QR Code Dialog + + + + + Request Payment + + + + + Amount: + + + + + Label: + + + + + Message: + + + + + &Save As... + + + + + Error encoding URI into QR Code. + + + + + The entered amount is invalid, please check. + + + + + Resulting URI too long, try to reduce the text for label / message. + + + + + Save QR Code + + + + + PNG Images (*.png) + + + + + RPCConsole + + + Client name + 클라이언트 이름 + + + + + + + + + + + + + N/A + 없음 + + + + Client version + 클라이언트 버전 + + + + &Information + 정보& + + + + Using OpenSSL version + 오픈SSL 버전을 사용합니다 + + + + Startup time + 시작 시간 + + + + Network + 네트워크 + + + + Number of connections + 연결 수 + + + + On testnet + + + + + Block chain + 블럭 체인 + + + + Current number of blocks + 현재 블럭 수 + + + + Estimated total blocks + 예상 전체 블럭 + + + + Last block time + 최종 블럭 시각 + + + + &Open + 열기(&O) + + + + Command-line options + + + + + Show the Arepacoin-Qt help message to get a list with possible Arepacoin command-line options. + + + + + &Show + + + + + &Console + 콘솔(&C) + + + + Build date + 빌드 날짜 + + + + Arepacoin - Debug window + + + + + Arepacoin Core + + + + + Debug log file + 로그 파일 디버그 + + + + Open the Arepacoin debug log file from the current data directory. This can take a few seconds for large log files. + + + + + Clear console + 콘솔 초기화 + + + + Welcome to the Arepacoin RPC console. + + + + + Use up and down arrows to navigate history, and <b>Ctrl-L</b> to clear screen. + 기록을 찾아보려면 위 아래 화살표 키를, 화면을 지우려면 <b>Ctrl-L</b>키를 사용하십시오. + + + + Type <b>help</b> for an overview of available commands. + 사용할 수 있는 명령을 둘러보려면 <b>help</b>를 입력하십시오. + + + + SendCoinsDialog + + + + + + + + + + Send Coins + 코인들 보내기 + + + + Coin Control Features + 코인 컨트롤 기능들 + + + + Inputs... + + + + + automatically selected + 자동 선택 + + + + Insufficient funds! + 자금이 부족합니다! + + + + Quantity: + 수량: + + + + + 0 + + + + + Bytes: + Bytes: + + + + Amount: + 거래량: + + + + + + + 0.00 BC + + + + + Priority: + 우선도: + + + + medium + + + + + Fee: + 수수료: + + + + Low Output: + + + + + no + + + + + After Fee: + 수수료 이후: + + + + Change + + + + + custom change address + + + + + Send to multiple recipients at once + 다수의 수령인들에게 한번에 보내기 + + + + Add &Recipient + 수령인 추가하기 + + + + Remove all transaction fields + + + + + Clear &All + 모두 지우기(&A) + + + + Balance: + 잔액: + + + + 123.456 BC + + + + + Confirm the send action + 전송 기능 확인 + + + + S&end + 보내기(&E) + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Copy quantity + 수량 복사 + + + + Copy amount + 거래액 복사 + + + + Copy fee + 수수료 복사 + + + + Copy after fee + 수수료 이후 복사 + + + + Copy bytes + bytes 복사 + + + + Copy priority + 우선도 복사 + + + + Copy low output + + + + + Copy change + + + + + <b>%1</b> to %2 (%3) + + + + + Confirm send coins + 코인 전송을 확인 + + + + Are you sure you want to send %1? + + + + + and + + + + + The recipient address is not valid, please recheck. + 수령인 주소가 정확하지 않습니다. 재확인 바랍니다 + + + + The amount to pay must be larger than 0. + 지불하는 금액은 0 보다 커야 합니다. + + + + The amount exceeds your balance. + 잔고를 초과하였습니다. + + + + The total exceeds your balance when the %1 transaction fee is included. + %1 의 거래수수료를 포함하면 잔고를 초과합니다. + + + + Duplicate address found, can only send to each address once per send operation. + 두개 이상의 주소입니다. 한번에 하나의 주소에만 작업할 수 있습니다. + + + + Error: Transaction creation failed. + + + + + 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. + + + + + WARNING: Invalid Arepacoin address + + + + + (no label) + (표 없슴) + + + + WARNING: unknown change address + + + + + SendCoinsEntry + + + Form + + + + + A&mount: + 금액: + + + + Pay &To: + 지급&수신: + + + + + Enter a label for this address to add it to your address book + 당신의 주소록에 이 주소를 추가하기 위하여 표를 입역하세요 + + + + &Label: + 표: + + + + The address to send the payment to (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Choose address from address book + + + + + Alt+A + Alt+A + + + + Paste address from clipboard + 클립보드로 부터 주소를 붙이세요 + + + + Alt+P + Alt+P + + + + Remove this recipient + + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + SignVerifyMessageDialog + + + Signatures - Sign / Verify a Message + 서명 - 싸인 / 메시지 확인 + + + + + &Sign Message + 메시지 서명(&S) + + + + You can sign messages with your addresses to prove you own them. Be careful not to sign anything vague, as phishing attacks may try to trick you into signing your identity over to them. Only sign fully-detailed statements you agree to. + 여러분 자신을 증명하기 위해 주소를 첨가하고 섬여할 수 있습니다. 피싱 공격으로 말미암아 여러분의 서명을 통해 속아 넘어가게 할 수 있으므로, 서명하지 않은 어떤 모호한 요소든 주의하십시오. 동의하는 완전 무결한 조항에만 서명하십시오. + + + + The address to sign the message with (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + + Choose an address from the address book + + + + + + Alt+A + Alt+A + + + + Paste address from clipboard + 클립보드로 부터 주소를 붙이세요 + + + + Alt+P + Alt+P + + + + Enter the message you want to sign here + 여기에 서명하려는 메시지를 입력하십시오 + + + + Copy the current signature to the system clipboard + 현재 서명을 시스템 클립보드에 복사 + + + + Sign the message to prove you own this Arepacoin address + + + + + Reset all sign message fields + 메시지 필드의 모든 서명 재설정 + + + + + Clear &All + 모두 지우기(&A) + + + + + &Verify Message + 메시지 검증(&V) + + + + Enter the signing address, message (ensure you copy line breaks, spaces, tabs, etc. exactly) and signature below to verify the message. Be careful not to read more into the signature than what is in the signed message itself, to avoid being tricked by a man-in-the-middle attack. + + + + + The address the message was signed with (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Verify the message to ensure it was signed with the specified Arepacoin address + + + + + Reset all verify message fields + 모든 검증 메시지 필드 재설정 + + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Click "Sign Message" to generate signature + 서명을 만들려면 "메시지 서명"을 누르십시오 + + + + Enter Arepacoin signature + + + + + + The entered address is invalid. + 입력한 주소가 잘못되었습니다. + + + + + + + Please check the address and try again. + 주소를 확인하고 다시 시도하십시오. + + + + + The entered address does not refer to a key. + 입력한 주소는 키에서 참조하지 않습니다. + + + + Wallet unlock was cancelled. + 지갑 잠금 해제를 취소했습니다. + + + + Private key for the entered address is not available. + 입력한 주소에 대한 개인키가 없습니다. + + + + Message signing failed. + 메시지 서명에 실패했습니다. + + + + Message signed. + 메시지를 서명했습니다. + + + + The signature could not be decoded. + 서명을 해독할 수 없습니다. + + + + + Please check the signature and try again. + 서명을 확인하고 다시 시도하십시오. + + + + The signature did not match the message digest. + 메시지 다이제스트와 서명이 일치하지 않습니다. + + + + Message verification failed. + 메시지 검증에 실패했습니다. + + + + Message verified. + 메시지를 검증했습니다. + + + + TransactionDesc + + + Open until %1 + %1 까지 열림 + + + + Open for %n block(s) + + + + + conflicted + 충돌 + + + + %1/offline + %1/오프라인 + + + + %1/unconfirmed + %1/미확인 + + + + %1 confirmations + %1 확인됨 + + + + Status + 상태 + + + + , broadcast through %n node(s) + + + + + Date + 날짜 + + + + Source + 소스 + + + + Generated + 생성하다 + + + + + From + 으로부터 + + + + + + To + 에게 + + + + + own address + 자신의 주소 + + + + label + 라벨 + + + + + + + + Credit + 예금 + + + + matures in %n more block(s) + + + + + not accepted + 허용되지 않는다 + + + + + + + Debit + 차변 + + + + Transaction fee + 송금 수수료 + + + + Net amount + 총액 + + + + Message + 메시지 + + + + Comment + 설명 + + + + Transaction ID + 송금 ID + + + + Generated coins must mature 6 blocks before they can be spent. When you generated this block, it was broadcast to the network to be added to the block chain. If it fails to get into the chain, its state will change to "not accepted" and it won't be spendable. This may occasionally happen if another node generates a block within a few seconds of yours. + + + + + Debug information + 디버깅 정보 + + + + Transaction + 송금 + + + + Inputs + 입력 + + + + Amount + 거래량 + + + + true + + + + + false + 거짓 + + + + , has not been successfully broadcast yet + . 아직 성공적으로 통보하지 않음 + + + + unknown + 알수없음 + + + + TransactionDescDialog + + + Transaction details + 거래 세부 내역 + + + + This pane shows a detailed description of the transaction + 이 창은 거래의 세부내역을 보여줍니다 + + + + TransactionTableModel + + + Date + 날짜 + + + + Type + 형식 + + + + Address + 주소 + + + + Amount + 수량 + + + + Open until %1 + %1 까지 열림 + + + + Confirmed (%1 confirmations) + 확인됨(%1 확인됨) + + + + Open for %n more block(s) + + + + + Offline + 오프라인 + + + + Unconfirmed + 미확인 + + + + Confirming (%1 of %2 recommended confirmations) + + + + + Conflicted + 충돌 + + + + Immature (%1 confirmations, will be available after %2) + + + + + This block was not received by any other nodes and will probably not be accepted! + 이 블럭은 다른 노드로부터 받지 않아 허용되지 않을 것임. + + + + Generated but not accepted + 생성되었으나 거절됨 + + + + Received with + 다음과 함께 받음 : + + + + Received from + 보낸 주소 + + + + Sent to + 다음에게 보냄 : + + + + Payment to yourself + 자신에게 지불 + + + + Mined + 채굴됨 + + + + (n/a) + (없음) + + + + Transaction status. Hover over this field to show number of confirmations. + 거래상황. 마우스를 올리면 승인횟수가 표시됩니다. + + + + Date and time that the transaction was received. + 거래가 이루어진 날짜와 시각. + + + + Type of transaction. + 거래의 종류. + + + + Destination address of transaction. + 거래가 도달할 주소 + + + + Amount removed from or added to balance. + 변경된 잔고. + + + + TransactionView + + + + All + 전체 + + + + Today + 오늘 + + + + This week + 이번주 + + + + This month + 이번 달 + + + + Last month + 지난 달 + + + + This year + 올 해 + + + + Range... + 범위... + + + + Received with + 보낸 주소 + + + + Sent to + 받는 주소 + + + + To yourself + 자기거래 + + + + Mined + 채굴 + + + + Other + 기타 + + + + Enter address or label to search + 검색하기 위한 주소 또는 표 입력 + + + + Min amount + 최소 거래량 + + + + Copy address + 주소 복사하기 + + + + Copy label + 표 복사하기 + + + + Copy amount + 거래액 복사 + + + + Copy transaction ID + 송금 ID 복사 + + + + Edit label + 표 수정하기 + + + + Show transaction details + 거래 내역 확인 + + + + Export Transaction Data + + + + + Comma separated file (*.csv) + 각각의 파일에 쉼표하기(*.csv) + + + + Confirmed + 확인됨 + + + + Date + 날짜 + + + + Type + 종류 + + + + Label + + + + + Address + 주소 + + + + Amount + 거래량 + + + + ID + 아이디 + + + + Error exporting + + + + + Could not write to file %1. + + + + + Range: + 범위: + + + + to + 상대방 + + + + WalletModel + + + Sending... + + + + + bitcoin-core + + + Arepacoin version + + + + + Usage: + 사용법: + + + + Send command to -server or arepacoind + + + + + List commands + 커맨드 목록 + + + + Get help for a command + 커맨드 도움말 + + + + Options: + 옵션: + + + + Specify configuration file (default: arepacoin.conf) + + + + + Specify pid file (default: arepacoind.pid) + + + + + Specify wallet file (within data directory) + 데이터 폴더 안에 지갑 파일을 선택하세요. + + + + Specify data directory + 데이터 폴더 지정 + + + + Set database cache size in megabytes (default: 25) + 데이터베이스 캐시 크기를 메가바이트로 지정(기본값:25) + + + + Set database disk log size in megabytes (default: 100) + + + + + Listen for connections on <port> (default: 9853 or testnet: 19853) + + + + + Maintain at most <n> connections to peers (default: 125) + 가장 잘 연결되는 사용자를 유지합니다(기본값: 125) + + + + Connect to a node to retrieve peer addresses, and disconnect + 피어 주소를 받기 위해 노드에 연결하고, 받은 후에 연결을 끊습니다 + + + + Specify your own public address + 공인 주소를 지정하십시오 + + + + Bind to given address. Use [host]:port notation for IPv6 + + + + + Stake your coins to support network and gain reward (default: 1) + + + + + Threshold for disconnecting misbehaving peers (default: 100) + 이상행동 네트워크 참여자의 연결을 차단시키기 위한 한계치 (기본값: 100) + + + + Number of seconds to keep misbehaving peers from reconnecting (default: 86400) + 이상행동을 하는 네트워크 참여자들을 다시 연결시키는데 걸리는 시간 (기본값: 86400초) + + + + An error occurred while setting up the RPC port %u for listening on IPv4: %s + IPv4 감청을 위한 RPC 포트 %u번을 설정중 오류가 발생했습니다: %s + + + + Detach block and address databases. Increases shutdown time (default: 0) + + + + + 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. + + + + + Error: This transaction requires a transaction fee of at least %s because of its amount, complexity, or use of recently received funds + + + + + Listen for JSON-RPC connections on <port> (default: 9852 or testnet: 19852) + + + + + Accept command line and JSON-RPC commands + 명령줄과 JSON-RPC 명령 수락 + + + + Error: Transaction creation failed + + + + + Error: Wallet locked, unable to create transaction + + + + + Importing blockchain data file. + + + + + Importing bootstrap blockchain data file. + + + + + Run in the background as a daemon and accept commands + 데몬으로 백그라운드에서 실행하고 명령을 허용 + + + + Use the test network + 테스트 네트워크 사용 + + + + Accept connections from outside (default: 1 if no -proxy or -connect) + 외부 접속을 승인합니다 + + + + An error occurred while setting up the RPC port %u for listening on IPv6, falling back to IPv4: %s + + + + + Error initializing database environment %s! To recover, BACKUP THAT DIRECTORY, then remove everything from it except for wallet.dat. + + + + + Set maximum size of high-priority/low-fee transactions in bytes (default: 27000) + + + + + Warning: -paytxfee is set very high! This is the transaction fee you will pay if you send a transaction. + 경고: -paytxfee값이 너무 큽니다! 이 값은 송금할때 지불할 송금 수수료입니다. + + + + Warning: Please check that your computer's date and time are correct! If your clock is wrong Arepacoin will not work properly. + + + + + Warning: error reading wallet.dat! All keys read correctly, but transaction data or address book entries might be missing or incorrect. + + + + + Warning: wallet.dat corrupt, data salvaged! Original wallet.dat saved as wallet.{timestamp}.bak in %s; if your balance or transactions are incorrect you should restore from a backup. + + + + + Attempt to recover private keys from a corrupt wallet.dat + 손상된 wallet.dat에서 개인키 복원을 시도합니다 + + + + Block creation options: + 블록 생성 옵션: + + + + Connect only to the specified node(s) + 지정된 노드에만 연결하기 + + + + Discover own IP address (default: 1 when listening and no -externalip) + + + + + Failed to listen on any port. Use -listen=0 if you want this. + + + + + Find peers using DNS lookup (default: 1) + + + + + Sync checkpoints policy (default: strict) + + + + + Invalid -tor address: '%s' + + + + + Invalid amount for -reservebalance=<amount> + + + + + Maximum per-connection receive buffer, <n>*1000 bytes (default: 5000) + + + + + Maximum per-connection send buffer, <n>*1000 bytes (default: 1000) + + + + + Only connect to nodes in network <net> (IPv4, IPv6 or Tor) + + + + + Output extra debugging information. Implies all other -debug* options + + + + + Output extra network debugging information + + + + + Prepend debug output with timestamp + + + + + SSL options: (see the Bitcoin Wiki for SSL setup instructions) + SSL 옵션: (SSL 설정 절차를 보혀면 비트코인 위키를 참조하십시오) + + + + Select the version of socks proxy to use (4-5, default: 5) + + + + + Send trace/debug info to console instead of debug.log file + 추적오류 정보를 degug.log 자료로 보내는 대신 콘솔로 보내기 + + + + Send trace/debug info to debugger + + + + + Set maximum block size in bytes (default: 250000) + + + + + Set minimum block size in bytes (default: 0) + 바이트 단위의 최소 블록 크기 설정(기본값: 0) + + + + Shrink debug.log file on client startup (default: 1 when no -debug) + 클라이언트 시작시 debug.log 파일 비우기(기본값: 디버그 안할때 1) + + + + Specify connection timeout in milliseconds (default: 5000) + 밀리초 단위로 연결 제한시간을 설정하십시오(기본값: 5000) + + + + Unable to sign checkpoint, wrong checkpointkey? + + + + + + Use UPnP to map the listening port (default: 0) + + + + + Use UPnP to map the listening port (default: 1 when listening) + + + + + Use proxy to reach tor hidden services (default: same as -proxy) + + + + + Username for JSON-RPC connections + JSON-RPC 연결에 사용할 사용자 이름 + + + + Verifying database integrity... + + + + + WARNING: syncronized checkpoint violation detected, but skipped! + + + + + Warning: Disk space is low! + + + + + Warning: This version is obsolete, upgrade required! + 경고: 이 버전이 오래되어 업그레이드가 필요합니다! + + + + wallet.dat corrupt, salvage failed + wallet.dat 파일이 손상되었고 복구가 실패하였습니다. + + + + Password for JSON-RPC connections + JSON-RPC 연결에 사용할 암호 + + + + %s, you must set a rpcpassword in the configuration file: + %s +It is recommended you use the following random password: +rpcuser=arepacoinrpc +rpcpassword=%s +(you do not need to remember this password) +The username and password MUST NOT be the same. +If the file does not exist, create it with owner-readable-only file permissions. +It is also recommended to set alertnotify so you are notified of problems; +for example: alertnotify=echo %%s | mail -s "Arepacoin Alert" admin@foo.com + + + + + + Find peers using internet relay chat (default: 0) + + + + + Sync time with other nodes. Disable if time on your system is precise e.g. syncing with NTP (default: 1) + + + + + When creating transactions, ignore inputs with value less than this (default: 0.01) + + + + + Allow JSON-RPC connections from specified IP address + 지정한 IP 주소의 JSON-RPC 연결 허용 + + + + Send commands to node running on <ip> (default: 127.0.0.1) + 실행 중인 노드로 명령 전송 <ip> (기본값: 127.0.0.1) + + + + Execute command when the best block changes (%s in cmd is replaced by block hash) + 최고의 블럭이 변하면 명령을 실행(cmd 에 있는 %s 는 블럭 해시에 의해 대체되어 짐) + + + + Execute command when a wallet transaction changes (%s in cmd is replaced by TxID) + + + + + Require a confirmations for change (default: 0) + + + + + Enforce transaction scripts to use canonical PUSH operators (default: 1) + + + + + Execute command when a relevant alert is received (%s in cmd is replaced by message) + + + + + Upgrade wallet to latest format + 지갑을 최근 형식으로 개선하시오 + + + + Set key pool size to <n> (default: 100) + 키 풀 크기 설정 <n>(기본값: 100) + + + + Rescan the block chain for missing wallet transactions + 누락된 지갑 송금에 대한 블록 체인 다시 검색 + + + + How many blocks to check at startup (default: 2500, 0 = all) + + + + + How thorough the block verification is (0-6, default: 1) + + + + + Imports blocks from external blk000?.dat file + + + + + Use OpenSSL (https) for JSON-RPC connections + JSON-RPC 연결에 OpenSSL(https) 사용 + + + + Server certificate file (default: server.cert) + 서버 인증 파일 (기본값: server.cert) + + + + Server private key (default: server.pem) + 서버 개인 키(기본값: server.pem) + + + + Acceptable ciphers (default: TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH) + + + + + Error: Wallet unlocked for staking only, unable to create transaction. + + + + + WARNING: Invalid checkpoint found! Displayed transactions may not be correct! You may need to upgrade, or notify developers. + + + + + This help message + 도움말 메시지입니다 + + + + Wallet %s resides outside data directory %s. + + + + + Cannot obtain a lock on data directory %s. Arepacoin is probably already running. + + + + + Arepacoin + + + + + Unable to bind to %s on this computer (bind returned error %d, %s) + 이 컴퓨터의 %s에 바인딩할 수 없습니다 (바인딩 과정에 %d 오류 발생, %s) + + + + Connect through socks proxy + + + + + Allow DNS lookups for -addnode, -seednode and -connect + -addnode, -seednode, -connect 옵션에 대해 DNS 탐색 허용 + + + + Loading addresses... + 주소를 불러오는 중... + + + + Error loading blkindex.dat + + + + + Error loading wallet.dat: Wallet corrupted + wallet.dat 불러오기 에러: 지갑 오류 + + + + Error loading wallet.dat: Wallet requires newer version of Arepacoin + + + + + Wallet needed to be rewritten: restart Arepacoin to complete + + + + + Error loading wallet.dat + wallet.dat 불러오기 에러 + + + + Invalid -proxy address: '%s' + 잘못된 -proxy 주소입니다: '%s' + + + + Unknown network specified in -onlynet: '%s' + -onlynet에 지정한 네트워크를 알 수 없습니다: '%s' + + + + Unknown -socks proxy version requested: %i + 요청한 -socks 프록히 버전을 알 수 없습니다: %i + + + + Cannot resolve -bind address: '%s' + -bind 주소를 확인할 수 없습니다: '%s' + + + + Cannot resolve -externalip address: '%s' + -externalip 주소를 확인할 수 없습니다: '%s' + + + + Invalid amount for -paytxfee=<amount>: '%s' + -paytxfee=<amount>에 대한 양이 잘못되었습니다: '%s' + + + + Error: could not start node + + + + + Sending... + + + + + Invalid amount + 효력없는 금액 + + + + Insufficient funds + 자금 부족 + + + + Loading block index... + 블럭 인덱스를 불러오는 중... + + + + Add a node to connect to and attempt to keep the connection open + + + + + Unable to bind to %s on this computer. Arepacoin is probably already running. + + + + + Fee per KB to add to transactions you send + + + + + Invalid amount for -mininput=<amount>: '%s' + + + + + Loading wallet... + 지갑을 불러오는 중... + + + + Cannot downgrade wallet + 지갑을 다운그레이드 할 수 없습니다 + + + + Cannot initialize keypool + + + + + Cannot write default address + 기본 계좌에 기록할 수 없습니다 + + + + Rescanning... + 재검색 중... + + + + Done loading + 로딩 완료 + + + + To use the %s option + %s 옵션을 사용하려면 + + + + Error + 오류 + + + + You must set rpcpassword=<password> in the configuration file: +%s +If the file does not exist, create it with owner-readable-only file permissions. + 설정 파일에 rpcpassword=<암호>를 설정해야 합니다: +%s +파일이 없으면 소유자 읽기 전용 파일 권한으로 만들어야 합니다. + + + \ No newline at end of file diff --git a/src/qt/locale/bitcoin_ky.ts b/src/qt/locale/bitcoin_ky.ts new file mode 100755 index 0000000..3cde91d --- /dev/null +++ b/src/qt/locale/bitcoin_ky.ts @@ -0,0 +1,3275 @@ + + + AboutDialog + + + About Arepacoin + + + + + <b>Arepacoin</b> version + + + + + Copyright © 2009-2014 The Bitcoin developers +Copyright © 2012-2014 The NovaCoin developers +Copyright © 2014 The Arepacoin developers + + + + + +This is experimental software. + +Distributed under the MIT/X11 software license, see the accompanying file COPYING or http://www.opensource.org/licenses/mit-license.php. + +This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit (http://www.openssl.org/) and cryptographic software written by Eric Young (eay@cryptsoft.com) and UPnP software written by Thomas Bernard. + + + + + AddressBookPage + + + Address Book + + + + + Double-click to edit address or label + + + + + Create a new address + Жаң даректи жасоо + + + + Copy the currently selected address to the system clipboard + + + + + &New Address + + + + + These are your Arepacoin addresses for receiving payments. You may want to give a different one to each sender so you can keep track of who is paying you. + + + + + &Copy Address + + + + + Show &QR Code + + + + + Sign a message to prove you own a Arepacoin address + + + + + Sign &Message + + + + + Delete the currently selected address from the list + + + + + Verify a message to ensure it was signed with a specified Arepacoin address + + + + + &Verify Message + + + + + &Delete + Ө&чүрүү + + + + Copy &Label + + + + + &Edit + + + + + Export Address Book Data + + + + + Comma separated file (*.csv) + + + + + Error exporting + + + + + Could not write to file %1. + + + + + AddressTableModel + + + Label + + + + + Address + Дарек + + + + (no label) + (аты жок) + + + + AskPassphraseDialog + + + Passphrase Dialog + + + + + Enter passphrase + + + + + New passphrase + + + + + Repeat new passphrase + + + + + Serves to disable the trivial sendmoney when OS account compromised. Provides no real security. + + + + + For staking only + + + + + Enter the new passphrase to the wallet.<br/>Please use a passphrase of <b>10 or more random characters</b>, or <b>eight or more words</b>. + + + + + Encrypt wallet + + + + + This operation needs your wallet passphrase to unlock the wallet. + + + + + Unlock wallet + + + + + This operation needs your wallet passphrase to decrypt the wallet. + + + + + Decrypt wallet + + + + + Change passphrase + + + + + Enter the old and new passphrase to the wallet. + + + + + Confirm wallet encryption + + + + + Warning: If you encrypt your wallet and lose your passphrase, you will <b>LOSE ALL OF YOUR COINS</b>! + + + + + Are you sure you wish to encrypt your wallet? + + + + + IMPORTANT: Any previous backups you have made of your wallet file should be replaced with the newly generated, encrypted wallet file. For security reasons, previous backups of the unencrypted wallet file will become useless as soon as you start using the new, encrypted wallet. + + + + + + Warning: The Caps Lock key is on! + + + + + + Wallet encrypted + + + + + Arepacoin will close now to finish the encryption process. Remember that encrypting your wallet cannot fully protect your coins from being stolen by malware infecting your computer. + + + + + + + + Wallet encryption failed + + + + + Wallet encryption failed due to an internal error. Your wallet was not encrypted. + + + + + + The supplied passphrases do not match. + + + + + Wallet unlock failed + + + + + + + The passphrase entered for the wallet decryption was incorrect. + + + + + Wallet decryption failed + + + + + Wallet passphrase was successfully changed. + + + + + BitcoinGUI + + + Sign &message... + + + + + Synchronizing with network... + + + + + &Overview + + + + + Show general overview of wallet + + + + + &Transactions + &Транзакциялар + + + + Browse transaction history + + + + + &Address Book + + + + + Edit the list of stored addresses and labels + + + + + &Receive coins + + + + + Show the list of addresses for receiving payments + + + + + &Send coins + + + + + E&xit + + + + + Quit application + + + + + Show information about Arepacoin + + + + + About &Qt + + + + + Show information about Qt + + + + + &Options... + + + + + &Encrypt Wallet... + + + + + &Backup Wallet... + + + + + &Change Passphrase... + + + + + ~%n block(s) remaining + + + + + Downloaded %1 of %2 blocks of transaction history (%3% done). + + + + + &Export... + + + + + Send coins to a Arepacoin address + + + + + Modify configuration options for Arepacoin + + + + + Export the data in the current tab to a file + + + + + Encrypt or decrypt wallet + + + + + Backup wallet to another location + + + + + Change the passphrase used for wallet encryption + + + + + &Debug window + + + + + Open debugging and diagnostic console + + + + + &Verify message... + Билдирүүнү &текшерүү... + + + + Arepacoin + + + + + Wallet + Капчык + + + + &About Arepacoin + + + + + &Show / Hide + + + + + Unlock wallet + + + + + &Lock Wallet + + + + + Lock wallet + + + + + &File + &Файл + + + + &Settings + + + + + &Help + &Жардам + + + + Tabs toolbar + + + + + Actions toolbar + + + + + + [testnet] + + + + + + Arepacoin client + + + + + %n active connection(s) to Arepacoin network + + + + + Downloaded %1 blocks of transaction history. + + + + + Staking.<br>Your weight is %1<br>Network weight is %2<br>Expected time to earn reward is %3 + + + + + Not staking because wallet is locked + + + + + Not staking because wallet is offline + + + + + Not staking because wallet is syncing + + + + + Not staking because you don't have mature coins + + + + + %n second(s) ago + + + + + &Unlock Wallet... + + + + + %n minute(s) ago + + + + + %n hour(s) ago + + + + + %n day(s) ago + + + + + Up to date + Жаңыланган + + + + Catching up... + + + + + Last received block was generated %1. + + + + + This transaction is over the size limit. You can still send it for a fee of %1, which goes to the nodes that process your transaction and helps to support the network. Do you want to pay the fee? + + + + + Confirm transaction fee + + + + + Sent transaction + + + + + Incoming transaction + + + + + Date: %1 +Amount: %2 +Type: %3 +Address: %4 + + + + + + + URI handling + + + + + + URI can not be parsed! This can be caused by an invalid Arepacoin address or malformed URI parameters. + + + + + Wallet is <b>encrypted</b> and currently <b>unlocked</b> + + + + + Wallet is <b>encrypted</b> and currently <b>locked</b> + + + + + Backup Wallet + + + + + Wallet Data (*.dat) + + + + + Backup Failed + + + + + There was an error trying to save the wallet data to the new location. + + + + + %n second(s) + + + + + %n minute(s) + + + + + %n hour(s) + + + + + %n day(s) + + + + + Not staking + + + + + A fatal error occurred. Arepacoin can no longer continue safely and will quit. + + + + + ClientModel + + + Network Alert + + + + + CoinControlDialog + + + Coin Control + + + + + Quantity: + + + + + Bytes: + + + + + Amount: + + + + + Priority: + + + + + Fee: + + + + + Low Output: + + + + + no + + + + + After Fee: + + + + + Change: + + + + + (un)select all + + + + + Tree mode + + + + + List mode + + + + + Amount + + + + + Label + + + + + Address + Дарек + + + + Date + Дата + + + + Confirmations + + + + + Confirmed + + + + + Priority + + + + + Copy address + + + + + Copy label + + + + + + Copy amount + + + + + Copy transaction ID + + + + + Copy quantity + + + + + Copy fee + + + + + Copy after fee + + + + + Copy bytes + + + + + Copy priority + + + + + Copy low output + + + + + Copy change + + + + + highest + + + + + high + + + + + medium-high + + + + + medium + + + + + low-medium + + + + + low + + + + + lowest + + + + + DUST + + + + + yes + + + + + This label turns red, if the transaction size is bigger than 10000 bytes. + + This means a fee of at least %1 per kb is required. + + Can vary +/- 1 Byte per input. + + + + + Transactions with higher priority get more likely into a block. + +This label turns red, if the priority is smaller than "medium". + + This means a fee of at least %1 per kb is required. + + + + + This label turns red, if any recipient receives an amount smaller than %1. + + This means a fee of at least %2 is required. + + Amounts below 0.546 times the minimum relay fee are shown as DUST. + + + + + This label turns red, if the change is smaller than %1. + + This means a fee of at least %2 is required. + + + + + + (no label) + (аты жок) + + + + change from %1 (%2) + + + + + (change) + + + + + EditAddressDialog + + + Edit Address + + + + + &Label + + + + + The label associated with this address book entry + + + + + &Address + &Дарек + + + + The address associated with this address book entry. This can only be modified for sending addresses. + + + + + New receiving address + + + + + New sending address + + + + + Edit receiving address + + + + + Edit sending address + + + + + The entered address "%1" is already in the address book. + + + + + The entered address "%1" is not a valid Arepacoin address. + + + + + Could not unlock wallet. + + + + + New key generation failed. + + + + + GUIUtil::HelpMessageBox + + + + Arepacoin-Qt + + + + + version + + + + + Usage: + + + + + command-line options + + + + + UI options + + + + + Set language, for example "de_DE" (default: system locale) + + + + + Start minimized + + + + + Show splash screen on startup (default: 1) + + + + + OptionsDialog + + + Options + + + + + &Main + + + + + Optional transaction fee per kB that helps make sure your transactions are processed quickly. Most transactions are 1 kB. Fee 0.01 recommended. + + + + + Pay transaction &fee + + + + + Reserved amount does not participate in staking and is therefore spendable at any time. + + + + + Reserve + + + + + Automatically start Arepacoin after logging in to the system. + + + + + &Start Arepacoin on system login + + + + + Detach block and address databases at shutdown. This means they can be moved to another data directory, but it slows down shutdown. The wallet is always detached. + + + + + &Detach databases at shutdown + + + + + &Network + &Тармак + + + + Automatically open the Arepacoin client port on the router. This only works when your router supports UPnP and it is enabled. + + + + + Map port using &UPnP + + + + + Connect to the Arepacoin network through a SOCKS proxy (e.g. when connecting through Tor). + + + + + &Connect through SOCKS proxy: + + + + + Proxy &IP: + + + + + IP address of the proxy (e.g. 127.0.0.1) + + + + + &Port: + &Порт: + + + + Port of the proxy (e.g. 9050) + + + + + SOCKS &Version: + + + + + SOCKS version of the proxy (e.g. 5) + + + + + &Window + &Терезе + + + + Show only a tray icon after minimizing the window. + + + + + &Minimize to the tray instead of the taskbar + + + + + Minimize instead of exit the application when the window is closed. When this option is enabled, the application will be closed only after selecting Quit in the menu. + + + + + M&inimize on close + + + + + &Display + + + + + User Interface &language: + + + + + The user interface language can be set here. This setting will take effect after restarting Arepacoin. + + + + + &Unit to show amounts in: + + + + + Choose the default subdivision unit to show in the interface and when sending coins. + + + + + Whether to show Arepacoin addresses in the transaction list or not. + + + + + &Display addresses in transaction list + + + + + Whether to show coin control features or not. + + + + + Display coin &control features (experts only!) + + + + + &OK + &Жарайт + + + + &Cancel + &Жокко чыгаруу + + + + &Apply + + + + + default + жарыяланбаган + + + + + Warning + + + + + + This setting will take effect after restarting Arepacoin. + + + + + The supplied proxy address is invalid. + + + + + OverviewPage + + + Form + + + + + + The displayed information may be out of date. Your wallet automatically synchronizes with the Arepacoin network after a connection is established, but this process has not completed yet. + + + + + Stake: + + + + + Unconfirmed: + + + + + Wallet + Капчык + + + + Spendable: + + + + + Your current spendable balance + + + + + Immature: + + + + + Mined balance that has not yet matured + + + + + Total: + + + + + Your current total balance + + + + + <b>Recent transactions</b> + + + + + Total of transactions that have yet to be confirmed, and do not yet count toward the current balance + + + + + Total of coins that was staked, and do not yet count toward the current balance + + + + + + out of sync + синхрондоштурулган эмес + + + + QRCodeDialog + + + QR Code Dialog + + + + + Request Payment + + + + + Amount: + + + + + Label: + + + + + Message: + + + + + &Save As... + + + + + Error encoding URI into QR Code. + + + + + The entered amount is invalid, please check. + + + + + Resulting URI too long, try to reduce the text for label / message. + + + + + Save QR Code + + + + + PNG Images (*.png) + + + + + RPCConsole + + + Client name + + + + + + + + + + + + + + N/A + + + + + Client version + + + + + &Information + + + + + Using OpenSSL version + + + + + Startup time + + + + + Network + + + + + Number of connections + + + + + On testnet + + + + + Block chain + + + + + Current number of blocks + + + + + Estimated total blocks + + + + + Last block time + + + + + &Open + &Ачуу + + + + Command-line options + + + + + Show the Arepacoin-Qt help message to get a list with possible Arepacoin command-line options. + + + + + &Show + + + + + &Console + &Консоль + + + + Build date + + + + + Arepacoin - Debug window + + + + + Arepacoin Core + + + + + Debug log file + + + + + Open the Arepacoin debug log file from the current data directory. This can take a few seconds for large log files. + + + + + Clear console + Консолду тазалоо + + + + Welcome to the Arepacoin RPC console. + + + + + Use up and down arrows to navigate history, and <b>Ctrl-L</b> to clear screen. + + + + + Type <b>help</b> for an overview of available commands. + + + + + SendCoinsDialog + + + + + + + + + + Send Coins + + + + + Coin Control Features + + + + + Inputs... + + + + + automatically selected + + + + + Insufficient funds! + + + + + Quantity: + + + + + + 0 + + + + + Bytes: + + + + + Amount: + + + + + + + + 0.00 BC + + + + + Priority: + + + + + medium + + + + + Fee: + + + + + Low Output: + + + + + no + + + + + After Fee: + + + + + Change + + + + + custom change address + + + + + Send to multiple recipients at once + + + + + Add &Recipient + + + + + Remove all transaction fields + + + + + Clear &All + &Бардыгын тазалоо + + + + Balance: + + + + + 123.456 BC + + + + + Confirm the send action + + + + + S&end + &Жөнөтүү + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Copy quantity + + + + + Copy amount + + + + + Copy fee + + + + + Copy after fee + + + + + Copy bytes + + + + + Copy priority + + + + + Copy low output + + + + + Copy change + + + + + <b>%1</b> to %2 (%3) + + + + + Confirm send coins + + + + + Are you sure you want to send %1? + + + + + and + + + + + The recipient address is not valid, please recheck. + + + + + The amount to pay must be larger than 0. + + + + + The amount exceeds your balance. + + + + + The total exceeds your balance when the %1 transaction fee is included. + + + + + Duplicate address found, can only send to each address once per send operation. + + + + + Error: Transaction creation failed. + + + + + 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. + + + + + WARNING: Invalid Arepacoin address + + + + + (no label) + (аты жок) + + + + WARNING: unknown change address + + + + + SendCoinsEntry + + + Form + + + + + A&mount: + + + + + Pay &To: + + + + + + Enter a label for this address to add it to your address book + + + + + &Label: + + + + + The address to send the payment to (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Choose address from address book + + + + + Alt+A + + + + + Paste address from clipboard + Даректи алмашуу буферинен коюу + + + + Alt+P + + + + + Remove this recipient + + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + SignVerifyMessageDialog + + + Signatures - Sign / Verify a Message + + + + + + &Sign Message + + + + + You can sign messages with your addresses to prove you own them. Be careful not to sign anything vague, as phishing attacks may try to trick you into signing your identity over to them. Only sign fully-detailed statements you agree to. + + + + + The address to sign the message with (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + + Choose an address from the address book + + + + + + Alt+A + + + + + Paste address from clipboard + Даректи алмашуу буферинен коюу + + + + Alt+P + + + + + Enter the message you want to sign here + + + + + Copy the current signature to the system clipboard + + + + + Sign the message to prove you own this Arepacoin address + + + + + Reset all sign message fields + + + + + + Clear &All + &Бардыгын тазалоо + + + + + &Verify Message + + + + + Enter the signing address, message (ensure you copy line breaks, spaces, tabs, etc. exactly) and signature below to verify the message. Be careful not to read more into the signature than what is in the signed message itself, to avoid being tricked by a man-in-the-middle attack. + + + + + The address the message was signed with (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Verify the message to ensure it was signed with the specified Arepacoin address + + + + + Reset all verify message fields + + + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Click "Sign Message" to generate signature + + + + + Enter Arepacoin signature + + + + + + The entered address is invalid. + + + + + + + + Please check the address and try again. + + + + + + The entered address does not refer to a key. + + + + + Wallet unlock was cancelled. + + + + + Private key for the entered address is not available. + + + + + Message signing failed. + + + + + Message signed. + + + + + The signature could not be decoded. + + + + + + Please check the signature and try again. + + + + + The signature did not match the message digest. + + + + + Message verification failed. + + + + + Message verified. + + + + + TransactionDesc + + + Open until %1 + + + + + Open for %n block(s) + + + + + conflicted + + + + + %1/offline + %1/тармакта эмес + + + + %1/unconfirmed + + + + + %1 confirmations + + + + + Status + + + + + , broadcast through %n node(s) + + + + + Date + Дата + + + + Source + + + + + Generated + + + + + + From + + + + + + + To + + + + + + own address + + + + + label + + + + + + + + + Credit + + + + + matures in %n more block(s) + + + + + not accepted + + + + + + + + Debit + + + + + Transaction fee + + + + + Net amount + + + + + Message + Билдирүү + + + + Comment + + + + + Transaction ID + + + + + Generated coins must mature 6 blocks before they can be spent. When you generated this block, it was broadcast to the network to be added to the block chain. If it fails to get into the chain, its state will change to "not accepted" and it won't be spendable. This may occasionally happen if another node generates a block within a few seconds of yours. + + + + + Debug information + + + + + Transaction + + + + + Inputs + + + + + Amount + + + + + true + + + + + false + + + + + , has not been successfully broadcast yet + + + + + unknown + + + + + TransactionDescDialog + + + Transaction details + + + + + This pane shows a detailed description of the transaction + + + + + TransactionTableModel + + + Date + Дата + + + + Type + + + + + Address + Дарек + + + + Amount + + + + + Open until %1 + + + + + Confirmed (%1 confirmations) + + + + + Open for %n more block(s) + + + + + Offline + + + + + Unconfirmed + + + + + Confirming (%1 of %2 recommended confirmations) + + + + + Conflicted + + + + + Immature (%1 confirmations, will be available after %2) + + + + + This block was not received by any other nodes and will probably not be accepted! + + + + + Generated but not accepted + + + + + Received with + + + + + Received from + + + + + Sent to + + + + + Payment to yourself + + + + + Mined + + + + + (n/a) + + + + + Transaction status. Hover over this field to show number of confirmations. + + + + + Date and time that the transaction was received. + + + + + Type of transaction. + + + + + Destination address of transaction. + + + + + Amount removed from or added to balance. + + + + + TransactionView + + + + All + + + + + Today + + + + + This week + + + + + This month + + + + + Last month + + + + + This year + + + + + Range... + + + + + Received with + + + + + Sent to + + + + + To yourself + + + + + Mined + + + + + Other + + + + + Enter address or label to search + + + + + Min amount + + + + + Copy address + + + + + Copy label + + + + + Copy amount + + + + + Copy transaction ID + + + + + Edit label + + + + + Show transaction details + + + + + Export Transaction Data + + + + + Comma separated file (*.csv) + + + + + Confirmed + + + + + Date + Дата + + + + Type + + + + + Label + + + + + Address + Дарек + + + + Amount + + + + + ID + + + + + Error exporting + + + + + Could not write to file %1. + + + + + Range: + + + + + to + + + + + WalletModel + + + Sending... + + + + + bitcoin-core + + + Arepacoin version + + + + + Usage: + + + + + Send command to -server or arepacoind + + + + + List commands + + + + + Get help for a command + + + + + Options: + + + + + Specify configuration file (default: arepacoin.conf) + + + + + Specify pid file (default: arepacoind.pid) + + + + + Specify wallet file (within data directory) + + + + + Specify data directory + + + + + Set database cache size in megabytes (default: 25) + + + + + Set database disk log size in megabytes (default: 100) + + + + + Listen for connections on <port> (default: 9853 or testnet: 19853) + + + + + Maintain at most <n> connections to peers (default: 125) + + + + + Connect to a node to retrieve peer addresses, and disconnect + + + + + Specify your own public address + + + + + Bind to given address. Use [host]:port notation for IPv6 + + + + + Stake your coins to support network and gain reward (default: 1) + + + + + Threshold for disconnecting misbehaving peers (default: 100) + + + + + Number of seconds to keep misbehaving peers from reconnecting (default: 86400) + + + + + An error occurred while setting up the RPC port %u for listening on IPv4: %s + + + + + Detach block and address databases. Increases shutdown time (default: 0) + + + + + 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. + + + + + Error: This transaction requires a transaction fee of at least %s because of its amount, complexity, or use of recently received funds + + + + + Listen for JSON-RPC connections on <port> (default: 9852 or testnet: 19852) + + + + + Accept command line and JSON-RPC commands + + + + + Error: Transaction creation failed + + + + + Error: Wallet locked, unable to create transaction + + + + + Importing blockchain data file. + + + + + Importing bootstrap blockchain data file. + + + + + Run in the background as a daemon and accept commands + + + + + Use the test network + + + + + Accept connections from outside (default: 1 if no -proxy or -connect) + + + + + An error occurred while setting up the RPC port %u for listening on IPv6, falling back to IPv4: %s + + + + + Error initializing database environment %s! To recover, BACKUP THAT DIRECTORY, then remove everything from it except for wallet.dat. + + + + + Set maximum size of high-priority/low-fee transactions in bytes (default: 27000) + + + + + Warning: -paytxfee is set very high! This is the transaction fee you will pay if you send a transaction. + + + + + Warning: Please check that your computer's date and time are correct! If your clock is wrong Arepacoin will not work properly. + + + + + Warning: error reading wallet.dat! All keys read correctly, but transaction data or address book entries might be missing or incorrect. + + + + + Warning: wallet.dat corrupt, data salvaged! Original wallet.dat saved as wallet.{timestamp}.bak in %s; if your balance or transactions are incorrect you should restore from a backup. + + + + + Attempt to recover private keys from a corrupt wallet.dat + + + + + Block creation options: + + + + + Connect only to the specified node(s) + + + + + Discover own IP address (default: 1 when listening and no -externalip) + + + + + Failed to listen on any port. Use -listen=0 if you want this. + + + + + Find peers using DNS lookup (default: 1) + + + + + Sync checkpoints policy (default: strict) + + + + + Invalid -tor address: '%s' + + + + + Invalid amount for -reservebalance=<amount> + + + + + Maximum per-connection receive buffer, <n>*1000 bytes (default: 5000) + + + + + Maximum per-connection send buffer, <n>*1000 bytes (default: 1000) + + + + + Only connect to nodes in network <net> (IPv4, IPv6 or Tor) + + + + + Output extra debugging information. Implies all other -debug* options + + + + + Output extra network debugging information + + + + + Prepend debug output with timestamp + + + + + SSL options: (see the Bitcoin Wiki for SSL setup instructions) + + + + + Select the version of socks proxy to use (4-5, default: 5) + + + + + Send trace/debug info to console instead of debug.log file + + + + + Send trace/debug info to debugger + + + + + Set maximum block size in bytes (default: 250000) + + + + + Set minimum block size in bytes (default: 0) + + + + + Shrink debug.log file on client startup (default: 1 when no -debug) + + + + + Specify connection timeout in milliseconds (default: 5000) + + + + + Unable to sign checkpoint, wrong checkpointkey? + + + + + + Use UPnP to map the listening port (default: 0) + + + + + Use UPnP to map the listening port (default: 1 when listening) + + + + + Use proxy to reach tor hidden services (default: same as -proxy) + + + + + Username for JSON-RPC connections + + + + + Verifying database integrity... + + + + + WARNING: syncronized checkpoint violation detected, but skipped! + + + + + Warning: Disk space is low! + + + + + Warning: This version is obsolete, upgrade required! + + + + + wallet.dat corrupt, salvage failed + + + + + Password for JSON-RPC connections + + + + + %s, you must set a rpcpassword in the configuration file: + %s +It is recommended you use the following random password: +rpcuser=arepacoinrpc +rpcpassword=%s +(you do not need to remember this password) +The username and password MUST NOT be the same. +If the file does not exist, create it with owner-readable-only file permissions. +It is also recommended to set alertnotify so you are notified of problems; +for example: alertnotify=echo %%s | mail -s "Arepacoin Alert" admin@foo.com + + + + + + Find peers using internet relay chat (default: 0) + + + + + Sync time with other nodes. Disable if time on your system is precise e.g. syncing with NTP (default: 1) + + + + + When creating transactions, ignore inputs with value less than this (default: 0.01) + + + + + Allow JSON-RPC connections from specified IP address + + + + + Send commands to node running on <ip> (default: 127.0.0.1) + + + + + Execute command when the best block changes (%s in cmd is replaced by block hash) + + + + + Execute command when a wallet transaction changes (%s in cmd is replaced by TxID) + + + + + Require a confirmations for change (default: 0) + + + + + Enforce transaction scripts to use canonical PUSH operators (default: 1) + + + + + Execute command when a relevant alert is received (%s in cmd is replaced by message) + + + + + Upgrade wallet to latest format + + + + + Set key pool size to <n> (default: 100) + + + + + Rescan the block chain for missing wallet transactions + + + + + How many blocks to check at startup (default: 2500, 0 = all) + + + + + How thorough the block verification is (0-6, default: 1) + + + + + Imports blocks from external blk000?.dat file + + + + + Use OpenSSL (https) for JSON-RPC connections + + + + + Server certificate file (default: server.cert) + + + + + Server private key (default: server.pem) + + + + + Acceptable ciphers (default: TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH) + + + + + Error: Wallet unlocked for staking only, unable to create transaction. + + + + + WARNING: Invalid checkpoint found! Displayed transactions may not be correct! You may need to upgrade, or notify developers. + + + + + This help message + + + + + Wallet %s resides outside data directory %s. + + + + + Cannot obtain a lock on data directory %s. Arepacoin is probably already running. + + + + + Arepacoin + + + + + Unable to bind to %s on this computer (bind returned error %d, %s) + + + + + Connect through socks proxy + + + + + Allow DNS lookups for -addnode, -seednode and -connect + + + + + Loading addresses... + + + + + Error loading blkindex.dat + + + + + Error loading wallet.dat: Wallet corrupted + + + + + Error loading wallet.dat: Wallet requires newer version of Arepacoin + + + + + Wallet needed to be rewritten: restart Arepacoin to complete + + + + + Error loading wallet.dat + + + + + Invalid -proxy address: '%s' + + + + + Unknown network specified in -onlynet: '%s' + + + + + Unknown -socks proxy version requested: %i + + + + + Cannot resolve -bind address: '%s' + + + + + Cannot resolve -externalip address: '%s' + + + + + Invalid amount for -paytxfee=<amount>: '%s' + + + + + Error: could not start node + + + + + Sending... + + + + + Invalid amount + + + + + Insufficient funds + + + + + Loading block index... + + + + + Add a node to connect to and attempt to keep the connection open + + + + + Unable to bind to %s on this computer. Arepacoin is probably already running. + + + + + Fee per KB to add to transactions you send + + + + + Invalid amount for -mininput=<amount>: '%s' + + + + + Loading wallet... + + + + + Cannot downgrade wallet + + + + + Cannot initialize keypool + + + + + Cannot write default address + + + + + Rescanning... + + + + + Done loading + + + + + To use the %s option + + + + + Error + Ката + + + + You must set rpcpassword=<password> in the configuration file: +%s +If the file does not exist, create it with owner-readable-only file permissions. + + + + \ No newline at end of file diff --git a/src/qt/locale/bitcoin_la.ts b/src/qt/locale/bitcoin_la.ts new file mode 100755 index 0000000..e418d23 --- /dev/null +++ b/src/qt/locale/bitcoin_la.ts @@ -0,0 +1,3285 @@ + + + AboutDialog + + + About Arepacoin + + + + + <b>Arepacoin</b> version + + + + + Copyright © 2009-2014 The Bitcoin developers +Copyright © 2012-2014 The NovaCoin developers +Copyright © 2014 The Arepacoin developers + + + + + +This is experimental software. + +Distributed under the MIT/X11 software license, see the accompanying file COPYING or http://www.opensource.org/licenses/mit-license.php. + +This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit (http://www.openssl.org/) and cryptographic software written by Eric Young (eay@cryptsoft.com) and UPnP software written by Thomas Bernard. + Hoc est experimentale programma. + +Distributum sub MIT/X11 licentia programmatum, vide comitantem plicam COPYING vel http://www.opensource.org/licenses/mit-license.php. + +Hoc productum continet programmata composita ab OpenSSL Project pro utendo in OpenSSL Toolkit (http://www.openssl.org/) et programmata cifrarum scripta ab Eric Young (eay@cryptsoft.com) et UPnP programmata scripta ab Thomas Bernard. + + + + AddressBookPage + + + Address Book + + + + + Double-click to edit address or label + Dupliciter-clicca ut inscriptionem vel titulum mutes + + + + Create a new address + Crea novam inscriptionem + + + + Copy the currently selected address to the system clipboard + Copia inscriptionem iam selectam in latibulum systematis + + + + &New Address + + + + + These are your Arepacoin addresses for receiving payments. You may want to give a different one to each sender so you can keep track of who is paying you. + + + + + &Copy Address + &Copia Inscriptionem + + + + Show &QR Code + + + + + Sign a message to prove you own a Arepacoin address + + + + + Sign &Message + + + + + Delete the currently selected address from the list + Dele active selectam inscriptionem ex enumeratione + + + + Verify a message to ensure it was signed with a specified Arepacoin address + + + + + &Verify Message + + + + + &Delete + &Dele + + + + Copy &Label + Copia &Titulum + + + + &Edit + &Muta + + + + Export Address Book Data + + + + + Comma separated file (*.csv) + Comma Separata Plica (*.csv) + + + + Error exporting + + + + + Could not write to file %1. + + + + + AddressTableModel + + + Label + Titulus + + + + Address + Inscriptio + + + + (no label) + (nullus titulus) + + + + AskPassphraseDialog + + + Passphrase Dialog + Dialogus Tesserae + + + + Enter passphrase + Insere tesseram + + + + New passphrase + Nova tessera + + + + Repeat new passphrase + Itera novam tesseram + + + + Serves to disable the trivial sendmoney when OS account compromised. Provides no real security. + + + + + For staking only + + + + + Enter the new passphrase to the wallet.<br/>Please use a passphrase of <b>10 or more random characters</b>, or <b>eight or more words</b>. + Insero novam tesseram cassidili.<br/>Sodes tessera <b>10 pluriumve fortuitarum litterarum</b> utere aut <b>octo pluriumve verborum</b>. + + + + Encrypt wallet + Cifra cassidile + + + + This operation needs your wallet passphrase to unlock the wallet. + Huic operationi necesse est tessera cassidili tuo ut cassidile reseret. + + + + Unlock wallet + Resera cassidile + + + + This operation needs your wallet passphrase to decrypt the wallet. + Huic operationi necesse est tessera cassidili tuo ut cassidile decifret. + + + + Decrypt wallet + Decifra cassidile + + + + Change passphrase + Muta tesseram + + + + Enter the old and new passphrase to the wallet. + Insero veterem novamque tesseram cassidili. + + + + Confirm wallet encryption + Confirma cifrationem cassidilis + + + + Warning: If you encrypt your wallet and lose your passphrase, you will <b>LOSE ALL OF YOUR COINS</b>! + + + + + Are you sure you wish to encrypt your wallet? + Certusne es te velle tuum cassidile cifrare? + + + + IMPORTANT: Any previous backups you have made of your wallet file should be replaced with the newly generated, encrypted wallet file. For security reasons, previous backups of the unencrypted wallet file will become useless as soon as you start using the new, encrypted wallet. + GRAVE: Oportet ulla prioria conservata quae fecisti de plica tui cassidilis reponi a nove generata cifrata plica cassidilis. Propter securitatem, prioria conservata de plica non cifrata cassidilis inutilia fiet simul atque incipis uti novo cifrato cassidili. + + + + + Warning: The Caps Lock key is on! + Monitio: Litterae ut capitales seratae sunt! + + + + + Wallet encrypted + Cassidile cifratum + + + + Arepacoin will close now to finish the encryption process. Remember that encrypting your wallet cannot fully protect your coins from being stolen by malware infecting your computer. + + + + + + + + Wallet encryption failed + Cassidile cifrare abortum est + + + + Wallet encryption failed due to an internal error. Your wallet was not encrypted. + Cassidile cifrare abortum est propter internum errorem. Tuum cassidile cifratum non est. + + + + + The supplied passphrases do not match. + Tesserae datae non eaedem sunt. + + + + Wallet unlock failed + Cassidile reserare abortum est. + + + + + + The passphrase entered for the wallet decryption was incorrect. + Tessera inserta pro cassidilis decifrando prava erat. + + + + Wallet decryption failed + Cassidile decifrare abortum est. + + + + Wallet passphrase was successfully changed. + Tessera cassidilis successa est in mutando. + + + + BitcoinGUI + + + Sign &message... + Signa &nuntium... + + + + Synchronizing with network... + Synchronizans cum rete... + + + + &Overview + &Summarium + + + + Show general overview of wallet + Monstra generale summarium cassidilis + + + + &Transactions + &Transactiones + + + + Browse transaction history + Inspicio historiam transactionum + + + + &Address Book + + + + + Edit the list of stored addresses and labels + + + + + &Receive coins + + + + + Show the list of addresses for receiving payments + + + + + &Send coins + + + + + E&xit + E&xi + + + + Quit application + Exi applicatione + + + + Show information about Arepacoin + + + + + About &Qt + Informatio de &Qt + + + + Show information about Qt + Monstra informationem de Qt + + + + &Options... + &Optiones + + + + &Encrypt Wallet... + &Cifra Cassidile... + + + + &Backup Wallet... + &Conserva Cassidile... + + + + &Change Passphrase... + &Muta tesseram... + + + + ~%n block(s) remaining + + + + + Downloaded %1 of %2 blocks of transaction history (%3% done). + + + + + &Export... + + + + + Send coins to a Arepacoin address + + + + + Modify configuration options for Arepacoin + + + + + Export the data in the current tab to a file + + + + + Encrypt or decrypt wallet + + + + + Backup wallet to another location + Conserva cassidile in locum alium + + + + Change the passphrase used for wallet encryption + Muta tesseram utam pro cassidilis cifrando + + + + &Debug window + Fenestra &Debug + + + + Open debugging and diagnostic console + Aperi terminalem debug et diagnosticalem + + + + &Verify message... + &Verifica nuntium... + + + + Arepacoin + + + + + Wallet + Cassidile + + + + &About Arepacoin + + + + + &Show / Hide + &Monstra/Occulta + + + + Unlock wallet + + + + + &Lock Wallet + + + + + Lock wallet + + + + + &File + &Plica + + + + &Settings + &Configuratio + + + + &Help + &Auxilium + + + + Tabs toolbar + Tabella instrumentorum "Tabs" + + + + Actions toolbar + + + + + + [testnet] + [testnet] + + + + + Arepacoin client + + + + + %n active connection(s) to Arepacoin network + + + + + Downloaded %1 blocks of transaction history. + + + + + Staking.<br>Your weight is %1<br>Network weight is %2<br>Expected time to earn reward is %3 + + + + + Not staking because wallet is locked + + + + + Not staking because wallet is offline + + + + + Not staking because wallet is syncing + + + + + Not staking because you don't have mature coins + + + + + %n second(s) ago + + + + + &Unlock Wallet... + + + + + %n minute(s) ago + + + + + %n hour(s) ago + + + + + %n day(s) ago + + + + + Up to date + Recentissimo + + + + Catching up... + Persequens... + + + + Last received block was generated %1. + + + + + This transaction is over the size limit. You can still send it for a fee of %1, which goes to the nodes that process your transaction and helps to support the network. Do you want to pay the fee? + + + + + Confirm transaction fee + + + + + Sent transaction + Transactio missa + + + + Incoming transaction + Transactio incipiens + + + + Date: %1 +Amount: %2 +Type: %3 +Address: %4 + + Dies: %1 +Quantitas: %2 +Typus: %3 +Inscriptio: %4 + + + + + + URI handling + + + + + + URI can not be parsed! This can be caused by an invalid Arepacoin address or malformed URI parameters. + + + + + Wallet is <b>encrypted</b> and currently <b>unlocked</b> + Cassidile <b>cifratum</b> est et iam nunc <b>reseratum</b> + + + + Wallet is <b>encrypted</b> and currently <b>locked</b> + Cassidile <b>cifratum</b> est et iam nunc <b>seratum</b> + + + + Backup Wallet + + + + + Wallet Data (*.dat) + + + + + Backup Failed + + + + + There was an error trying to save the wallet data to the new location. + + + + + %n second(s) + + + + + %n minute(s) + + + + + %n hour(s) + %n hora%n horae + + + + %n day(s) + %n dies%n dies + + + + Not staking + + + + + A fatal error occurred. Arepacoin can no longer continue safely and will quit. + + + + + ClientModel + + + Network Alert + Monitio Retis + + + + CoinControlDialog + + + Coin Control + + + + + Quantity: + + + + + Bytes: + + + + + Amount: + Quantitas: + + + + Priority: + + + + + Fee: + + + + + Low Output: + + + + + no + + + + + After Fee: + + + + + Change: + + + + + (un)select all + + + + + Tree mode + + + + + List mode + + + + + Amount + Quantitas + + + + Label + + + + + Address + Inscriptio + + + + Date + Dies + + + + Confirmations + + + + + Confirmed + Confirmatum + + + + Priority + + + + + Copy address + Copia inscriptionem + + + + Copy label + Copia titulum + + + + + Copy amount + Copia quantitatem + + + + Copy transaction ID + Copia transactionis ID + + + + Copy quantity + + + + + Copy fee + + + + + Copy after fee + + + + + Copy bytes + + + + + Copy priority + + + + + Copy low output + + + + + Copy change + + + + + highest + + + + + high + + + + + medium-high + + + + + medium + + + + + low-medium + + + + + low + + + + + lowest + + + + + DUST + + + + + yes + + + + + This label turns red, if the transaction size is bigger than 10000 bytes. + + This means a fee of at least %1 per kb is required. + + Can vary +/- 1 Byte per input. + + + + + Transactions with higher priority get more likely into a block. + +This label turns red, if the priority is smaller than "medium". + + This means a fee of at least %1 per kb is required. + + + + + This label turns red, if any recipient receives an amount smaller than %1. + + This means a fee of at least %2 is required. + + Amounts below 0.546 times the minimum relay fee are shown as DUST. + + + + + This label turns red, if the change is smaller than %1. + + This means a fee of at least %2 is required. + + + + + + (no label) + (nullus titulus) + + + + change from %1 (%2) + + + + + (change) + + + + + EditAddressDialog + + + Edit Address + Muta Inscriptionem + + + + &Label + &Titulus + + + + The label associated with this address book entry + + + + + &Address + &Inscriptio + + + + The address associated with this address book entry. This can only be modified for sending addresses. + + + + + New receiving address + Nova inscriptio accipiendi + + + + New sending address + Nova inscriptio mittendi + + + + Edit receiving address + Muta inscriptionem accipiendi + + + + Edit sending address + Muta inscriptionem mittendi + + + + The entered address "%1" is already in the address book. + Inserta inscriptio "%1" iam in libro inscriptionum est. + + + + The entered address "%1" is not a valid Arepacoin address. + + + + + Could not unlock wallet. + Non potuisse cassidile reserare + + + + New key generation failed. + Generare novam clavem abortum est. + + + + GUIUtil::HelpMessageBox + + + + Arepacoin-Qt + + + + + version + + + + + Usage: + + + + + command-line options + + + + + UI options + + + + + Set language, for example "de_DE" (default: system locale) + + + + + Start minimized + + + + + Show splash screen on startup (default: 1) + + + + + OptionsDialog + + + Options + Optiones + + + + &Main + &Princeps + + + + Optional transaction fee per kB that helps make sure your transactions are processed quickly. Most transactions are 1 kB. Fee 0.01 recommended. + + + + + Pay transaction &fee + Solve &mercedem transactionis + + + + Reserved amount does not participate in staking and is therefore spendable at any time. + + + + + Reserve + + + + + Automatically start Arepacoin after logging in to the system. + + + + + &Start Arepacoin on system login + + + + + Detach block and address databases at shutdown. This means they can be moved to another data directory, but it slows down shutdown. The wallet is always detached. + + + + + &Detach databases at shutdown + + + + + &Network + &Rete + + + + Automatically open the Arepacoin client port on the router. This only works when your router supports UPnP and it is enabled. + + + + + Map port using &UPnP + Designa portam utendo &UPnP + + + + Connect to the Arepacoin network through a SOCKS proxy (e.g. when connecting through Tor). + + + + + &Connect through SOCKS proxy: + + + + + Proxy &IP: + &IP vicarii: + + + + IP address of the proxy (e.g. 127.0.0.1) + + + + + &Port: + &Porta: + + + + Port of the proxy (e.g. 9050) + Porta vicarii (e.g. 9050) + + + + SOCKS &Version: + SOCKS &Versio: + + + + SOCKS version of the proxy (e.g. 5) + SOCKS versio vicarii (e.g. 5) + + + + &Window + &Fenestra + + + + Show only a tray icon after minimizing the window. + Monstra tantum iconem in tabella systematis postquam fenestram minifactam est. + + + + &Minimize to the tray instead of the taskbar + &Minifac in tabellam systematis potius quam applicationum + + + + Minimize instead of exit the application when the window is closed. When this option is enabled, the application will be closed only after selecting Quit in the menu. + Minifac potius quam exire applicatione quando fenestra clausa sit. Si haec optio activa est, applicatio clausa erit tantum postquam selegeris Exi in menu. + + + + M&inimize on close + M&inifac ad claudendum + + + + &Display + &UI + + + + User Interface &language: + &Lingua monstranda utenti: + + + + The user interface language can be set here. This setting will take effect after restarting Arepacoin. + + + + + &Unit to show amounts in: + &Unita qua quantitates monstrare: + + + + Choose the default subdivision unit to show in the interface and when sending coins. + Selige praedefinitam unitam subdivisionis monstrare in interfacie et quando nummos mittere + + + + Whether to show Arepacoin addresses in the transaction list or not. + + + + + &Display addresses in transaction list + &Monstra inscriptiones in enumeratione transactionum + + + + Whether to show coin control features or not. + + + + + Display coin &control features (experts only!) + + + + + &OK + &OK + + + + &Cancel + &Cancella + + + + &Apply + + + + + default + praedefinitum + + + + + Warning + + + + + + This setting will take effect after restarting Arepacoin. + + + + + The supplied proxy address is invalid. + Inscriptio vicarii tradita non valida est. + + + + OverviewPage + + + Form + Schema + + + + + The displayed information may be out of date. Your wallet automatically synchronizes with the Arepacoin network after a connection is established, but this process has not completed yet. + + + + + Stake: + + + + + Unconfirmed: + + + + + Wallet + Cassidile + + + + Spendable: + + + + + Your current spendable balance + + + + + Immature: + Immatura: + + + + Mined balance that has not yet matured + Fossum pendendum quod nondum maturum est + + + + Total: + + + + + Your current total balance + + + + + <b>Recent transactions</b> + <b>Recentes transactiones</b> + + + + Total of transactions that have yet to be confirmed, and do not yet count toward the current balance + + + + + Total of coins that was staked, and do not yet count toward the current balance + + + + + + out of sync + non synchronizato + + + + QRCodeDialog + + + QR Code Dialog + + + + + Request Payment + + + + + Amount: + + + + + Label: + + + + + Message: + + + + + &Save As... + + + + + Error encoding URI into QR Code. + + + + + The entered amount is invalid, please check. + + + + + Resulting URI too long, try to reduce the text for label / message. + + + + + Save QR Code + + + + + PNG Images (*.png) + + + + + RPCConsole + + + Client name + Nomen clientis + + + + + + + + + + + + + N/A + N/A + + + + Client version + Versio clientis + + + + &Information + &Informatio + + + + Using OpenSSL version + Utens OpenSSL versione + + + + Startup time + Tempus initiandi + + + + Network + Rete + + + + Number of connections + Numerus conexionum + + + + On testnet + + + + + Block chain + Catena frustorum + + + + Current number of blocks + Numerus frustorum iam nunc + + + + Estimated total blocks + Aestimatus totalis numerus frustorum + + + + Last block time + Hora postremi frusti + + + + &Open + &Aperi + + + + Command-line options + + + + + Show the Arepacoin-Qt help message to get a list with possible Arepacoin command-line options. + + + + + &Show + + + + + &Console + &Terminale + + + + Build date + Dies aedificandi + + + + Arepacoin - Debug window + + + + + Arepacoin Core + + + + + Debug log file + Debug catalogi plica + + + + Open the Arepacoin debug log file from the current data directory. This can take a few seconds for large log files. + + + + + Clear console + Vacuefac terminale + + + + Welcome to the Arepacoin RPC console. + + + + + Use up and down arrows to navigate history, and <b>Ctrl-L</b> to clear screen. + Utere sagittis sursum deorsumque ut per historiam naviges, et <b>Ctrl+L</b> ut scrinium vacuefacias. + + + + Type <b>help</b> for an overview of available commands. + Scribe <b>help</b> pro summario possibilium mandatorum. + + + + SendCoinsDialog + + + + + + + + + + Send Coins + Mitte Nummos + + + + Coin Control Features + + + + + Inputs... + + + + + automatically selected + + + + + Insufficient funds! + + + + + Quantity: + + + + + + 0 + + + + + Bytes: + + + + + Amount: + Quantitas: + + + + + + + 0.00 BC + + + + + Priority: + + + + + medium + + + + + Fee: + + + + + Low Output: + + + + + no + + + + + After Fee: + + + + + Change + + + + + custom change address + + + + + Send to multiple recipients at once + Mitte pluribus accipientibus simul + + + + Add &Recipient + Adde &Accipientem + + + + Remove all transaction fields + + + + + Clear &All + Vacuefac &Omnia + + + + Balance: + Pendendum: + + + + 123.456 BC + + + + + Confirm the send action + Confirma actionem mittendi + + + + S&end + &Mitte + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Copy quantity + + + + + Copy amount + Copia quantitatem + + + + Copy fee + + + + + Copy after fee + + + + + Copy bytes + + + + + Copy priority + + + + + Copy low output + + + + + Copy change + + + + + <b>%1</b> to %2 (%3) + + + + + Confirm send coins + Confirma mittendum nummorum + + + + Are you sure you want to send %1? + + + + + and + + + + + The recipient address is not valid, please recheck. + Inscriptio accipientis non est valida, sodes reproba. + + + + The amount to pay must be larger than 0. + Oportet quantitatem ad pensandum maiorem quam 0 esse. + + + + The amount exceeds your balance. + Quantitas est ultra quod habes. + + + + The total exceeds your balance when the %1 transaction fee is included. + Quantitas est ultra quod habes cum merces transactionis %1 includitur. + + + + Duplicate address found, can only send to each address once per send operation. + Geminata inscriptio inventa, tantum posse mittere ad quamque inscriptionem semel singulare operatione. + + + + Error: Transaction creation failed. + + + + + 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. + + + + + WARNING: Invalid Arepacoin address + + + + + (no label) + (nullus titulus) + + + + WARNING: unknown change address + + + + + SendCoinsEntry + + + Form + + + + + A&mount: + &Quantitas: + + + + Pay &To: + Pensa &Ad: + + + + + Enter a label for this address to add it to your address book + Insero titulum huic inscriptioni ut eam in tuum librum inscriptionum addas. + + + + &Label: + &Titulus: + + + + The address to send the payment to (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Choose address from address book + + + + + Alt+A + Alt+A + + + + Paste address from clipboard + Conglutina inscriptionem ex latibulo + + + + Alt+P + Alt+P + + + + Remove this recipient + + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + SignVerifyMessageDialog + + + Signatures - Sign / Verify a Message + Signationes - Signa / Verifica nuntium + + + + + &Sign Message + &Signa Nuntium + + + + You can sign messages with your addresses to prove you own them. Be careful not to sign anything vague, as phishing attacks may try to trick you into signing your identity over to them. Only sign fully-detailed statements you agree to. + Potes nuntios signare inscriptionibus tuis ut demonstres te eas possidere. Cautus es non amibiguum signare, quia impetus phiscatorum conentur te fallere ut signes identitatem tuam ad eos. Solas signa sententias cuncte descriptas quibus convenis. + + + + The address to sign the message with (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + + Choose an address from the address book + + + + + + Alt+A + Alt+A + + + + Paste address from clipboard + Glutina inscriptionem ex latibulo + + + + Alt+P + Alt+P + + + + Enter the message you want to sign here + Insere hic nuntium quod vis signare + + + + Copy the current signature to the system clipboard + Copia signationem in latibulum systematis + + + + Sign the message to prove you own this Arepacoin address + + + + + Reset all sign message fields + Reconstitue omnes campos signandi nuntii + + + + + Clear &All + Vacuefac &Omnia + + + + + &Verify Message + &Verifica Nuntium + + + + Enter the signing address, message (ensure you copy line breaks, spaces, tabs, etc. exactly) and signature below to verify the message. Be careful not to read more into the signature than what is in the signed message itself, to avoid being tricked by a man-in-the-middle attack. + Insere inscriptionem signantem, nuntium (cura ut copias intermissiones linearum, spatia, tabs, et cetera exacte) et signationem infra ut nuntium verifices. Cautus esto ne magis legas in signationem quam in nuntio signato ipso est, ut vites falli ab impetu homo-in-medio. + + + + The address the message was signed with (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Verify the message to ensure it was signed with the specified Arepacoin address + + + + + Reset all verify message fields + Reconstitue omnes campos verificandi nuntii + + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Click "Sign Message" to generate signature + Clicca "Signa Nuntium" ut signatio generetur + + + + Enter Arepacoin signature + + + + + + The entered address is invalid. + Inscriptio inserta non valida est. + + + + + + + Please check the address and try again. + Sodes inscriptionem proba et rursus conare. + + + + + The entered address does not refer to a key. + Inserta inscriptio clavem non refert. + + + + Wallet unlock was cancelled. + Cassidilis reserare cancellatum est. + + + + Private key for the entered address is not available. + Clavis privata absens est pro inserta inscriptione. + + + + Message signing failed. + Nuntium signare abortum est. + + + + Message signed. + Nuntius signatus. + + + + The signature could not be decoded. + Signatio decodificari non potuit. + + + + + Please check the signature and try again. + Sodes signationem proba et rursus conare. + + + + The signature did not match the message digest. + Signatio non convenit digesto nuntii + + + + Message verification failed. + Nuntium verificare abortum est. + + + + Message verified. + Nuntius verificatus. + + + + TransactionDesc + + + Open until %1 + Apertum donec %1 + + + + Open for %n block(s) + + + + + conflicted + + + + + %1/offline + %1/non conecto + + + + %1/unconfirmed + %1/non confirmata + + + + %1 confirmations + %1 confirmationes + + + + Status + Status + + + + , broadcast through %n node(s) + , disseminatum per %n nodo, disseminata per %n nodis + + + + Date + Dies + + + + Source + Fons + + + + Generated + Generatum + + + + + From + Ab + + + + + + To + Ad + + + + + own address + inscriptio propria + + + + label + titulus + + + + + + + + Credit + Creditum + + + + matures in %n more block(s) + maturum erit in %n plure frustomaturum erit in %n pluribus frustis + + + + not accepted + non acceptum + + + + + + + Debit + Debitum + + + + Transaction fee + Transactionis merces + + + + Net amount + Cuncta quantitas + + + + Message + Nuntius + + + + Comment + Annotatio + + + + Transaction ID + ID transactionis + + + + Generated coins must mature 6 blocks before they can be spent. When you generated this block, it was broadcast to the network to be added to the block chain. If it fails to get into the chain, its state will change to "not accepted" and it won't be spendable. This may occasionally happen if another node generates a block within a few seconds of yours. + + + + + Debug information + Informatio de debug + + + + Transaction + Transactio + + + + Inputs + Lectenda + + + + Amount + Quantitas + + + + true + verum + + + + false + falsum + + + + , has not been successfully broadcast yet + , nondum prospere disseminatum est + + + + unknown + ignotum + + + + TransactionDescDialog + + + Transaction details + Particularia transactionis + + + + This pane shows a detailed description of the transaction + Haec tabula monstrat descriptionem verbosam transactionis + + + + TransactionTableModel + + + Date + Dies + + + + Type + Typus + + + + Address + Inscriptio + + + + Amount + Quantitas + + + + Open until %1 + Apertum donec %1 + + + + Confirmed (%1 confirmations) + Confirmatum (%1 confirmationes) + + + + Open for %n more block(s) + Aperi pro %n plure frustoAperi pro %n pluribus frustis + + + + Offline + + + + + Unconfirmed + + + + + Confirming (%1 of %2 recommended confirmations) + + + + + Conflicted + + + + + Immature (%1 confirmations, will be available after %2) + + + + + This block was not received by any other nodes and will probably not be accepted! + Hoc frustum non acceptum est ab ulla alia nodis et probabiliter non acceptum erit! + + + + Generated but not accepted + Generatum sed non acceptum + + + + Received with + Acceptum cum + + + + Received from + Acceptum ab + + + + Sent to + Missum ad + + + + Payment to yourself + Pensitatio ad te ipsum + + + + Mined + Fossa + + + + (n/a) + (n/a) + + + + Transaction status. Hover over this field to show number of confirmations. + Status transactionis. Supervola cum mure ut monstretur numerus confirmationum. + + + + Date and time that the transaction was received. + Dies et tempus quando transactio accepta est. + + + + Type of transaction. + Typus transactionis. + + + + Destination address of transaction. + Inscriptio destinationis transactionis. + + + + Amount removed from or added to balance. + Quantitas remota ex pendendo aut addita ei. + + + + TransactionView + + + + All + Omne + + + + Today + Hodie + + + + This week + Hac hebdomade + + + + This month + Hoc mense + + + + Last month + Postremo mense + + + + This year + Hoc anno + + + + Range... + Intervallum... + + + + Received with + Acceptum cum + + + + Sent to + Missum ad + + + + To yourself + Ad te ipsum + + + + Mined + Fossa + + + + Other + Alia + + + + Enter address or label to search + Insere inscriptionem vel titulum ut quaeras + + + + Min amount + Quantitas minima + + + + Copy address + Copia inscriptionem + + + + Copy label + Copia titulum + + + + Copy amount + Copia quantitatem + + + + Copy transaction ID + Copia transactionis ID + + + + Edit label + Muta titulum + + + + Show transaction details + Monstra particularia transactionis + + + + Export Transaction Data + + + + + Comma separated file (*.csv) + Comma Separata Plica (*.csv) + + + + Confirmed + Confirmatum + + + + Date + Dies + + + + Type + Typus + + + + Label + Titulus + + + + Address + Inscriptio + + + + Amount + Quantitas + + + + ID + ID + + + + Error exporting + + + + + Could not write to file %1. + + + + + Range: + Intervallum: + + + + to + ad + + + + WalletModel + + + Sending... + + + + + bitcoin-core + + + Arepacoin version + + + + + Usage: + Usus: + + + + Send command to -server or arepacoind + + + + + List commands + Enumera mandata + + + + Get help for a command + Accipe auxilium pro mandato + + + + Options: + Optiones: + + + + Specify configuration file (default: arepacoin.conf) + + + + + Specify pid file (default: arepacoind.pid) + + + + + Specify wallet file (within data directory) + + + + + Specify data directory + Specifica indicem datorum + + + + Set database cache size in megabytes (default: 25) + Constitue magnitudinem databasis cache in megabytes (praedefinitum: 25) + + + + Set database disk log size in megabytes (default: 100) + + + + + Listen for connections on <port> (default: 9853 or testnet: 19853) + + + + + Maintain at most <n> connections to peers (default: 125) + Manutene non plures quam <n> conexiones ad paria (praedefinitum: 125) + + + + Connect to a node to retrieve peer addresses, and disconnect + Conecta ad nodum acceptare inscriptiones parium, et disconecte + + + + Specify your own public address + Specifica tuam propriam publicam inscriptionem + + + + Bind to given address. Use [host]:port notation for IPv6 + + + + + Stake your coins to support network and gain reward (default: 1) + + + + + Threshold for disconnecting misbehaving peers (default: 100) + Limen pro disconectendo paria improba (praedefinitum: 100) + + + + Number of seconds to keep misbehaving peers from reconnecting (default: 86400) + Numerum secundorum prohibere ne paria improba reconectant (praedefinitum: 86400) + + + + An error occurred while setting up the RPC port %u for listening on IPv4: %s + Error erat dum initians portam RPC %u pro auscultando in IPv4: %s + + + + Detach block and address databases. Increases shutdown time (default: 0) + + + + + 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. + + + + + Error: This transaction requires a transaction fee of at least %s because of its amount, complexity, or use of recently received funds + + + + + Listen for JSON-RPC connections on <port> (default: 9852 or testnet: 19852) + + + + + Accept command line and JSON-RPC commands + Accipe terminalis et JSON-RPC mandata. + + + + Error: Transaction creation failed + + + + + Error: Wallet locked, unable to create transaction + + + + + Importing blockchain data file. + + + + + Importing bootstrap blockchain data file. + + + + + Run in the background as a daemon and accept commands + Operare infere sicut daemon et mandata accipe + + + + Use the test network + Utere rete experimentale + + + + Accept connections from outside (default: 1 if no -proxy or -connect) + Accipe conexiones externas (praedefinitum: 1 nisi -proxy neque -connect) + + + + An error occurred while setting up the RPC port %u for listening on IPv6, falling back to IPv4: %s + Error erat dum initians portam RPC %u pro auscultando in IPv6, labens retrorsum ad IPv4: %s + + + + Error initializing database environment %s! To recover, BACKUP THAT DIRECTORY, then remove everything from it except for wallet.dat. + + + + + Set maximum size of high-priority/low-fee transactions in bytes (default: 27000) + + + + + Warning: -paytxfee is set very high! This is the transaction fee you will pay if you send a transaction. + Monitio: -paytxfee constitutum valde magnum! Hoc est merces transactionis solves si mittis transactionem. + + + + Warning: Please check that your computer's date and time are correct! If your clock is wrong Arepacoin will not work properly. + + + + + Warning: error reading wallet.dat! All keys read correctly, but transaction data or address book entries might be missing or incorrect. + Monitio: error legendo wallet.dat! Omnes claves recte lectae, sed data transactionum vel libri inscriptionum fortasse desint vel prava sint. + + + + Warning: wallet.dat corrupt, data salvaged! Original wallet.dat saved as wallet.{timestamp}.bak in %s; if your balance or transactions are incorrect you should restore from a backup. + Monitio: wallet.data corrupta, data salvata! Originalis wallet.dat salvata ut wallet.{timestamp}.bak in %s; si pendendum tuum vel transactiones pravae sunt, oportet ab conservato restituere. + + + + Attempt to recover private keys from a corrupt wallet.dat + Conare recipere claves privatas de corrupto wallet.dat + + + + Block creation options: + Optiones creandi frustorum: + + + + Connect only to the specified node(s) + Conecte sole ad nodos specificatos (vel nodum specificatum) + + + + Discover own IP address (default: 1 when listening and no -externalip) + Discooperi propriam inscriptionem IP (praedefinitum: 1 quando auscultans et nullum -externalip) + + + + Failed to listen on any port. Use -listen=0 if you want this. + Non potuisse auscultare in ulla porta. Utere -listen=0 si hoc vis. + + + + Find peers using DNS lookup (default: 1) + + + + + Sync checkpoints policy (default: strict) + + + + + Invalid -tor address: '%s' + + + + + Invalid amount for -reservebalance=<amount> + + + + + Maximum per-connection receive buffer, <n>*1000 bytes (default: 5000) + Maxima magnitudo memoriae pro datis accipendis singulis conexionibus, <n>*1000 octetis/bytes (praedefinitum: 5000) + + + + Maximum per-connection send buffer, <n>*1000 bytes (default: 1000) + Maxima magnitudo memoriae pro datis mittendis singulis conexionibus, <n>*1000 octetis/bytes (praedefinitum: 1000) + + + + Only connect to nodes in network <net> (IPv4, IPv6 or Tor) + Tantum conecte ad nodos in rete <net> (IPv4, IPv6 aut Tor) + + + + Output extra debugging information. Implies all other -debug* options + + + + + Output extra network debugging information + + + + + Prepend debug output with timestamp + + + + + SSL options: (see the Bitcoin Wiki for SSL setup instructions) + Optiones SSL: (vide vici de Bitcoin pro instructionibus SSL configurationis) + + + + Select the version of socks proxy to use (4-5, default: 5) + + + + + Send trace/debug info to console instead of debug.log file + Mitte informationem vestigii/debug ad terminale potius quam plicam debug.log + + + + Send trace/debug info to debugger + + + + + Set maximum block size in bytes (default: 250000) + + + + + Set minimum block size in bytes (default: 0) + Constitue minimam magnitudinem frusti in octetis/bytes (praedefinitum: 0) + + + + Shrink debug.log file on client startup (default: 1 when no -debug) + Diminue plicam debug.log ad initium clientis (praedefinitum: 1 nisi -debug) + + + + Specify connection timeout in milliseconds (default: 5000) + Specifica tempumfati conexionis in millisecundis (praedefinitum: 5000) + + + + Unable to sign checkpoint, wrong checkpointkey? + + + + + + Use UPnP to map the listening port (default: 0) + Utere UPnP designare portam auscultandi (praedefinitum: 0) + + + + Use UPnP to map the listening port (default: 1 when listening) + Utere UPnP designare portam auscultandi (praedefinitum: 1 quando auscultans) + + + + Use proxy to reach tor hidden services (default: same as -proxy) + + + + + Username for JSON-RPC connections + Nomen utentis pro conexionibus JSON-RPC + + + + Verifying database integrity... + + + + + WARNING: syncronized checkpoint violation detected, but skipped! + + + + + Warning: Disk space is low! + + + + + Warning: This version is obsolete, upgrade required! + Monitio: Haec versio obsoleta est, progressio postulata! + + + + wallet.dat corrupt, salvage failed + wallet.dat corrupta, salvare abortum est + + + + Password for JSON-RPC connections + Tessera pro conexionibus JSON-RPC + + + + %s, you must set a rpcpassword in the configuration file: + %s +It is recommended you use the following random password: +rpcuser=arepacoinrpc +rpcpassword=%s +(you do not need to remember this password) +The username and password MUST NOT be the same. +If the file does not exist, create it with owner-readable-only file permissions. +It is also recommended to set alertnotify so you are notified of problems; +for example: alertnotify=echo %%s | mail -s "Arepacoin Alert" admin@foo.com + + + + + + Find peers using internet relay chat (default: 0) + + + + + Sync time with other nodes. Disable if time on your system is precise e.g. syncing with NTP (default: 1) + + + + + When creating transactions, ignore inputs with value less than this (default: 0.01) + + + + + Allow JSON-RPC connections from specified IP address + Permitte conexionibus JSON-RPC ex inscriptione specificata + + + + Send commands to node running on <ip> (default: 127.0.0.1) + Mitte mandata nodo operanti in <ip> (praedefinitum: 127.0.0.1) + + + + Execute command when the best block changes (%s in cmd is replaced by block hash) + Pelle mandatum quando optissimum frustum mutat (%s in mandato substituitur ab hash frusti) + + + + Execute command when a wallet transaction changes (%s in cmd is replaced by TxID) + Facere mandatum quotiescumque cassidilis transactio mutet (%s in mandato sbstituitur ab TxID) + + + + Require a confirmations for change (default: 0) + + + + + Enforce transaction scripts to use canonical PUSH operators (default: 1) + + + + + Execute command when a relevant alert is received (%s in cmd is replaced by message) + + + + + Upgrade wallet to latest format + Progredere cassidile ad formam recentissimam + + + + Set key pool size to <n> (default: 100) + Constitue magnitudinem stagni clavium ad <n> (praedefinitum: 100) + + + + Rescan the block chain for missing wallet transactions + Iterum perlege catenam frustorum propter absentes cassidilis transactiones + + + + How many blocks to check at startup (default: 2500, 0 = all) + + + + + How thorough the block verification is (0-6, default: 1) + + + + + Imports blocks from external blk000?.dat file + + + + + Use OpenSSL (https) for JSON-RPC connections + Utere OpenSSL (https) pro conexionibus JSON-RPC + + + + Server certificate file (default: server.cert) + Plica certificationis daemonis moderantis (praedefinitum: server.cert) + + + + Server private key (default: server.pem) + Clavis privata daemonis moderans (praedefinitum: server.pem) + + + + Acceptable ciphers (default: TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH) + + + + + Error: Wallet unlocked for staking only, unable to create transaction. + + + + + WARNING: Invalid checkpoint found! Displayed transactions may not be correct! You may need to upgrade, or notify developers. + + + + + This help message + Hic nuntius auxilii + + + + Wallet %s resides outside data directory %s. + + + + + Cannot obtain a lock on data directory %s. Arepacoin is probably already running. + + + + + Arepacoin + + + + + Unable to bind to %s on this computer (bind returned error %d, %s) + Non posse conglutinare ad %s in hoc computatro (conglutinare redidit errorem %d, %s) + + + + Connect through socks proxy + + + + + Allow DNS lookups for -addnode, -seednode and -connect + Permitte quaerenda DNS pro -addnode, -seednode, et -connect + + + + Loading addresses... + Legens inscriptiones... + + + + Error loading blkindex.dat + + + + + Error loading wallet.dat: Wallet corrupted + Error legendi wallet.dat: Cassidile corruptum + + + + Error loading wallet.dat: Wallet requires newer version of Arepacoin + + + + + Wallet needed to be rewritten: restart Arepacoin to complete + + + + + Error loading wallet.dat + Error legendi wallet.dat + + + + Invalid -proxy address: '%s' + Inscriptio -proxy non valida: '%s' + + + + Unknown network specified in -onlynet: '%s' + Ignotum rete specificatum in -onlynet: '%s' + + + + Unknown -socks proxy version requested: %i + Ignota -socks vicarii versio postulata: %i + + + + Cannot resolve -bind address: '%s' + Non posse resolvere -bind inscriptonem: '%s' + + + + Cannot resolve -externalip address: '%s' + Non posse resolvere -externalip inscriptionem: '%s' + + + + Invalid amount for -paytxfee=<amount>: '%s' + Quantitas non valida pro -paytxfee=<quantitas>: '%s' + + + + Error: could not start node + + + + + Sending... + + + + + Invalid amount + Quantitas non valida + + + + Insufficient funds + Inopia nummorum + + + + Loading block index... + Legens indicem frustorum... + + + + Add a node to connect to and attempt to keep the connection open + Adice nodum cui conectere et conare sustinere conexionem apertam + + + + Unable to bind to %s on this computer. Arepacoin is probably already running. + + + + + Fee per KB to add to transactions you send + + + + + Invalid amount for -mininput=<amount>: '%s' + + + + + Loading wallet... + Legens cassidile... + + + + Cannot downgrade wallet + Non posse cassidile regredi + + + + Cannot initialize keypool + + + + + Cannot write default address + Non posse scribere praedefinitam inscriptionem + + + + Rescanning... + Iterum perlegens... + + + + Done loading + Completo lengendi + + + + To use the %s option + Ut utaris optione %s + + + + Error + Error + + + + You must set rpcpassword=<password> in the configuration file: +%s +If the file does not exist, create it with owner-readable-only file permissions. + Necesse est te rpcpassword=<tesseram> constituere in plica configurationum: +%s +Si plica non existat, crea eam cum permissionibus ut solus eius dominus eam legere sinatur. + + + \ No newline at end of file diff --git a/src/qt/locale/bitcoin_lt.ts b/src/qt/locale/bitcoin_lt.ts new file mode 100755 index 0000000..3836649 --- /dev/null +++ b/src/qt/locale/bitcoin_lt.ts @@ -0,0 +1,3282 @@ + + + AboutDialog + + + About Arepacoin + + + + + <b>Arepacoin</b> version + + + + + Copyright © 2009-2014 The Bitcoin developers +Copyright © 2012-2014 The NovaCoin developers +Copyright © 2014 The Arepacoin developers + + + + + +This is experimental software. + +Distributed under the MIT/X11 software license, see the accompanying file COPYING or http://www.opensource.org/licenses/mit-license.php. + +This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit (http://www.openssl.org/) and cryptographic software written by Eric Young (eay@cryptsoft.com) and UPnP software written by Thomas Bernard. + Tai eksperimentinė programa. + +Platinama pagal MIT/X11 licenciją, kurią rasite faile COPYING arba http://www.opensource.org/licenses/mit-license.php. + +Šiame produkte yra OpenSSL projekto kuriamas OpenSSL Toolkit (http://www.openssl.org/), Eric Young parašyta kriptografinė programinė įranga bei Thomas Bernard sukurta UPnP programinė įranga. + + + + AddressBookPage + + + Address Book + + + + + Double-click to edit address or label + Spragtelėkite, kad pakeistumėte adresą arba žymę + + + + Create a new address + Sukurti naują adresą + + + + Copy the currently selected address to the system clipboard + Kopijuoti esamą adresą į mainų atmintį + + + + &New Address + + + + + These are your Arepacoin addresses for receiving payments. You may want to give a different one to each sender so you can keep track of who is paying you. + + + + + &Copy Address + &Kopijuoti adresą + + + + Show &QR Code + + + + + Sign a message to prove you own a Arepacoin address + + + + + Sign &Message + + + + + Delete the currently selected address from the list + + + + + Verify a message to ensure it was signed with a specified Arepacoin address + + + + + &Verify Message + + + + + &Delete + &Trinti + + + + Copy &Label + Kopijuoti ž&ymę + + + + &Edit + &Keisti + + + + Export Address Book Data + + + + + Comma separated file (*.csv) + Kableliais išskirtas failas (*.csv) + + + + Error exporting + + + + + Could not write to file %1. + + + + + AddressTableModel + + + Label + Žymė + + + + Address + Adresas + + + + (no label) + (nėra žymės) + + + + AskPassphraseDialog + + + Passphrase Dialog + Slaptafrazės dialogas + + + + Enter passphrase + Įvesti slaptafrazę + + + + New passphrase + Nauja slaptafrazė + + + + Repeat new passphrase + Pakartokite naują slaptafrazę + + + + Serves to disable the trivial sendmoney when OS account compromised. Provides no real security. + + + + + For staking only + + + + + Enter the new passphrase to the wallet.<br/>Please use a passphrase of <b>10 or more random characters</b>, or <b>eight or more words</b>. + Įveskite naują piniginės slaptafrazę.<br/>Prašome naudoti slaptafrazę iš <b> 10 ar daugiau atsitiktinių simbolių</b> arba <b>aštuonių ar daugiau žodžių</b>. + + + + Encrypt wallet + Užšifruoti piniginę + + + + This operation needs your wallet passphrase to unlock the wallet. + Ši operacija reikalauja jūsų piniginės slaptafrazės jai atrakinti. + + + + Unlock wallet + Atrakinti piniginę + + + + This operation needs your wallet passphrase to decrypt the wallet. + Ši operacija reikalauja jūsų piniginės slaptafrazės jai iššifruoti. + + + + Decrypt wallet + Iššifruoti piniginę + + + + Change passphrase + Pakeisti slaptafrazę + + + + Enter the old and new passphrase to the wallet. + Įveskite seną ir naują piniginės slaptafrazes. + + + + Confirm wallet encryption + Patvirtinkite piniginės užšifravimą + + + + Warning: If you encrypt your wallet and lose your passphrase, you will <b>LOSE ALL OF YOUR COINS</b>! + + + + + Are you sure you wish to encrypt your wallet? + Ar tikrai norite šifruoti savo piniginę? + + + + IMPORTANT: Any previous backups you have made of your wallet file should be replaced with the newly generated, encrypted wallet file. For security reasons, previous backups of the unencrypted wallet file will become useless as soon as you start using the new, encrypted wallet. + + + + + + Warning: The Caps Lock key is on! + Įspėjimas: įjungtas Caps Lock klavišas! + + + + + Wallet encrypted + Piniginė užšifruota + + + + Arepacoin will close now to finish the encryption process. Remember that encrypting your wallet cannot fully protect your coins from being stolen by malware infecting your computer. + + + + + + + + Wallet encryption failed + Nepavyko užšifruoti piniginę + + + + Wallet encryption failed due to an internal error. Your wallet was not encrypted. + Dėl vidinės klaidos nepavyko užšifruoti piniginę.Piniginė neužšifruota. + + + + + The supplied passphrases do not match. + Įvestos slaptafrazės nesutampa. + + + + Wallet unlock failed + Nepavyko atrakinti piniginę + + + + + + The passphrase entered for the wallet decryption was incorrect. + Neteisingai įvestas slaptažodis piniginės iššifravimui. + + + + Wallet decryption failed + Nepavyko iššifruoti piniginės + + + + Wallet passphrase was successfully changed. + Piniginės slaptažodis sėkmingai pakeistas. + + + + BitcoinGUI + + + Sign &message... + Pasirašyti ži&nutę... + + + + Synchronizing with network... + Sinchronizavimas su tinklu ... + + + + &Overview + &Apžvalga + + + + Show general overview of wallet + Rodyti piniginės bendrą apžvalgą + + + + &Transactions + &Sandoriai + + + + Browse transaction history + Apžvelgti sandorių istoriją + + + + &Address Book + + + + + Edit the list of stored addresses and labels + + + + + &Receive coins + + + + + Show the list of addresses for receiving payments + + + + + &Send coins + + + + + E&xit + &Išeiti + + + + Quit application + Išjungti programą + + + + Show information about Arepacoin + + + + + About &Qt + Apie &Qt + + + + Show information about Qt + Rodyti informaciją apie Qt + + + + &Options... + &Parinktys... + + + + &Encrypt Wallet... + &Užšifruoti piniginę... + + + + &Backup Wallet... + &Backup piniginę... + + + + &Change Passphrase... + &Keisti slaptafrazę... + + + + ~%n block(s) remaining + + + + + Downloaded %1 of %2 blocks of transaction history (%3% done). + + + + + &Export... + + + + + Send coins to a Arepacoin address + + + + + Modify configuration options for Arepacoin + + + + + Export the data in the current tab to a file + + + + + Encrypt or decrypt wallet + + + + + Backup wallet to another location + Daryti piniginės atsarginę kopiją + + + + Change the passphrase used for wallet encryption + Pakeisti slaptafrazę naudojamą piniginės užšifravimui + + + + &Debug window + &Derinimo langas + + + + Open debugging and diagnostic console + Atverti derinimo ir diagnostikos konsolę + + + + &Verify message... + &Tikrinti žinutę... + + + + Arepacoin + + + + + Wallet + Piniginė + + + + &About Arepacoin + + + + + &Show / Hide + &Rodyti / Slėpti + + + + Unlock wallet + + + + + &Lock Wallet + + + + + Lock wallet + + + + + &File + &Failas + + + + &Settings + &Nustatymai + + + + &Help + &Pagalba + + + + Tabs toolbar + Kortelių įrankinė + + + + Actions toolbar + + + + + + [testnet] + [testavimotinklas] + + + + + Arepacoin client + + + + + %n active connection(s) to Arepacoin network + + + + + Downloaded %1 blocks of transaction history. + + + + + Staking.<br>Your weight is %1<br>Network weight is %2<br>Expected time to earn reward is %3 + + + + + Not staking because wallet is locked + + + + + Not staking because wallet is offline + + + + + Not staking because wallet is syncing + + + + + Not staking because you don't have mature coins + + + + + %n second(s) ago + + + + + &Unlock Wallet... + + + + + %n minute(s) ago + + + + + %n hour(s) ago + + + + + %n day(s) ago + + + + + Up to date + Atnaujinta + + + + Catching up... + Vejamasi... + + + + Last received block was generated %1. + + + + + This transaction is over the size limit. You can still send it for a fee of %1, which goes to the nodes that process your transaction and helps to support the network. Do you want to pay the fee? + + + + + Confirm transaction fee + + + + + Sent transaction + Sandoris nusiųstas + + + + Incoming transaction + Ateinantis sandoris + + + + Date: %1 +Amount: %2 +Type: %3 +Address: %4 + + Data: %1 +Suma: %2 +Tipas: %3 +Adresas: %4 + + + + + URI handling + + + + + + URI can not be parsed! This can be caused by an invalid Arepacoin address or malformed URI parameters. + + + + + Wallet is <b>encrypted</b> and currently <b>unlocked</b> + Piniginė <b>užšifruota</b> ir šiuo metu <b>atrakinta</b> + + + + Wallet is <b>encrypted</b> and currently <b>locked</b> + Piniginė <b>užšifruota</b> ir šiuo metu <b>užrakinta</b> + + + + Backup Wallet + + + + + Wallet Data (*.dat) + + + + + Backup Failed + + + + + There was an error trying to save the wallet data to the new location. + + + + + %n second(s) + + + + + %n minute(s) + + + + + %n hour(s) + %n valanda%n valandos%n valandų + + + + %n day(s) + %n diena%n dienos%n dienų + + + + Not staking + + + + + A fatal error occurred. Arepacoin can no longer continue safely and will quit. + + + + + ClientModel + + + Network Alert + Tinklo įspėjimas + + + + CoinControlDialog + + + Coin Control + + + + + Quantity: + + + + + Bytes: + + + + + Amount: + Suma: + + + + Priority: + + + + + Fee: + + + + + Low Output: + + + + + no + + + + + After Fee: + + + + + Change: + + + + + (un)select all + + + + + Tree mode + + + + + List mode + + + + + Amount + Suma + + + + Label + + + + + Address + Adresas + + + + Date + Data + + + + Confirmations + + + + + Confirmed + Patvirtintas + + + + Priority + + + + + Copy address + Kopijuoti adresą + + + + Copy label + Kopijuoti žymę + + + + + Copy amount + Kopijuoti sumą + + + + Copy transaction ID + + + + + Copy quantity + + + + + Copy fee + + + + + Copy after fee + + + + + Copy bytes + + + + + Copy priority + + + + + Copy low output + + + + + Copy change + + + + + highest + + + + + high + + + + + medium-high + + + + + medium + + + + + low-medium + + + + + low + + + + + lowest + + + + + DUST + + + + + yes + + + + + This label turns red, if the transaction size is bigger than 10000 bytes. + + This means a fee of at least %1 per kb is required. + + Can vary +/- 1 Byte per input. + + + + + Transactions with higher priority get more likely into a block. + +This label turns red, if the priority is smaller than "medium". + + This means a fee of at least %1 per kb is required. + + + + + This label turns red, if any recipient receives an amount smaller than %1. + + This means a fee of at least %2 is required. + + Amounts below 0.546 times the minimum relay fee are shown as DUST. + + + + + This label turns red, if the change is smaller than %1. + + This means a fee of at least %2 is required. + + + + + + (no label) + (nėra žymės) + + + + change from %1 (%2) + + + + + (change) + + + + + EditAddressDialog + + + Edit Address + Keisti adresą + + + + &Label + Ž&ymė + + + + The label associated with this address book entry + + + + + &Address + &Adresas + + + + The address associated with this address book entry. This can only be modified for sending addresses. + + + + + New receiving address + Naujas gavimo adresas + + + + New sending address + Naujas siuntimo adresas + + + + Edit receiving address + Keisti gavimo adresą + + + + Edit sending address + Keisti siuntimo adresą + + + + The entered address "%1" is already in the address book. + Įvestas adresas „%1“ jau yra adresų knygelėje. + + + + The entered address "%1" is not a valid Arepacoin address. + + + + + Could not unlock wallet. + Nepavyko atrakinti piniginės. + + + + New key generation failed. + Naujo rakto generavimas nepavyko. + + + + GUIUtil::HelpMessageBox + + + + Arepacoin-Qt + + + + + version + + + + + Usage: + + + + + command-line options + + + + + UI options + + + + + Set language, for example "de_DE" (default: system locale) + + + + + Start minimized + + + + + Show splash screen on startup (default: 1) + + + + + OptionsDialog + + + Options + Parinktys + + + + &Main + &Pagrindinės + + + + Optional transaction fee per kB that helps make sure your transactions are processed quickly. Most transactions are 1 kB. Fee 0.01 recommended. + + + + + Pay transaction &fee + &Mokėti sandorio mokestį + + + + Reserved amount does not participate in staking and is therefore spendable at any time. + + + + + Reserve + + + + + Automatically start Arepacoin after logging in to the system. + + + + + &Start Arepacoin on system login + + + + + Detach block and address databases at shutdown. This means they can be moved to another data directory, but it slows down shutdown. The wallet is always detached. + + + + + &Detach databases at shutdown + + + + + &Network + &Tinklas + + + + Automatically open the Arepacoin client port on the router. This only works when your router supports UPnP and it is enabled. + + + + + Map port using &UPnP + Persiųsti prievadą naudojant &UPnP + + + + Connect to the Arepacoin network through a SOCKS proxy (e.g. when connecting through Tor). + + + + + &Connect through SOCKS proxy: + + + + + Proxy &IP: + Tarpinio serverio &IP: + + + + IP address of the proxy (e.g. 127.0.0.1) + + + + + &Port: + &Prievadas: + + + + Port of the proxy (e.g. 9050) + Tarpinio serverio preivadas (pvz, 9050) + + + + SOCKS &Version: + SOCKS &versija: + + + + SOCKS version of the proxy (e.g. 5) + Tarpinio serverio SOCKS versija (pvz., 5) + + + + &Window + &Langas + + + + Show only a tray icon after minimizing the window. + Po programos lango sumažinimo rodyti tik programos ikoną. + + + + &Minimize to the tray instead of the taskbar + &M sumažinti langą bet ne užduočių juostą + + + + Minimize instead of exit the application when the window is closed. When this option is enabled, the application will be closed only after selecting Quit in the menu. + Uždarant langą neuždaryti programos. Kai ši parinktis įjungta, programa bus uždaryta tik pasirinkus meniu komandą Baigti. + + + + M&inimize on close + &Sumažinti uždarant + + + + &Display + &Rodymas + + + + User Interface &language: + Naudotojo sąsajos &kalba: + + + + The user interface language can be set here. This setting will take effect after restarting Arepacoin. + + + + + &Unit to show amounts in: + &Vienetai, kuriais rodyti sumas: + + + + Choose the default subdivision unit to show in the interface and when sending coins. + Rodomų ir siunčiamų monetų kiekio matavimo vienetai + + + + Whether to show Arepacoin addresses in the transaction list or not. + + + + + &Display addresses in transaction list + &Rodyti adresus sandorių sąraše + + + + Whether to show coin control features or not. + + + + + Display coin &control features (experts only!) + + + + + &OK + &Gerai + + + + &Cancel + &Atšaukti + + + + &Apply + + + + + default + numatyta + + + + + Warning + + + + + + This setting will take effect after restarting Arepacoin. + + + + + The supplied proxy address is invalid. + Nurodytas tarpinio serverio adresas negalioja. + + + + OverviewPage + + + Form + Forma + + + + + The displayed information may be out of date. Your wallet automatically synchronizes with the Arepacoin network after a connection is established, but this process has not completed yet. + + + + + Stake: + + + + + Unconfirmed: + + + + + Wallet + Piniginė + + + + Spendable: + + + + + Your current spendable balance + + + + + Immature: + Nepribrendę: + + + + Mined balance that has not yet matured + + + + + Total: + Viso: + + + + Your current total balance + Jūsų balansas + + + + <b>Recent transactions</b> + <b>Naujausi sandoriai</b> + + + + Total of transactions that have yet to be confirmed, and do not yet count toward the current balance + + + + + Total of coins that was staked, and do not yet count toward the current balance + + + + + + out of sync + nesinchronizuota + + + + QRCodeDialog + + + QR Code Dialog + + + + + Request Payment + + + + + Amount: + + + + + Label: + + + + + Message: + + + + + &Save As... + + + + + Error encoding URI into QR Code. + + + + + The entered amount is invalid, please check. + + + + + Resulting URI too long, try to reduce the text for label / message. + + + + + Save QR Code + + + + + PNG Images (*.png) + + + + + RPCConsole + + + Client name + Kliento pavadinimas + + + + + + + + + + + + + N/A + nėra + + + + Client version + Kliento versija + + + + &Information + &Informacija + + + + Using OpenSSL version + Naudojama OpenSSL versija + + + + Startup time + Paleidimo laikas + + + + Network + Tinklas + + + + Number of connections + Prisijungimų kiekis + + + + On testnet + + + + + Block chain + Blokų grandinė + + + + Current number of blocks + Dabartinis blokų skaičius + + + + Estimated total blocks + + + + + Last block time + Paskutinio bloko laikas + + + + &Open + &Atverti + + + + Command-line options + + + + + Show the Arepacoin-Qt help message to get a list with possible Arepacoin command-line options. + + + + + &Show + + + + + &Console + &Konsolė + + + + Build date + Kompiliavimo data + + + + Arepacoin - Debug window + + + + + Arepacoin Core + + + + + Debug log file + Derinimo žurnalo failas + + + + Open the Arepacoin debug log file from the current data directory. This can take a few seconds for large log files. + + + + + Clear console + Išvalyti konsolę + + + + Welcome to the Arepacoin RPC console. + + + + + Use up and down arrows to navigate history, and <b>Ctrl-L</b> to clear screen. + + + + + Type <b>help</b> for an overview of available commands. + + + + + SendCoinsDialog + + + + + + + + + + Send Coins + Siųsti monetas + + + + Coin Control Features + + + + + Inputs... + + + + + automatically selected + + + + + Insufficient funds! + + + + + Quantity: + + + + + + 0 + + + + + Bytes: + + + + + Amount: + Suma: + + + + + + + 0.00 BC + + + + + Priority: + + + + + medium + + + + + Fee: + + + + + Low Output: + + + + + no + + + + + After Fee: + + + + + Change + + + + + custom change address + + + + + Send to multiple recipients at once + Siųsti keliems gavėjams vienu metu + + + + Add &Recipient + &A Pridėti gavėją + + + + Remove all transaction fields + + + + + Clear &All + Išvalyti &viską + + + + Balance: + Balansas: + + + + 123.456 BC + + + + + Confirm the send action + Patvirtinti siuntimo veiksmą + + + + S&end + &Siųsti + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Copy quantity + + + + + Copy amount + Kopijuoti sumą + + + + Copy fee + + + + + Copy after fee + + + + + Copy bytes + + + + + Copy priority + + + + + Copy low output + + + + + Copy change + + + + + <b>%1</b> to %2 (%3) + + + + + Confirm send coins + Patvirtinti monetų siuntimą + + + + Are you sure you want to send %1? + + + + + and + + + + + The recipient address is not valid, please recheck. + Negaliojantis gavėjo adresas. Patikrinkite. + + + + The amount to pay must be larger than 0. + Apmokėjimo suma turi būti didesnė nei 0. + + + + The amount exceeds your balance. + Suma viršija jūsų balansą. + + + + The total exceeds your balance when the %1 transaction fee is included. + Jei pridedame sandorio mokestį %1 bendra suma viršija jūsų balansą. + + + + Duplicate address found, can only send to each address once per send operation. + Rastas adreso dublikatas. + + + + Error: Transaction creation failed. + + + + + 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. + + + + + WARNING: Invalid Arepacoin address + + + + + (no label) + (nėra žymės) + + + + WARNING: unknown change address + + + + + SendCoinsEntry + + + Form + + + + + A&mount: + Su&ma: + + + + Pay &To: + Mokėti &gavėjui: + + + + + Enter a label for this address to add it to your address book + Įveskite žymę šiam adresui kad galėtumėte įtraukti ją į adresų knygelę + + + + &Label: + Ž&ymė: + + + + The address to send the payment to (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Choose address from address book + + + + + Alt+A + Alt+A + + + + Paste address from clipboard + Įvesti adresą iš mainų atminties + + + + Alt+P + Alt+P + + + + Remove this recipient + + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + SignVerifyMessageDialog + + + Signatures - Sign / Verify a Message + + + + + + &Sign Message + &Pasirašyti žinutę + + + + You can sign messages with your addresses to prove you own them. Be careful not to sign anything vague, as phishing attacks may try to trick you into signing your identity over to them. Only sign fully-detailed statements you agree to. + + + + + The address to sign the message with (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + + Choose an address from the address book + + + + + + Alt+A + Alt+A + + + + Paste address from clipboard + Įvesti adresą iš mainų atminties + + + + Alt+P + Alt+P + + + + Enter the message you want to sign here + Įveskite pranešimą, kurį norite pasirašyti čia + + + + Copy the current signature to the system clipboard + + + + + Sign the message to prove you own this Arepacoin address + + + + + Reset all sign message fields + + + + + + Clear &All + Išvalyti &viską + + + + + &Verify Message + &Patikrinti žinutę + + + + Enter the signing address, message (ensure you copy line breaks, spaces, tabs, etc. exactly) and signature below to verify the message. Be careful not to read more into the signature than what is in the signed message itself, to avoid being tricked by a man-in-the-middle attack. + + + + + The address the message was signed with (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Verify the message to ensure it was signed with the specified Arepacoin address + + + + + Reset all verify message fields + + + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Click "Sign Message" to generate signature + Spragtelėkite "Registruotis žinutę" tam, kad gauti parašą + + + + Enter Arepacoin signature + + + + + + The entered address is invalid. + Įvestas adresas negalioja. + + + + + + + Please check the address and try again. + Prašom patikrinti adresą ir bandyti iš naujo. + + + + + The entered address does not refer to a key. + + + + + Wallet unlock was cancelled. + Piniginės atrakinimas atšauktas. + + + + Private key for the entered address is not available. + + + + + Message signing failed. + Žinutės pasirašymas nepavyko. + + + + Message signed. + Žinutė pasirašyta. + + + + The signature could not be decoded. + Nepavyko iškoduoti parašo. + + + + + Please check the signature and try again. + Prašom patikrinti parašą ir bandyti iš naujo. + + + + The signature did not match the message digest. + Parašas neatitinka žinutės. + + + + Message verification failed. + Žinutės tikrinimas nepavyko. + + + + Message verified. + Žinutė patikrinta. + + + + TransactionDesc + + + Open until %1 + Atidaryta iki %1 + + + + Open for %n block(s) + + + + + conflicted + + + + + %1/offline + %1/neprisijungęs + + + + %1/unconfirmed + %1/nepatvirtintas + + + + %1 confirmations + %1 patvirtinimų + + + + Status + Būsena + + + + , broadcast through %n node(s) + + + + + Date + Data + + + + Source + Šaltinis + + + + Generated + Sugeneruotas + + + + + From + Nuo + + + + + + To + Kam + + + + + own address + savo adresas + + + + label + žymė + + + + + + + + Credit + Kreditas + + + + matures in %n more block(s) + + + + + not accepted + nepriimta + + + + + + + Debit + Debitas + + + + Transaction fee + Sandorio mokestis + + + + Net amount + Neto suma + + + + Message + Žinutė + + + + Comment + Komentaras + + + + Transaction ID + Sandorio ID + + + + Generated coins must mature 6 blocks before they can be spent. When you generated this block, it was broadcast to the network to be added to the block chain. If it fails to get into the chain, its state will change to "not accepted" and it won't be spendable. This may occasionally happen if another node generates a block within a few seconds of yours. + + + + + Debug information + Derinimo informacija + + + + Transaction + Sandoris + + + + Inputs + + + + + Amount + Suma + + + + true + tiesa + + + + false + netiesa + + + + , has not been successfully broadcast yet + , transliavimas dar nebuvo sėkmingas + + + + unknown + nežinomas + + + + TransactionDescDialog + + + Transaction details + Sandorio detelės + + + + This pane shows a detailed description of the transaction + Šis langas sandorio detalų aprašymą + + + + TransactionTableModel + + + Date + Data + + + + Type + Tipas + + + + Address + Adresas + + + + Amount + Suma + + + + Open until %1 + Atidaryta iki %1 + + + + Confirmed (%1 confirmations) + Patvirtinta (%1 patvirtinimai) + + + + Open for %n more block(s) + + + + + Offline + + + + + Unconfirmed + + + + + Confirming (%1 of %2 recommended confirmations) + + + + + Conflicted + + + + + Immature (%1 confirmations, will be available after %2) + + + + + This block was not received by any other nodes and will probably not be accepted! + Šis blokas negautas nė vienu iš mazgų ir matomai nepriimtas + + + + Generated but not accepted + Išgauta bet nepriimta + + + + Received with + Gauta su + + + + Received from + Gauta iš + + + + Sent to + Siųsta + + + + Payment to yourself + Mokėjimas sau + + + + Mined + Išgauta + + + + (n/a) + nepasiekiama + + + + Transaction status. Hover over this field to show number of confirmations. + Sandorio būklė. Užvedus pelės žymeklį ant šios srities matysite patvirtinimų skaičių. + + + + Date and time that the transaction was received. + Sandorio gavimo data ir laikas + + + + Type of transaction. + Sandorio tipas. + + + + Destination address of transaction. + Sandorio paskirties adresas + + + + Amount removed from or added to balance. + Suma pridėta ar išskaičiuota iš balanso + + + + TransactionView + + + + All + Visi + + + + Today + Šiandien + + + + This week + Šią savaitę + + + + This month + Šį mėnesį + + + + Last month + Paskutinį mėnesį + + + + This year + Šiais metais + + + + Range... + Intervalas... + + + + Received with + Gauta su + + + + Sent to + Išsiųsta + + + + To yourself + Skirta sau + + + + Mined + Išgauta + + + + Other + Kita + + + + Enter address or label to search + Įveskite adresą ar žymę į paiešką + + + + Min amount + Minimali suma + + + + Copy address + Kopijuoti adresą + + + + Copy label + Kopijuoti žymę + + + + Copy amount + Kopijuoti sumą + + + + Copy transaction ID + + + + + Edit label + Taisyti žymę + + + + Show transaction details + Rodyti sandėrio detales + + + + Export Transaction Data + + + + + Comma separated file (*.csv) + Kableliais atskirtų duomenų failas (*.csv) + + + + Confirmed + Patvirtintas + + + + Date + Data + + + + Type + Tipas + + + + Label + Žymė + + + + Address + Adresas + + + + Amount + Suma + + + + ID + ID + + + + Error exporting + + + + + Could not write to file %1. + + + + + Range: + Grupė: + + + + to + skirta + + + + WalletModel + + + Sending... + + + + + bitcoin-core + + + Arepacoin version + + + + + Usage: + Naudojimas: + + + + Send command to -server or arepacoind + + + + + List commands + Komandų sąrašas + + + + Get help for a command + Suteikti pagalba komandai + + + + Options: + Parinktys: + + + + Specify configuration file (default: arepacoin.conf) + + + + + Specify pid file (default: arepacoind.pid) + + + + + Specify wallet file (within data directory) + + + + + Specify data directory + Nustatyti duomenų aplanką + + + + Set database cache size in megabytes (default: 25) + + + + + Set database disk log size in megabytes (default: 100) + + + + + Listen for connections on <port> (default: 9853 or testnet: 19853) + + + + + Maintain at most <n> connections to peers (default: 125) + Palaikyti ne daugiau <n> jungčių kolegoms (pagal nutylėjimą: 125) + + + + Connect to a node to retrieve peer addresses, and disconnect + + + + + Specify your own public address + + + + + Bind to given address. Use [host]:port notation for IPv6 + + + + + Stake your coins to support network and gain reward (default: 1) + + + + + Threshold for disconnecting misbehaving peers (default: 100) + Atjungimo dėl netinkamo kolegų elgesio riba (pagal nutylėjimą: 100) + + + + Number of seconds to keep misbehaving peers from reconnecting (default: 86400) + Sekundžių kiekis eikiamas palaikyti ryšį dėl lygiarangių nestabilumo (pagal nutylėjimą: 86.400) + + + + An error occurred while setting up the RPC port %u for listening on IPv4: %s + + + + + Detach block and address databases. Increases shutdown time (default: 0) + + + + + 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. + + + + + Error: This transaction requires a transaction fee of at least %s because of its amount, complexity, or use of recently received funds + + + + + Listen for JSON-RPC connections on <port> (default: 9852 or testnet: 19852) + + + + + Accept command line and JSON-RPC commands + Priimti komandinę eilutę ir JSON-RPC komandas + + + + Error: Transaction creation failed + + + + + Error: Wallet locked, unable to create transaction + + + + + Importing blockchain data file. + + + + + Importing bootstrap blockchain data file. + + + + + Run in the background as a daemon and accept commands + Dirbti fone kaip šešėlyje ir priimti komandas + + + + Use the test network + Naudoti testavimo tinklą + + + + Accept connections from outside (default: 1 if no -proxy or -connect) + + + + + An error occurred while setting up the RPC port %u for listening on IPv6, falling back to IPv4: %s + + + + + Error initializing database environment %s! To recover, BACKUP THAT DIRECTORY, then remove everything from it except for wallet.dat. + + + + + Set maximum size of high-priority/low-fee transactions in bytes (default: 27000) + + + + + Warning: -paytxfee is set very high! This is the transaction fee you will pay if you send a transaction. + Įspėjimas: -paytxfee yra nustatytas per didelis. Tai sandorio mokestis, kurį turėsite mokėti, jei siųsite sandorį. + + + + Warning: Please check that your computer's date and time are correct! If your clock is wrong Arepacoin will not work properly. + + + + + Warning: error reading wallet.dat! All keys read correctly, but transaction data or address book entries might be missing or incorrect. + + + + + Warning: wallet.dat corrupt, data salvaged! Original wallet.dat saved as wallet.{timestamp}.bak in %s; if your balance or transactions are incorrect you should restore from a backup. + + + + + Attempt to recover private keys from a corrupt wallet.dat + + + + + Block creation options: + + + + + Connect only to the specified node(s) + Prisijungti tik prie nurodyto mazgo + + + + Discover own IP address (default: 1 when listening and no -externalip) + + + + + Failed to listen on any port. Use -listen=0 if you want this. + + + + + Find peers using DNS lookup (default: 1) + + + + + Sync checkpoints policy (default: strict) + + + + + Invalid -tor address: '%s' + + + + + Invalid amount for -reservebalance=<amount> + + + + + Maximum per-connection receive buffer, <n>*1000 bytes (default: 5000) + Maksimalus buferis priėmimo sujungimui <n>*1000 bitų (pagal nutylėjimą: 5000) + + + + Maximum per-connection send buffer, <n>*1000 bytes (default: 1000) + Maksimalus buferis siuntimo sujungimui <n>*1000 bitų (pagal nutylėjimą: 1000) + + + + Only connect to nodes in network <net> (IPv4, IPv6 or Tor) + + + + + Output extra debugging information. Implies all other -debug* options + + + + + Output extra network debugging information + + + + + Prepend debug output with timestamp + + + + + SSL options: (see the Bitcoin Wiki for SSL setup instructions) + SSL opcijos (žr.e Bitcoin Wiki for SSL setup instructions) + + + + Select the version of socks proxy to use (4-5, default: 5) + + + + + Send trace/debug info to console instead of debug.log file + Siųsti atsekimo/derinimo info į konsolę vietoj debug.log failo + + + + Send trace/debug info to debugger + + + + + Set maximum block size in bytes (default: 250000) + + + + + Set minimum block size in bytes (default: 0) + + + + + Shrink debug.log file on client startup (default: 1 when no -debug) + + + + + Specify connection timeout in milliseconds (default: 5000) + Nustatyti sujungimo trukmę milisekundėmis (pagal nutylėjimą: 5000) + + + + Unable to sign checkpoint, wrong checkpointkey? + + + + + + Use UPnP to map the listening port (default: 0) + Bandymas naudoti UPnP struktūra klausymosi prievadui (default: 0) + + + + Use UPnP to map the listening port (default: 1 when listening) + Bandymas naudoti UPnP struktūra klausymosi prievadui (default: 1 when listening) + + + + Use proxy to reach tor hidden services (default: same as -proxy) + + + + + Username for JSON-RPC connections + Vartotojo vardas JSON-RPC jungimuisi + + + + Verifying database integrity... + + + + + WARNING: syncronized checkpoint violation detected, but skipped! + + + + + Warning: Disk space is low! + + + + + Warning: This version is obsolete, upgrade required! + + + + + wallet.dat corrupt, salvage failed + + + + + Password for JSON-RPC connections + Slaptažodis JSON-RPC sujungimams + + + + %s, you must set a rpcpassword in the configuration file: + %s +It is recommended you use the following random password: +rpcuser=arepacoinrpc +rpcpassword=%s +(you do not need to remember this password) +The username and password MUST NOT be the same. +If the file does not exist, create it with owner-readable-only file permissions. +It is also recommended to set alertnotify so you are notified of problems; +for example: alertnotify=echo %%s | mail -s "Arepacoin Alert" admin@foo.com + + + + + + Find peers using internet relay chat (default: 0) + + + + + Sync time with other nodes. Disable if time on your system is precise e.g. syncing with NTP (default: 1) + + + + + When creating transactions, ignore inputs with value less than this (default: 0.01) + + + + + Allow JSON-RPC connections from specified IP address + Leisti JSON-RPC tik iš nurodytų IP adresų + + + + Send commands to node running on <ip> (default: 127.0.0.1) + Siųsti komandą mazgui dirbančiam <ip> (pagal nutylėjimą: 127.0.0.1) + + + + Execute command when the best block changes (%s in cmd is replaced by block hash) + + + + + Execute command when a wallet transaction changes (%s in cmd is replaced by TxID) + + + + + Require a confirmations for change (default: 0) + + + + + Enforce transaction scripts to use canonical PUSH operators (default: 1) + + + + + Execute command when a relevant alert is received (%s in cmd is replaced by message) + + + + + Upgrade wallet to latest format + Atnaujinti piniginę į naujausią formatą + + + + Set key pool size to <n> (default: 100) + Nustatyti rakto apimties dydį <n> (pagal nutylėjimą: 100) + + + + Rescan the block chain for missing wallet transactions + Ieškoti prarastų piniginės sandorių blokų grandinėje + + + + How many blocks to check at startup (default: 2500, 0 = all) + + + + + How thorough the block verification is (0-6, default: 1) + + + + + Imports blocks from external blk000?.dat file + + + + + Use OpenSSL (https) for JSON-RPC connections + Naudoti OpenSSL (https) jungimuisi JSON-RPC + + + + Server certificate file (default: server.cert) + Serverio sertifikato failas (pagal nutylėjimą: server.cert) + + + + Server private key (default: server.pem) + Serverio privatus raktas (pagal nutylėjimą: server.pem) + + + + Acceptable ciphers (default: TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH) + + + + + Error: Wallet unlocked for staking only, unable to create transaction. + + + + + WARNING: Invalid checkpoint found! Displayed transactions may not be correct! You may need to upgrade, or notify developers. + + + + + This help message + Pagelbos žinutė + + + + Wallet %s resides outside data directory %s. + + + + + Cannot obtain a lock on data directory %s. Arepacoin is probably already running. + + + + + Arepacoin + + + + + Unable to bind to %s on this computer (bind returned error %d, %s) + Nepavyko susieti šiame kompiuteryje prievado %s (bind returned error %d, %s) + + + + Connect through socks proxy + + + + + Allow DNS lookups for -addnode, -seednode and -connect + Leisti DNS paiešką sujungimui ir mazgo pridėjimui + + + + Loading addresses... + Užkraunami adresai... + + + + Error loading blkindex.dat + + + + + Error loading wallet.dat: Wallet corrupted + wallet.dat pakrovimo klaida, wallet.dat sugadintas + + + + Error loading wallet.dat: Wallet requires newer version of Arepacoin + + + + + Wallet needed to be rewritten: restart Arepacoin to complete + + + + + Error loading wallet.dat + wallet.dat pakrovimo klaida + + + + Invalid -proxy address: '%s' + Neteisingas proxy adresas: '%s' + + + + Unknown network specified in -onlynet: '%s' + + + + + Unknown -socks proxy version requested: %i + + + + + Cannot resolve -bind address: '%s' + + + + + Cannot resolve -externalip address: '%s' + + + + + Invalid amount for -paytxfee=<amount>: '%s' + Neteisinga suma -paytxfee=<amount>: '%s' + + + + Error: could not start node + + + + + Sending... + + + + + Invalid amount + Neteisinga suma + + + + Insufficient funds + Nepakanka lėšų + + + + Loading block index... + Įkeliamas blokų indeksas... + + + + Add a node to connect to and attempt to keep the connection open + Pridėti mazgą prie sujungti su and attempt to keep the connection open + + + + Unable to bind to %s on this computer. Arepacoin is probably already running. + + + + + Fee per KB to add to transactions you send + + + + + Invalid amount for -mininput=<amount>: '%s' + + + + + Loading wallet... + Užkraunama piniginė... + + + + Cannot downgrade wallet + + + + + Cannot initialize keypool + + + + + Cannot write default address + + + + + Rescanning... + Peržiūra + + + + Done loading + Įkėlimas baigtas + + + + To use the %s option + + + + + Error + Klaida + + + + You must set rpcpassword=<password> in the configuration file: +%s +If the file does not exist, create it with owner-readable-only file permissions. + + + + \ No newline at end of file diff --git a/src/qt/locale/bitcoin_lv_LV.ts b/src/qt/locale/bitcoin_lv_LV.ts new file mode 100755 index 0000000..338700a --- /dev/null +++ b/src/qt/locale/bitcoin_lv_LV.ts @@ -0,0 +1,3281 @@ + + + AboutDialog + + + About Arepacoin + + + + + <b>Arepacoin</b> version + + + + + Copyright © 2009-2014 The Bitcoin developers +Copyright © 2012-2014 The NovaCoin developers +Copyright © 2014 The Arepacoin developers + + + + + +This is experimental software. + +Distributed under the MIT/X11 software license, see the accompanying file COPYING or http://www.opensource.org/licenses/mit-license.php. + +This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit (http://www.openssl.org/) and cryptographic software written by Eric Young (eay@cryptsoft.com) and UPnP software written by Thomas Bernard. + + + + + AddressBookPage + + + Address Book + + + + + Double-click to edit address or label + Adresi vai nosaukumu rediģē ar dubultklikšķi + + + + Create a new address + Izveidot jaunu adresi + + + + Copy the currently selected address to the system clipboard + Kopēt iezīmēto adresi uz starpliktuvi + + + + &New Address + + + + + These are your Arepacoin addresses for receiving payments. You may want to give a different one to each sender so you can keep track of who is paying you. + + + + + &Copy Address + &Kopēt adresi + + + + Show &QR Code + + + + + Sign a message to prove you own a Arepacoin address + + + + + Sign &Message + + + + + Delete the currently selected address from the list + + + + + Verify a message to ensure it was signed with a specified Arepacoin address + + + + + &Verify Message + + + + + &Delete + &Dzēst + + + + Copy &Label + Kopēt &Nosaukumu + + + + &Edit + &Rediģēt + + + + Export Address Book Data + + + + + Comma separated file (*.csv) + Fails ar komatu kā atdalītāju (*.csv) + + + + Error exporting + + + + + Could not write to file %1. + + + + + AddressTableModel + + + Label + Nosaukums + + + + Address + Adrese + + + + (no label) + (bez nosaukuma) + + + + AskPassphraseDialog + + + Passphrase Dialog + Paroles dialogs + + + + Enter passphrase + Ierakstiet paroli + + + + New passphrase + Jauna parole + + + + Repeat new passphrase + Jaunā parole vēlreiz + + + + Serves to disable the trivial sendmoney when OS account compromised. Provides no real security. + + + + + For staking only + + + + + Enter the new passphrase to the wallet.<br/>Please use a passphrase of <b>10 or more random characters</b>, or <b>eight or more words</b>. + Ierakstiet maciņa jauno paroli.<br/>Lūdzu izmantojiet <b>10 vai vairāk nejauši izvēlētas zīmes</b>, vai <b>astoņus un vairāk vārdus</b>. + + + + Encrypt wallet + Šifrēt maciņu + + + + This operation needs your wallet passphrase to unlock the wallet. + Lai veikto šo darbību, maciņš jāatslēdz ar paroli. + + + + Unlock wallet + Atslēgt maciņu + + + + This operation needs your wallet passphrase to decrypt the wallet. + Šai darbībai maciņš jāatšifrē ar maciņa paroli. + + + + Decrypt wallet + Atšifrēt maciņu + + + + Change passphrase + Mainīt paroli + + + + Enter the old and new passphrase to the wallet. + Ierakstiet maciņa veco un jauno paroli. + + + + Confirm wallet encryption + Apstiprināt maciņa šifrēšanu + + + + Warning: If you encrypt your wallet and lose your passphrase, you will <b>LOSE ALL OF YOUR COINS</b>! + + + + + Are you sure you wish to encrypt your wallet? + + + + + IMPORTANT: Any previous backups you have made of your wallet file should be replaced with the newly generated, encrypted wallet file. For security reasons, previous backups of the unencrypted wallet file will become useless as soon as you start using the new, encrypted wallet. + + + + + + Warning: The Caps Lock key is on! + + + + + + Wallet encrypted + Maciņš nošifrēts + + + + Arepacoin will close now to finish the encryption process. Remember that encrypting your wallet cannot fully protect your coins from being stolen by malware infecting your computer. + + + + + + + + Wallet encryption failed + Maciņa šifrēšana neizdevās + + + + Wallet encryption failed due to an internal error. Your wallet was not encrypted. + Maciņa šifrēšana neizdevās programmas kļūdas dēļ. Jūsu maciņš netika šifrēts. + + + + + The supplied passphrases do not match. + Ievadītās paroles nav vienādas. + + + + Wallet unlock failed + Maciņu atšifrēt neizdevās + + + + + + The passphrase entered for the wallet decryption was incorrect. + Maciņa atšifrēšanai ievadītā parole nav pareiza. + + + + Wallet decryption failed + Maciņu neizdevās atšifrēt + + + + Wallet passphrase was successfully changed. + + + + + BitcoinGUI + + + Sign &message... + Parakstīt &ziņojumu... + + + + Synchronizing with network... + Sinhronizācija ar tīklu... + + + + &Overview + &Pārskats + + + + Show general overview of wallet + Rādīt vispārēju maciņa pārskatu + + + + &Transactions + &Transakcijas + + + + Browse transaction history + Skatīt transakciju vēsturi + + + + &Address Book + + + + + Edit the list of stored addresses and labels + + + + + &Receive coins + + + + + Show the list of addresses for receiving payments + + + + + &Send coins + + + + + E&xit + &Iziet + + + + Quit application + Aizvērt programmu + + + + Show information about Arepacoin + + + + + About &Qt + Par &Qt + + + + Show information about Qt + Parādīt informāciju par Qt + + + + &Options... + &Iespējas + + + + &Encrypt Wallet... + Š&ifrēt maciņu... + + + + &Backup Wallet... + &Izveidot maciņa rezerves kopiju + + + + &Change Passphrase... + &Mainīt paroli + + + + ~%n block(s) remaining + + + + + Downloaded %1 of %2 blocks of transaction history (%3% done). + + + + + &Export... + + + + + Send coins to a Arepacoin address + + + + + Modify configuration options for Arepacoin + + + + + Export the data in the current tab to a file + + + + + Encrypt or decrypt wallet + + + + + Backup wallet to another location + Izveidot maciņa rezerves kopiju citur + + + + Change the passphrase used for wallet encryption + Mainīt maciņa šifrēšanas paroli + + + + &Debug window + &Debug logs + + + + Open debugging and diagnostic console + Atvērt atkļūdošanas un diagnostikas konsoli + + + + &Verify message... + &Pārbaudīt ziņojumu... + + + + Arepacoin + + + + + Wallet + Maciņš + + + + &About Arepacoin + + + + + &Show / Hide + + + + + Unlock wallet + + + + + &Lock Wallet + + + + + Lock wallet + + + + + &File + &Fails + + + + &Settings + &Uzstādījumi + + + + &Help + &Palīdzība + + + + Tabs toolbar + Ciļņu rīkjosla + + + + Actions toolbar + + + + + + [testnet] + [testnet] + + + + + Arepacoin client + + + + + %n active connection(s) to Arepacoin network + + + + + Downloaded %1 blocks of transaction history. + + + + + Staking.<br>Your weight is %1<br>Network weight is %2<br>Expected time to earn reward is %3 + + + + + Not staking because wallet is locked + + + + + Not staking because wallet is offline + + + + + Not staking because wallet is syncing + + + + + Not staking because you don't have mature coins + + + + + %n second(s) ago + + + + + &Unlock Wallet... + + + + + %n minute(s) ago + + + + + %n hour(s) ago + + + + + %n day(s) ago + + + + + Up to date + Sinhronizēts + + + + Catching up... + Sinhronizējos... + + + + Last received block was generated %1. + + + + + This transaction is over the size limit. You can still send it for a fee of %1, which goes to the nodes that process your transaction and helps to support the network. Do you want to pay the fee? + + + + + Confirm transaction fee + + + + + Sent transaction + Transakcija nosūtīta + + + + Incoming transaction + Ienākoša transakcija + + + + Date: %1 +Amount: %2 +Type: %3 +Address: %4 + + Datums: %1 +Daudzums: %2 +Tips: %3 +Adrese: %4 + + + + + + URI handling + + + + + + URI can not be parsed! This can be caused by an invalid Arepacoin address or malformed URI parameters. + + + + + Wallet is <b>encrypted</b> and currently <b>unlocked</b> + Maciņš ir <b>šifrēts</b> un pašlaik <b>atslēgts</b> + + + + Wallet is <b>encrypted</b> and currently <b>locked</b> + Maciņš ir <b>šifrēts</b> un pašlaik <b>slēgts</b> + + + + Backup Wallet + + + + + Wallet Data (*.dat) + + + + + Backup Failed + + + + + There was an error trying to save the wallet data to the new location. + + + + + %n second(s) + + + + + %n minute(s) + + + + + %n hour(s) + + + + + %n day(s) + + + + + Not staking + + + + + A fatal error occurred. Arepacoin can no longer continue safely and will quit. + + + + + ClientModel + + + Network Alert + Tīkla brīdinājums + + + + CoinControlDialog + + + Coin Control + + + + + Quantity: + + + + + Bytes: + + + + + Amount: + Daudzums: + + + + Priority: + + + + + Fee: + + + + + Low Output: + + + + + no + + + + + After Fee: + + + + + Change: + + + + + (un)select all + + + + + Tree mode + + + + + List mode + + + + + Amount + Daudzums + + + + Label + + + + + Address + Adrese + + + + Date + Datums + + + + Confirmations + + + + + Confirmed + Apstiprināts + + + + Priority + + + + + Copy address + Kopēt adresi + + + + Copy label + Kopēt nosaukumu + + + + + Copy amount + Kopēt daudzumu + + + + Copy transaction ID + + + + + Copy quantity + + + + + Copy fee + + + + + Copy after fee + + + + + Copy bytes + + + + + Copy priority + + + + + Copy low output + + + + + Copy change + + + + + highest + + + + + high + + + + + medium-high + + + + + medium + + + + + low-medium + + + + + low + + + + + lowest + + + + + DUST + + + + + yes + + + + + This label turns red, if the transaction size is bigger than 10000 bytes. + + This means a fee of at least %1 per kb is required. + + Can vary +/- 1 Byte per input. + + + + + Transactions with higher priority get more likely into a block. + +This label turns red, if the priority is smaller than "medium". + + This means a fee of at least %1 per kb is required. + + + + + This label turns red, if any recipient receives an amount smaller than %1. + + This means a fee of at least %2 is required. + + Amounts below 0.546 times the minimum relay fee are shown as DUST. + + + + + This label turns red, if the change is smaller than %1. + + This means a fee of at least %2 is required. + + + + + + (no label) + (bez nosaukuma) + + + + change from %1 (%2) + + + + + (change) + + + + + EditAddressDialog + + + Edit Address + Mainīt adrese + + + + &Label + &Nosaukums + + + + The label associated with this address book entry + + + + + &Address + &Adrese + + + + The address associated with this address book entry. This can only be modified for sending addresses. + + + + + New receiving address + Jauna saņemšanas adrese + + + + New sending address + Jauna nosūtīšanas adrese + + + + Edit receiving address + Mainīt saņemšanas adresi + + + + Edit sending address + Mainīt nosūtīšanas adresi + + + + The entered address "%1" is already in the address book. + Nupat ierakstītā adrese "%1" jau atrodas adrešu grāmatā. + + + + The entered address "%1" is not a valid Arepacoin address. + + + + + Could not unlock wallet. + Nav iespējams atslēgt maciņu. + + + + New key generation failed. + Neizdevās ģenerēt jaunu atslēgu. + + + + GUIUtil::HelpMessageBox + + + + Arepacoin-Qt + + + + + version + + + + + Usage: + + + + + command-line options + + + + + UI options + + + + + Set language, for example "de_DE" (default: system locale) + + + + + Start minimized + + + + + Show splash screen on startup (default: 1) + + + + + OptionsDialog + + + Options + Iespējas + + + + &Main + &Galvenais + + + + Optional transaction fee per kB that helps make sure your transactions are processed quickly. Most transactions are 1 kB. Fee 0.01 recommended. + + + + + Pay transaction &fee + &Maksāt par transakciju + + + + Reserved amount does not participate in staking and is therefore spendable at any time. + + + + + Reserve + + + + + Automatically start Arepacoin after logging in to the system. + + + + + &Start Arepacoin on system login + + + + + Detach block and address databases at shutdown. This means they can be moved to another data directory, but it slows down shutdown. The wallet is always detached. + + + + + &Detach databases at shutdown + + + + + &Network + &Tīkls + + + + Automatically open the Arepacoin client port on the router. This only works when your router supports UPnP and it is enabled. + + + + + Map port using &UPnP + Kartēt portu, izmantojot &UPnP + + + + Connect to the Arepacoin network through a SOCKS proxy (e.g. when connecting through Tor). + + + + + &Connect through SOCKS proxy: + + + + + Proxy &IP: + Proxy &IP: + + + + IP address of the proxy (e.g. 127.0.0.1) + + + + + &Port: + &Ports: + + + + Port of the proxy (e.g. 9050) + Proxy ports (piem. 9050) + + + + SOCKS &Version: + SOCKS &Versija: + + + + SOCKS version of the proxy (e.g. 5) + proxy SOCKS versija (piem. 5) + + + + &Window + &Logs + + + + Show only a tray icon after minimizing the window. + Pēc loga minimizācijas rādīt tikai ikonu sistēmas teknē. + + + + &Minimize to the tray instead of the taskbar + &Minimizēt uz sistēmas tekni, nevis rīkjoslu + + + + Minimize instead of exit the application when the window is closed. When this option is enabled, the application will be closed only after selecting Quit in the menu. + Logu aizverot, minimizēt, nevis beigt darbu. Kad šī izvēlne iespējota, programma aizvērsies tikai pēc Beigt komandas izvēlnē. + + + + M&inimize on close + M&inimizēt aizverot + + + + &Display + &Izskats + + + + User Interface &language: + Lietotāja interfeiss un &valoda: + + + + The user interface language can be set here. This setting will take effect after restarting Arepacoin. + + + + + &Unit to show amounts in: + &Vienības, kurās attēlot daudzumus: + + + + Choose the default subdivision unit to show in the interface and when sending coins. + Izvēlēties dalījuma vienību pēc noklusēšanas, ko izmantot interfeisā un nosūtot bitkoinus. + + + + Whether to show Arepacoin addresses in the transaction list or not. + + + + + &Display addresses in transaction list + &Attēlot adreses transakciju sarakstā + + + + Whether to show coin control features or not. + + + + + Display coin &control features (experts only!) + + + + + &OK + &OK + + + + &Cancel + &Atcelt + + + + &Apply + + + + + default + pēc noklusēšanas + + + + + Warning + + + + + + This setting will take effect after restarting Arepacoin. + + + + + The supplied proxy address is invalid. + Norādītā proxy adrese nav derīga. + + + + OverviewPage + + + Form + Forma + + + + + The displayed information may be out of date. Your wallet automatically synchronizes with the Arepacoin network after a connection is established, but this process has not completed yet. + + + + + Stake: + + + + + Unconfirmed: + + + + + Wallet + Maciņš + + + + Spendable: + + + + + Your current spendable balance + + + + + Immature: + Nenobriedušu: + + + + Mined balance that has not yet matured + + + + + Total: + + + + + Your current total balance + + + + + <b>Recent transactions</b> + <b>Pēdējās transakcijas</b> + + + + Total of transactions that have yet to be confirmed, and do not yet count toward the current balance + + + + + Total of coins that was staked, and do not yet count toward the current balance + + + + + + out of sync + nav sinhronizēts + + + + QRCodeDialog + + + QR Code Dialog + + + + + Request Payment + + + + + Amount: + + + + + Label: + + + + + Message: + + + + + &Save As... + + + + + Error encoding URI into QR Code. + + + + + The entered amount is invalid, please check. + + + + + Resulting URI too long, try to reduce the text for label / message. + + + + + Save QR Code + + + + + PNG Images (*.png) + + + + + RPCConsole + + + Client name + Klienta vārds + + + + + + + + + + + + + N/A + N/A + + + + Client version + Klienta versija + + + + &Information + &Informācija + + + + Using OpenSSL version + + + + + Startup time + Sākuma laiks + + + + Network + Tīkls + + + + Number of connections + Savienojumu skaits + + + + On testnet + + + + + Block chain + Bloku virkne + + + + Current number of blocks + Pašreizējais bloku skaits + + + + Estimated total blocks + Bloku skaita novērtējums + + + + Last block time + Pēdējā bloka laiks + + + + &Open + &Atvērt + + + + Command-line options + + + + + Show the Arepacoin-Qt help message to get a list with possible Arepacoin command-line options. + + + + + &Show + + + + + &Console + &Konsole + + + + Build date + Kompilācijas datums + + + + Arepacoin - Debug window + + + + + Arepacoin Core + + + + + Debug log file + + + + + Open the Arepacoin debug log file from the current data directory. This can take a few seconds for large log files. + + + + + Clear console + Notīrīt konsoli + + + + Welcome to the Arepacoin RPC console. + + + + + Use up and down arrows to navigate history, and <b>Ctrl-L</b> to clear screen. + Izmantojiet bultiņas uz augšu un leju, lai pārvietotos pa vēsturi, un <b>Ctrl-L</b> ekrāna notīrīšanai. + + + + Type <b>help</b> for an overview of available commands. + Ierakstiet <b>help</b> lai iegūtu pieejamo komandu sarakstu. + + + + SendCoinsDialog + + + + + + + + + + Send Coins + Sūtīt bitkoinus + + + + Coin Control Features + + + + + Inputs... + + + + + automatically selected + + + + + Insufficient funds! + + + + + Quantity: + + + + + + 0 + + + + + Bytes: + + + + + Amount: + Daudzums: + + + + + + + 0.00 BC + + + + + Priority: + + + + + medium + + + + + Fee: + + + + + Low Output: + + + + + no + + + + + After Fee: + + + + + Change + + + + + custom change address + + + + + Send to multiple recipients at once + Sūtīt vairākiem saņēmējiem uzreiz + + + + Add &Recipient + + + + + Remove all transaction fields + + + + + Clear &All + &Notīrīt visu + + + + Balance: + Bilance: + + + + 123.456 BC + + + + + Confirm the send action + Apstiprināt nosūtīšanu + + + + S&end + + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Copy quantity + + + + + Copy amount + Kopēt daudzumu + + + + Copy fee + + + + + Copy after fee + + + + + Copy bytes + + + + + Copy priority + + + + + Copy low output + + + + + Copy change + + + + + <b>%1</b> to %2 (%3) + + + + + Confirm send coins + Apstiprināt bitkoinu sūtīšanu + + + + Are you sure you want to send %1? + + + + + and + + + + + The recipient address is not valid, please recheck. + + + + + The amount to pay must be larger than 0. + Nosūtāmajai summai jābūt lielākai par 0. + + + + The amount exceeds your balance. + Daudzums pārsniedz pieejamo. + + + + The total exceeds your balance when the %1 transaction fee is included. + Kopsumma pārsniedz pieejamo, ja pieskaitīta %1 transakcijas maksa. + + + + Duplicate address found, can only send to each address once per send operation. + Atrastas divas vienādas adreses, vienā nosūtīšanas reizē uz katru adresi var sūtīt tikai vienreiz. + + + + Error: Transaction creation failed. + + + + + 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. + + + + + WARNING: Invalid Arepacoin address + + + + + (no label) + (bez nosaukuma) + + + + WARNING: unknown change address + + + + + SendCoinsEntry + + + Form + + + + + A&mount: + Apjo&ms + + + + Pay &To: + &Saņēmējs: + + + + + Enter a label for this address to add it to your address book + Lai pievienotu adresi adrešu grāmatai, tai jādod nosaukums + + + + &Label: + &Nosaukums: + + + + The address to send the payment to (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Choose address from address book + + + + + Alt+A + Alt+A + + + + Paste address from clipboard + ielīmēt adresi no starpliktuves + + + + Alt+P + Alt+P + + + + Remove this recipient + + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + SignVerifyMessageDialog + + + Signatures - Sign / Verify a Message + + + + + + &Sign Message + + + + + You can sign messages with your addresses to prove you own them. Be careful not to sign anything vague, as phishing attacks may try to trick you into signing your identity over to them. Only sign fully-detailed statements you agree to. + + + + + The address to sign the message with (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + + Choose an address from the address book + + + + + + Alt+A + Alt+A + + + + Paste address from clipboard + ielīmēt adresi no starpliktuves + + + + Alt+P + Alt+P + + + + Enter the message you want to sign here + + + + + Copy the current signature to the system clipboard + + + + + Sign the message to prove you own this Arepacoin address + + + + + Reset all sign message fields + + + + + + Clear &All + &Notīrīt visu + + + + + &Verify Message + + + + + Enter the signing address, message (ensure you copy line breaks, spaces, tabs, etc. exactly) and signature below to verify the message. Be careful not to read more into the signature than what is in the signed message itself, to avoid being tricked by a man-in-the-middle attack. + + + + + The address the message was signed with (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Verify the message to ensure it was signed with the specified Arepacoin address + + + + + Reset all verify message fields + + + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Click "Sign Message" to generate signature + + + + + Enter Arepacoin signature + + + + + + The entered address is invalid. + + + + + + + + Please check the address and try again. + + + + + + The entered address does not refer to a key. + + + + + Wallet unlock was cancelled. + + + + + Private key for the entered address is not available. + + + + + Message signing failed. + + + + + Message signed. + + + + + The signature could not be decoded. + + + + + + Please check the signature and try again. + + + + + The signature did not match the message digest. + + + + + Message verification failed. + + + + + Message verified. + + + + + TransactionDesc + + + Open until %1 + Atvērts līdz %1 + + + + Open for %n block(s) + + + + + conflicted + + + + + %1/offline + + + + + %1/unconfirmed + %1/neapstiprinātas + + + + %1 confirmations + %1 apstiprinājumu + + + + Status + + + + + , broadcast through %n node(s) + + + + + Date + Datums + + + + Source + + + + + Generated + + + + + + From + + + + + + + To + + + + + + own address + + + + + label + + + + + + + + + Credit + + + + + matures in %n more block(s) + + + + + not accepted + + + + + + + + Debit + + + + + Transaction fee + + + + + Net amount + + + + + Message + + + + + Comment + + + + + Transaction ID + + + + + Generated coins must mature 6 blocks before they can be spent. When you generated this block, it was broadcast to the network to be added to the block chain. If it fails to get into the chain, its state will change to "not accepted" and it won't be spendable. This may occasionally happen if another node generates a block within a few seconds of yours. + + + + + Debug information + + + + + Transaction + + + + + Inputs + + + + + Amount + Daudzums + + + + true + + + + + false + + + + + , has not been successfully broadcast yet + , vēl nav veiksmīgi izziņots + + + + unknown + nav zināms + + + + TransactionDescDialog + + + Transaction details + Transakcijas detaļas + + + + This pane shows a detailed description of the transaction + Šis panelis parāda transakcijas detaļas + + + + TransactionTableModel + + + Date + Datums + + + + Type + Tips + + + + Address + Adrese + + + + Amount + Daudzums + + + + Open until %1 + Atvērts līdz %1 + + + + Confirmed (%1 confirmations) + Apstiprināts (%1 apstiprinājumu) + + + + Open for %n more block(s) + + + + + Offline + + + + + Unconfirmed + + + + + Confirming (%1 of %2 recommended confirmations) + + + + + Conflicted + + + + + Immature (%1 confirmations, will be available after %2) + + + + + This block was not received by any other nodes and will probably not be accepted! + Neviens cits mezgls šo bloku nav saņēmis un droši vien netiks akceptēts! + + + + Generated but not accepted + Ģenerēts, taču nav akceptēts + + + + Received with + Saņemts ar + + + + Received from + Saņemts no + + + + Sent to + Nosūtīts + + + + Payment to yourself + Maksājums sev + + + + Mined + Atrasts + + + + (n/a) + (nav pieejams) + + + + Transaction status. Hover over this field to show number of confirmations. + Transakcijas statuss. Turiet peli virs šī lauka, lai redzētu apstiprinājumu skaitu. + + + + Date and time that the transaction was received. + Transakcijas saņemšanas datums un laiks. + + + + Type of transaction. + Transakcijas tips. + + + + Destination address of transaction. + Transakcijas mērķa adrese. + + + + Amount removed from or added to balance. + Bilancei pievienotais vai atņemtais daudzums. + + + + TransactionView + + + + All + Visi + + + + Today + Šodien + + + + This week + Šonedēļ + + + + This month + Šomēnes + + + + Last month + Pēdējais mēnesis + + + + This year + Šogad + + + + Range... + Diapazons... + + + + Received with + Saņemts ar + + + + Sent to + Nosūtīts + + + + To yourself + Sev + + + + Mined + Atrasts + + + + Other + Cits + + + + Enter address or label to search + Ierakstiet meklējamo nosaukumu vai adresi + + + + Min amount + Minimālais daudzums + + + + Copy address + Kopēt adresi + + + + Copy label + Kopēt nosaukumu + + + + Copy amount + Kopēt daudzumu + + + + Copy transaction ID + + + + + Edit label + Mainīt nosaukumu + + + + Show transaction details + Rādīt transakcijas detaļas + + + + Export Transaction Data + + + + + Comma separated file (*.csv) + Fails ar komatu kā atdalītāju (*.csv) + + + + Confirmed + Apstiprināts + + + + Date + Datums + + + + Type + Tips + + + + Label + Nosaukums + + + + Address + Adrese + + + + Amount + Daudzums + + + + ID + ID + + + + Error exporting + + + + + Could not write to file %1. + + + + + Range: + Diapazons: + + + + to + uz + + + + WalletModel + + + Sending... + + + + + bitcoin-core + + + Arepacoin version + + + + + Usage: + Lietojums: + + + + Send command to -server or arepacoind + + + + + List commands + Komandu saraksts + + + + Get help for a command + Palīdzība par komandu + + + + Options: + Iespējas: + + + + Specify configuration file (default: arepacoin.conf) + + + + + Specify pid file (default: arepacoind.pid) + + + + + Specify wallet file (within data directory) + + + + + Specify data directory + Norādiet datu direktoriju + + + + Set database cache size in megabytes (default: 25) + Uzstādiet datu bāzes bufera izmēru megabaitos (pēc noklusēšanas: 25) + + + + Set database disk log size in megabytes (default: 100) + + + + + Listen for connections on <port> (default: 9853 or testnet: 19853) + + + + + Maintain at most <n> connections to peers (default: 125) + Uzturēt līdz <n> savienojumiem ar citiem mezgliem(pēc noklusēšanas: 125) + + + + Connect to a node to retrieve peer addresses, and disconnect + Pievienoties mezglam, lai iegūtu citu mezglu adreses, un atvienoties + + + + Specify your own public address + Norādiet savu publisko adresi + + + + Bind to given address. Use [host]:port notation for IPv6 + + + + + Stake your coins to support network and gain reward (default: 1) + + + + + Threshold for disconnecting misbehaving peers (default: 100) + Slieksnis pārkāpējmezglu atvienošanai (pēc noklusēšanas: 100) + + + + Number of seconds to keep misbehaving peers from reconnecting (default: 86400) + Sekundes, cik ilgi atturēt pārkāpējmezglus no atkārtotas pievienošanās (pēc noklusēšanas: 86400) + + + + An error occurred while setting up the RPC port %u for listening on IPv4: %s + + + + + Detach block and address databases. Increases shutdown time (default: 0) + + + + + 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. + + + + + Error: This transaction requires a transaction fee of at least %s because of its amount, complexity, or use of recently received funds + + + + + Listen for JSON-RPC connections on <port> (default: 9852 or testnet: 19852) + + + + + Accept command line and JSON-RPC commands + Pieņemt komandrindas un JSON-RPC komandas + + + + Error: Transaction creation failed + + + + + Error: Wallet locked, unable to create transaction + + + + + Importing blockchain data file. + + + + + Importing bootstrap blockchain data file. + + + + + Run in the background as a daemon and accept commands + Darbināt fonā kā servisu un pieņemt komandas + + + + Use the test network + Izmantot testa tīklu + + + + Accept connections from outside (default: 1 if no -proxy or -connect) + + + + + An error occurred while setting up the RPC port %u for listening on IPv6, falling back to IPv4: %s + + + + + Error initializing database environment %s! To recover, BACKUP THAT DIRECTORY, then remove everything from it except for wallet.dat. + + + + + Set maximum size of high-priority/low-fee transactions in bytes (default: 27000) + + + + + Warning: -paytxfee is set very high! This is the transaction fee you will pay if you send a transaction. + + + + + Warning: Please check that your computer's date and time are correct! If your clock is wrong Arepacoin will not work properly. + + + + + Warning: error reading wallet.dat! All keys read correctly, but transaction data or address book entries might be missing or incorrect. + + + + + Warning: wallet.dat corrupt, data salvaged! Original wallet.dat saved as wallet.{timestamp}.bak in %s; if your balance or transactions are incorrect you should restore from a backup. + + + + + Attempt to recover private keys from a corrupt wallet.dat + + + + + Block creation options: + + + + + Connect only to the specified node(s) + + + + + Discover own IP address (default: 1 when listening and no -externalip) + + + + + Failed to listen on any port. Use -listen=0 if you want this. + + + + + Find peers using DNS lookup (default: 1) + + + + + Sync checkpoints policy (default: strict) + + + + + Invalid -tor address: '%s' + + + + + Invalid amount for -reservebalance=<amount> + + + + + Maximum per-connection receive buffer, <n>*1000 bytes (default: 5000) + + + + + Maximum per-connection send buffer, <n>*1000 bytes (default: 1000) + + + + + Only connect to nodes in network <net> (IPv4, IPv6 or Tor) + + + + + Output extra debugging information. Implies all other -debug* options + + + + + Output extra network debugging information + + + + + Prepend debug output with timestamp + + + + + SSL options: (see the Bitcoin Wiki for SSL setup instructions) + + + + + Select the version of socks proxy to use (4-5, default: 5) + + + + + Send trace/debug info to console instead of debug.log file + Debug/trace informāciju izvadīt konsolē, nevis debug.log failā + + + + Send trace/debug info to debugger + + + + + Set maximum block size in bytes (default: 250000) + + + + + Set minimum block size in bytes (default: 0) + + + + + Shrink debug.log file on client startup (default: 1 when no -debug) + + + + + Specify connection timeout in milliseconds (default: 5000) + + + + + Unable to sign checkpoint, wrong checkpointkey? + + + + + + Use UPnP to map the listening port (default: 0) + + + + + Use UPnP to map the listening port (default: 1 when listening) + + + + + Use proxy to reach tor hidden services (default: same as -proxy) + + + + + Username for JSON-RPC connections + JSON-RPC savienojumu lietotājvārds + + + + Verifying database integrity... + + + + + WARNING: syncronized checkpoint violation detected, but skipped! + + + + + Warning: Disk space is low! + + + + + Warning: This version is obsolete, upgrade required! + + + + + wallet.dat corrupt, salvage failed + + + + + Password for JSON-RPC connections + JSON-RPC savienojumu parole + + + + %s, you must set a rpcpassword in the configuration file: + %s +It is recommended you use the following random password: +rpcuser=arepacoinrpc +rpcpassword=%s +(you do not need to remember this password) +The username and password MUST NOT be the same. +If the file does not exist, create it with owner-readable-only file permissions. +It is also recommended to set alertnotify so you are notified of problems; +for example: alertnotify=echo %%s | mail -s "Arepacoin Alert" admin@foo.com + + + + + + Find peers using internet relay chat (default: 0) + + + + + Sync time with other nodes. Disable if time on your system is precise e.g. syncing with NTP (default: 1) + + + + + When creating transactions, ignore inputs with value less than this (default: 0.01) + + + + + Allow JSON-RPC connections from specified IP address + Atļaut JSON-RPC savienojumus no norādītās IP adreses + + + + Send commands to node running on <ip> (default: 127.0.0.1) + Nosūtīt komandas mezglam, kas darbojas adresē <ip> (pēc noklusēšanas: 127.0.0.1) + + + + Execute command when the best block changes (%s in cmd is replaced by block hash) + Izpildīt komandu, kad labāk atbilstošais bloks izmainās (%s cmd aizvieto ar bloka hešu) + + + + Execute command when a wallet transaction changes (%s in cmd is replaced by TxID) + + + + + Require a confirmations for change (default: 0) + + + + + Enforce transaction scripts to use canonical PUSH operators (default: 1) + + + + + Execute command when a relevant alert is received (%s in cmd is replaced by message) + + + + + Upgrade wallet to latest format + Atjaunot maciņa formātu uz jaunāko + + + + Set key pool size to <n> (default: 100) + Uzstādīt atslēgu bufera izmēru uz <n> (pēc noklusēšanas: 100) + + + + Rescan the block chain for missing wallet transactions + Atkārtoti skanēt bloku virkni, meklējot trūkstošās maciņa transakcijas + + + + How many blocks to check at startup (default: 2500, 0 = all) + + + + + How thorough the block verification is (0-6, default: 1) + + + + + Imports blocks from external blk000?.dat file + + + + + Use OpenSSL (https) for JSON-RPC connections + JSON-RPC savienojumiem izmantot OpenSSL (https) + + + + Server certificate file (default: server.cert) + Servera sertifikāta fails (pēc noklusēšanas: server.cert) + + + + Server private key (default: server.pem) + Servera privātā atslēga (pēc noklusēšanas: server.pem) + + + + Acceptable ciphers (default: TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH) + + + + + Error: Wallet unlocked for staking only, unable to create transaction. + + + + + WARNING: Invalid checkpoint found! Displayed transactions may not be correct! You may need to upgrade, or notify developers. + + + + + This help message + Šis palīdzības paziņojums + + + + Wallet %s resides outside data directory %s. + + + + + Cannot obtain a lock on data directory %s. Arepacoin is probably already running. + + + + + Arepacoin + + + + + Unable to bind to %s on this computer (bind returned error %d, %s) + Nevar pievienoties pie %s šajā datorā (pievienošanās atgrieza kļūdu %d, %s) + + + + Connect through socks proxy + + + + + Allow DNS lookups for -addnode, -seednode and -connect + Atļaut DNS uzmeklēšanu priekš -addnode, -seednode un -connect + + + + Loading addresses... + Ielādē adreses... + + + + Error loading blkindex.dat + + + + + Error loading wallet.dat: Wallet corrupted + Nevar ielādēt wallet.dat: maciņš bojāts + + + + Error loading wallet.dat: Wallet requires newer version of Arepacoin + + + + + Wallet needed to be rewritten: restart Arepacoin to complete + + + + + Error loading wallet.dat + Kļūda ielādējot wallet.dat + + + + Invalid -proxy address: '%s' + Nederīga -proxy adrese: '%s' + + + + Unknown network specified in -onlynet: '%s' + -onlynet komandā norādīts nepazīstams tīkls: '%s' + + + + Unknown -socks proxy version requested: %i + Pieprasīta nezināma -socks proxy versija: %i + + + + Cannot resolve -bind address: '%s' + Nevar uzmeklēt -bind adresi: '%s' + + + + Cannot resolve -externalip address: '%s' + Nevar atrisināt -externalip adresi: '%s' + + + + Invalid amount for -paytxfee=<amount>: '%s' + Nederīgs daudzums priekš -paytxfree=<amount>: '%s' + + + + Error: could not start node + + + + + Sending... + + + + + Invalid amount + Nederīgs daudzums + + + + Insufficient funds + Nepietiek bitkoinu + + + + Loading block index... + Ielādē bloku indeksu... + + + + Add a node to connect to and attempt to keep the connection open + Pievienot mezglu, kam pievienoties un turēt savienojumu atvērtu + + + + Unable to bind to %s on this computer. Arepacoin is probably already running. + + + + + Fee per KB to add to transactions you send + + + + + Invalid amount for -mininput=<amount>: '%s' + + + + + Loading wallet... + Ielādē maciņu... + + + + Cannot downgrade wallet + Nevar maciņa formātu padarīt vecāku + + + + Cannot initialize keypool + + + + + Cannot write default address + Nevar ierakstīt adresi pēc noklusēšanas + + + + Rescanning... + Skanēju no jauna... + + + + Done loading + Ielāde pabeigta + + + + To use the %s option + Izmantot opciju %s + + + + Error + Kļūda + + + + You must set rpcpassword=<password> in the configuration file: +%s +If the file does not exist, create it with owner-readable-only file permissions. + Konfigurācijas failā jāuzstāda rpcpassword=<password>: +%s +Ja fails neeksistē, izveidojiet to ar atļauju lasīšanai tikai īpašniekam. + + + \ No newline at end of file diff --git a/src/qt/locale/bitcoin_ms_MY.ts b/src/qt/locale/bitcoin_ms_MY.ts new file mode 100755 index 0000000..c23220c --- /dev/null +++ b/src/qt/locale/bitcoin_ms_MY.ts @@ -0,0 +1,3275 @@ + + + AboutDialog + + + About Arepacoin + + + + + <b>Arepacoin</b> version + + + + + Copyright © 2009-2014 The Bitcoin developers +Copyright © 2012-2014 The NovaCoin developers +Copyright © 2014 The Arepacoin developers + + + + + +This is experimental software. + +Distributed under the MIT/X11 software license, see the accompanying file COPYING or http://www.opensource.org/licenses/mit-license.php. + +This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit (http://www.openssl.org/) and cryptographic software written by Eric Young (eay@cryptsoft.com) and UPnP software written by Thomas Bernard. + + + + + AddressBookPage + + + Address Book + + + + + Double-click to edit address or label + Klik dua kali untuk mengubah alamat atau label + + + + Create a new address + Cipta alamat baru + + + + Copy the currently selected address to the system clipboard + Salin alamat terpilih ke dalam sistem papan klip + + + + &New Address + Alamat baru + + + + These are your Arepacoin addresses for receiving payments. You may want to give a different one to each sender so you can keep track of who is paying you. + + + + + &Copy Address + + + + + Show &QR Code + + + + + Sign a message to prove you own a Arepacoin address + + + + + Sign &Message + + + + + Delete the currently selected address from the list + + + + + Verify a message to ensure it was signed with a specified Arepacoin address + + + + + &Verify Message + + + + + &Delete + &Padam + + + + Copy &Label + + + + + &Edit + + + + + Export Address Book Data + + + + + Comma separated file (*.csv) + Fail yang dipisahkan dengan koma + + + + Error exporting + + + + + Could not write to file %1. + + + + + AddressTableModel + + + Label + + + + + Address + Alamat + + + + (no label) + + + + + AskPassphraseDialog + + + Passphrase Dialog + + + + + Enter passphrase + Kata laluan + + + + New passphrase + Kata laluan baru + + + + Repeat new passphrase + Ulang kata laluan baru + + + + Serves to disable the trivial sendmoney when OS account compromised. Provides no real security. + + + + + For staking only + + + + + Enter the new passphrase to the wallet.<br/>Please use a passphrase of <b>10 or more random characters</b>, or <b>eight or more words</b>. + + + + + Encrypt wallet + + + + + This operation needs your wallet passphrase to unlock the wallet. + + + + + Unlock wallet + + + + + This operation needs your wallet passphrase to decrypt the wallet. + + + + + Decrypt wallet + + + + + Change passphrase + + + + + Enter the old and new passphrase to the wallet. + + + + + Confirm wallet encryption + + + + + Warning: If you encrypt your wallet and lose your passphrase, you will <b>LOSE ALL OF YOUR COINS</b>! + + + + + Are you sure you wish to encrypt your wallet? + + + + + IMPORTANT: Any previous backups you have made of your wallet file should be replaced with the newly generated, encrypted wallet file. For security reasons, previous backups of the unencrypted wallet file will become useless as soon as you start using the new, encrypted wallet. + + + + + + Warning: The Caps Lock key is on! + + + + + + Wallet encrypted + + + + + Arepacoin will close now to finish the encryption process. Remember that encrypting your wallet cannot fully protect your coins from being stolen by malware infecting your computer. + + + + + + + + Wallet encryption failed + + + + + Wallet encryption failed due to an internal error. Your wallet was not encrypted. + + + + + + The supplied passphrases do not match. + + + + + Wallet unlock failed + + + + + + + The passphrase entered for the wallet decryption was incorrect. + + + + + Wallet decryption failed + + + + + Wallet passphrase was successfully changed. + + + + + BitcoinGUI + + + Sign &message... + + + + + Synchronizing with network... + + + + + &Overview + + + + + Show general overview of wallet + + + + + &Transactions + + + + + Browse transaction history + + + + + &Address Book + Buku Alamat + + + + Edit the list of stored addresses and labels + + + + + &Receive coins + + + + + Show the list of addresses for receiving payments + + + + + &Send coins + + + + + E&xit + + + + + Quit application + + + + + Show information about Arepacoin + + + + + About &Qt + + + + + Show information about Qt + + + + + &Options... + Pilihan + + + + &Encrypt Wallet... + + + + + &Backup Wallet... + + + + + &Change Passphrase... + + + + + ~%n block(s) remaining + + + + + Downloaded %1 of %2 blocks of transaction history (%3% done). + + + + + &Export... + + + + + Send coins to a Arepacoin address + + + + + Modify configuration options for Arepacoin + + + + + Export the data in the current tab to a file + + + + + Encrypt or decrypt wallet + + + + + Backup wallet to another location + + + + + Change the passphrase used for wallet encryption + + + + + &Debug window + + + + + Open debugging and diagnostic console + + + + + &Verify message... + + + + + Arepacoin + + + + + Wallet + + + + + &About Arepacoin + + + + + &Show / Hide + + + + + Unlock wallet + + + + + &Lock Wallet + + + + + Lock wallet + + + + + &File + + + + + &Settings + + + + + &Help + + + + + Tabs toolbar + + + + + Actions toolbar + + + + + + [testnet] + + + + + + Arepacoin client + + + + + %n active connection(s) to Arepacoin network + + + + + Downloaded %1 blocks of transaction history. + + + + + Staking.<br>Your weight is %1<br>Network weight is %2<br>Expected time to earn reward is %3 + + + + + Not staking because wallet is locked + + + + + Not staking because wallet is offline + + + + + Not staking because wallet is syncing + + + + + Not staking because you don't have mature coins + + + + + %n second(s) ago + + + + + &Unlock Wallet... + + + + + %n minute(s) ago + + + + + %n hour(s) ago + + + + + %n day(s) ago + + + + + Up to date + + + + + Catching up... + + + + + Last received block was generated %1. + + + + + This transaction is over the size limit. You can still send it for a fee of %1, which goes to the nodes that process your transaction and helps to support the network. Do you want to pay the fee? + + + + + Confirm transaction fee + + + + + Sent transaction + + + + + Incoming transaction + + + + + Date: %1 +Amount: %2 +Type: %3 +Address: %4 + + + + + + + URI handling + + + + + + URI can not be parsed! This can be caused by an invalid Arepacoin address or malformed URI parameters. + + + + + Wallet is <b>encrypted</b> and currently <b>unlocked</b> + + + + + Wallet is <b>encrypted</b> and currently <b>locked</b> + + + + + Backup Wallet + + + + + Wallet Data (*.dat) + + + + + Backup Failed + + + + + There was an error trying to save the wallet data to the new location. + + + + + %n second(s) + + + + + %n minute(s) + + + + + %n hour(s) + + + + + %n day(s) + + + + + Not staking + + + + + A fatal error occurred. Arepacoin can no longer continue safely and will quit. + + + + + ClientModel + + + Network Alert + + + + + CoinControlDialog + + + Coin Control + + + + + Quantity: + + + + + Bytes: + + + + + Amount: + + + + + Priority: + + + + + Fee: + + + + + Low Output: + + + + + no + + + + + After Fee: + + + + + Change: + + + + + (un)select all + + + + + Tree mode + + + + + List mode + + + + + Amount + + + + + Label + + + + + Address + Alamat + + + + Date + + + + + Confirmations + + + + + Confirmed + + + + + Priority + + + + + Copy address + + + + + Copy label + + + + + + Copy amount + + + + + Copy transaction ID + + + + + Copy quantity + + + + + Copy fee + + + + + Copy after fee + + + + + Copy bytes + + + + + Copy priority + + + + + Copy low output + + + + + Copy change + + + + + highest + + + + + high + + + + + medium-high + + + + + medium + + + + + low-medium + + + + + low + + + + + lowest + + + + + DUST + + + + + yes + + + + + This label turns red, if the transaction size is bigger than 10000 bytes. + + This means a fee of at least %1 per kb is required. + + Can vary +/- 1 Byte per input. + + + + + Transactions with higher priority get more likely into a block. + +This label turns red, if the priority is smaller than "medium". + + This means a fee of at least %1 per kb is required. + + + + + This label turns red, if any recipient receives an amount smaller than %1. + + This means a fee of at least %2 is required. + + Amounts below 0.546 times the minimum relay fee are shown as DUST. + + + + + This label turns red, if the change is smaller than %1. + + This means a fee of at least %2 is required. + + + + + + (no label) + + + + + change from %1 (%2) + + + + + (change) + + + + + EditAddressDialog + + + Edit Address + Alamat + + + + &Label + + + + + The label associated with this address book entry + + + + + &Address + Alamat + + + + The address associated with this address book entry. This can only be modified for sending addresses. + + + + + New receiving address + + + + + New sending address + + + + + Edit receiving address + + + + + Edit sending address + + + + + The entered address "%1" is already in the address book. + + + + + The entered address "%1" is not a valid Arepacoin address. + + + + + Could not unlock wallet. + + + + + New key generation failed. + + + + + GUIUtil::HelpMessageBox + + + + Arepacoin-Qt + + + + + version + + + + + Usage: + + + + + command-line options + + + + + UI options + + + + + Set language, for example "de_DE" (default: system locale) + + + + + Start minimized + + + + + Show splash screen on startup (default: 1) + + + + + OptionsDialog + + + Options + + + + + &Main + + + + + Optional transaction fee per kB that helps make sure your transactions are processed quickly. Most transactions are 1 kB. Fee 0.01 recommended. + + + + + Pay transaction &fee + + + + + Reserved amount does not participate in staking and is therefore spendable at any time. + + + + + Reserve + + + + + Automatically start Arepacoin after logging in to the system. + + + + + &Start Arepacoin on system login + + + + + Detach block and address databases at shutdown. This means they can be moved to another data directory, but it slows down shutdown. The wallet is always detached. + + + + + &Detach databases at shutdown + + + + + &Network + + + + + Automatically open the Arepacoin client port on the router. This only works when your router supports UPnP and it is enabled. + + + + + Map port using &UPnP + + + + + Connect to the Arepacoin network through a SOCKS proxy (e.g. when connecting through Tor). + + + + + &Connect through SOCKS proxy: + + + + + Proxy &IP: + + + + + IP address of the proxy (e.g. 127.0.0.1) + + + + + &Port: + + + + + Port of the proxy (e.g. 9050) + + + + + SOCKS &Version: + + + + + SOCKS version of the proxy (e.g. 5) + + + + + &Window + + + + + Show only a tray icon after minimizing the window. + + + + + &Minimize to the tray instead of the taskbar + + + + + Minimize instead of exit the application when the window is closed. When this option is enabled, the application will be closed only after selecting Quit in the menu. + + + + + M&inimize on close + + + + + &Display + + + + + User Interface &language: + + + + + The user interface language can be set here. This setting will take effect after restarting Arepacoin. + + + + + &Unit to show amounts in: + + + + + Choose the default subdivision unit to show in the interface and when sending coins. + + + + + Whether to show Arepacoin addresses in the transaction list or not. + + + + + &Display addresses in transaction list + + + + + Whether to show coin control features or not. + + + + + Display coin &control features (experts only!) + + + + + &OK + + + + + &Cancel + + + + + &Apply + + + + + default + + + + + + Warning + + + + + + This setting will take effect after restarting Arepacoin. + + + + + The supplied proxy address is invalid. + + + + + OverviewPage + + + Form + + + + + + The displayed information may be out of date. Your wallet automatically synchronizes with the Arepacoin network after a connection is established, but this process has not completed yet. + + + + + Stake: + + + + + Unconfirmed: + + + + + Wallet + + + + + Spendable: + + + + + Your current spendable balance + + + + + Immature: + + + + + Mined balance that has not yet matured + + + + + Total: + + + + + Your current total balance + + + + + <b>Recent transactions</b> + + + + + Total of transactions that have yet to be confirmed, and do not yet count toward the current balance + + + + + Total of coins that was staked, and do not yet count toward the current balance + + + + + + out of sync + + + + + QRCodeDialog + + + QR Code Dialog + + + + + Request Payment + + + + + Amount: + + + + + Label: + + + + + Message: + + + + + &Save As... + + + + + Error encoding URI into QR Code. + + + + + The entered amount is invalid, please check. + + + + + Resulting URI too long, try to reduce the text for label / message. + + + + + Save QR Code + + + + + PNG Images (*.png) + + + + + RPCConsole + + + Client name + + + + + + + + + + + + + + N/A + + + + + Client version + + + + + &Information + + + + + Using OpenSSL version + + + + + Startup time + + + + + Network + + + + + Number of connections + + + + + On testnet + + + + + Block chain + + + + + Current number of blocks + + + + + Estimated total blocks + + + + + Last block time + + + + + &Open + + + + + Command-line options + + + + + Show the Arepacoin-Qt help message to get a list with possible Arepacoin command-line options. + + + + + &Show + + + + + &Console + + + + + Build date + + + + + Arepacoin - Debug window + + + + + Arepacoin Core + + + + + Debug log file + + + + + Open the Arepacoin debug log file from the current data directory. This can take a few seconds for large log files. + + + + + Clear console + + + + + Welcome to the Arepacoin RPC console. + + + + + Use up and down arrows to navigate history, and <b>Ctrl-L</b> to clear screen. + + + + + Type <b>help</b> for an overview of available commands. + + + + + SendCoinsDialog + + + + + + + + + + Send Coins + + + + + Coin Control Features + + + + + Inputs... + + + + + automatically selected + + + + + Insufficient funds! + + + + + Quantity: + + + + + + 0 + + + + + Bytes: + + + + + Amount: + + + + + + + + 0.00 BC + + + + + Priority: + + + + + medium + + + + + Fee: + + + + + Low Output: + + + + + no + + + + + After Fee: + + + + + Change + + + + + custom change address + + + + + Send to multiple recipients at once + + + + + Add &Recipient + + + + + Remove all transaction fields + + + + + Clear &All + + + + + Balance: + Baki + + + + 123.456 BC + + + + + Confirm the send action + + + + + S&end + + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Copy quantity + + + + + Copy amount + + + + + Copy fee + + + + + Copy after fee + + + + + Copy bytes + + + + + Copy priority + + + + + Copy low output + + + + + Copy change + + + + + <b>%1</b> to %2 (%3) + + + + + Confirm send coins + + + + + Are you sure you want to send %1? + + + + + and + + + + + The recipient address is not valid, please recheck. + + + + + The amount to pay must be larger than 0. + + + + + The amount exceeds your balance. + + + + + The total exceeds your balance when the %1 transaction fee is included. + + + + + Duplicate address found, can only send to each address once per send operation. + + + + + Error: Transaction creation failed. + + + + + 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. + + + + + WARNING: Invalid Arepacoin address + + + + + (no label) + + + + + WARNING: unknown change address + + + + + SendCoinsEntry + + + Form + + + + + A&mount: + + + + + Pay &To: + + + + + + Enter a label for this address to add it to your address book + + + + + &Label: + + + + + The address to send the payment to (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Choose address from address book + + + + + Alt+A + + + + + Paste address from clipboard + + + + + Alt+P + + + + + Remove this recipient + + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + SignVerifyMessageDialog + + + Signatures - Sign / Verify a Message + + + + + + &Sign Message + + + + + You can sign messages with your addresses to prove you own them. Be careful not to sign anything vague, as phishing attacks may try to trick you into signing your identity over to them. Only sign fully-detailed statements you agree to. + + + + + The address to sign the message with (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + + Choose an address from the address book + + + + + + Alt+A + + + + + Paste address from clipboard + + + + + Alt+P + + + + + Enter the message you want to sign here + + + + + Copy the current signature to the system clipboard + + + + + Sign the message to prove you own this Arepacoin address + + + + + Reset all sign message fields + + + + + + Clear &All + + + + + + &Verify Message + + + + + Enter the signing address, message (ensure you copy line breaks, spaces, tabs, etc. exactly) and signature below to verify the message. Be careful not to read more into the signature than what is in the signed message itself, to avoid being tricked by a man-in-the-middle attack. + + + + + The address the message was signed with (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Verify the message to ensure it was signed with the specified Arepacoin address + + + + + Reset all verify message fields + + + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Click "Sign Message" to generate signature + + + + + Enter Arepacoin signature + + + + + + The entered address is invalid. + + + + + + + + Please check the address and try again. + + + + + + The entered address does not refer to a key. + + + + + Wallet unlock was cancelled. + + + + + Private key for the entered address is not available. + + + + + Message signing failed. + + + + + Message signed. + + + + + The signature could not be decoded. + + + + + + Please check the signature and try again. + + + + + The signature did not match the message digest. + + + + + Message verification failed. + + + + + Message verified. + + + + + TransactionDesc + + + Open until %1 + + + + + Open for %n block(s) + + + + + conflicted + + + + + %1/offline + + + + + %1/unconfirmed + + + + + %1 confirmations + + + + + Status + + + + + , broadcast through %n node(s) + + + + + Date + + + + + Source + + + + + Generated + + + + + + From + + + + + + + To + + + + + + own address + + + + + label + + + + + + + + + Credit + + + + + matures in %n more block(s) + + + + + not accepted + + + + + + + + Debit + + + + + Transaction fee + + + + + Net amount + + + + + Message + + + + + Comment + + + + + Transaction ID + + + + + Generated coins must mature 6 blocks before they can be spent. When you generated this block, it was broadcast to the network to be added to the block chain. If it fails to get into the chain, its state will change to "not accepted" and it won't be spendable. This may occasionally happen if another node generates a block within a few seconds of yours. + + + + + Debug information + + + + + Transaction + + + + + Inputs + + + + + Amount + + + + + true + + + + + false + + + + + , has not been successfully broadcast yet + + + + + unknown + + + + + TransactionDescDialog + + + Transaction details + + + + + This pane shows a detailed description of the transaction + + + + + TransactionTableModel + + + Date + + + + + Type + + + + + Address + Alamat + + + + Amount + + + + + Open until %1 + + + + + Confirmed (%1 confirmations) + + + + + Open for %n more block(s) + + + + + Offline + + + + + Unconfirmed + + + + + Confirming (%1 of %2 recommended confirmations) + + + + + Conflicted + + + + + Immature (%1 confirmations, will be available after %2) + + + + + This block was not received by any other nodes and will probably not be accepted! + + + + + Generated but not accepted + + + + + Received with + + + + + Received from + + + + + Sent to + + + + + Payment to yourself + + + + + Mined + + + + + (n/a) + + + + + Transaction status. Hover over this field to show number of confirmations. + + + + + Date and time that the transaction was received. + + + + + Type of transaction. + + + + + Destination address of transaction. + + + + + Amount removed from or added to balance. + + + + + TransactionView + + + + All + + + + + Today + + + + + This week + + + + + This month + + + + + Last month + + + + + This year + + + + + Range... + + + + + Received with + + + + + Sent to + + + + + To yourself + + + + + Mined + + + + + Other + + + + + Enter address or label to search + + + + + Min amount + + + + + Copy address + + + + + Copy label + + + + + Copy amount + + + + + Copy transaction ID + + + + + Edit label + + + + + Show transaction details + + + + + Export Transaction Data + + + + + Comma separated file (*.csv) + Fail yang dipisahkan dengan koma + + + + Confirmed + + + + + Date + + + + + Type + + + + + Label + + + + + Address + Alamat + + + + Amount + + + + + ID + + + + + Error exporting + + + + + Could not write to file %1. + + + + + Range: + + + + + to + + + + + WalletModel + + + Sending... + + + + + bitcoin-core + + + Arepacoin version + + + + + Usage: + + + + + Send command to -server or arepacoind + + + + + List commands + + + + + Get help for a command + + + + + Options: + + + + + Specify configuration file (default: arepacoin.conf) + + + + + Specify pid file (default: arepacoind.pid) + + + + + Specify wallet file (within data directory) + + + + + Specify data directory + + + + + Set database cache size in megabytes (default: 25) + + + + + Set database disk log size in megabytes (default: 100) + + + + + Listen for connections on <port> (default: 9853 or testnet: 19853) + + + + + Maintain at most <n> connections to peers (default: 125) + + + + + Connect to a node to retrieve peer addresses, and disconnect + + + + + Specify your own public address + + + + + Bind to given address. Use [host]:port notation for IPv6 + + + + + Stake your coins to support network and gain reward (default: 1) + + + + + Threshold for disconnecting misbehaving peers (default: 100) + + + + + Number of seconds to keep misbehaving peers from reconnecting (default: 86400) + + + + + An error occurred while setting up the RPC port %u for listening on IPv4: %s + + + + + Detach block and address databases. Increases shutdown time (default: 0) + + + + + 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. + + + + + Error: This transaction requires a transaction fee of at least %s because of its amount, complexity, or use of recently received funds + + + + + Listen for JSON-RPC connections on <port> (default: 9852 or testnet: 19852) + + + + + Accept command line and JSON-RPC commands + + + + + Error: Transaction creation failed + + + + + Error: Wallet locked, unable to create transaction + + + + + Importing blockchain data file. + + + + + Importing bootstrap blockchain data file. + + + + + Run in the background as a daemon and accept commands + + + + + Use the test network + + + + + Accept connections from outside (default: 1 if no -proxy or -connect) + + + + + An error occurred while setting up the RPC port %u for listening on IPv6, falling back to IPv4: %s + + + + + Error initializing database environment %s! To recover, BACKUP THAT DIRECTORY, then remove everything from it except for wallet.dat. + + + + + Set maximum size of high-priority/low-fee transactions in bytes (default: 27000) + + + + + Warning: -paytxfee is set very high! This is the transaction fee you will pay if you send a transaction. + + + + + Warning: Please check that your computer's date and time are correct! If your clock is wrong Arepacoin will not work properly. + + + + + Warning: error reading wallet.dat! All keys read correctly, but transaction data or address book entries might be missing or incorrect. + + + + + Warning: wallet.dat corrupt, data salvaged! Original wallet.dat saved as wallet.{timestamp}.bak in %s; if your balance or transactions are incorrect you should restore from a backup. + + + + + Attempt to recover private keys from a corrupt wallet.dat + + + + + Block creation options: + + + + + Connect only to the specified node(s) + + + + + Discover own IP address (default: 1 when listening and no -externalip) + + + + + Failed to listen on any port. Use -listen=0 if you want this. + + + + + Find peers using DNS lookup (default: 1) + + + + + Sync checkpoints policy (default: strict) + + + + + Invalid -tor address: '%s' + + + + + Invalid amount for -reservebalance=<amount> + + + + + Maximum per-connection receive buffer, <n>*1000 bytes (default: 5000) + + + + + Maximum per-connection send buffer, <n>*1000 bytes (default: 1000) + + + + + Only connect to nodes in network <net> (IPv4, IPv6 or Tor) + + + + + Output extra debugging information. Implies all other -debug* options + + + + + Output extra network debugging information + + + + + Prepend debug output with timestamp + + + + + SSL options: (see the Bitcoin Wiki for SSL setup instructions) + + + + + Select the version of socks proxy to use (4-5, default: 5) + + + + + Send trace/debug info to console instead of debug.log file + + + + + Send trace/debug info to debugger + + + + + Set maximum block size in bytes (default: 250000) + + + + + Set minimum block size in bytes (default: 0) + + + + + Shrink debug.log file on client startup (default: 1 when no -debug) + + + + + Specify connection timeout in milliseconds (default: 5000) + + + + + Unable to sign checkpoint, wrong checkpointkey? + + + + + + Use UPnP to map the listening port (default: 0) + + + + + Use UPnP to map the listening port (default: 1 when listening) + + + + + Use proxy to reach tor hidden services (default: same as -proxy) + + + + + Username for JSON-RPC connections + + + + + Verifying database integrity... + + + + + WARNING: syncronized checkpoint violation detected, but skipped! + + + + + Warning: Disk space is low! + + + + + Warning: This version is obsolete, upgrade required! + + + + + wallet.dat corrupt, salvage failed + + + + + Password for JSON-RPC connections + + + + + %s, you must set a rpcpassword in the configuration file: + %s +It is recommended you use the following random password: +rpcuser=arepacoinrpc +rpcpassword=%s +(you do not need to remember this password) +The username and password MUST NOT be the same. +If the file does not exist, create it with owner-readable-only file permissions. +It is also recommended to set alertnotify so you are notified of problems; +for example: alertnotify=echo %%s | mail -s "Arepacoin Alert" admin@foo.com + + + + + + Find peers using internet relay chat (default: 0) + + + + + Sync time with other nodes. Disable if time on your system is precise e.g. syncing with NTP (default: 1) + + + + + When creating transactions, ignore inputs with value less than this (default: 0.01) + + + + + Allow JSON-RPC connections from specified IP address + + + + + Send commands to node running on <ip> (default: 127.0.0.1) + + + + + Execute command when the best block changes (%s in cmd is replaced by block hash) + + + + + Execute command when a wallet transaction changes (%s in cmd is replaced by TxID) + + + + + Require a confirmations for change (default: 0) + + + + + Enforce transaction scripts to use canonical PUSH operators (default: 1) + + + + + Execute command when a relevant alert is received (%s in cmd is replaced by message) + + + + + Upgrade wallet to latest format + + + + + Set key pool size to <n> (default: 100) + + + + + Rescan the block chain for missing wallet transactions + + + + + How many blocks to check at startup (default: 2500, 0 = all) + + + + + How thorough the block verification is (0-6, default: 1) + + + + + Imports blocks from external blk000?.dat file + + + + + Use OpenSSL (https) for JSON-RPC connections + + + + + Server certificate file (default: server.cert) + + + + + Server private key (default: server.pem) + + + + + Acceptable ciphers (default: TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH) + + + + + Error: Wallet unlocked for staking only, unable to create transaction. + + + + + WARNING: Invalid checkpoint found! Displayed transactions may not be correct! You may need to upgrade, or notify developers. + + + + + This help message + + + + + Wallet %s resides outside data directory %s. + + + + + Cannot obtain a lock on data directory %s. Arepacoin is probably already running. + + + + + Arepacoin + + + + + Unable to bind to %s on this computer (bind returned error %d, %s) + + + + + Connect through socks proxy + + + + + Allow DNS lookups for -addnode, -seednode and -connect + + + + + Loading addresses... + + + + + Error loading blkindex.dat + + + + + Error loading wallet.dat: Wallet corrupted + + + + + Error loading wallet.dat: Wallet requires newer version of Arepacoin + + + + + Wallet needed to be rewritten: restart Arepacoin to complete + + + + + Error loading wallet.dat + + + + + Invalid -proxy address: '%s' + + + + + Unknown network specified in -onlynet: '%s' + + + + + Unknown -socks proxy version requested: %i + + + + + Cannot resolve -bind address: '%s' + + + + + Cannot resolve -externalip address: '%s' + + + + + Invalid amount for -paytxfee=<amount>: '%s' + + + + + Error: could not start node + + + + + Sending... + + + + + Invalid amount + + + + + Insufficient funds + + + + + Loading block index... + + + + + Add a node to connect to and attempt to keep the connection open + + + + + Unable to bind to %s on this computer. Arepacoin is probably already running. + + + + + Fee per KB to add to transactions you send + + + + + Invalid amount for -mininput=<amount>: '%s' + + + + + Loading wallet... + + + + + Cannot downgrade wallet + + + + + Cannot initialize keypool + + + + + Cannot write default address + + + + + Rescanning... + + + + + Done loading + + + + + To use the %s option + + + + + Error + + + + + You must set rpcpassword=<password> in the configuration file: +%s +If the file does not exist, create it with owner-readable-only file permissions. + + + + \ No newline at end of file diff --git a/src/qt/locale/bitcoin_nb.ts b/src/qt/locale/bitcoin_nb.ts new file mode 100755 index 0000000..a14d2d1 --- /dev/null +++ b/src/qt/locale/bitcoin_nb.ts @@ -0,0 +1,3288 @@ + + + AboutDialog + + + About Arepacoin + Om Arepacoin + + + + <b>Arepacoin</b> version + <b>Arepacoin</b> versjon + + + + Copyright © 2009-2014 The Bitcoin developers +Copyright © 2012-2014 The NovaCoin developers +Copyright © 2014 The Arepacoin developers + + + + + +This is experimental software. + +Distributed under the MIT/X11 software license, see the accompanying file COPYING or http://www.opensource.org/licenses/mit-license.php. + +This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit (http://www.openssl.org/) and cryptographic software written by Eric Young (eay@cryptsoft.com) and UPnP software written by Thomas Bernard. + +Dette er eksperimentell programvare. + +Distribuert under MIT/X11 programvarelisensen, se medfølgende fil COPYING eller http://www.opensource.org/licenses/mit-license.php. + +Dette produktet inneholder programvare utviklet av OpenSSL prosjektet for bruk i OpenSSL Toolkit (http://www.openssl.org/) og kryptografisk programvare skrevet av Eric Young (eay@cryptsoft.com) og UPnP programvare skrevet av Thomas Bernard. + + + + AddressBookPage + + + Address Book + Adressebok + + + + Double-click to edit address or label + Dobbeltklikk for å redigere adresse eller merkelapp + + + + Create a new address + Lag en ny adresse + + + + Copy the currently selected address to the system clipboard + Kopier den valgte adressen til systemets utklippstavle + + + + &New Address + &Ny Adresse + + + + These are your Arepacoin addresses for receiving payments. You may want to give a different one to each sender so you can keep track of who is paying you. + Dette er adressene for å motta betalinger. Du ønsker kanskje å gi ulike adresser til hver avsender så du lettere kan holde øye med hvem som betaler deg. + + + + &Copy Address + &Kopier Adresse + + + + Show &QR Code + Vis &QR Kode + + + + Sign a message to prove you own a Arepacoin address + Signer en melding for å bevise din egen Arepacoin adresse. + + + + Sign &Message + Signer &Melding + + + + Delete the currently selected address from the list + Slett den valgte adressen fra listen. + + + + Verify a message to ensure it was signed with a specified Arepacoin address + Verifiser en melding får å forsikre deg om at den er signert med en spesifikk Arepacoin adresse + + + + &Verify Message + &Verifiser en melding + + + + &Delete + &Slett + + + + Copy &Label + Kopier &Merkelapp + + + + &Edit + &Rediger + + + + Export Address Book Data + Eksporter Adressebok + + + + Comma separated file (*.csv) + Kommaseparert fil (*.csv) + + + + Error exporting + Feil under eksportering + + + + Could not write to file %1. + Kunne ikke skrive til filen %1 + + + + AddressTableModel + + + Label + Merkelapp + + + + Address + Adresse + + + + (no label) + (ingen merkelapp) + + + + AskPassphraseDialog + + + Passphrase Dialog + Dialog for Adgangsfrase + + + + Enter passphrase + Angi adgangsfrase + + + + New passphrase + Ny adgangsfrase + + + + Repeat new passphrase + Gjenta ny adgangsfrase + + + + Serves to disable the trivial sendmoney when OS account compromised. Provides no real security. + + + + + For staking only + + + + + Enter the new passphrase to the wallet.<br/>Please use a passphrase of <b>10 or more random characters</b>, or <b>eight or more words</b>. + Skriv inn den nye adgangsfrasen for lommeboken.<br/>Vennligst bruk en adgangsfrase med <b>10 eller flere tilfeldige tegn</b>, eller <b>åtte eller flere ord</b>. + + + + Encrypt wallet + Krypter lommebok + + + + This operation needs your wallet passphrase to unlock the wallet. + Denne operasjonen krever adgangsfrasen til lommeboken for å låse den opp. + + + + Unlock wallet + Lås opp lommebok + + + + This operation needs your wallet passphrase to decrypt the wallet. + Denne operasjonen krever adgangsfrasen til lommeboken for å dekryptere den. + + + + Decrypt wallet + Dekrypter lommebok + + + + Change passphrase + Endre adgangsfrase + + + + Enter the old and new passphrase to the wallet. + Skriv inn gammel og ny adgangsfrase for lommeboken. + + + + Confirm wallet encryption + Bekreft kryptering av lommebok + + + + Warning: If you encrypt your wallet and lose your passphrase, you will <b>LOSE ALL OF YOUR COINS</b>! + + + + + Are you sure you wish to encrypt your wallet? + Er du sikker på at du vil kryptere lommeboken? + + + + IMPORTANT: Any previous backups you have made of your wallet file should be replaced with the newly generated, encrypted wallet file. For security reasons, previous backups of the unencrypted wallet file will become useless as soon as you start using the new, encrypted wallet. + VIKTIG: Tidligere sikkerhetskopier av din lommebok-fil, bør erstattes med den nylig genererte, krypterte filen, da de blir ugyldiggjort av sikkerhetshensyn så snart du begynner å bruke den nye krypterte lommeboken. + + + + + Warning: The Caps Lock key is on! + Advarsel: Caps Lock er på ! + + + + + Wallet encrypted + Lommebok kryptert + + + + Arepacoin will close now to finish the encryption process. Remember that encrypting your wallet cannot fully protect your coins from being stolen by malware infecting your computer. + + + + + + + + Wallet encryption failed + Kryptering av lommebok feilet + + + + Wallet encryption failed due to an internal error. Your wallet was not encrypted. + Kryptering av lommebok feilet på grunn av en intern feil. Din lommebok ble ikke kryptert. + + + + + The supplied passphrases do not match. + De angitte adgangsfrasene er ulike. + + + + Wallet unlock failed + Opplåsing av lommebok feilet + + + + + + The passphrase entered for the wallet decryption was incorrect. + Adgangsfrasen angitt for dekryptering av lommeboken var feil. + + + + Wallet decryption failed + Dekryptering av lommebok feilet + + + + Wallet passphrase was successfully changed. + Adgangsfrase for lommebok endret. + + + + BitcoinGUI + + + Sign &message... + Signer &melding... + + + + Synchronizing with network... + Synkroniserer med nettverk... + + + + &Overview + &Oversikt + + + + Show general overview of wallet + Vis generell oversikt over lommeboken + + + + &Transactions + &Transaksjoner + + + + Browse transaction history + Vis transaksjonshistorikk + + + + &Address Book + &Adressebok + + + + Edit the list of stored addresses and labels + Endre listen med lagrede adresser og merkelapper + + + + &Receive coins + &Mottatte coins + + + + Show the list of addresses for receiving payments + Vis listen med adresser for å motta betalinger + + + + &Send coins + &Send coins + + + + E&xit + &Avslutt + + + + Quit application + Avslutt applikasjonen + + + + Show information about Arepacoin + Vis info om Arepacoin + + + + About &Qt + Om &Qt + + + + Show information about Qt + Vis informasjon om Qt + + + + &Options... + &Innstillinger... + + + + &Encrypt Wallet... + &Krypter Lommebok... + + + + &Backup Wallet... + Lag &Sikkerhetskopi av Lommebok... + + + + &Change Passphrase... + &Endre Adgangsfrase... + + + + ~%n block(s) remaining + ~%n blokker igjen~%n blokker igjen + + + + Downloaded %1 of %2 blocks of transaction history (%3% done). + Lastet ned %1 av %2 blokker med transaksjonshistorie (%3 ferdig). + + + + &Export... + &Eksporter... + + + + Send coins to a Arepacoin address + Send coins til en Arepacoin adresse + + + + Modify configuration options for Arepacoin + Endre innstillingene til Arepacoin + + + + Export the data in the current tab to a file + Eksporter dataene i nåværende fane til en fil + + + + Encrypt or decrypt wallet + Krypter eller dekrypter lommeboken + + + + Backup wallet to another location + Sikkerhetskopiér lommebok til annet sted + + + + Change the passphrase used for wallet encryption + Endre adgangsfrasen brukt for kryptering av lommebok + + + + &Debug window + &Feilsøkingsvindu + + + + Open debugging and diagnostic console + Åpne konsoll for feilsøk og diagnostikk + + + + &Verify message... + &Verifiser melding... + + + + Arepacoin + Arepacoin + + + + Wallet + Lommebok + + + + &About Arepacoin + &Om Arepacoin + + + + &Show / Hide + &Gjem / vis + + + + Unlock wallet + Lås opp lommebok + + + + &Lock Wallet + &Lås Lommeboken + + + + Lock wallet + Lås lommeboken + + + + &File + &Fil + + + + &Settings + &Innstillinger + + + + &Help + &Hjelp + + + + Tabs toolbar + Verktøylinje for faner + + + + Actions toolbar + + + + + + [testnet] + [testnett] + + + + + Arepacoin client + Arepacoin klient + + + + %n active connection(s) to Arepacoin network + %n aktiv tilkobling til Arepacoin nettverket%n aktive tilkoblinger til Arepacoin nettverket + + + + Downloaded %1 blocks of transaction history. + Lastet ned %1 blokker med transaksjonshistorie + + + + Staking.<br>Your weight is %1<br>Network weight is %2<br>Expected time to earn reward is %3 + + + + + Not staking because wallet is locked + + + + + Not staking because wallet is offline + + + + + Not staking because wallet is syncing + + + + + Not staking because you don't have mature coins + + + + + %n second(s) ago + %n sekunder siden%n sekunder siden + + + + &Unlock Wallet... + &Lås opp lommeboken + + + + %n minute(s) ago + %n minutt siden%n minutter siden + + + + %n hour(s) ago + %n time siden%n timer siden + + + + %n day(s) ago + %n dag siden%n dager siden + + + + Up to date + Ajour + + + + Catching up... + Kommer ajour... + + + + Last received block was generated %1. + + + + + This transaction is over the size limit. You can still send it for a fee of %1, which goes to the nodes that process your transaction and helps to support the network. Do you want to pay the fee? + + + + + Confirm transaction fee + + + + + Sent transaction + Sendt transaksjon + + + + Incoming transaction + Innkommende transaksjon + + + + Date: %1 +Amount: %2 +Type: %3 +Address: %4 + + Dato: %1 +Beløp: %2 +Type: %3 +Adresse: %4 + + + + + + URI handling + + + + + + URI can not be parsed! This can be caused by an invalid Arepacoin address or malformed URI parameters. + + + + + Wallet is <b>encrypted</b> and currently <b>unlocked</b> + Lommeboken er <b>kryptert</b> og for tiden <b>ulåst</b> + + + + Wallet is <b>encrypted</b> and currently <b>locked</b> + Lommeboken er <b>kryptert</b> og for tiden <b>låst</b> + + + + Backup Wallet + + + + + Wallet Data (*.dat) + + + + + Backup Failed + Backup Mislyktes + + + + There was an error trying to save the wallet data to the new location. + + + + + %n second(s) + %n sekund%n sekunder + + + + %n minute(s) + %n minutt%n minutter + + + + %n hour(s) + %n time%n timer + + + + %n day(s) + %n dag%n dager + + + + Not staking + + + + + A fatal error occurred. Arepacoin can no longer continue safely and will quit. + + + + + ClientModel + + + Network Alert + Nettverksvarsel + + + + CoinControlDialog + + + Coin Control + + + + + Quantity: + Mengde: + + + + Bytes: + Bytes: + + + + Amount: + Beløp: + + + + Priority: + Prioritet: + + + + Fee: + Avgift: + + + + Low Output: + Lav Utdata: + + + + no + nei + + + + After Fee: + Etter Avgift: + + + + Change: + Endring: + + + + (un)select all + Fjern alt valgt + + + + Tree mode + Tre modus + + + + List mode + Liste modus + + + + Amount + Beløp + + + + Label + Merkelapp + + + + Address + Adresse + + + + Date + Dato + + + + Confirmations + Bekreftelser + + + + Confirmed + Bekreftet + + + + Priority + Prioritet + + + + Copy address + Kopier adresse + + + + Copy label + Kopier merkelapp + + + + + Copy amount + Kopiér beløp + + + + Copy transaction ID + Kopier transaksjons-ID + + + + Copy quantity + Kopier mengde + + + + Copy fee + Kopier gebyr + + + + Copy after fee + Kopier etter gebyr + + + + Copy bytes + + + + + Copy priority + Kopier prioritet + + + + Copy low output + + + + + Copy change + Kopier veksel + + + + highest + høyest + + + + high + høy + + + + medium-high + medium-høy + + + + medium + medium + + + + low-medium + lav-medium + + + + low + lav + + + + lowest + lavest + + + + DUST + + + + + yes + ja + + + + This label turns red, if the transaction size is bigger than 10000 bytes. + + This means a fee of at least %1 per kb is required. + + Can vary +/- 1 Byte per input. + + + + + Transactions with higher priority get more likely into a block. + +This label turns red, if the priority is smaller than "medium". + + This means a fee of at least %1 per kb is required. + + + + + This label turns red, if any recipient receives an amount smaller than %1. + + This means a fee of at least %2 is required. + + Amounts below 0.546 times the minimum relay fee are shown as DUST. + + + + + This label turns red, if the change is smaller than %1. + + This means a fee of at least %2 is required. + Denne merkelappen blir rød, viss endringen er mindre enn %1 + +Dette betyr at det trengs en avgift på minimum %2. + + + + + (no label) + (ingen merkelapp) + + + + change from %1 (%2) + endring fra %1 (%2) + + + + (change) + (endring) + + + + EditAddressDialog + + + Edit Address + Rediger adresse + + + + &Label + &Merkelapp + + + + The label associated with this address book entry + Navnet assosiert med denne adressen + + + + &Address + &Adresse + + + + The address associated with this address book entry. This can only be modified for sending addresses. + + + + + New receiving address + Ny mottaksadresse + + + + New sending address + Ny utsendingsadresse + + + + Edit receiving address + Rediger mottaksadresse + + + + Edit sending address + Rediger utsendingsadresse + + + + The entered address "%1" is already in the address book. + Den oppgitte adressen "%1" er allerede i adresseboken. + + + + The entered address "%1" is not a valid Arepacoin address. + Den angitte adressen "%1" er ikke en gyldig Arepacoin adresse. + + + + Could not unlock wallet. + Kunne ikke låse opp lommeboken. + + + + New key generation failed. + Generering av ny nøkkel feilet. + + + + GUIUtil::HelpMessageBox + + + + Arepacoin-Qt + Arepacoin-Qt + + + + version + versjon + + + + Usage: + Bruk: + + + + command-line options + + + + + UI options + + + + + Set language, for example "de_DE" (default: system locale) + + + + + Start minimized + Start Minimert + + + + Show splash screen on startup (default: 1) + + + + + OptionsDialog + + + Options + Innstillinger + + + + &Main + &Hoved + + + + Optional transaction fee per kB that helps make sure your transactions are processed quickly. Most transactions are 1 kB. Fee 0.01 recommended. + + + + + Pay transaction &fee + Betal transaksjons&gebyr + + + + Reserved amount does not participate in staking and is therefore spendable at any time. + + + + + Reserve + + + + + Automatically start Arepacoin after logging in to the system. + + + + + &Start Arepacoin on system login + &Start Arepacoin ved innlogging + + + + Detach block and address databases at shutdown. This means they can be moved to another data directory, but it slows down shutdown. The wallet is always detached. + + + + + &Detach databases at shutdown + + + + + &Network + &Nettverk + + + + Automatically open the Arepacoin client port on the router. This only works when your router supports UPnP and it is enabled. + + + + + Map port using &UPnP + Sett opp port vha. &UPnP + + + + Connect to the Arepacoin network through a SOCKS proxy (e.g. when connecting through Tor). + + + + + &Connect through SOCKS proxy: + &Koble til via en SOCKS proxy: + + + + Proxy &IP: + Proxy &IP: + + + + IP address of the proxy (e.g. 127.0.0.1) + + + + + &Port: + &Port: + + + + Port of the proxy (e.g. 9050) + Proxyens port (f.eks. 9050) + + + + SOCKS &Version: + SOCKS &Versjon: + + + + SOCKS version of the proxy (e.g. 5) + Proxyens SOCKS versjon (f.eks. 5) + + + + &Window + &Vindu + + + + Show only a tray icon after minimizing the window. + Vis kun ikon i systemkurv etter minimering av vinduet. + + + + &Minimize to the tray instead of the taskbar + &Minimer til systemkurv istedenfor oppgavelinjen + + + + Minimize instead of exit the application when the window is closed. When this option is enabled, the application will be closed only after selecting Quit in the menu. + Minimerer vinduet istedenfor å avslutte applikasjonen når vinduet lukkes. Når dette er slått på avsluttes applikasjonen kun ved å velge avslutt i menyen. + + + + M&inimize on close + M&inimer ved lukking + + + + &Display + &Visning + + + + User Interface &language: + &Språk for brukergrensesnitt + + + + The user interface language can be set here. This setting will take effect after restarting Arepacoin. + + + + + &Unit to show amounts in: + &Enhet for visning av beløper: + + + + Choose the default subdivision unit to show in the interface and when sending coins. + Velg standard delt enhet for visning i grensesnittet og for sending av bitcoins. + + + + Whether to show Arepacoin addresses in the transaction list or not. + + + + + &Display addresses in transaction list + &Vis adresser i transaksjonslisten + + + + Whether to show coin control features or not. + Skal mynt kontroll funksjoner vises eller ikke. + + + + Display coin &control features (experts only!) + + + + + &OK + &OK + + + + &Cancel + &Avbryt + + + + &Apply + &Bruk + + + + default + standardverdi + + + + + Warning + Advarsel + + + + + This setting will take effect after restarting Arepacoin. + + + + + The supplied proxy address is invalid. + Angitt proxyadresse er ugyldig. + + + + OverviewPage + + + Form + Skjema + + + + + The displayed information may be out of date. Your wallet automatically synchronizes with the Arepacoin network after a connection is established, but this process has not completed yet. + + + + + Stake: + + + + + Unconfirmed: + Ubekreftet: + + + + Wallet + Lommebok + + + + Spendable: + Disponibelt: + + + + Your current spendable balance + Din nåværende saldo + + + + Immature: + Umoden: + + + + Mined balance that has not yet matured + Minet saldo har ikke modnet enda + + + + Total: + Totalt: + + + + Your current total balance + Din nåværende saldo + + + + <b>Recent transactions</b> + <b>Siste transaksjoner</b> + + + + Total of transactions that have yet to be confirmed, and do not yet count toward the current balance + + + + + Total of coins that was staked, and do not yet count toward the current balance + + + + + + out of sync + ute av synk + + + + QRCodeDialog + + + QR Code Dialog + + + + + Request Payment + + + + + Amount: + Beløp: + + + + Label: + Merkelapp: + + + + Message: + Melding: + + + + &Save As... + &Lagre som... + + + + Error encoding URI into QR Code. + + + + + The entered amount is invalid, please check. + + + + + Resulting URI too long, try to reduce the text for label / message. + + + + + Save QR Code + + + + + PNG Images (*.png) + PNG Bilder (*.png) + + + + RPCConsole + + + Client name + Klientnavn + + + + + + + + + + + + + N/A + - + + + + Client version + Klientversjon + + + + &Information + &Informasjon + + + + Using OpenSSL version + Bruker OpenSSL versjon + + + + Startup time + Oppstartstidspunkt + + + + Network + Nettverk + + + + Number of connections + Antall tilkoblinger + + + + On testnet + + + + + Block chain + Blokkjeden + + + + Current number of blocks + Nåværende antall blokker + + + + Estimated total blocks + Estimert totalt antall blokker + + + + Last block time + Tidspunkt for siste blokk + + + + &Open + &Åpne + + + + Command-line options + + + + + Show the Arepacoin-Qt help message to get a list with possible Arepacoin command-line options. + + + + + &Show + &Vis + + + + &Console + &Konsoll + + + + Build date + Byggedato + + + + Arepacoin - Debug window + + + + + Arepacoin Core + + + + + Debug log file + Loggfil for feilsøk + + + + Open the Arepacoin debug log file from the current data directory. This can take a few seconds for large log files. + + + + + Clear console + Tøm konsoll + + + + Welcome to the Arepacoin RPC console. + + + + + Use up and down arrows to navigate history, and <b>Ctrl-L</b> to clear screen. + Bruk opp og ned pil for å navigere historikken, og <b>Ctrl-L</b> for å tømme skjermen. + + + + Type <b>help</b> for an overview of available commands. + Skriv <b>help</b> for en oversikt over kommandoer. + + + + SendCoinsDialog + + + + + + + + + + Send Coins + Send Bitcoins + + + + Coin Control Features + Mynt Kontroll Funksjoner + + + + Inputs... + Inndata... + + + + automatically selected + automatisk valgte + + + + Insufficient funds! + Utilstrekkelige midler! + + + + Quantity: + Mengde: + + + + + 0 + + + + + Bytes: + Bytes: + + + + Amount: + Beløp: + + + + + + + 0.00 BC + + + + + Priority: + Prioritet: + + + + medium + + + + + Fee: + Avgift: + + + + Low Output: + Lav Utdata: + + + + no + nei + + + + After Fee: + Etter Avgift: + + + + Change + + + + + custom change address + + + + + Send to multiple recipients at once + Send til flere enn én mottaker + + + + Add &Recipient + &Legg til Mottaker + + + + Remove all transaction fields + + + + + Clear &All + Fjern &Alt + + + + Balance: + Saldo: + + + + 123.456 BC + + + + + Confirm the send action + Bekreft sending + + + + S&end + S&end + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Copy quantity + Kopier mengde + + + + Copy amount + Kopiér beløp + + + + Copy fee + Kopier gebyr + + + + Copy after fee + + + + + Copy bytes + + + + + Copy priority + + + + + Copy low output + + + + + Copy change + + + + + <b>%1</b> to %2 (%3) + + + + + Confirm send coins + Bekreft sending av bitcoins + + + + Are you sure you want to send %1? + Er du sikker på du ønsker å sende %1? + + + + and + og + + + + The recipient address is not valid, please recheck. + Adresse for mottaker er ugyldig. + + + + The amount to pay must be larger than 0. + Beløpen som skal betales må være over 0. + + + + The amount exceeds your balance. + Beløpet overstiger saldo. + + + + The total exceeds your balance when the %1 transaction fee is included. + Totalbeløpet overstiger saldo etter at %1 transaksjonsgebyr er lagt til. + + + + Duplicate address found, can only send to each address once per send operation. + Duplikate adresser funnet. Kan bare sende én gang til hver adresse per operasjon. + + + + Error: Transaction creation failed. + + + + + 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. + + + + + WARNING: Invalid Arepacoin address + ADVARSEL: Ugyldig Arepacoin adresse + + + + (no label) + (ingen merkelapp) + + + + WARNING: unknown change address + + + + + SendCoinsEntry + + + Form + + + + + A&mount: + &Beløp: + + + + Pay &To: + Betal &Til: + + + + + Enter a label for this address to add it to your address book + Skriv inn en merkelapp for denne adressen for å legge den til i din adressebok + + + + &Label: + &Merkelapp: + + + + The address to send the payment to (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Choose address from address book + Velg adresse fra adresseboken + + + + Alt+A + Alt+A + + + + Paste address from clipboard + Lim inn adresse fra utklippstavlen + + + + Alt+P + Alt+P + + + + Remove this recipient + Fjern denne mottakeren + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + SignVerifyMessageDialog + + + Signatures - Sign / Verify a Message + Signaturer - Signer / Verifiser en melding + + + + + &Sign Message + &Signér Melding + + + + You can sign messages with your addresses to prove you own them. Be careful not to sign anything vague, as phishing attacks may try to trick you into signing your identity over to them. Only sign fully-detailed statements you agree to. + Du kan signere meldinger med dine adresser for å bevise at du eier dem. Ikke signér vage meldinger da phishing-angrep kan prøve å lure deg til å signere din identitet over til andre. Signér kun fullt detaljerte utsagn som du er enig i. + + + + The address to sign the message with (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + + Choose an address from the address book + Velg en adresse fra adresseboken + + + + + Alt+A + Alt+A + + + + Paste address from clipboard + Lim inn adresse fra utklippstavlen + + + + Alt+P + Alt+P + + + + Enter the message you want to sign here + Skriv inn meldingen du vil signere her + + + + Copy the current signature to the system clipboard + Kopier valgt signatur til utklippstavle + + + + Sign the message to prove you own this Arepacoin address + + + + + Reset all sign message fields + Tilbakestill alle felter for meldingssignering + + + + + Clear &All + Fjern &Alt + + + + + &Verify Message + &Verifiser Melding + + + + Enter the signing address, message (ensure you copy line breaks, spaces, tabs, etc. exactly) and signature below to verify the message. Be careful not to read more into the signature than what is in the signed message itself, to avoid being tricked by a man-in-the-middle attack. + Angi adresse for signering, melding (vær sikker på at du kopierer linjeskift, mellomrom, tab, etc. helt nøyaktig) og signatur under for å verifisere meldingen. Vær forsiktig med at du ikke gir signaturen mer betydning enn det som faktisk står i meldingen, for å unngå å bli lurt av såkalte "man-in-the-middle" angrep. + + + + The address the message was signed with (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Verify the message to ensure it was signed with the specified Arepacoin address + + + + + Reset all verify message fields + Tilbakestill alle felter for meldingsverifikasjon + + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Click "Sign Message" to generate signature + Klikk "Signer Melding" for å generere signatur + + + + Enter Arepacoin signature + + + + + + The entered address is invalid. + Angitt adresse er ugyldig. + + + + + + + Please check the address and try again. + Vennligst sjekk adressen og prøv igjen. + + + + + The entered address does not refer to a key. + Angitt adresse refererer ikke til en nøkkel. + + + + Wallet unlock was cancelled. + Opplåsing av lommebok ble avbrutt. + + + + Private key for the entered address is not available. + Privat nøkkel for den angitte adressen er ikke tilgjengelig. + + + + Message signing failed. + Signering av melding feilet. + + + + Message signed. + Melding signert. + + + + The signature could not be decoded. + Signaturen kunne ikke dekodes. + + + + + Please check the signature and try again. + Vennligst sjekk signaturen og prøv igjen. + + + + The signature did not match the message digest. + Signaturen passer ikke til meldingen. + + + + Message verification failed. + Verifikasjon av melding feilet. + + + + Message verified. + Melding verifisert. + + + + TransactionDesc + + + Open until %1 + Åpen til %1 + + + + Open for %n block(s) + + + + + conflicted + + + + + %1/offline + %1/frakoblet + + + + %1/unconfirmed + %1/ubekreftet + + + + %1 confirmations + %1 bekreftelser + + + + Status + Status + + + + , broadcast through %n node(s) + , kringkast gjennom %n node, kringkast gjennom %n noder + + + + Date + Dato + + + + Source + Kilde + + + + Generated + Generert + + + + + From + Fra + + + + + + To + Til + + + + + own address + egen adresse + + + + label + merkelapp + + + + + + + + Credit + Kredit + + + + matures in %n more block(s) + blir moden om %n blokkblir moden om %n blokker + + + + not accepted + ikke akseptert + + + + + + + Debit + Debet + + + + Transaction fee + Transaksjonsgebyr + + + + Net amount + Nettobeløp + + + + Message + Melding + + + + Comment + Kommentar + + + + Transaction ID + Transaksjons-ID + + + + Generated coins must mature 6 blocks before they can be spent. When you generated this block, it was broadcast to the network to be added to the block chain. If it fails to get into the chain, its state will change to "not accepted" and it won't be spendable. This may occasionally happen if another node generates a block within a few seconds of yours. + + + + + Debug information + Informasjon for feilsøk + + + + Transaction + Transaksjon + + + + Inputs + Inndata + + + + Amount + Beløp + + + + true + sann + + + + false + usann + + + + , has not been successfully broadcast yet + , har ikke blitt kringkastet uten problemer enda. + + + + unknown + ukjent + + + + TransactionDescDialog + + + Transaction details + Transaksjonsdetaljer + + + + This pane shows a detailed description of the transaction + Her vises en detaljert beskrivelse av transaksjonen + + + + TransactionTableModel + + + Date + Dato + + + + Type + Type + + + + Address + Adresse + + + + Amount + Beløp + + + + Open until %1 + Åpen til %1 + + + + Confirmed (%1 confirmations) + Bekreftet (%1 bekreftelser) + + + + Open for %n more block(s) + Åpen for %n blokk tilÅpen for %n blokker til + + + + Offline + + + + + Unconfirmed + Ubekreftet + + + + Confirming (%1 of %2 recommended confirmations) + Bekrefter (%1 av %2 anbefalte bekreftelser) + + + + Conflicted + + + + + Immature (%1 confirmations, will be available after %2) + + + + + This block was not received by any other nodes and will probably not be accepted! + Denne blokken har ikke blitt mottatt av noen andre noder og vil sannsynligvis ikke bli akseptert! + + + + Generated but not accepted + Generert men ikke akseptert + + + + Received with + Mottatt med + + + + Received from + Mottatt fra + + + + Sent to + Sendt til + + + + Payment to yourself + Betaling til deg selv + + + + Mined + Utvunnet + + + + (n/a) + - + + + + Transaction status. Hover over this field to show number of confirmations. + Transaksjonsstatus. Hold muspekeren over dette feltet for å se antall bekreftelser. + + + + Date and time that the transaction was received. + Dato og tid for da transaksjonen ble mottat. + + + + Type of transaction. + Type transaksjon. + + + + Destination address of transaction. + Mottaksadresse for transaksjonen + + + + Amount removed from or added to balance. + Beløp fjernet eller lagt til saldo. + + + + TransactionView + + + + All + Alle + + + + Today + I dag + + + + This week + Denne uken + + + + This month + Denne måneden + + + + Last month + Forrige måned + + + + This year + Dette året + + + + Range... + Intervall... + + + + Received with + Mottatt med + + + + Sent to + Sendt til + + + + To yourself + Til deg selv + + + + Mined + Utvunnet + + + + Other + Andre + + + + Enter address or label to search + Skriv inn adresse eller merkelapp for søk + + + + Min amount + Minimumsbeløp + + + + Copy address + Kopier adresse + + + + Copy label + Kopier merkelapp + + + + Copy amount + Kopiér beløp + + + + Copy transaction ID + Kopier transaksjons-ID + + + + Edit label + Rediger merkelapp + + + + Show transaction details + Vis transaksjonsdetaljer + + + + Export Transaction Data + + + + + Comma separated file (*.csv) + Kommaseparert fil (*.csv) + + + + Confirmed + Bekreftet + + + + Date + Dato + + + + Type + Type + + + + Label + Merkelapp + + + + Address + Adresse + + + + Amount + Beløp + + + + ID + ID + + + + Error exporting + + + + + Could not write to file %1. + Kunne ikke skrive til filen %1 + + + + Range: + Intervall: + + + + to + til + + + + WalletModel + + + Sending... + Sender... + + + + bitcoin-core + + + Arepacoin version + Arepacoin versjon + + + + Usage: + Bruk: + + + + Send command to -server or arepacoind + + + + + List commands + List opp kommandoer + + + + Get help for a command + Vis hjelpetekst for en kommando + + + + Options: + Innstillinger: + + + + Specify configuration file (default: arepacoin.conf) + + + + + Specify pid file (default: arepacoind.pid) + + + + + Specify wallet file (within data directory) + Angi lommebok fil (inne i data mappe) + + + + Specify data directory + Angi mappe for datafiler + + + + Set database cache size in megabytes (default: 25) + Sett størrelse på mellomlager for database i megabytes (standardverdi: 25) + + + + Set database disk log size in megabytes (default: 100) + + + + + Listen for connections on <port> (default: 9853 or testnet: 19853) + + + + + Maintain at most <n> connections to peers (default: 125) + Hold maks <n> koblinger åpne til andre noder (standardverdi: 125) + + + + Connect to a node to retrieve peer addresses, and disconnect + Koble til node for å hente adresser til andre noder, koble så fra igjen + + + + Specify your own public address + Angi din egen offentlige adresse + + + + Bind to given address. Use [host]:port notation for IPv6 + + + + + Stake your coins to support network and gain reward (default: 1) + + + + + Threshold for disconnecting misbehaving peers (default: 100) + Grenseverdi for å koble fra noder med dårlig oppførsel (standardverdi: 100) + + + + Number of seconds to keep misbehaving peers from reconnecting (default: 86400) + Antall sekunder noder med dårlig oppførsel hindres fra å koble til på nytt (standardverdi: 86400) + + + + An error occurred while setting up the RPC port %u for listening on IPv4: %s + En feil oppstod ved opprettelse av RPC port %u for lytting: %s + + + + Detach block and address databases. Increases shutdown time (default: 0) + + + + + 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. + + + + + Error: This transaction requires a transaction fee of at least %s because of its amount, complexity, or use of recently received funds + + + + + Listen for JSON-RPC connections on <port> (default: 9852 or testnet: 19852) + + + + + Accept command line and JSON-RPC commands + Ta imot kommandolinje- og JSON-RPC-kommandoer + + + + Error: Transaction creation failed + Feil: Opprettelse av transaksjonen mislyktes + + + + Error: Wallet locked, unable to create transaction + + + + + Importing blockchain data file. + + + + + Importing bootstrap blockchain data file. + + + + + Run in the background as a daemon and accept commands + Kjør i bakgrunnen som daemon og ta imot kommandoer + + + + Use the test network + Bruk testnettverket + + + + Accept connections from outside (default: 1 if no -proxy or -connect) + Ta imot tilkoblinger fra utsiden (standardverdi: 1 hvis uten -proxy eller -connect) + + + + An error occurred while setting up the RPC port %u for listening on IPv6, falling back to IPv4: %s + En feil oppstod under oppsettet av RPC port %u for IPv6, tilbakestilles til IPv4: %s + + + + Error initializing database environment %s! To recover, BACKUP THAT DIRECTORY, then remove everything from it except for wallet.dat. + + + + + Set maximum size of high-priority/low-fee transactions in bytes (default: 27000) + + + + + Warning: -paytxfee is set very high! This is the transaction fee you will pay if you send a transaction. + Advarsel: -paytxfee er satt veldig høyt! Dette er transaksjonsgebyret du betaler når du sender transaksjoner. + + + + Warning: Please check that your computer's date and time are correct! If your clock is wrong Arepacoin will not work properly. + + + + + Warning: error reading wallet.dat! All keys read correctly, but transaction data or address book entries might be missing or incorrect. + Advarsel: Feil ved lesing av wallet.dat! Alle taster lest riktig, men transaksjon dataene eller adresse innlegg er kanskje manglende eller feil. + + + + Warning: wallet.dat corrupt, data salvaged! Original wallet.dat saved as wallet.{timestamp}.bak in %s; if your balance or transactions are incorrect you should restore from a backup. + Advarsel: wallet.dat korrupt, data reddet! Original wallet.dat lagret som wallet.{timestamp}.bak i %s; hvis din saldo eller dine transaksjoner ikke er korrekte bør du gjenopprette fra en backup. + + + + Attempt to recover private keys from a corrupt wallet.dat + Forsøk å berge private nøkler fra en korrupt wallet.dat + + + + Block creation options: + Valg for opprettelse av blokker: + + + + Connect only to the specified node(s) + Koble kun til angitt(e) node(r) + + + + Discover own IP address (default: 1 when listening and no -externalip) + Oppdag egen IP-adresse (standardverdi: 1 ved lytting og uten -externalip) + + + + Failed to listen on any port. Use -listen=0 if you want this. + Kunne ikke lytte på noen port. Bruk -listen=0 hvis det er dette du vil. + + + + Find peers using DNS lookup (default: 1) + + + + + Sync checkpoints policy (default: strict) + + + + + Invalid -tor address: '%s' + + + + + Invalid amount for -reservebalance=<amount> + + + + + Maximum per-connection receive buffer, <n>*1000 bytes (default: 5000) + Maks mottaksbuffer per forbindelse, <n>*1000 bytes (standardverdi: 5000) + + + + Maximum per-connection send buffer, <n>*1000 bytes (default: 1000) + Maks sendebuffer per forbindelse, <n>*1000 bytes (standardverdi: 1000) + + + + Only connect to nodes in network <net> (IPv4, IPv6 or Tor) + Koble kun til noder i nettverket <nett> (IPv4, IPv6 eller Tor) + + + + Output extra debugging information. Implies all other -debug* options + + + + + Output extra network debugging information + + + + + Prepend debug output with timestamp + + + + + SSL options: (see the Bitcoin Wiki for SSL setup instructions) + SSL valg: (se Bitcoin Wiki for instruksjoner for oppsett av SSL) + + + + Select the version of socks proxy to use (4-5, default: 5) + + + + + Send trace/debug info to console instead of debug.log file + Send spor/debug informasjon til konsollet istedenfor debug.log filen + + + + Send trace/debug info to debugger + + + + + Set maximum block size in bytes (default: 250000) + + + + + Set minimum block size in bytes (default: 0) + Sett minimum blokkstørrelse i bytes (standardverdi: 0) + + + + Shrink debug.log file on client startup (default: 1 when no -debug) + Krymp debug.log filen når klienten starter (standardverdi: 1 hvis uten -debug) + + + + Specify connection timeout in milliseconds (default: 5000) + Angi tidsavbrudd for forbindelse i millisekunder (standardverdi: 5000) + + + + Unable to sign checkpoint, wrong checkpointkey? + + + + + + Use UPnP to map the listening port (default: 0) + Bruk UPnP for lytteport (standardverdi: 0) + + + + Use UPnP to map the listening port (default: 1 when listening) + Bruk UPnP for lytteport (standardverdi: 1 ved lytting) + + + + Use proxy to reach tor hidden services (default: same as -proxy) + + + + + Username for JSON-RPC connections + Brukernavn for JSON-RPC forbindelser + + + + Verifying database integrity... + Verifiserer databasens integritet... + + + + WARNING: syncronized checkpoint violation detected, but skipped! + + + + + Warning: Disk space is low! + Advarsel: Lite lagringsplass! + + + + Warning: This version is obsolete, upgrade required! + Advarsel: Denne versjonen er foreldet, oppgradering kreves! + + + + wallet.dat corrupt, salvage failed + wallet.dat korrupt, bergning feilet + + + + Password for JSON-RPC connections + Passord for JSON-RPC forbindelser + + + + %s, you must set a rpcpassword in the configuration file: + %s +It is recommended you use the following random password: +rpcuser=arepacoinrpc +rpcpassword=%s +(you do not need to remember this password) +The username and password MUST NOT be the same. +If the file does not exist, create it with owner-readable-only file permissions. +It is also recommended to set alertnotify so you are notified of problems; +for example: alertnotify=echo %%s | mail -s "Arepacoin Alert" admin@foo.com + + + + + + Find peers using internet relay chat (default: 0) + + + + + Sync time with other nodes. Disable if time on your system is precise e.g. syncing with NTP (default: 1) + + + + + When creating transactions, ignore inputs with value less than this (default: 0.01) + + + + + Allow JSON-RPC connections from specified IP address + Tillat JSON-RPC tilkoblinger fra angitt IP-adresse + + + + Send commands to node running on <ip> (default: 127.0.0.1) + Send kommandoer til node på <ip> (standardverdi: 127.0.0.1) + + + + Execute command when the best block changes (%s in cmd is replaced by block hash) + Eksekvér kommando når beste blokk endrer seg (%s i kommandoen erstattes med blokkens hash) + + + + Execute command when a wallet transaction changes (%s in cmd is replaced by TxID) + Kjør kommando når en lommeboktransaksjon endres (%s i cmd er erstattet med TxID) + + + + Require a confirmations for change (default: 0) + + + + + Enforce transaction scripts to use canonical PUSH operators (default: 1) + + + + + Execute command when a relevant alert is received (%s in cmd is replaced by message) + + + + + Upgrade wallet to latest format + Oppgradér lommebok til nyeste format + + + + Set key pool size to <n> (default: 100) + Angi størrelse på nøkkel-lager til <n> (standardverdi: 100) + + + + Rescan the block chain for missing wallet transactions + Se gjennom blokk-kjeden etter manglende lommeboktransaksjoner + + + + How many blocks to check at startup (default: 2500, 0 = all) + + + + + How thorough the block verification is (0-6, default: 1) + + + + + Imports blocks from external blk000?.dat file + + + + + Use OpenSSL (https) for JSON-RPC connections + Bruk OpenSSL (https) for JSON-RPC forbindelser + + + + Server certificate file (default: server.cert) + Servers sertifikat (standardverdi: server.cert) + + + + Server private key (default: server.pem) + Servers private nøkkel (standardverdi: server.pem) + + + + Acceptable ciphers (default: TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH) + + + + + Error: Wallet unlocked for staking only, unable to create transaction. + + + + + WARNING: Invalid checkpoint found! Displayed transactions may not be correct! You may need to upgrade, or notify developers. + + + + + This help message + Denne hjelpemeldingen + + + + Wallet %s resides outside data directory %s. + Lommeboken %s holder til utenfor data mappen %s. + + + + Cannot obtain a lock on data directory %s. Arepacoin is probably already running. + + + + + Arepacoin + Arepacoin + + + + Unable to bind to %s on this computer (bind returned error %d, %s) + Kan ikke binde til %s på denne datamaskinen (bind returnerte feil %d, %s) + + + + Connect through socks proxy + + + + + Allow DNS lookups for -addnode, -seednode and -connect + Tillat DNS oppslag for -addnode, -seednode og -connect + + + + Loading addresses... + Laster adresser... + + + + Error loading blkindex.dat + + + + + Error loading wallet.dat: Wallet corrupted + Feil ved lasting av wallet.dat: Lommeboken er skadet + + + + Error loading wallet.dat: Wallet requires newer version of Arepacoin + + + + + Wallet needed to be rewritten: restart Arepacoin to complete + + + + + Error loading wallet.dat + Feil ved lasting av wallet.dat + + + + Invalid -proxy address: '%s' + Ugyldig -proxy adresse: '%s' + + + + Unknown network specified in -onlynet: '%s' + Ukjent nettverk angitt i -onlynet '%s' + + + + Unknown -socks proxy version requested: %i + Ukjent -socks proxy versjon angitt: %i + + + + Cannot resolve -bind address: '%s' + Kunne ikke slå opp -bind adresse: '%s' + + + + Cannot resolve -externalip address: '%s' + Kunne ikke slå opp -externalip adresse: '%s' + + + + Invalid amount for -paytxfee=<amount>: '%s' + Ugyldig beløp for -paytxfee=<beløp>: '%s' + + + + Error: could not start node + + + + + Sending... + Sender... + + + + Invalid amount + Ugyldig beløp + + + + Insufficient funds + Utilstrekkelige midler + + + + Loading block index... + Laster blokkindeks... + + + + Add a node to connect to and attempt to keep the connection open + Legg til node for tilkobling og hold forbindelsen åpen + + + + Unable to bind to %s on this computer. Arepacoin is probably already running. + + + + + Fee per KB to add to transactions you send + Gebyr per KB som skal legges til transaksjoner du sender + + + + Invalid amount for -mininput=<amount>: '%s' + + + + + Loading wallet... + Laster lommebok... + + + + Cannot downgrade wallet + Kan ikke nedgradere lommebok + + + + Cannot initialize keypool + + + + + Cannot write default address + Kan ikke skrive standardadresse + + + + Rescanning... + Leser gjennom... + + + + Done loading + Ferdig med lasting + + + + To use the %s option + For å bruke %s opsjonen + + + + Error + Feil + + + + You must set rpcpassword=<password> in the configuration file: +%s +If the file does not exist, create it with owner-readable-only file permissions. + Du må sette rpcpassword=<passord> i konfigurasjonsfilen: +%s +Hvis filen ikke finnes, opprett den med leserettighet kun for eier av filen. + + + \ No newline at end of file diff --git a/src/qt/locale/bitcoin_nl.ts b/src/qt/locale/bitcoin_nl.ts new file mode 100755 index 0000000..4053cd2 --- /dev/null +++ b/src/qt/locale/bitcoin_nl.ts @@ -0,0 +1,3312 @@ + + + AboutDialog + + + About Arepacoin + Over Arepacoin + + + + <b>Arepacoin</b> version + <b>Arepacoin</b> versie + + + + Copyright © 2009-2014 The Bitcoin developers +Copyright © 2012-2014 The NovaCoin developers +Copyright © 2014 The Arepacoin developers + Copyright © 2009-2014 De Bitcoin ontwikkelaars +Copyright © 2012-2014 De NovaCoin ontwikkelaars +Copyright © 2014 De Arepacoin ontwikkelaars + + + + +This is experimental software. + +Distributed under the MIT/X11 software license, see the accompanying file COPYING or http://www.opensource.org/licenses/mit-license.php. + +This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit (http://www.openssl.org/) and cryptographic software written by Eric Young (eay@cryptsoft.com) and UPnP software written by Thomas Bernard. + +Dit is experimentele software. + +Gedistribueerd onder de MIT/X11 software licentie, zie het bijgevoegde bestand COPYING of http://www.opensource.org/licenses/mit-license.php. + +Dit product bevat software ontwikkeld door het OpenSSL Project voor gebruik in de OpenSSL Toolkit (http://www.openssl.org/) en cryptografische software gemaakt door Eric Young (eay@cryptsoft.com) en UPnP software geschreven door Thomas Bernard. + + + + AddressBookPage + + + Address Book + Adresboek + + + + Double-click to edit address or label + Dubbelklik om het adres of label te wijzigen + + + + Create a new address + Maak een nieuw adres aan + + + + Copy the currently selected address to the system clipboard + Kopieer het huidig geselecteerde adres naar het klembord + + + + &New Address + &Nieuw adres + + + + These are your Arepacoin addresses for receiving payments. You may want to give a different one to each sender so you can keep track of who is paying you. + Dit zijn al jou Arepacoin adressen om betalingen mee te ontvangen. Je kunt iedere verzender een apart adres geven zodat je kunt volgen wie jou betaald. + + + + &Copy Address + &Kopiëer Adres + + + + Show &QR Code + Toon &QR Code + + + + Sign a message to prove you own a Arepacoin address + Teken een bericht om te bewijzen dat je een Arepacoin adres bezit. + + + + Sign &Message + Teken &Bericht + + + + Delete the currently selected address from the list + Verwijder het geselecteerde adres van de lijst + + + + Verify a message to ensure it was signed with a specified Arepacoin address + Verifieer een bericht om zeker te zijn dat deze is ondertekend met een specifiek Arepacoin adres + + + + &Verify Message + &Verifieer Bericht + + + + &Delete + &Verwijder + + + + Copy &Label + Kopiëer &Label + + + + &Edit + &Bewerk + + + + Export Address Book Data + Exporteer Adresboek Data + + + + Comma separated file (*.csv) + Kommagescheiden bestand (*.csv) + + + + Error exporting + Fout bij exporteren + + + + Could not write to file %1. + Kan niet schrijven naat bestand %1 + + + + AddressTableModel + + + Label + Label + + + + Address + Adres + + + + (no label) + (geen label) + + + + AskPassphraseDialog + + + Passphrase Dialog + Wachtwoordscherm + + + + Enter passphrase + Voer wachtwoord in + + + + New passphrase + Nieuw wachtwoord + + + + Repeat new passphrase + Herhaal wachtwoord + + + + Serves to disable the trivial sendmoney when OS account compromised. Provides no real security. + Bedoeld om het command 'sendmoney' uit te schakelen indien het OS niet meer veilig is. Geeft geen echte beveiliging. + + + + For staking only + Alleen voor staking + + + + Enter the new passphrase to the wallet.<br/>Please use a passphrase of <b>10 or more random characters</b>, or <b>eight or more words</b>. + Vul een nieuw wachtwoord in voor uw portemonnee. <br/> Gebruik een wachtwoord van <b>10 of meer verschillende karakters</b>, of <b> acht of meer woorden</b> . + + + + Encrypt wallet + Versleutel portemonnee + + + + This operation needs your wallet passphrase to unlock the wallet. + Deze operatie vereist uw portemonneewachtwoord om de portemonnee te openen. + + + + Unlock wallet + Open portemonnee + + + + This operation needs your wallet passphrase to decrypt the wallet. + Deze operatie vereist uw portemonneewachtwoord om de portemonnee te ontsleutelen + + + + Decrypt wallet + Ontsleutel portemonnee + + + + Change passphrase + Wijzig wachtwoord + + + + Enter the old and new passphrase to the wallet. + Vul uw oude en nieuwe portemonneewachtwoord in. + + + + Confirm wallet encryption + Bevestig versleuteling van de portemonnee + + + + Warning: If you encrypt your wallet and lose your passphrase, you will <b>LOSE ALL OF YOUR COINS</b>! + Waarschuwing: Als je je portemonnee versleuteld en je verliest je wachtwoord zul je <b>AL JE MUNTEN VERLIEZEN</b>! + + + + Are you sure you wish to encrypt your wallet? + Weet u zeker dat u uw portemonnee wilt versleutelen? + + + + IMPORTANT: Any previous backups you have made of your wallet file should be replaced with the newly generated, encrypted wallet file. For security reasons, previous backups of the unencrypted wallet file will become useless as soon as you start using the new, encrypted wallet. + BELANGRIJK: Elke eerder gemaakte backup van uw portemonneebestand dient u te vervangen door het nieuw gegenereerde, versleutelde portemonneebestand. Om veiligheidsredenen zullen eerdere backups van het niet-versleutelde portemonneebestand onbruikbaar worden zodra u uw nieuwe, versleutelde, portemonnee begint te gebruiken. + + + + + Warning: The Caps Lock key is on! + Waarschuwing: De Caps-Lock-toets staat aan! + + + + + Wallet encrypted + Portemonnee versleuteld + + + + Arepacoin will close now to finish the encryption process. Remember that encrypting your wallet cannot fully protect your coins from being stolen by malware infecting your computer. + Arepacoin zal nu sluiten om het versleutel proces te voltooien. Onthou dat het versleutelen van je portemonnee je niet volledig beschermt tegen diefstal van munten door malware op je computer. + + + + + + + Wallet encryption failed + Portemonneeversleuteling mislukt + + + + Wallet encryption failed due to an internal error. Your wallet was not encrypted. + Portemonneeversleuteling mislukt door een interne fout. Uw portemonnee is niet versleuteld. + + + + + The supplied passphrases do not match. + De opgegeven wachtwoorden komen niet overeen + + + + Wallet unlock failed + Portemonnee openen mislukt + + + + + + The passphrase entered for the wallet decryption was incorrect. + Het opgegeven wachtwoord voor de portemonnee-ontsleuteling is niet correct. + + + + Wallet decryption failed + Portemonnee-ontsleuteling mislukt + + + + Wallet passphrase was successfully changed. + Portemonneewachtwoord is met succes gewijzigd. + + + + BitcoinGUI + + + Sign &message... + &Onderteken bericht... + + + + Synchronizing with network... + Synchroniseren met netwerk... + + + + &Overview + &Overzicht + + + + Show general overview of wallet + Toon algemeen overzicht van de portemonnee + + + + &Transactions + &Transacties + + + + Browse transaction history + Blader door transactieverleden + + + + &Address Book + &Adresboek + + + + Edit the list of stored addresses and labels + Wijzig de lijst met bewaarde adressen en labels + + + + &Receive coins + &Ontvang munten + + + + Show the list of addresses for receiving payments + Toon de lijst aan adressen voor ontvangen betalingen + + + + &Send coins + Verstuur munten + + + + E&xit + &Afsluiten + + + + Quit application + Programma afsluiten + + + + Show information about Arepacoin + Toon informatie over Arepacoin + + + + About &Qt + Over &Qt + + + + Show information about Qt + Toon informatie over Qt + + + + &Options... + &Opties... + + + + &Encrypt Wallet... + &Versleutel Portemonnee... + + + + &Backup Wallet... + &Backup Portemonnee... + + + + &Change Passphrase... + &Wijzig Wachtwoord + + + + ~%n block(s) remaining + ~%n blok nodig~%n blokken nodig + + + + Downloaded %1 of %2 blocks of transaction history (%3% done). + %1 van %2 aan transactie historie blokken gedownload (%3% klaar). + + + + &Export... + &Exporteren... + + + + Send coins to a Arepacoin address + Verstuur munten naar een Arepacoin adres + + + + Modify configuration options for Arepacoin + Verander configuratie opties voor Arepacoin + + + + Export the data in the current tab to a file + Exporteer de data in de huidige tab naar een bestand + + + + Encrypt or decrypt wallet + Versleutel of ontsleutel de portemonnee + + + + Backup wallet to another location + Backup portemonnee naar een andere locatie + + + + Change the passphrase used for wallet encryption + Wijzig het wachtwoord voor uw portemonneversleuteling + + + + &Debug window + &Debugscherm + + + + Open debugging and diagnostic console + Open debugging en diagnostische console + + + + &Verify message... + &Verifiëer bericht... + + + + Arepacoin + Arepacoin + + + + Wallet + Portemonnee + + + + &About Arepacoin + &Over Arepacoin + + + + &Show / Hide + &Toon / Verberg + + + + Unlock wallet + Open portemonnee + + + + &Lock Wallet + &Sluit portemonnee + + + + Lock wallet + Sluit portemonnee + + + + &File + &Bestand + + + + &Settings + &Instellingen + + + + &Help + &Hulp + + + + Tabs toolbar + Tab-werkbalk + + + + Actions toolbar + Acties werkbalk + + + + + [testnet] + [testnetwerk] + + + + + Arepacoin client + Arepacoin client + + + + %n active connection(s) to Arepacoin network + %n actieve verbinding naar Arepacoin netwerk%n actieve verbindingen naar Arepacoin netwerk + + + + Downloaded %1 blocks of transaction history. + %1 blokken van transactie geschiedenis gedownload. + + + + Staking.<br>Your weight is %1<br>Network weight is %2<br>Expected time to earn reward is %3 + Staking. <br> Uw gewicht wordt %1 <br> Network gewicht is %2 <br> Verwachte tijd om beloning te verdienen is %3 + + + + Not staking because wallet is locked + Niet staking omdat portemonnee aan het beveiligd is + + + + Not staking because wallet is offline + Niet staking omdat portemonnee aan het offline is + + + + Not staking because wallet is syncing + Niet staking omdat portemonnee aan het synchroniseren is. + + + + Not staking because you don't have mature coins + Niet staking omdat je geen mature munten hebt + + + + %n second(s) ago + %n seconden geleden%n seconden geleden + + + + &Unlock Wallet... + Ontgrendel portemonnee... + + + + %n minute(s) ago + %n minuut geleden%n minuten geleden + + + + %n hour(s) ago + %n uur geleden%n uren geleden + + + + %n day(s) ago + %n dag geleden%n dagen geleden + + + + Up to date + Bijgewerkt + + + + Catching up... + Aan het bijwerken... + + + + Last received block was generated %1. + Laatst ontvangen blok is gegenereerd op %1. + + + + This transaction is over the size limit. You can still send it for a fee of %1, which goes to the nodes that process your transaction and helps to support the network. Do you want to pay the fee? + De grootte van deze transactie overschrijdt de limiet. U kan deze transactie laten uitvoeren voor een meerkost van %1, dewelke doorgestuurd wordt naar de nodes die uw transactie verwerken, alsook ter ondersteuning van het netwerk. Wil u deze meerkost betalen? + + + + Confirm transaction fee + Bevestig transactie kosten + + + + Sent transaction + Verzonden transactie + + + + Incoming transaction + Binnenkomende transactie + + + + Date: %1 +Amount: %2 +Type: %3 +Address: %4 + + Datum: %1 +Bedrag: %2 +Type: %3 +Adres: %4 + + + + + + URI handling + URI-behandeling + + + + + URI can not be parsed! This can be caused by an invalid Arepacoin address or malformed URI parameters. + URI kan niet ontleedt worden! Mogelijke oorzaken zijn een ongeldig Arepacoin adres of incorrecte URI parameters. + + + + Wallet is <b>encrypted</b> and currently <b>unlocked</b> + Portemonnee is <b>versleuteld</b> en momenteel <b>geopend</b> + + + + Wallet is <b>encrypted</b> and currently <b>locked</b> + Portemonnee is <b>versleuteld</b> en momenteel <b>gesloten</b> + + + + Backup Wallet + Backup Portemonnee + + + + Wallet Data (*.dat) + Portemonnee bestanden (*.dat) + + + + Backup Failed + Backup mislukt + + + + There was an error trying to save the wallet data to the new location. + Er was een fout opgetreden bij het opslaan van de wallet data naar de nieuwe locatie. + + + + %n second(s) + %n seconden%n seconden + + + + %n minute(s) + %n minuut%n minuten + + + + %n hour(s) + %n uur%n uur + + + + %n day(s) + %n dag%n dagen + + + + Not staking + Niet aan het staken. + + + + A fatal error occurred. Arepacoin can no longer continue safely and will quit. + Een fatale fout . Arepacoin kan niet langer veilig doorgaan en sluit af. + + + + ClientModel + + + Network Alert + Netwerkwaarschuwing + + + + CoinControlDialog + + + Coin Control + Coin controle opties + + + + Quantity: + Kwantiteit + + + + Bytes: + Bytes: + + + + Amount: + Bedrag: + + + + Priority: + Prioriteit: + + + + Fee: + Vergoeding: + + + + Low Output: + Lage uitvoer: + + + + no + nee + + + + After Fee: + Na vergoeding: + + + + Change: + Wijzigen: + + + + (un)select all + (de)selecteer alles + + + + Tree mode + Boom modus + + + + List mode + Lijst modus + + + + Amount + Bedrag + + + + Label + Label + + + + Address + Adres + + + + Date + Datum + + + + Confirmations + Bevestigingen + + + + Confirmed + Bevestigd + + + + Priority + Prioriteit + + + + Copy address + Kopieer adres + + + + Copy label + Kopieer label + + + + + Copy amount + Kopieer bedrag + + + + Copy transaction ID + Kopieer transactie-ID + + + + Copy quantity + Kopieer aantal + + + + Copy fee + Kopieer vergoeding + + + + Copy after fee + Kopieer na vergoeding + + + + Copy bytes + Kopieer bytes + + + + Copy priority + Kopieer prioriteit + + + + Copy low output + Kopieer lage uitvoer + + + + Copy change + Kopieer wijzig + + + + highest + hoogste + + + + high + hoog + + + + medium-high + gemiddeld hoog + + + + medium + gemiddeld + + + + low-medium + laag gemiddeld + + + + low + laag + + + + lowest + laagste + + + + DUST + STOF + + + + yes + ja + + + + This label turns red, if the transaction size is bigger than 10000 bytes. + + This means a fee of at least %1 per kb is required. + + Can vary +/- 1 Byte per input. + Dit label wordt rood, als de transactie grootte groter is dan 10000 bytes.<br> + +Dit betekend een fee van minimaal %1 per kb is noodzakelijk.<br> + +Kan varieren van +/- 1 Byte per invulling + + + + Transactions with higher priority get more likely into a block. + +This label turns red, if the priority is smaller than "medium". + + This means a fee of at least %1 per kb is required. + Transacties met hogere prioriteit komen sneller in een blok + +Dit label wordt rood, als de prioriteit kleiner is dan "normaal". + +Dit betekend een fee van minimaal %1 per kb is noodzakelijk. + + + + This label turns red, if any recipient receives an amount smaller than %1. + + This means a fee of at least %2 is required. + + Amounts below 0.546 times the minimum relay fee are shown as DUST. + Dit label wordt rood, als elke ontvanger ontvangt een bedrag dat kleiner is dan 1%. + +Dit betekent dat een vergoeding van ten minste 2% is vereist. + +Bedragen onder 0.546 keer het minimum vergoeding worden weergegeven als DUST. + + + + This label turns red, if the change is smaller than %1. + + This means a fee of at least %2 is required. + Dit label wordt rood, als de verandering kleiner is dan %1. + +Dit betekend dat een fee van %2 is vereist. + + + + + (no label) + (geen label) + + + + change from %1 (%2) + wijzig van %1 (%2) + + + + (change) + (wijzig) + + + + EditAddressDialog + + + Edit Address + Bewerk Adres + + + + &Label + &Label + + + + The label associated with this address book entry + Het label geassocieerd met deze notitie in het adresboek + + + + &Address + &Adres + + + + The address associated with this address book entry. This can only be modified for sending addresses. + Het adres geassocieerd met deze notitie in het adresboek. Dit kan enkel aangepast worden bij verzend-adressen. + + + + New receiving address + Nieuw ontvangstadres + + + + New sending address + Nieuw adres om naar te verzenden + + + + Edit receiving address + Bewerk ontvangstadres + + + + Edit sending address + Bewerk adres om naar te verzenden + + + + The entered address "%1" is already in the address book. + Het opgegeven adres "%1" bestaat al in uw adresboek. + + + + The entered address "%1" is not a valid Arepacoin address. + Het ingevoerde adres "%1" is geen geldig Arepacoin adres. + + + + Could not unlock wallet. + Kon de portemonnee niet openen. + + + + New key generation failed. + Genereren nieuwe sleutel mislukt. + + + + GUIUtil::HelpMessageBox + + + + Arepacoin-Qt + Arepacoin-Qt + + + + version + versie + + + + Usage: + Gebruik: + + + + command-line options + Commandoregel-opties + + + + UI options + Gebruikerinterface-opties + + + + Set language, for example "de_DE" (default: system locale) + Stel taal in, bijvoorbeeld "de_DE" (standaard: systeeminstellingen) + + + + Start minimized + Geminimaliseerd starten + + + + Show splash screen on startup (default: 1) + Laat laadscherm zien bij het opstarten. (standaard: 1) + + + + OptionsDialog + + + Options + Opties + + + + &Main + &Algemeen + + + + Optional transaction fee per kB that helps make sure your transactions are processed quickly. Most transactions are 1 kB. Fee 0.01 recommended. + Optioneel transactiekosten per kB dat helpt ervoor zorgen dat uw transacties worden snel verwerkt. De meeste transacties zijn 1 kB. Fee 0.01 aanbevolen. + + + + Pay transaction &fee + Betaal &transactiekosten + + + + Reserved amount does not participate in staking and is therefore spendable at any time. + Gereserveerde hoeveelheid doet niet mee in staking en is daarom altijd uitgeefbaar. + + + + Reserve + Gereserveerd + + + + Automatically start Arepacoin after logging in to the system. + Automatisch starten van Arepacoin na inloggen van het systeem. + + + + &Start Arepacoin on system login + &Start Arepacoin bij systeem aanmelding + + + + Detach block and address databases at shutdown. This means they can be moved to another data directory, but it slows down shutdown. The wallet is always detached. + Los blok en adressenbestanden bij het afsluiten. Dit betekent dat ze naar een ander data-map worden verplaatst, maar het vertraagt ​​shutdown. De portemonnee is altijd vrijstaand. + + + + &Detach databases at shutdown + &Koppel database los bij afsluiten + + + + &Network + &Netwerk + + + + Automatically open the Arepacoin client port on the router. This only works when your router supports UPnP and it is enabled. + De Arepacoin client poort automatisch openen op de router. Dit werkt alleen wanneer uw router UPnP ondersteunt en deze is ingeschakeld. + + + + Map port using &UPnP + Portmapping via &UPnP + + + + Connect to the Arepacoin network through a SOCKS proxy (e.g. when connecting through Tor). + Verbinding maken met het Arepacoin netwerk via een SOCKS proxy (bijvoorbeeld als U gebruik maakt van Tor) + + + + &Connect through SOCKS proxy: + &Verbind door SOCKS proxy: + + + + Proxy &IP: + Proxy &IP: + + + + IP address of the proxy (e.g. 127.0.0.1) + IP Adres van de proxy (bijv. 127.0.0.1) + + + + &Port: + &Poort: + + + + Port of the proxy (e.g. 9050) + Poort van de proxy (bijv. 9050) + + + + SOCKS &Version: + SOCKS-&Versie: + + + + SOCKS version of the proxy (e.g. 5) + SOCKS-versie van de proxy (bijv. 5) + + + + &Window + &Scherm + + + + Show only a tray icon after minimizing the window. + Laat alleen een systeemvak-icoon zien wanneer het venster geminimaliseerd is + + + + &Minimize to the tray instead of the taskbar + &Minimaliseer naar het systeemvak in plaats van de taakbalk + + + + Minimize instead of exit the application when the window is closed. When this option is enabled, the application will be closed only after selecting Quit in the menu. + Minimaliseer het venster in de plaats van de applicatie af te sluiten als het venster gesloten wordt. Wanneer deze optie aan staan, kan de applicatie alleen worden afgesloten door Afsluiten te kiezen in het menu. + + + + M&inimize on close + Minimaliseer bij sluiten van het &venster + + + + &Display + &Interface + + + + User Interface &language: + Taal &Gebruikersinterface: + + + + The user interface language can be set here. This setting will take effect after restarting Arepacoin. + De user interface-taal kan hier ingesteld worden. Deze instelling word toegepast na Arepacoin opnieuw op te starten. + + + + &Unit to show amounts in: + &Eenheid om bedrag in te tonen: + + + + Choose the default subdivision unit to show in the interface and when sending coins. + Kies de standaard onderverdelingseenheid om weer te geven in uw programma, en voor het versturen van munten + + + + Whether to show Arepacoin addresses in the transaction list or not. + Arepacoin adressen in de transactielijst weergeven of niet + + + + &Display addresses in transaction list + Toon a&dressen in de transactielijst + + + + Whether to show coin control features or not. + Munt controle functies weergeven of niet. + + + + Display coin &control features (experts only!) + Laat coin & control functies zien (enkel voor gevorderden!) + + + + &OK + &OK + + + + &Cancel + Ann&uleren + + + + &Apply + &Toepassen + + + + default + standaard + + + + + Warning + Waarschuwing + + + + + This setting will take effect after restarting Arepacoin. + Deze instelling word toegepast na een restart van Arepacoin. + + + + The supplied proxy address is invalid. + Het opgegeven proxyadres is ongeldig. + + + + OverviewPage + + + Form + Vorm + + + + + The displayed information may be out of date. Your wallet automatically synchronizes with the Arepacoin network after a connection is established, but this process has not completed yet. + De weergegeven informatie kan verouderd zijn, Je portemonnee synchroniseerd automatisch met het Arepacoin netwerk nadat er verbindig is gemaakt, maar dit proces is nog niet voltooid. + + + + Stake: + Stake: + + + + Unconfirmed: + Onbevestigd: + + + + Wallet + Portemonnee + + + + Spendable: + Uitgeefbaar: + + + + Your current spendable balance + Uw beschikbare saldo + + + + Immature: + Immatuur: + + + + Mined balance that has not yet matured + Gedolven saldo dat nog niet tot wasdom is gekomen + + + + Total: + Totaal: + + + + Your current total balance + Uw totale saldo + + + + <b>Recent transactions</b> + <b>Recente transacties</b> + + + + Total of transactions that have yet to be confirmed, and do not yet count toward the current balance + Totaal van de transacties die nog moeten worden bevestigd, en nog niet mee voor het huidige balans + + + + Total of coins that was staked, and do not yet count toward the current balance + Totaal aantal munten dat was staked, en nog niet telt voor huidige balans. + + + + + out of sync + niet gesynchroniseerd + + + + QRCodeDialog + + + QR Code Dialog + QR Code Scherm + + + + Request Payment + Vraag betaling + + + + Amount: + Hoeveelheid: + + + + Label: + Label: + + + + Message: + Bericht: + + + + &Save As... + &Opslaan als... + + + + Error encoding URI into QR Code. + Fout tijdens encoderen URI in QR-code + + + + The entered amount is invalid, please check. + De ingevoerde hoeveel is ongeldig, controleer aub. + + + + Resulting URI too long, try to reduce the text for label / message. + Resulterende URI te lang, probeer de tekst korter te maken voor het label/bericht. + + + + Save QR Code + Sla QR Code op. + + + + PNG Images (*.png) + PNG Afbeeldingen (*.png) + + + + RPCConsole + + + Client name + Clientnaam + + + + + + + + + + + + + N/A + N.v.t. + + + + Client version + Clientversie + + + + &Information + &Informatie + + + + Using OpenSSL version + Gebruikt OpenSSL versie + + + + Startup time + Opstarttijd + + + + Network + Netwerk + + + + Number of connections + Aantal connecties + + + + On testnet + Op testnetwerk + + + + Block chain + Blokketen + + + + Current number of blocks + Huidig aantal blokken + + + + Estimated total blocks + Geschat totaal aantal blokken + + + + Last block time + Tijd laatste blok + + + + &Open + &Open + + + + Command-line options + Commandoregel-opties + + + + Show the Arepacoin-Qt help message to get a list with possible Arepacoin command-line options. + Laat het Arepacoin-QT help bericht zien om een lijst te krijgen met mogelijke Arepacoin command-regel opties. + + + + &Show + &Show + + + + &Console + &Console + + + + Build date + Bouwdatum + + + + Arepacoin - Debug window + Arepacoin - Debugscherm + + + + Arepacoin Core + Arepacoin Kern + + + + Debug log file + Debug-logbestand + + + + Open the Arepacoin debug log file from the current data directory. This can take a few seconds for large log files. + Open het Arepacoin debug log bestand van de huidige data map. Dit kan een paar seconden duren voor grote log bestanden. + + + + Clear console + Maak console leeg + + + + Welcome to the Arepacoin RPC console. + Welkom bij de Arepacoin RPC console. + + + + Use up and down arrows to navigate history, and <b>Ctrl-L</b> to clear screen. + Gebruik de pijltjestoetsen om door de geschiedenis te navigeren, en <b>Ctrl-L</b> om het scherm leeg te maken. + + + + Type <b>help</b> for an overview of available commands. + Typ <b>help</b> voor een overzicht van de beschikbare commando's. + + + + SendCoinsDialog + + + + + + + + + + Send Coins + Verstuur munten + + + + Coin Control Features + Coin controle opties + + + + Inputs... + Invoer... + + + + automatically selected + automatisch geselecteerd + + + + Insufficient funds! + Onvoldoende fonds! + + + + Quantity: + Kwantiteit + + + + + 0 + 0 + + + + Bytes: + Bytes: + + + + Amount: + Bedrag: + + + + + + + 0.00 BC + 123.456 BC + + + + Priority: + Prioriteit: + + + + medium + gemiddeld + + + + Fee: + Vergoeding: + + + + Low Output: + Lage uitvoer: + + + + no + nee + + + + After Fee: + Na vergoeding: + + + + Change + Wijzigen + + + + custom change address + handmatig veranderen adres + + + + Send to multiple recipients at once + Verstuur aan verschillende ontvangers ineens + + + + Add &Recipient + Voeg &Ontvanger Toe + + + + Remove all transaction fields + Verwijder alles in de invulvelden + + + + Clear &All + Verwijder &Alles + + + + Balance: + Saldo: + + + + 123.456 BC + 123.456 BC + + + + Confirm the send action + Bevestig de verstuuractie + + + + S&end + &Verstuur + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + Voeg een Arepacoin adres in (bijv. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + Copy quantity + Kopieer aantal + + + + Copy amount + Kopieer bedrag + + + + Copy fee + Kopieer vergoeding + + + + Copy after fee + Kopieer na vergoeding + + + + Copy bytes + Kopieer bytes + + + + Copy priority + Kopieer prioriteit + + + + Copy low output + Kopieer lage uitvoer + + + + Copy change + Kopieer wijzig + + + + <b>%1</b> to %2 (%3) + <b> %1 </b> to %2 (%3) + + + + Confirm send coins + Bevestig versturen munten + + + + Are you sure you want to send %1? + Weet je zeker dat je %1 wilt verzenden? + + + + and + en + + + + The recipient address is not valid, please recheck. + Het ontvangstadres is niet geldig, controleer uw invoer. + + + + The amount to pay must be larger than 0. + Het ingevoerde bedrag moet groter zijn dan 0. + + + + The amount exceeds your balance. + Bedrag is hoger dan uw huidige saldo + + + + The total exceeds your balance when the %1 transaction fee is included. + Totaal overschrijdt uw huidige saldo wanneer de %1 transactiekosten worden meegerekend + + + + Duplicate address found, can only send to each address once per send operation. + Dubbel adres gevonden, u kunt slechts eenmaal naar een bepaald adres verzenden per verstuurtransactie + + + + Error: Transaction creation failed. + FOUT: Creëren van transactie mislukt. + + + + 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. + Fout: De transactie was geweigerd, Dit kan gebeuren als sommige munten in je portemonnee al gebruikt zijn, door het gebruik van een kopie van wallet.dat en de munten in de kopie zijn niet gemarkeerd als gebruikt. + + + + WARNING: Invalid Arepacoin address + WAARSCHUWING: Ongeldig Arepacoin adres + + + + (no label) + (geen label) + + + + WARNING: unknown change address + WAARSCHUWING: Onbekend adres + + + + SendCoinsEntry + + + Form + Vorm + + + + A&mount: + Bedra&g: + + + + Pay &To: + Betaal &Aan: + + + + + Enter a label for this address to add it to your address book + Vul een label in voor dit adres om het toe te voegen aan uw adresboek + + + + &Label: + &Label: + + + + The address to send the payment to (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + Het adres om naar te betalen (bijv. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + Choose address from address book + Kies adres uit adresboek + + + + Alt+A + Alt+A + + + + Paste address from clipboard + Plak adres vanuit klembord + + + + Alt+P + Alt+P + + + + Remove this recipient + Verwijder deze ontvanger + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + Voeg een Arepacoin adres in (bijv. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + SignVerifyMessageDialog + + + Signatures - Sign / Verify a Message + Handtekeningen - Onderteken een bericht / Verifiëer een handtekening + + + + + &Sign Message + O&nderteken Bericht + + + + You can sign messages with your addresses to prove you own them. Be careful not to sign anything vague, as phishing attacks may try to trick you into signing your identity over to them. Only sign fully-detailed statements you agree to. + U kunt berichten ondertekenen met een van uw adressen om te bewijzen dat u dit adres bezit. Pas op dat u geen onduidelijke dingen ondertekent, want phishingaanvallen zouden u kunnen misleiden om zo uw identiteit te stelen. Onderteken alleen berichten waarmee u het volledig eens bent. + + + + The address to sign the message with (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + Het adres om het bericht te ondertekenen (bijv. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Choose an address from the address book + Kies een adres uit het adresboek + + + + + Alt+A + Alt+A + + + + Paste address from clipboard + Plak adres vanuit klembord + + + + Alt+P + Alt+P + + + + Enter the message you want to sign here + Typ hier het bericht dat u wilt ondertekenen + + + + Copy the current signature to the system clipboard + Kopieer de huidige handtekening naar het systeemklembord + + + + Sign the message to prove you own this Arepacoin address + Teken een bericht om te bewijzen dat je een Arepacoin adres bezit. + + + + Reset all sign message fields + Verwijder alles in de invulvelden + + + + + Clear &All + Verwijder &Alles + + + + + &Verify Message + &Verifiëer Bericht + + + + Enter the signing address, message (ensure you copy line breaks, spaces, tabs, etc. exactly) and signature below to verify the message. Be careful not to read more into the signature than what is in the signed message itself, to avoid being tricked by a man-in-the-middle attack. + Voer het ondertekenende adres, bericht en handtekening hieronder in (let erop dat u nieuwe regels, spaties en tabs juist overneemt) om de handtekening te verifiëren. Let erop dat u niet meer uit het bericht interpreteert dan er daadwerkelijk staat, om te voorkomen dat u wordt misleid in een man-in-the-middle-aanval. + + + + The address the message was signed with (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + Het adres van het bericht is ondertekend met (bijv. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + Verify the message to ensure it was signed with the specified Arepacoin address + Verifieer een bericht om zeker te zijn dat deze is ondertekend met een specifiek Arepacoin adres + + + + Reset all verify message fields + Verwijder alles in de invulvelden + + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + Voeg een Arepacoin adres in (bijv. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + Click "Sign Message" to generate signature + Klik "Onderteken Bericht" om de handtekening te genereren + + + + Enter Arepacoin signature + Voer Arepacoin handtekening in + + + + + The entered address is invalid. + Het opgegeven adres is ongeldig. + + + + + + + Please check the address and try again. + Controleer s.v.p. het adres en probeer het opnieuw. + + + + + The entered address does not refer to a key. + Het opgegeven adres verwijst niet naar een sleutel. + + + + Wallet unlock was cancelled. + Portemonnee-ontsleuteling is geannuleerd + + + + Private key for the entered address is not available. + Geheime sleutel voor het ingevoerde adres is niet beschikbaar. + + + + Message signing failed. + Ondertekenen van het bericht is mislukt. + + + + Message signed. + Bericht ondertekend. + + + + The signature could not be decoded. + De handtekening kon niet worden gedecodeerd. + + + + + Please check the signature and try again. + Controleer s.v.p. de handtekening en probeer het opnieuw. + + + + The signature did not match the message digest. + De handtekening hoort niet bij het bericht. + + + + Message verification failed. + Berichtverificatie mislukt. + + + + Message verified. + Bericht correct geverifiëerd. + + + + TransactionDesc + + + Open until %1 + Openen totdat %1 + + + + Open for %n block(s) + Open voor nog %n blokOpen voor nog %n blokken + + + + conflicted + conflicted + + + + %1/offline + %1/offline + + + + %1/unconfirmed + %1/onbevestigd + + + + %1 confirmations + %1 bevestigingen + + + + Status + Status + + + + , broadcast through %n node(s) + , uitgezonden naar %n node, uitgezonden naar %n nodes + + + + Date + Datum + + + + Source + Bron + + + + Generated + Gegenereerd + + + + + From + Van + + + + + + To + Aan + + + + + own address + eigen adres + + + + label + label + + + + + + + + Credit + Credit + + + + matures in %n more block(s) + komt tot wasdom na %n nieuw blokkomt tot wasdom na %n nieuwe blokken + + + + not accepted + niet geaccepteerd + + + + + + + Debit + Debet + + + + Transaction fee + Transactiekosten + + + + Net amount + Netto bedrag + + + + Message + Bericht + + + + Comment + Opmerking + + + + Transaction ID + Transactie-ID: + + + + Generated coins must mature 6 blocks before they can be spent. When you generated this block, it was broadcast to the network to be added to the block chain. If it fails to get into the chain, its state will change to "not accepted" and it won't be spendable. This may occasionally happen if another node generates a block within a few seconds of yours. + Gegenereerd munten moeten 6 blokken maturen voordat ze kunnen worden besteed. Wanneer je een blok genereerd, het naar het netwerk is verzonden en toegevoegd aan de blokketen, zal de status veranderen naar "niet geaccepteerd"and kan het niet uitgegeven worden. Dit kan soms gebeuren als een ander knooppunt genereert een blok binnen een paar seconden na jou. + + + + Debug information + Debug-informatie + + + + Transaction + Transactie + + + + Inputs + Inputs + + + + Amount + Bedrag + + + + true + waar + + + + false + onwaar + + + + , has not been successfully broadcast yet + , is nog niet met succes uitgezonden + + + + unknown + onbekend + + + + TransactionDescDialog + + + Transaction details + Transactiedetails + + + + This pane shows a detailed description of the transaction + Dit venster laat een uitgebreide beschrijving van de transactie zien + + + + TransactionTableModel + + + Date + Datum + + + + Type + Type + + + + Address + Adres + + + + Amount + Bedrag + + + + Open until %1 + Open tot %1 + + + + Confirmed (%1 confirmations) + Bevestigd (%1 bevestigingen) + + + + Open for %n more block(s) + Open voor nog %n blokOpen voor nog %n blokken + + + + Offline + Offline + + + + Unconfirmed + Onbevestigd: + + + + Confirming (%1 of %2 recommended confirmations) + Bevestigen.. (%1 van de %2 bevestigingen) + + + + Conflicted + Conflicted + + + + Immature (%1 confirmations, will be available after %2) + Immature (%1 bevestiging, word beschikbaar na %2) + + + + This block was not received by any other nodes and will probably not be accepted! + Dit blok is niet ontvangen bij andere nodes en zal waarschijnlijk niet worden geaccepteerd! + + + + Generated but not accepted + Gegenereerd maar niet geaccepteerd + + + + Received with + Ontvangen met + + + + Received from + Ontvangen van + + + + Sent to + Verzonden aan + + + + Payment to yourself + Betaling aan uzelf + + + + Mined + Gedolven + + + + (n/a) + (nvt) + + + + Transaction status. Hover over this field to show number of confirmations. + Transactiestatus. Houd de muiscursor boven dit veld om het aantal bevestigingen te laten zien. + + + + Date and time that the transaction was received. + Datum en tijd waarop deze transactie is ontvangen. + + + + Type of transaction. + Type transactie. + + + + Destination address of transaction. + Ontvangend adres van transactie. + + + + Amount removed from or added to balance. + Bedrag verwijderd van of toegevoegd aan saldo + + + + TransactionView + + + + All + Alles + + + + Today + Vandaag + + + + This week + Deze week + + + + This month + Deze maand + + + + Last month + Vorige maand + + + + This year + Dit jaar + + + + Range... + Bereik... + + + + Received with + Ontvangen met + + + + Sent to + Verzonden aan + + + + To yourself + Aan uzelf + + + + Mined + Gedolven + + + + Other + Anders + + + + Enter address or label to search + Vul adres of label in om te zoeken + + + + Min amount + Min. bedrag + + + + Copy address + Kopieer adres + + + + Copy label + Kopieer label + + + + Copy amount + Kopieer bedrag + + + + Copy transaction ID + Kopieer transactie-ID + + + + Edit label + Bewerk label + + + + Show transaction details + Toon transactiedetails + + + + Export Transaction Data + Exporteer Transactie Data + + + + Comma separated file (*.csv) + Kommagescheiden bestand (*.csv) + + + + Confirmed + Bevestigd + + + + Date + Datum + + + + Type + Type + + + + Label + Label + + + + Address + Adres + + + + Amount + Bedrag + + + + ID + ID + + + + Error exporting + Fout bij exporteren + + + + Could not write to file %1. + Kan niet schrijven naar bestand %1 + + + + Range: + Bereik: + + + + to + naar + + + + WalletModel + + + Sending... + Versturen... + + + + bitcoin-core + + + Arepacoin version + Arepacoin versie + + + + Usage: + Gebruik: + + + + Send command to -server or arepacoind + Verstuur commando naar -server of arepacoind + + + + List commands + Lijst van commando's + + + + Get help for a command + Toon hulp voor een commando + + + + Options: + Opties: + + + + Specify configuration file (default: arepacoin.conf) + Selecteer configuratie bestand (standaard: arepacoin.conf) + + + + Specify pid file (default: arepacoind.pid) + Selecteer pid bestand (standaard: arepacoin.conf) + + + + Specify wallet file (within data directory) + Specificeer het portemonnee bestand (vanuit de gegevensmap) + + + + Specify data directory + Stel datamap in + + + + Set database cache size in megabytes (default: 25) + Stel databankcachegrootte in in megabytes (standaard: 25) + + + + Set database disk log size in megabytes (default: 100) + Stel database cache grootte in in megabytes (standaard: 100) + + + + Listen for connections on <port> (default: 9853 or testnet: 19853) + Luister voor verbindingen op <poort> (standaard: 9853 of testnet: 19853) + + + + Maintain at most <n> connections to peers (default: 125) + Onderhoud maximaal <n> verbindingen naar peers (standaard: 125) + + + + Connect to a node to retrieve peer addresses, and disconnect + Verbind naar een node om adressen van anderen op te halen, en verbreek vervolgens de verbinding + + + + Specify your own public address + Specificeer uw eigen publieke adres + + + + Bind to given address. Use [host]:port notation for IPv6 + Koppel aan gegeven adres. Gebruik [host]:poort notatie voor IPv6 + + + + Stake your coins to support network and gain reward (default: 1) + Stake je munten om netwerk te supporten en krijg hiervoor beloning (standaard: 1) + + + + Threshold for disconnecting misbehaving peers (default: 100) + Drempel om verbinding te verbreken naar zich misdragende peers (standaard: 100) + + + + Number of seconds to keep misbehaving peers from reconnecting (default: 86400) + Aantal seconden dat zich misdragende peers niet opnieuw mogen verbinden (standaard: 86400) + + + + An error occurred while setting up the RPC port %u for listening on IPv4: %s + Er is een fout opgetreden tijdens het instellen van de inkomende RPC-poort %u op IPv4: %s + + + + Detach block and address databases. Increases shutdown time (default: 0) + Ontkoppel blok en adressenbestanden. Verhoogt shutdown tijd (standaard: 0) + + + + 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. + Fout: De transactie was geweigerd, Dit kan gebeuren als sommige munten in je portemonnee al gebruikt zijn, door het gebruik van een kopie van wallet.dat en de munten in de kopie zijn niet gemarkeerd als gebruikt. + + + + Error: This transaction requires a transaction fee of at least %s because of its amount, complexity, or use of recently received funds + Fout: Deze transactie vereist een transactie vergoeding van ten minste %s vanwege de hoeveelheid, complexiteit, of het gebruik van recent ontvangen gelden + + + + Listen for JSON-RPC connections on <port> (default: 9852 or testnet: 19852) + Wacht op JSON-RPC-connecties op <poort> (standaard: 9852 of testnet: 19852) + + + + Accept command line and JSON-RPC commands + Aanvaard commandoregel- en JSON-RPC-commando's + + + + Error: Transaction creation failed + Fout: Creëren van transactie mislukt. + + + + Error: Wallet locked, unable to create transaction + Fout: Portemonnee is op slot, niet mogelijk een transactie te creëren. + + + + Importing blockchain data file. + Importeren van blokketen data bestand. + + + + Importing bootstrap blockchain data file. + Importeren van blokketen data bestand. + + + + Run in the background as a daemon and accept commands + Draai in de achtergrond als daemon en aanvaard commando's + + + + Use the test network + Gebruik het testnetwerk + + + + Accept connections from outside (default: 1 if no -proxy or -connect) + Accepteer verbindingen van buitenaf (standaard: 1 als geen -proxy of -connect is opgegeven) + + + + An error occurred while setting up the RPC port %u for listening on IPv6, falling back to IPv4: %s + Er is een fout opgetreden tijdens het instellen van de inkomende RPC-poort %u op IPv6, terugval naar IPv4: %s + + + + Error initializing database environment %s! To recover, BACKUP THAT DIRECTORY, then remove everything from it except for wallet.dat. + Fout bij het ​​initialiseren van de database omgeving %s! Om te herstellen, BACKUP die directory, verwijder dan alles van behalve het wallet.dat. + + + + Set maximum size of high-priority/low-fee transactions in bytes (default: 27000) + Stel maximale grootte van high-priority/low-fee transacties in bytes (standaard: 27000) + + + + Warning: -paytxfee is set very high! This is the transaction fee you will pay if you send a transaction. + Waarschuwing: -paytxfee is zeer hoog ingesteld. Dit zijn de transactiekosten die u betaalt bij het versturen van een transactie. + + + + Warning: Please check that your computer's date and time are correct! If your clock is wrong Arepacoin will not work properly. + Waarschuwing: Controleer of de datum en tijd van de computer juist zijn! Als uw klok verkeerd is Arepacoin zal niet goed werken. + + + + Warning: error reading wallet.dat! All keys read correctly, but transaction data or address book entries might be missing or incorrect. + Waarschuwing: Fout bij het lezen van wallet.dat! Alle sleutels zijn in goede orde uitgelezen, maar transactiedata of adresboeklemma's zouden kunnen ontbreken of fouten bevatten. + + + + Warning: wallet.dat corrupt, data salvaged! Original wallet.dat saved as wallet.{timestamp}.bak in %s; if your balance or transactions are incorrect you should restore from a backup. + Waarschuwing: wallet.dat is corrupt, data is veiliggesteld! Originele wallet.dat is opgeslagen als wallet.{tijdstip}.bak in %s; als uw balans of transacties incorrect zijn dient u een backup terug te zetten. + + + + Attempt to recover private keys from a corrupt wallet.dat + Poog de geheime sleutels uit een corrupt wallet.dat bestand terug te halen + + + + Block creation options: + Blokcreatie-opties: + + + + Connect only to the specified node(s) + Verbind alleen naar de gespecificeerde node(s) + + + + Discover own IP address (default: 1 when listening and no -externalip) + Ontdek eigen IP-adres (standaard: 1 als er wordt geluisterd en geen -externalip is opgegeven) + + + + Failed to listen on any port. Use -listen=0 if you want this. + Mislukt om op welke poort dan ook te luisteren. Gebruik -listen=0 as u dit wilt. + + + + Find peers using DNS lookup (default: 1) + Zoek peers doormiddel van DNS lookup (standaard: 1) + + + + Sync checkpoints policy (default: strict) + Sync checkpoints beleid (standaard: strikt) + + + + Invalid -tor address: '%s' + Ongeldig-tor adres: '%s' + + + + Invalid amount for -reservebalance=<amount> + Ongeldig bedrag voor -reservebalance = <bedrag> + + + + Maximum per-connection receive buffer, <n>*1000 bytes (default: 5000) + Maximum per-connectie ontvangstbuffer, <n>*1000 bytes (standaard: 5000) + + + + Maximum per-connection send buffer, <n>*1000 bytes (default: 1000) + Maximum per-connectie zendbuffer, <n>*1000 bytes (standaard: 1000) + + + + Only connect to nodes in network <net> (IPv4, IPv6 or Tor) + Verbind alleen naar nodes in netwerk <net> (IPv4, IPv6 of Tor) + + + + Output extra debugging information. Implies all other -debug* options + Geef extra debugging informatie weer. Impliceert alle andere debug * opties + + + + Output extra network debugging information + Geef extra netwerk debug informatie weer + + + + Prepend debug output with timestamp + Voeg een tijdstempel toe aan debug output + + + + SSL options: (see the Bitcoin Wiki for SSL setup instructions) + SSL-opties: (zie de Bitcoin wiki voor SSL-instructies) + + + + Select the version of socks proxy to use (4-5, default: 5) + Selecteer de versie van socks proxy (4-5, default: 5) + + + + Send trace/debug info to console instead of debug.log file + Stuur trace/debug-info naar de console in plaats van het debug.log bestand + + + + Send trace/debug info to debugger + Stuur trace/debug info naar de debugger + + + + Set maximum block size in bytes (default: 250000) + Stel maximale block grootte in bytes in (standaard: 250000) + + + + Set minimum block size in bytes (default: 0) + Stel minimum blokgrootte in in bytes (standaard: 0) + + + + Shrink debug.log file on client startup (default: 1 when no -debug) + Verklein debug.log-bestand bij het opstarten van de client (standaard: 1 als geen -debug) + + + + Specify connection timeout in milliseconds (default: 5000) + Specificeer de time-outtijd in milliseconden (standaard: 5000) + + + + Unable to sign checkpoint, wrong checkpointkey? + + Kan checkpoint niet ondertekenen, verkeerde checkpoint sleutel? + + + + + Use UPnP to map the listening port (default: 0) + Gebruik UPnP om de luisterende poort te mappen (standaard: 0) + + + + Use UPnP to map the listening port (default: 1 when listening) + Gebruik UPnP om de luisterende poort te mappen (standaard: 1 als er wordt geluisterd) + + + + Use proxy to reach tor hidden services (default: same as -proxy) + Gebruik proxy tor verborgen diensten (standaard: zelfde als -proxy) + + + + Username for JSON-RPC connections + Gebruikersnaam voor JSON-RPC-verbindingen + + + + Verifying database integrity... + Database integriteit wordt geverifieërd + + + + WARNING: syncronized checkpoint violation detected, but skipped! + WAARSCHUWING: gesynchroniseerd checkpoint overtreding is geconstateerd, maar overgeslagen! + + + + Warning: Disk space is low! + Waarschuwing: Hardeschijf raakt vol! + + + + Warning: This version is obsolete, upgrade required! + Waarschuwing: Deze versie is verouderd, een upgrade is vereist! + + + + wallet.dat corrupt, salvage failed + wallet.dat corrupt, veiligstellen mislukt + + + + Password for JSON-RPC connections + Wachtwoord voor JSON-RPC-verbindingen + + + + %s, you must set a rpcpassword in the configuration file: + %s +It is recommended you use the following random password: +rpcuser=arepacoinrpc +rpcpassword=%s +(you do not need to remember this password) +The username and password MUST NOT be the same. +If the file does not exist, create it with owner-readable-only file permissions. +It is also recommended to set alertnotify so you are notified of problems; +for example: alertnotify=echo %%s | mail -s "Arepacoin Alert" admin@foo.com + + %s, u moet een rpcpassword instellen in het configuratiebestand: +%s +Het wordt aanbevolen de volgende willekeurig wachtwoord gebruiken: +rpcuser = arepacoinrpc +rpcpassword = %s +(je hoeft niet dit wachtwoord te onthouden) +De gebruikersnaam en het wachtwoord MAG NIET hetzelfde zijn. +Als het bestand niet bestaat, maakt u met leesbare-alleen-eigenaar bestandsbeheermachtigingen. +Het wordt ook aanbevolen om alertnotify instellen zodat u een melding van problemen; +bijvoorbeeld: alertnotify = echo %%s | mail -s "Arepacoin Alert" admin@foo.com + + + + Find peers using internet relay chat (default: 0) + Zoek peers door gebruik van Internet Relay Chat (standaard: 1) {? 0)} + + + + Sync time with other nodes. Disable if time on your system is precise e.g. syncing with NTP (default: 1) + Synchroniseer tijd met andere connecties. Uitschakelen als de tijd op uw systeem nauwkeurig is bijv. synchroniseren met NTP (standaard: 1) + + + + When creating transactions, ignore inputs with value less than this (default: 0.01) + Bij het maken van transacties, negeer ingangen met waarde minder dan dit (standaard: 0,01) + + + + Allow JSON-RPC connections from specified IP address + Sta JSON-RPC verbindingen van opgegeven IP-adres toe + + + + Send commands to node running on <ip> (default: 127.0.0.1) + Verstuur commando's naar proces dat op <ip> draait (standaard: 127.0.0.1) + + + + Execute command when the best block changes (%s in cmd is replaced by block hash) + Voer commando uit zodra het beste blok verandert (%s in cmd wordt vervangen door blockhash) + + + + Execute command when a wallet transaction changes (%s in cmd is replaced by TxID) + Voer opdracht uit zodra een portemonneetransactie verandert (%s in cmd wordt vervangen door TxID) + + + + Require a confirmations for change (default: 0) + Vereist een bevestiging voor verandering (standaard: 0) + + + + Enforce transaction scripts to use canonical PUSH operators (default: 1) + Dwing transactie scripts gebruik van canonieke PUSH operatoren (standaard: 1) + + + + Execute command when a relevant alert is received (%s in cmd is replaced by message) + Voer opdracht uit zodra een relevante waarschuwing wordt ontvangen (%s in cmd wordt vervangen door bericht) + + + + Upgrade wallet to latest format + Vernieuw portemonnee naar nieuwste versie + + + + Set key pool size to <n> (default: 100) + Stel sleutelpoelgrootte in op <n> (standaard: 100) + + + + Rescan the block chain for missing wallet transactions + Doorzoek de blokketen op ontbrekende portemonnee-transacties + + + + How many blocks to check at startup (default: 2500, 0 = all) + Hoeveel blokken controleren bij opstarten (standaard: 2500, 0= alles) + + + + How thorough the block verification is (0-6, default: 1) + Hoe grondig het blokverificatie is (0-6, standaard: 1) + + + + Imports blocks from external blk000?.dat file + Importeer blokken van extern blk000?.dat bestand + + + + Use OpenSSL (https) for JSON-RPC connections + Gebruik OpenSSL (https) voor JSON-RPC-verbindingen + + + + Server certificate file (default: server.cert) + Certificaat-bestand voor server (standaard: server.cert) + + + + Server private key (default: server.pem) + Geheime sleutel voor server (standaard: server.pem) + + + + Acceptable ciphers (default: TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH) + Aanvaardbare cijfers (standaard: TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH) + + + + Error: Wallet unlocked for staking only, unable to create transaction. + Fout: Portemonnee ontgrendeld voor alleen staking, niet in staat om de transactie te maken. + + + + WARNING: Invalid checkpoint found! Displayed transactions may not be correct! You may need to upgrade, or notify developers. + WAARSCHUWING: Ongeldig controlepunt gevonden! Weergegeven transacties kunnen niet kloppen! Het is mogelijk dat je moet upgraden, of developers moet waarschuwen. + + + + This help message + Dit helpbericht + + + + Wallet %s resides outside data directory %s. + Portemonnee %s bevindt zich buiten de datamap %s. + + + + Cannot obtain a lock on data directory %s. Arepacoin is probably already running. + Kan een slot op data directory %s niet verkrijgen. Arepacoin wordt waarschijnlijk al uitgevoerd. + + + + Arepacoin + Arepacoin + + + + Unable to bind to %s on this computer (bind returned error %d, %s) + Niet in staat om aan %s te binden op deze computer (bind gaf error %d, %s) + + + + Connect through socks proxy + Verbind door socks proxy + + + + Allow DNS lookups for -addnode, -seednode and -connect + Sta DNS-naslag toe voor -addnode, -seednode en -connect + + + + Loading addresses... + Adressen aan het laden... + + + + Error loading blkindex.dat + Fout bij laden van blkindex.dat + + + + Error loading wallet.dat: Wallet corrupted + Fout bij laden wallet.dat: Portemonnee corrupt + + + + Error loading wallet.dat: Wallet requires newer version of Arepacoin + Fout bij laden van wallet.dat: Portemonnee vereist een nieuwere versie van Arepacoin + + + + Wallet needed to be rewritten: restart Arepacoin to complete + Portemonnee moet herschreven worden: herstart Arepacoin om te voltooien + + + + Error loading wallet.dat + Fout bij laden wallet.dat + + + + Invalid -proxy address: '%s' + Ongeldig -proxy adres: '%s' + + + + Unknown network specified in -onlynet: '%s' + Onbekend netwerk gespecificeerd in -onlynet: '%s' + + + + Unknown -socks proxy version requested: %i + Onbekende -socks proxyversie aangegeven: %i + + + + Cannot resolve -bind address: '%s' + Kan -bind adres niet herleiden: '%s' + + + + Cannot resolve -externalip address: '%s' + Kan -externlip adres niet herleiden: '%s' + + + + Invalid amount for -paytxfee=<amount>: '%s' + Ongeldig bedrag voor -paytxfee=<bedrag>: '%s' + + + + Error: could not start node + Fout: kan geen verbinding maken met node + + + + Sending... + Versturen... + + + + Invalid amount + Ongeldig bedrag + + + + Insufficient funds + Ontoereikend saldo + + + + Loading block index... + Blokindex aan het laden... + + + + Add a node to connect to and attempt to keep the connection open + Voeg een node om naar te verbinden toe en probeer de verbinding open te houden + + + + Unable to bind to %s on this computer. Arepacoin is probably already running. + Niet mogelijk om %s op deze computer. Arepacoin is waarschijnlijk al geopened. + + + + Fee per KB to add to transactions you send + Vergoeding per KB toe te voegen aan de transacties die u verzendt + + + + Invalid amount for -mininput=<amount>: '%s' + Ongeldig bedrag voor -mininput = <bedrag>: '%s' + + + + Loading wallet... + Portemonnee aan het laden... + + + + Cannot downgrade wallet + Kan portemonnee niet downgraden + + + + Cannot initialize keypool + Kan keypool niet initialiseren + + + + Cannot write default address + Kan standaardadres niet schrijven + + + + Rescanning... + Blokketen aan het doorzoeken... + + + + Done loading + Klaar met laden + + + + To use the %s option + Om de %s optie te gebruiken + + + + Error + Fout + + + + You must set rpcpassword=<password> in the configuration file: +%s +If the file does not exist, create it with owner-readable-only file permissions. + U dient rpcpassword=<wachtwoord> in te stellen in het configuratiebestand: +%s +Als het bestand niet bestaat, maak het dan aan, met een alleen-lezen permissie. + + + \ No newline at end of file diff --git a/src/qt/locale/bitcoin_pam.ts b/src/qt/locale/bitcoin_pam.ts new file mode 100755 index 0000000..27eb14b --- /dev/null +++ b/src/qt/locale/bitcoin_pam.ts @@ -0,0 +1,3284 @@ + + + AboutDialog + + + About Arepacoin + + + + + <b>Arepacoin</b> version + + + + + Copyright © 2009-2014 The Bitcoin developers +Copyright © 2012-2014 The NovaCoin developers +Copyright © 2014 The Arepacoin developers + + + + + +This is experimental software. + +Distributed under the MIT/X11 software license, see the accompanying file COPYING or http://www.opensource.org/licenses/mit-license.php. + +This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit (http://www.openssl.org/) and cryptographic software written by Eric Young (eay@cryptsoft.com) and UPnP software written by Thomas Bernard. + +Metung ya ining experimental software. +Me-distribute ya lalam na ning lisensya na ning MIT/X11 software, lawan ye ing makayabeng file COPYING o http://www.opensource.org/licenses/mit-license.php. +Ing produktung ini atin yang makayabeng software a gewa dareng OpenSSL Project para gamit king OpenSSL Toolkit(http://www.openssl.org/) at cryptographic software a sinulat ng Eric Young (eay@cryptsoft.com) at UPnp software a sinulat ng Thomas Bernard. + + + + AddressBookPage + + + Address Book + + + + + Double-click to edit address or label + Pindutan meng makatidduang besis ban ayalilan me ing address o label + + + + Create a new address + Maglalang kang bayung address + + + + Copy the currently selected address to the system clipboard + Kopyan me ing salukuyan at makipiling address keng system clipboard + + + + &New Address + + + + + These are your Arepacoin addresses for receiving payments. You may want to give a different one to each sender so you can keep track of who is paying you. + + + + + &Copy Address + &Kopyan ing address + + + + Show &QR Code + + + + + Sign a message to prove you own a Arepacoin address + + + + + Sign &Message + + + + + Delete the currently selected address from the list + Ilako ya ing kasalungsungan makapiling address keng listahan + + + + Verify a message to ensure it was signed with a specified Arepacoin address + + + + + &Verify Message + + + + + &Delete + &Ilako + + + + Copy &Label + Kopyan ing &Label + + + + &Edit + &Alilan + + + + Export Address Book Data + + + + + Comma separated file (*.csv) + Comma separated file (*.csv) + + + + Error exporting + + + + + Could not write to file %1. + + + + + AddressTableModel + + + Label + Label + + + + Address + Address + + + + (no label) + (alang label) + + + + AskPassphraseDialog + + + Passphrase Dialog + Dialogo ning Passphrase + + + + Enter passphrase + Mamalub kang passphrase + + + + New passphrase + Panibayung passphrase + + + + Repeat new passphrase + Pasibayuan ya ing bayung passphrase + + + + Serves to disable the trivial sendmoney when OS account compromised. Provides no real security. + + + + + For staking only + + + + + Enter the new passphrase to the wallet.<br/>Please use a passphrase of <b>10 or more random characters</b>, or <b>eight or more words</b>. + Palub ye ing bayung passphrase king wallet.<br/>Maliari pu sanang gumamit kayung passphrase a maki</b> 10 or dakal pang miyayaliuang characters</b>, o ualu o dakal pang salita</b> + + + + Encrypt wallet + I-encrypt ye ing wallet + + + + This operation needs your wallet passphrase to unlock the wallet. + Ing operasyun a ini kailangan ne ing kekayung wallet passphrase, ban a-unlock ya ing wallet + + + + Unlock wallet + Unlock ya ing wallet + + + + This operation needs your wallet passphrase to decrypt the wallet. + Ing operasyun a ini kailangan ne ing kekang wallet passphrase ban a-decrypt ne ing wallet. + + + + Decrypt wallet + I-decrypt ya ing wallet + + + + Change passphrase + Alilan ya ing passphrase + + + + Enter the old and new passphrase to the wallet. + Palub ye ing luma ampo ing bayung passphrase king wallet. + + + + Confirm wallet encryption + Kumpirman ya ing wallet encryption + + + + Warning: If you encrypt your wallet and lose your passphrase, you will <b>LOSE ALL OF YOUR COINS</b>! + + + + + Are you sure you wish to encrypt your wallet? + Siguradu na kang buri meng i-encrypt ing kekang wallet? + + + + IMPORTANT: Any previous backups you have made of your wallet file should be replaced with the newly generated, encrypted wallet file. For security reasons, previous backups of the unencrypted wallet file will become useless as soon as you start using the new, encrypted wallet. + Mayalaga: Reng milabas a backups a gewa mu gamit ing wallet file mu dapat lamung mialilan bayung gawang encrypted wallet file. Para keng seguridad , reng milabas a backups dareng ali maka encrypt a wallet file ma-ala nala istung inumpisan mu nalang gamitan reng bayu, at me encrypt a wallet. + + + + + Warning: The Caps Lock key is on! + Kapabaluan: Makabuklat ya ing Caps Lock key! + + + + + Wallet encrypted + Me-encrypt ne ing wallet + + + + Arepacoin will close now to finish the encryption process. Remember that encrypting your wallet cannot fully protect your coins from being stolen by malware infecting your computer. + + + + + + + + Wallet encryption failed + Memali ya ing pamag-encrypt king wallet + + + + Wallet encryption failed due to an internal error. Your wallet was not encrypted. + Memali ya ing encryption uli na ning ausan dang internal error. E ya me-encrypt ing wallet yu. + + + + + The supplied passphrases do not match. + E la mitutugma ring mibieng passphrase + + + + Wallet unlock failed + Memali ya ing pamag-unlock king wallet + + + + + + The passphrase entered for the wallet decryption was incorrect. + E ya istu ing passphrase a pepalub da para king wallet decryption + + + + Wallet decryption failed + Me-mali ya ing pamag-decrypt king wallet + + + + Wallet passphrase was successfully changed. + Mi-alilan ne ing passphrase na ning wallet. + + + + BitcoinGUI + + + Sign &message... + I-sign ing &mensayi + + + + Synchronizing with network... + Mag-sychronize ne king network... + + + + &Overview + &Overview + + + + Show general overview of wallet + Ipakit ing kabuuang lawe ning wallet + + + + &Transactions + &Transaksion + + + + Browse transaction history + Lawan ing kasalesayan ning transaksion + + + + &Address Book + + + + + Edit the list of stored addresses and labels + + + + + &Receive coins + + + + + Show the list of addresses for receiving payments + + + + + &Send coins + + + + + E&xit + L&umwal + + + + Quit application + Tuknangan ing aplikasyon + + + + Show information about Arepacoin + + + + + About &Qt + Tungkul &Qt + + + + Show information about Qt + Magpakit impormasion tungkul king Qt + + + + &Options... + &Pipamilian... + + + + &Encrypt Wallet... + I-&Encrypt in Wallet... + + + + &Backup Wallet... + I-&Backup ing Wallet... + + + + &Change Passphrase... + &Alilan ing Passphrase... + + + + ~%n block(s) remaining + + + + + Downloaded %1 of %2 blocks of transaction history (%3% done). + + + + + &Export... + + + + + Send coins to a Arepacoin address + + + + + Modify configuration options for Arepacoin + + + + + Export the data in the current tab to a file + + + + + Encrypt or decrypt wallet + + + + + Backup wallet to another location + I-backup ing wallet king aliwang lugal + + + + Change the passphrase used for wallet encryption + Alilan ya ing passphrase a gagamitan para king wallet encryption + + + + &Debug window + I-&Debug ing awang + + + + Open debugging and diagnostic console + Ibuklat ing debugging at diagnostic console + + + + &Verify message... + &Beripikan ing message... + + + + Arepacoin + + + + + Wallet + Wallet + + + + &About Arepacoin + + + + + &Show / Hide + &Ipalto / Isalikut + + + + Unlock wallet + + + + + &Lock Wallet + + + + + Lock wallet + + + + + &File + &File + + + + &Settings + &Pamag-ayus + + + + &Help + &Saup + + + + Tabs toolbar + Gamit para king Tabs + + + + Actions toolbar + + + + + + [testnet] + [testnet] + + + + + Arepacoin client + + + + + %n active connection(s) to Arepacoin network + + + + + Downloaded %1 blocks of transaction history. + + + + + Staking.<br>Your weight is %1<br>Network weight is %2<br>Expected time to earn reward is %3 + + + + + Not staking because wallet is locked + + + + + Not staking because wallet is offline + + + + + Not staking because wallet is syncing + + + + + Not staking because you don't have mature coins + + + + + %n second(s) ago + + + + + &Unlock Wallet... + + + + + %n minute(s) ago + + + + + %n hour(s) ago + + + + + %n day(s) ago + + + + + Up to date + Makatuki ya king aldo + + + + Catching up... + Catching up... + + + + Last received block was generated %1. + + + + + This transaction is over the size limit. You can still send it for a fee of %1, which goes to the nodes that process your transaction and helps to support the network. Do you want to pay the fee? + + + + + Confirm transaction fee + + + + + Sent transaction + Mipadalang transaksion + + + + Incoming transaction + Paparatang a transaksion + + + + Date: %1 +Amount: %2 +Type: %3 +Address: %4 + + Aldo: %1 +Alaga: %2 +Type: %3 +Address: %4 + + + + + + URI handling + + + + + + URI can not be parsed! This can be caused by an invalid Arepacoin address or malformed URI parameters. + + + + + Wallet is <b>encrypted</b> and currently <b>unlocked</b> + Maka-<b>encrypt</b> ya ing wallet at kasalukuyan yang maka-<b>unlocked</b> + + + + Wallet is <b>encrypted</b> and currently <b>locked</b> + Maka-<b>encrypt</b> ya ing wallet at kasalukuyan yang maka-<b>locked</b> + + + + Backup Wallet + + + + + Wallet Data (*.dat) + + + + + Backup Failed + + + + + There was an error trying to save the wallet data to the new location. + + + + + %n second(s) + + + + + %n minute(s) + + + + + %n hour(s) + + + + + %n day(s) + + + + + Not staking + + + + + A fatal error occurred. Arepacoin can no longer continue safely and will quit. + + + + + ClientModel + + + Network Alert + Alertu ning Network + + + + CoinControlDialog + + + Coin Control + + + + + Quantity: + + + + + Bytes: + + + + + Amount: + + + + + Priority: + + + + + Fee: + + + + + Low Output: + + + + + no + + + + + After Fee: + + + + + Change: + + + + + (un)select all + + + + + Tree mode + + + + + List mode + + + + + Amount + Alaga + + + + Label + + + + + Address + Address + + + + Date + Kaaldauan + + + + Confirmations + + + + + Confirmed + Me-kumpirma + + + + Priority + + + + + Copy address + Kopyan ing address + + + + Copy label + Kopyan ing label + + + + + Copy amount + Kopyan ing alaga + + + + Copy transaction ID + + + + + Copy quantity + + + + + Copy fee + + + + + Copy after fee + + + + + Copy bytes + + + + + Copy priority + + + + + Copy low output + + + + + Copy change + + + + + highest + + + + + high + + + + + medium-high + + + + + medium + + + + + low-medium + + + + + low + + + + + lowest + + + + + DUST + + + + + yes + + + + + This label turns red, if the transaction size is bigger than 10000 bytes. + + This means a fee of at least %1 per kb is required. + + Can vary +/- 1 Byte per input. + + + + + Transactions with higher priority get more likely into a block. + +This label turns red, if the priority is smaller than "medium". + + This means a fee of at least %1 per kb is required. + + + + + This label turns red, if any recipient receives an amount smaller than %1. + + This means a fee of at least %2 is required. + + Amounts below 0.546 times the minimum relay fee are shown as DUST. + + + + + This label turns red, if the change is smaller than %1. + + This means a fee of at least %2 is required. + + + + + + (no label) + (alang label) + + + + change from %1 (%2) + + + + + (change) + + + + + EditAddressDialog + + + Edit Address + Alilan ing Address + + + + &Label + &Label + + + + The label associated with this address book entry + + + + + &Address + &Address + + + + The address associated with this address book entry. This can only be modified for sending addresses. + + + + + New receiving address + Bayung address king pamagtanggap + + + + New sending address + Bayung address king pamagpadala + + + + Edit receiving address + Alilan ya ing address king pamagpadala + + + + Edit sending address + Alilan ya ing address king pamagpadala + + + + The entered address "%1" is already in the address book. + Ing pepalub yung address "%1" ati na yu king aklat dareng address + + + + The entered address "%1" is not a valid Arepacoin address. + + + + + Could not unlock wallet. + Ali ya bisang mag-unlock ing wallet + + + + New key generation failed. + Memali ya ing pamangaua king key + + + + GUIUtil::HelpMessageBox + + + + Arepacoin-Qt + + + + + version + + + + + Usage: + + + + + command-line options + + + + + UI options + + + + + Set language, for example "de_DE" (default: system locale) + + + + + Start minimized + + + + + Show splash screen on startup (default: 1) + + + + + OptionsDialog + + + Options + Pipamilian + + + + &Main + &Pun + + + + Optional transaction fee per kB that helps make sure your transactions are processed quickly. Most transactions are 1 kB. Fee 0.01 recommended. + + + + + Pay transaction &fee + Mamayad &bayad para king transaksion + + + + Reserved amount does not participate in staking and is therefore spendable at any time. + + + + + Reserve + + + + + Automatically start Arepacoin after logging in to the system. + + + + + &Start Arepacoin on system login + + + + + Detach block and address databases at shutdown. This means they can be moved to another data directory, but it slows down shutdown. The wallet is always detached. + + + + + &Detach databases at shutdown + + + + + &Network + &Network + + + + Automatically open the Arepacoin client port on the router. This only works when your router supports UPnP and it is enabled. + + + + + Map port using &UPnP + Mapa ng ning port gamit ing &UPnP + + + + Connect to the Arepacoin network through a SOCKS proxy (e.g. when connecting through Tor). + + + + + &Connect through SOCKS proxy: + + + + + Proxy &IP: + Proxy &IP: + + + + IP address of the proxy (e.g. 127.0.0.1) + + + + + &Port: + &Port: + + + + Port of the proxy (e.g. 9050) + Port na ning proxy(e.g. 9050) + + + + SOCKS &Version: + &Bersion na ning SOCKS + + + + SOCKS version of the proxy (e.g. 5) + Bersion a SOCKS ning proxy (e.g 5) + + + + &Window + &Awang + + + + Show only a tray icon after minimizing the window. + Ipakit mu ing tray icon kaibat meng pelatian ing awang. + + + + &Minimize to the tray instead of the taskbar + &Latian ya ing tray kesa king taskbar + + + + Minimize instead of exit the application when the window is closed. When this option is enabled, the application will be closed only after selecting Quit in the menu. + Palatian namu kesa king iluwal ya ing aplikasion istung makasara ya ing awang. Istung ing pipamilian a ini atiu king "magsilbi", ing aplikasion misara yamu kaibat meng pinili ing "Tuknangan" king menu. + + + + M&inimize on close + P&alatian istung isara + + + + &Display + &Ipalto + + + + User Interface &language: + Amanu na ning user interface: + + + + The user interface language can be set here. This setting will take effect after restarting Arepacoin. + + + + + &Unit to show amounts in: + Ing &Unit a ipakit king alaga ning: + + + + Choose the default subdivision unit to show in the interface and when sending coins. + Pilinan ing default subdivision unit a ipalto o ipakit king interface at istung magpadala kang barya. + + + + Whether to show Arepacoin addresses in the transaction list or not. + + + + + &Display addresses in transaction list + &Ipakit ing address king listahan naning transaksion + + + + Whether to show coin control features or not. + + + + + Display coin &control features (experts only!) + + + + + &OK + &OK + + + + &Cancel + I-&Cancel + + + + &Apply + + + + + default + default + + + + + Warning + + + + + + This setting will take effect after restarting Arepacoin. + + + + + The supplied proxy address is invalid. + Ing milageng proxy address eya katanggap-tanggap. + + + + OverviewPage + + + Form + Form + + + + + The displayed information may be out of date. Your wallet automatically synchronizes with the Arepacoin network after a connection is established, but this process has not completed yet. + + + + + Stake: + + + + + Unconfirmed: + + + + + Wallet + Wallet + + + + Spendable: + + + + + Your current spendable balance + Ing kekang kasalungsungan balanse a malyari mung gastusan + + + + Immature: + Immature: + + + + Mined balance that has not yet matured + Reng me-minang balanse a epa meg-matured + + + + Total: + Kabuuan: + + + + Your current total balance + Ing kekang kasalungsungan kabuuang balanse + + + + <b>Recent transactions</b> + <b>Reng kapilan pamung transaksion</b> + + + + Total of transactions that have yet to be confirmed, and do not yet count toward the current balance + + + + + Total of coins that was staked, and do not yet count toward the current balance + + + + + + out of sync + ali ya maka-sync + + + + QRCodeDialog + + + QR Code Dialog + + + + + Request Payment + + + + + Amount: + + + + + Label: + + + + + Message: + + + + + &Save As... + + + + + Error encoding URI into QR Code. + + + + + The entered amount is invalid, please check. + + + + + Resulting URI too long, try to reduce the text for label / message. + + + + + Save QR Code + + + + + PNG Images (*.png) + + + + + RPCConsole + + + Client name + Lagyu ning kliente + + + + + + + + + + + + + N/A + N/A + + + + Client version + Bersion ning Cliente + + + + &Information + &Impormasion + + + + Using OpenSSL version + Gagamit bersion na ning OpenSSL + + + + Startup time + Oras ning umpisa + + + + Network + Network + + + + Number of connections + Bilang dareng koneksion + + + + On testnet + + + + + Block chain + Block chain + + + + Current number of blocks + Kasalungsungan bilang dareng blocks + + + + Estimated total blocks + Estima kareng kabuuan dareng blocks + + + + Last block time + Tatauling oras na ning block + + + + &Open + &Ibuklat + + + + Command-line options + + + + + Show the Arepacoin-Qt help message to get a list with possible Arepacoin command-line options. + + + + + &Show + + + + + &Console + &Console + + + + Build date + Kaaldauan ning pamaglalang + + + + Arepacoin - Debug window + + + + + Arepacoin Core + + + + + Debug log file + Debug log file + + + + Open the Arepacoin debug log file from the current data directory. This can take a few seconds for large log files. + + + + + Clear console + I-Clear ing console + + + + Welcome to the Arepacoin RPC console. + + + + + Use up and down arrows to navigate history, and <b>Ctrl-L</b> to clear screen. + Gamitan me ing patas at pababang arrow para alibut me ing kasalesayan, at <b>Ctrl-L</b> ban I-clear ya ing screen. + + + + Type <b>help</b> for an overview of available commands. + I-type ing <b>help</b> ban akit la reng ati at magsilbing commands. + + + + SendCoinsDialog + + + + + + + + + + Send Coins + Magpadalang Barya + + + + Coin Control Features + + + + + Inputs... + + + + + automatically selected + + + + + Insufficient funds! + + + + + Quantity: + + + + + + 0 + + + + + Bytes: + + + + + Amount: + + + + + + + + 0.00 BC + + + + + Priority: + + + + + medium + + + + + Fee: + + + + + Low Output: + + + + + no + + + + + After Fee: + + + + + Change + + + + + custom change address + + + + + Send to multiple recipients at once + Misanang magpadala kareng alialiuang tumanggap + + + + Add &Recipient + Maglage &Tumanggap + + + + Remove all transaction fields + + + + + Clear &All + I-Clear &Eganagana + + + + Balance: + Balanse: + + + + 123.456 BC + + + + + Confirm the send action + Kumpirman ing aksion king pamagpadala + + + + S&end + Ipadala + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Copy quantity + + + + + Copy amount + Kopyan ing alaga + + + + Copy fee + + + + + Copy after fee + + + + + Copy bytes + + + + + Copy priority + + + + + Copy low output + + + + + Copy change + + + + + <b>%1</b> to %2 (%3) + + + + + Confirm send coins + Kumpirman ing pamagpadalang barya + + + + Are you sure you want to send %1? + + + + + and + + + + + The recipient address is not valid, please recheck. + Ing address na ning tumanggap ali ya katanggap-tanggap, maliari pung pakilaue pasibayu. + + + + The amount to pay must be larger than 0. + Ing alaga na ning bayaran dapat mung mas matas ya king 0. + + + + The amount exceeds your balance. + Ing alaga mipasobra ya king kekang balanse. + + + + The total exceeds your balance when the %1 transaction fee is included. + Ing kabuuan mipasobra ya king kekang balanse istung inabe ya ing %1 a bayad king transaksion + + + + Duplicate address found, can only send to each address once per send operation. + Atin meakit a milupang address, maliari kamung magpadalang misan king metung a address king misan a pamagpadalang transaksion. + + + + Error: Transaction creation failed. + + + + + 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. + + + + + WARNING: Invalid Arepacoin address + + + + + (no label) + (alang label) + + + + WARNING: unknown change address + + + + + SendCoinsEntry + + + Form + + + + + A&mount: + A&laga: + + + + Pay &To: + Ibayad &kang: + + + + + Enter a label for this address to add it to your address book + Magpalub kang label para king address a ini ban a-iabe me king aklat dareng address + + + + &Label: + &Label: + + + + The address to send the payment to (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Choose address from address book + + + + + Alt+A + Alt+A + + + + Paste address from clipboard + Idikit ing address menibat king clipboard + + + + Alt+P + Alt+P + + + + Remove this recipient + + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + SignVerifyMessageDialog + + + Signatures - Sign / Verify a Message + Pirma - Pirman / I-beripika ing mensayi + + + + + &Sign Message + &Pirman ing Mensayi + + + + You can sign messages with your addresses to prove you own them. Be careful not to sign anything vague, as phishing attacks may try to trick you into signing your identity over to them. Only sign fully-detailed statements you agree to. + Maliari kang mamirmang mensayi king kekang address bilang patune na keka ya ini. Mimingat mu king pamag-pirmang e malino uling mapalyari kang mabiktimang phishing attack a manloku keka na pirman me ing sarili mu para king karela. Only sign fully-detailed statements you agree to. + + + + The address to sign the message with (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + + Choose an address from the address book + + + + + + Alt+A + Alt+A + + + + Paste address from clipboard + Idikit ing address menibat clipboard + + + + Alt+P + Alt+P + + + + Enter the message you want to sign here + Ipalub ing mensayi a buri mung pirman keni + + + + Copy the current signature to the system clipboard + Kopyan ing kasalungsungan pirma king system clipboard + + + + Sign the message to prove you own this Arepacoin address + + + + + Reset all sign message fields + Ibalik keng dati reng ngan fields keng pamamirmang mensayi + + + + + Clear &All + I-Clear &Eganagana + + + + + &Verify Message + &Beripikan ing Mensayi + + + + Enter the signing address, message (ensure you copy line breaks, spaces, tabs, etc. exactly) and signature below to verify the message. Be careful not to read more into the signature than what is in the signed message itself, to avoid being tricked by a man-in-the-middle attack. + + + + + The address the message was signed with (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Verify the message to ensure it was signed with the specified Arepacoin address + + + + + Reset all verify message fields + Ibalik king dati reng ngan fields na ning pamag beripikang mensayi + + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Click "Sign Message" to generate signature + I-click ing "Pirman ing Mensayi" ban agawa ya ing metung a pirma + + + + Enter Arepacoin signature + + + + + + The entered address is invalid. + Ing milub a address e ya katanggap-tanggap. + + + + + + + Please check the address and try again. + Maliaring pakilawe pasibayu ing address at pasibayuan ya iti. + + + + + The entered address does not refer to a key. + Ing milub a address ali ya mag-refer king metung a key. + + + + Wallet unlock was cancelled. + Me-kansela ya ing pamag-unlock king wallet. + + + + Private key for the entered address is not available. + Ing private key para king milub a address, ala ya. + + + + Message signing failed. + Me-mali ya ing pamag-pirma king mensayi . + + + + Message signed. + Me-pirman ne ing mensayi. + + + + The signature could not be decoded. + Ing pirma ali ya bisang ma-decode. + + + + + Please check the signature and try again. + Maliaring pakilawe pasibayu ing pirma kaibat pasibayuan ya iti. + + + + The signature did not match the message digest. + Ing pirma ali ya makatugma king message digest. + + + + Message verification failed. + Me-mali ya ing pamag-beripika king mensayi. + + + + Message verified. + Me-beripika ne ing mensayi. + + + + TransactionDesc + + + Open until %1 + Makabuklat anggang %1 + + + + Open for %n block(s) + + + + + conflicted + + + + + %1/offline + %1/offline + + + + %1/unconfirmed + %1/ali me-kumpirma + + + + %1 confirmations + %1 kumpirmasion + + + + Status + Kabilian + + + + , broadcast through %n node(s) + + + + + Date + Kaaldauan + + + + Source + Pikuanan + + + + Generated + Megawa + + + + + From + Menibat + + + + + + To + Para kang + + + + + own address + sariling address + + + + label + label + + + + + + + + Credit + Credit + + + + matures in %n more block(s) + + + + + not accepted + ali metanggap + + + + + + + Debit + Debit + + + + Transaction fee + Bayad king Transaksion + + + + Net amount + Alaga dareng eganagana + + + + Message + Mensayi + + + + Comment + Komentu + + + + Transaction ID + ID ning Transaksion + + + + Generated coins must mature 6 blocks before they can be spent. When you generated this block, it was broadcast to the network to be added to the block chain. If it fails to get into the chain, its state will change to "not accepted" and it won't be spendable. This may occasionally happen if another node generates a block within a few seconds of yours. + + + + + Debug information + Impormasion ning Debug + + + + Transaction + Transaksion + + + + Inputs + + + + + Amount + Alaga + + + + true + tutu + + + + false + e tutu + + + + , has not been successfully broadcast yet + , eya matagumpeng mibalita + + + + unknown + e miya balu + + + + TransactionDescDialog + + + Transaction details + Detalye ning Transaksion + + + + This pane shows a detailed description of the transaction + Ining pane a ini magpakit yang detalyadung description ning transaksion + + + + TransactionTableModel + + + Date + Kaaldauan + + + + Type + Klase + + + + Address + Address + + + + Amount + Alaga + + + + Open until %1 + Makabuklat anggang %1 + + + + Confirmed (%1 confirmations) + Me-kumpirma(%1 kumpirmasion) + + + + Open for %n more block(s) + + + + + Offline + + + + + Unconfirmed + + + + + Confirming (%1 of %2 recommended confirmations) + + + + + Conflicted + + + + + Immature (%1 confirmations, will be available after %2) + + + + + This block was not received by any other nodes and will probably not be accepted! + Ing block a ini ali de atanggap deng aliwa pang nodes ania ali ya magsilbing tanggapan + + + + Generated but not accepted + Me-generate ya oneng ali ya metanggap + + + + Received with + Atanggap kayabe ning + + + + Received from + Atanggap menibat kang + + + + Sent to + Mipadala kang + + + + Payment to yourself + Kabayaran keka + + + + Mined + Me-mina + + + + (n/a) + (n/a) + + + + Transaction status. Hover over this field to show number of confirmations. + Status ning Transaksion: Itapat me babo na ning field a ini ban ipakit dala reng bilang dareng me-kumpirma na + + + + Date and time that the transaction was received. + Aldo at oras nung kapilan me tanggap ya ing transaksion + + + + Type of transaction. + Klase ning transaksion + + + + Destination address of transaction. + Kepuntalan a address ning transaksion + + + + Amount removed from or added to balance. + Alagang milako o miragdag king balanse. + + + + TransactionView + + + + All + Eganagana + + + + Today + Aldo iti + + + + This week + Paruminggung iti + + + + This month + Bulan a iti + + + + Last month + Milabas a bulan + + + + This year + Banuang iti + + + + Range... + Angganan... + + + + Received with + Atanggap kayabe ning + + + + Sent to + Mipadala kang + + + + To yourself + Keng sarili mu + + + + Mined + Me-mina + + + + Other + Aliwa + + + + Enter address or label to search + Magpalub kang address o label para pantunan + + + + Min amount + Pekaditak a alaga + + + + Copy address + Kopyan ing address + + + + Copy label + Kopyan ing label + + + + Copy amount + Kopyan ing alaga + + + + Copy transaction ID + + + + + Edit label + Alilan ing label + + + + Show transaction details + Ipakit ing detalye ning transaksion + + + + Export Transaction Data + + + + + Comma separated file (*.csv) + Comma separated file (*.csv) + + + + Confirmed + Me-kumpirma + + + + Date + Kaaldauan + + + + Type + Klase + + + + Label + Label + + + + Address + Address + + + + Amount + Alaga + + + + ID + ID + + + + Error exporting + + + + + Could not write to file %1. + + + + + Range: + Angga: + + + + to + para kang + + + + WalletModel + + + Sending... + + + + + bitcoin-core + + + Arepacoin version + + + + + Usage: + Pamanggamit: + + + + Send command to -server or arepacoind + + + + + List commands + Listahan dareng commands + + + + Get help for a command + Maniauad saup para kareng command + + + + Options: + Pipamilian: + + + + Specify configuration file (default: arepacoin.conf) + + + + + Specify pid file (default: arepacoind.pid) + + + + + Specify wallet file (within data directory) + + + + + Specify data directory + Pilinan ing data directory + + + + Set database cache size in megabytes (default: 25) + Ilage ya ing dagul o lati na ing database cache king megabytes (default: 25) + + + + Set database disk log size in megabytes (default: 100) + + + + + Listen for connections on <port> (default: 9853 or testnet: 19853) + + + + + Maintain at most <n> connections to peers (default: 125) + Mag-maintain peka <n> koneksion keng peers (default: 125) + + + + Connect to a node to retrieve peer addresses, and disconnect + Kumunekta king note ban ayakua mula reng peer address, at mako king panga konekta + + + + Specify your own public address + Sabyan me ing kekang pampublikong address + + + + Bind to given address. Use [host]:port notation for IPv6 + + + + + Stake your coins to support network and gain reward (default: 1) + + + + + Threshold for disconnecting misbehaving peers (default: 100) + Threshold for disconnecting misbehaving peers (default: 100) + + + + Number of seconds to keep misbehaving peers from reconnecting (default: 86400) + Number of seconds to keep misbehaving peers from reconnecting (default: 86400) + + + + An error occurred while setting up the RPC port %u for listening on IPv4: %s + Atin kamalian a milyari kabang ayusan ya ing RPC port %u para keng pamakiramdam king IPv4: %s + + + + Detach block and address databases. Increases shutdown time (default: 0) + + + + + 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. + + + + + Error: This transaction requires a transaction fee of at least %s because of its amount, complexity, or use of recently received funds + + + + + Listen for JSON-RPC connections on <port> (default: 9852 or testnet: 19852) + + + + + Accept command line and JSON-RPC commands + Tumanggap command line at JSON-RPC commands + + + + Error: Transaction creation failed + + + + + Error: Wallet locked, unable to create transaction + + + + + Importing blockchain data file. + + + + + Importing bootstrap blockchain data file. + + + + + Run in the background as a daemon and accept commands + Gumana king gulut bilang daemon at tumanggap commands + + + + Use the test network + Gamitan ing test network + + + + Accept connections from outside (default: 1 if no -proxy or -connect) + Tumanggap koneksion menibat king kilwal (default: 1 if no -proxy or -connect) + + + + An error occurred while setting up the RPC port %u for listening on IPv6, falling back to IPv4: %s + + + + + Error initializing database environment %s! To recover, BACKUP THAT DIRECTORY, then remove everything from it except for wallet.dat. + + + + + Set maximum size of high-priority/low-fee transactions in bytes (default: 27000) + + + + + Warning: -paytxfee is set very high! This is the transaction fee you will pay if you send a transaction. + Kapabaluan: Sobra ya katas ing makalage king -paytxfee. Ini ing maging bayad mu para king bayad na ning transaksion istung pepadala me ing transaksion a ini. + + + + Warning: Please check that your computer's date and time are correct! If your clock is wrong Arepacoin will not work properly. + + + + + Warning: error reading wallet.dat! All keys read correctly, but transaction data or address book entries might be missing or incorrect. + + + + + Warning: wallet.dat corrupt, data salvaged! Original wallet.dat saved as wallet.{timestamp}.bak in %s; if your balance or transactions are incorrect you should restore from a backup. + + + + + Attempt to recover private keys from a corrupt wallet.dat + + + + + Block creation options: + Pipamilian king pamag-gawang block: + + + + Connect only to the specified node(s) + Kumunekta mu king mepiling node(s) + + + + Discover own IP address (default: 1 when listening and no -externalip) + I-discover ing sariling IP address (default: 1 istung makiramdam at -externalip) + + + + Failed to listen on any port. Use -listen=0 if you want this. + Memali ya ing pamakiramdam kareng gang nanung port. Gamita me ini -listen=0 nung buri me ini. + + + + Find peers using DNS lookup (default: 1) + + + + + Sync checkpoints policy (default: strict) + + + + + Invalid -tor address: '%s' + + + + + Invalid amount for -reservebalance=<amount> + + + + + Maximum per-connection receive buffer, <n>*1000 bytes (default: 5000) + + + + + Maximum per-connection send buffer, <n>*1000 bytes (default: 1000) + + + + + Only connect to nodes in network <net> (IPv4, IPv6 or Tor) + + + + + Output extra debugging information. Implies all other -debug* options + + + + + Output extra network debugging information + + + + + Prepend debug output with timestamp + + + + + SSL options: (see the Bitcoin Wiki for SSL setup instructions) + Pipamilian ning SSL: (lawen ye ing Bitcoin Wiki para king SSL setup instructions) + + + + Select the version of socks proxy to use (4-5, default: 5) + + + + + Send trace/debug info to console instead of debug.log file + Magpadalang trace/debug info okeng console kesa keng debug.log file + + + + Send trace/debug info to debugger + + + + + Set maximum block size in bytes (default: 250000) + + + + + Set minimum block size in bytes (default: 0) + Ilage ing pekaditak a dagul na ning block king bytes (default: 0) + + + + Shrink debug.log file on client startup (default: 1 when no -debug) + + + + + Specify connection timeout in milliseconds (default: 5000) + + + + + Unable to sign checkpoint, wrong checkpointkey? + + + + + + Use UPnP to map the listening port (default: 0) + + + + + Use UPnP to map the listening port (default: 1 when listening) + + + + + Use proxy to reach tor hidden services (default: same as -proxy) + + + + + Username for JSON-RPC connections + Username para king JSON-RPC koneksion + + + + Verifying database integrity... + + + + + WARNING: syncronized checkpoint violation detected, but skipped! + + + + + Warning: Disk space is low! + + + + + Warning: This version is obsolete, upgrade required! + Kapabaluan: Ing bersioin a ini laus ne, kailangan nang mag-upgrade! + + + + wallet.dat corrupt, salvage failed + + + + + Password for JSON-RPC connections + Password para king JSON-RPC koneksion + + + + %s, you must set a rpcpassword in the configuration file: + %s +It is recommended you use the following random password: +rpcuser=arepacoinrpc +rpcpassword=%s +(you do not need to remember this password) +The username and password MUST NOT be the same. +If the file does not exist, create it with owner-readable-only file permissions. +It is also recommended to set alertnotify so you are notified of problems; +for example: alertnotify=echo %%s | mail -s "Arepacoin Alert" admin@foo.com + + + + + + Find peers using internet relay chat (default: 0) + + + + + Sync time with other nodes. Disable if time on your system is precise e.g. syncing with NTP (default: 1) + + + + + When creating transactions, ignore inputs with value less than this (default: 0.01) + + + + + Allow JSON-RPC connections from specified IP address + Payagan ya i JSON-RPC koneksion para king metung a IP address + + + + Send commands to node running on <ip> (default: 127.0.0.1) + Magpadalang command king node a gagana king <ip>(default: 127.0.0.1) + + + + Execute command when the best block changes (%s in cmd is replaced by block hash) + I-execute ing command istung mialilan ya ing best block (%s in cmd is replaced by block hash) + + + + Execute command when a wallet transaction changes (%s in cmd is replaced by TxID) + + + + + Require a confirmations for change (default: 0) + + + + + Enforce transaction scripts to use canonical PUSH operators (default: 1) + + + + + Execute command when a relevant alert is received (%s in cmd is replaced by message) + + + + + Upgrade wallet to latest format + I-upgrade ing wallet king pekabayung porma + + + + Set key pool size to <n> (default: 100) + I-set ing key pool size king <n>(default: 100) + + + + Rescan the block chain for missing wallet transactions + I-scan pasibayu ing block chain para kareng mauaualang transaksion + + + + How many blocks to check at startup (default: 2500, 0 = all) + + + + + How thorough the block verification is (0-6, default: 1) + + + + + Imports blocks from external blk000?.dat file + + + + + Use OpenSSL (https) for JSON-RPC connections + Gumamit OpenSSL(https) para king JSON-RPC koneksion + + + + Server certificate file (default: server.cert) + Server certificate file (default: server.cert) + + + + Server private key (default: server.pem) + Server private key (default: server.pem) + + + + Acceptable ciphers (default: TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH) + + + + + Error: Wallet unlocked for staking only, unable to create transaction. + + + + + WARNING: Invalid checkpoint found! Displayed transactions may not be correct! You may need to upgrade, or notify developers. + + + + + This help message + Ining saup a mensayi + + + + Wallet %s resides outside data directory %s. + + + + + Cannot obtain a lock on data directory %s. Arepacoin is probably already running. + + + + + Arepacoin + + + + + Unable to bind to %s on this computer (bind returned error %d, %s) + Ali ya magsilbing mag-bind keng %s kening kompyuter a ini (bind returned error %d, %s) + + + + Connect through socks proxy + + + + + Allow DNS lookups for -addnode, -seednode and -connect + Payagan ing pamaglawe DNS para king -addnode, -seednode and -connect + + + + Loading addresses... + Lo-load da ne ing address... + + + + Error loading blkindex.dat + + + + + Error loading wallet.dat: Wallet corrupted + Me-mali ya ing pamag-load king wallet.dat: Me-corrupt ya ing wallet + + + + Error loading wallet.dat: Wallet requires newer version of Arepacoin + + + + + Wallet needed to be rewritten: restart Arepacoin to complete + + + + + Error loading wallet.dat + Me-mali ya ing pamag-load king wallet.dat + + + + Invalid -proxy address: '%s' + Ali katanggap-tanggap a -proxy addresss: '%s' + + + + Unknown network specified in -onlynet: '%s' + E kilalang network ing mepili king -onlynet: '%s' + + + + Unknown -socks proxy version requested: %i + E kilalang -socks proxy version requested: %i + + + + Cannot resolve -bind address: '%s' + Eya me-resolve ing -bind address: '%s' + + + + Cannot resolve -externalip address: '%s' + Eya me-resolve ing -externalip address: '%s' + + + + Invalid amount for -paytxfee=<amount>: '%s' + Eya maliari ing alaga keng -paytxfee=<amount>: '%s' + + + + Error: could not start node + + + + + Sending... + + + + + Invalid amount + Ing alaga e ya katanggap-tanggap + + + + Insufficient funds + Kulang a pondo + + + + Loading block index... + Lo-load dane ing block index... + + + + Add a node to connect to and attempt to keep the connection open + Magdagdag a node ban kumunekta at subuknan apanatili yang makabuklat ing koneksion + + + + Unable to bind to %s on this computer. Arepacoin is probably already running. + + + + + Fee per KB to add to transactions you send + + + + + Invalid amount for -mininput=<amount>: '%s' + + + + + Loading wallet... + Lo-load dane ing wallet... + + + + Cannot downgrade wallet + Ali ya magsilbing i-downgrade ing wallet + + + + Cannot initialize keypool + + + + + Cannot write default address + Eya misulat ing default address + + + + Rescanning... + I-scan deng pasibayu... + + + + Done loading + Yari ne ing pamag-load + + + + To use the %s option + Para agamit ing %s a pimamilian + + + + Error + Mali + + + + You must set rpcpassword=<password> in the configuration file: +%s +If the file does not exist, create it with owner-readable-only file permissions. + Dapat meng ilage ing rpcpassword=<password> king configuration file: +%s +Nung ing file ala ya, gawa ka gamit ing owner-readable-only file permissions. + + + \ No newline at end of file diff --git a/src/qt/locale/bitcoin_pl.ts b/src/qt/locale/bitcoin_pl.ts new file mode 100755 index 0000000..77e88d9 --- /dev/null +++ b/src/qt/locale/bitcoin_pl.ts @@ -0,0 +1,3287 @@ + + + AboutDialog + + + About Arepacoin + O Arepacoin + + + + <b>Arepacoin</b> version + <b>Arepacoin</b> wersja + + + + Copyright © 2009-2014 The Bitcoin developers +Copyright © 2012-2014 The NovaCoin developers +Copyright © 2014 The Arepacoin developers + + + + + +This is experimental software. + +Distributed under the MIT/X11 software license, see the accompanying file COPYING or http://www.opensource.org/licenses/mit-license.php. + +This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit (http://www.openssl.org/) and cryptographic software written by Eric Young (eay@cryptsoft.com) and UPnP software written by Thomas Bernard. + +Oprogramowanie eksperymentalne. + +Distributed under the MIT/X11 software license, see the accompanying file COPYING or http://www.opensource.org/licenses/mit-license.php. + +This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit (http://www.openssl.org/) and cryptographic software written by Eric Young (eay@cryptsoft.com) and UPnP software written by Thomas Bernard. + + + + AddressBookPage + + + Address Book + Książka Adresowa + + + + Double-click to edit address or label + Kliknij dwukrotnie, aby edytować adres lub etykietę + + + + Create a new address + Utwórz nowy adres + + + + Copy the currently selected address to the system clipboard + Skopiuj aktualnie wybrany adres do schowka + + + + &New Address + Nowy Adres + + + + These are your Arepacoin addresses for receiving payments. You may want to give a different one to each sender so you can keep track of who is paying you. + Tutaj znajdują się twoje adresy do odbierania wpłat. +Możesz dodać kolejny adres dla każdego wysyłającego aby określić od kogo pochodzi wpłata. + + + + &Copy Address + &Kopiuj adres + + + + Show &QR Code + Pokaż &Kod QR + + + + Sign a message to prove you own a Arepacoin address + Podpisz wiadomość by udowodnić, że jesteś właścicielem adresu Arepacoin + + + + Sign &Message + Podpisz &Wiadomość + + + + Delete the currently selected address from the list + Usuń zaznaczony adres z listy + + + + Verify a message to ensure it was signed with a specified Arepacoin address + Zweryfikuj wiadomość, w celu zapewnienia, że została podpisana z określonego adresu Arepacoin + + + + &Verify Message + &Zweryfikuj wiadomość + + + + &Delete + &Usuń + + + + Copy &Label + Kopiuj &Etykietę + + + + &Edit + &Edytuj + + + + Export Address Book Data + Exportuj Książkę Adresową + + + + Comma separated file (*.csv) + Plik *.CSV (rozdzielany przecinkami) + + + + Error exporting + Błąd exportowania + + + + Could not write to file %1. + Nie mogę zapisać do pliku %1 + + + + AddressTableModel + + + Label + Etykieta + + + + Address + Adres + + + + (no label) + (bez etykiety) + + + + AskPassphraseDialog + + + Passphrase Dialog + Okienko Hasła + + + + Enter passphrase + Wpisz hasło + + + + New passphrase + Nowe hasło + + + + Repeat new passphrase + Powtórz nowe hasło + + + + Serves to disable the trivial sendmoney when OS account compromised. Provides no real security. + + + + + For staking only + + + + + Enter the new passphrase to the wallet.<br/>Please use a passphrase of <b>10 or more random characters</b>, or <b>eight or more words</b>. + Wprowadź nowe hasło dla portfela.<br/>Proszę użyć hasła składającego się z <b>10 lub więcej losowych znaków</b> lub <b>ośmiu lub więcej słów</b>. + + + + Encrypt wallet + Zaszyfruj portfel + + + + This operation needs your wallet passphrase to unlock the wallet. + Ta operacja wymaga hasła do portfela ażeby odblokować portfel. + + + + Unlock wallet + Odblokuj portfel + + + + This operation needs your wallet passphrase to decrypt the wallet. + Ta operacja wymaga hasła do portfela ażeby odszyfrować portfel. + + + + Decrypt wallet + Odszyfruj portfel + + + + Change passphrase + Zmień hasło + + + + Enter the old and new passphrase to the wallet. + Podaj stare i nowe hasło do portfela. + + + + Confirm wallet encryption + Potwierdź szyfrowanie portfela + + + + Warning: If you encrypt your wallet and lose your passphrase, you will <b>LOSE ALL OF YOUR COINS</b>! + Uwaga: Jeśli zaszyfrujesz swój portfel i zgubisz hasło, wtedy<b>UTRACISZ SWOJE MONETY!</b>! + + + + Are you sure you wish to encrypt your wallet? + Jesteś pewien, że chcesz zaszyfrować swój portfel? + + + + IMPORTANT: Any previous backups you have made of your wallet file should be replaced with the newly generated, encrypted wallet file. For security reasons, previous backups of the unencrypted wallet file will become useless as soon as you start using the new, encrypted wallet. + WAŻNE: Wszystkie wykonane wcześniej kopie pliku portfela powinny być zamienione na nowe, szyfrowane pliki. Z powodów bezpieczeństwa, poprzednie kopie nieszyfrowanych plików portfela staną się bezużyteczne jak tylko zaczniesz korzystać z nowego, szyfrowanego portfela. + + + + + Warning: The Caps Lock key is on! + Uwaga: Klawisz Caps Lock jest włączony + + + + + Wallet encrypted + Portfel zaszyfrowany + + + + Arepacoin will close now to finish the encryption process. Remember that encrypting your wallet cannot fully protect your coins from being stolen by malware infecting your computer. + + + + + + + + Wallet encryption failed + Szyfrowanie portfela nie powiodło się + + + + Wallet encryption failed due to an internal error. Your wallet was not encrypted. + Szyfrowanie portfela nie powiodło się z powodu wewnętrznego błędu. Twój portfel nie został zaszyfrowany. + + + + + The supplied passphrases do not match. + Podane hasła nie są takie same. + + + + Wallet unlock failed + Odblokowanie portfela nie powiodło się + + + + + + The passphrase entered for the wallet decryption was incorrect. + Wprowadzone hasło do odszyfrowania portfela jest niepoprawne. + + + + Wallet decryption failed + Odszyfrowanie portfela nie powiodło się + + + + Wallet passphrase was successfully changed. + Hasło portfela zostało pomyślnie zmienione. + + + + BitcoinGUI + + + Sign &message... + Podpisz wiado&mość... + + + + Synchronizing with network... + Synchronizacja z siecią... + + + + &Overview + P&odsumowanie + + + + Show general overview of wallet + Pokazuje ogólny zarys portfela + + + + &Transactions + &Transakcje + + + + Browse transaction history + Przeglądaj historię transakcji + + + + &Address Book + &Książka Adresowa + + + + Edit the list of stored addresses and labels + Edytuj listę przechowywanych adresów i etykiet + + + + &Receive coins + &Odbierz monety + + + + Show the list of addresses for receiving payments + Pokaż listę adresów do odbierania wpłat + + + + &Send coins + &Wyślij monety + + + + E&xit + &Zakończ + + + + Quit application + Zamknij program + + + + Show information about Arepacoin + Pokaż informacje dotyczące Arepacoin + + + + About &Qt + O &Qt + + + + Show information about Qt + Pokazuje informacje o Qt + + + + &Options... + &Opcje... + + + + &Encrypt Wallet... + Zaszyfruj Portf&el + + + + &Backup Wallet... + Wykonaj kopię zapasową... + + + + &Change Passphrase... + &Zmień hasło... + + + + ~%n block(s) remaining + + + + + Downloaded %1 of %2 blocks of transaction history (%3% done). + Pobrano %1 z %2 bloków historii transakcji (%3% gotowe). + + + + &Export... + &Exportuj + + + + Send coins to a Arepacoin address + Wyślij monety na adres Arepacoin + + + + Modify configuration options for Arepacoin + + + + + Export the data in the current tab to a file + + + + + Encrypt or decrypt wallet + + + + + Backup wallet to another location + Zapasowy portfel w innej lokalizacji + + + + Change the passphrase used for wallet encryption + Zmień hasło użyte do szyfrowania portfela + + + + &Debug window + &Okno debugowania + + + + Open debugging and diagnostic console + Otwórz konsolę debugowania i diagnostyki + + + + &Verify message... + &Zweryfikuj wiadomość... + + + + Arepacoin + Arepacoin + + + + Wallet + Portfel + + + + &About Arepacoin + + + + + &Show / Hide + &Pokaż / Ukryj + + + + Unlock wallet + + + + + &Lock Wallet + + + + + Lock wallet + + + + + &File + &Plik + + + + &Settings + P&referencje + + + + &Help + Pomo&c + + + + Tabs toolbar + Pasek zakładek + + + + Actions toolbar + + + + + + [testnet] + [testnet] + + + + + Arepacoin client + + + + + %n active connection(s) to Arepacoin network + + + + + Downloaded %1 blocks of transaction history. + + + + + Staking.<br>Your weight is %1<br>Network weight is %2<br>Expected time to earn reward is %3 + + + + + Not staking because wallet is locked + + + + + Not staking because wallet is offline + + + + + Not staking because wallet is syncing + + + + + Not staking because you don't have mature coins + + + + + %n second(s) ago + + + + + &Unlock Wallet... + + + + + %n minute(s) ago + + + + + %n hour(s) ago + + + + + %n day(s) ago + + + + + Up to date + Aktualny + + + + Catching up... + Łapanie bloków... + + + + Last received block was generated %1. + + + + + This transaction is over the size limit. You can still send it for a fee of %1, which goes to the nodes that process your transaction and helps to support the network. Do you want to pay the fee? + + + + + Confirm transaction fee + + + + + Sent transaction + Transakcja wysłana + + + + Incoming transaction + Transakcja przychodząca + + + + Date: %1 +Amount: %2 +Type: %3 +Address: %4 + + Data: %1 +Kwota: %2 +Typ: %3 +Adres: %4 + + + + + + URI handling + + + + + + URI can not be parsed! This can be caused by an invalid Arepacoin address or malformed URI parameters. + + + + + Wallet is <b>encrypted</b> and currently <b>unlocked</b> + Portfel jest <b>zaszyfrowany</b> i obecnie <b>niezablokowany</b> + + + + Wallet is <b>encrypted</b> and currently <b>locked</b> + Portfel jest <b>zaszyfrowany</b> i obecnie <b>zablokowany</b> + + + + Backup Wallet + + + + + Wallet Data (*.dat) + + + + + Backup Failed + + + + + There was an error trying to save the wallet data to the new location. + + + + + %n second(s) + + + + + %n minute(s) + + + + + %n hour(s) + %n godzina%n godzin%n godzin + + + + %n day(s) + %n dzień%n dni%n dni + + + + Not staking + + + + + A fatal error occurred. Arepacoin can no longer continue safely and will quit. + + + + + ClientModel + + + Network Alert + Sieć Alert + + + + CoinControlDialog + + + Coin Control + + + + + Quantity: + Ilość: + + + + Bytes: + Bajtów: + + + + Amount: + Kwota: + + + + Priority: + Priorytet: + + + + Fee: + Opłata: + + + + Low Output: + + + + + no + nie + + + + After Fee: + Po opłacie: + + + + Change: + Reszta: + + + + (un)select all + Zaznacz/Odznacz wszystko + + + + Tree mode + Widok drzewa + + + + List mode + Widok listy + + + + Amount + Kwota + + + + Label + + + + + Address + Adres + + + + Date + Data + + + + Confirmations + Potwierdzenia + + + + Confirmed + Potwierdzony + + + + Priority + Priorytet + + + + Copy address + Kopiuj adres + + + + Copy label + Kopiuj etykietę + + + + + Copy amount + Kopiuj kwotę + + + + Copy transaction ID + Skopiuj ID transakcji + + + + Copy quantity + Skopiuj ilość + + + + Copy fee + Skopiuj opłatę + + + + Copy after fee + Skopiuj ilość po opłacie + + + + Copy bytes + Skopiuj ilość bajtów + + + + Copy priority + Skopiuj priorytet + + + + Copy low output + + + + + Copy change + Skopiuj resztę + + + + highest + najwyższa + + + + high + wysoka + + + + medium-high + średnio wysoki + + + + medium + średnia + + + + low-medium + średnio niski + + + + low + niski + + + + lowest + najniższy + + + + DUST + + + + + yes + tak + + + + This label turns red, if the transaction size is bigger than 10000 bytes. + + This means a fee of at least %1 per kb is required. + + Can vary +/- 1 Byte per input. + + + + + Transactions with higher priority get more likely into a block. + +This label turns red, if the priority is smaller than "medium". + + This means a fee of at least %1 per kb is required. + + + + + This label turns red, if any recipient receives an amount smaller than %1. + + This means a fee of at least %2 is required. + + Amounts below 0.546 times the minimum relay fee are shown as DUST. + + + + + This label turns red, if the change is smaller than %1. + + This means a fee of at least %2 is required. + + + + + + (no label) + (bez etykiety) + + + + change from %1 (%2) + reszta z %1 (%2) + + + + (change) + (reszta) + + + + EditAddressDialog + + + Edit Address + Edytuj adres + + + + &Label + &Etykieta + + + + The label associated with this address book entry + + + + + &Address + &Adres + + + + The address associated with this address book entry. This can only be modified for sending addresses. + + + + + New receiving address + Nowy adres odbiorczy + + + + New sending address + Nowy adres wysyłania + + + + Edit receiving address + Edytuj adres odbioru + + + + Edit sending address + Edytuj adres wysyłania + + + + The entered address "%1" is already in the address book. + Wprowadzony adres "%1" już istnieje w książce adresowej. + + + + The entered address "%1" is not a valid Arepacoin address. + + + + + Could not unlock wallet. + Nie można było odblokować portfela. + + + + New key generation failed. + Tworzenie nowego klucza nie powiodło się. + + + + GUIUtil::HelpMessageBox + + + + Arepacoin-Qt + + + + + version + + + + + Usage: + + + + + command-line options + + + + + UI options + + + + + Set language, for example "de_DE" (default: system locale) + + + + + Start minimized + + + + + Show splash screen on startup (default: 1) + + + + + OptionsDialog + + + Options + Opcje + + + + &Main + Główne + + + + Optional transaction fee per kB that helps make sure your transactions are processed quickly. Most transactions are 1 kB. Fee 0.01 recommended. + + + + + Pay transaction &fee + Płać prowizję za transakcje + + + + Reserved amount does not participate in staking and is therefore spendable at any time. + + + + + Reserve + + + + + Automatically start Arepacoin after logging in to the system. + + + + + &Start Arepacoin on system login + + + + + Detach block and address databases at shutdown. This means they can be moved to another data directory, but it slows down shutdown. The wallet is always detached. + + + + + &Detach databases at shutdown + + + + + &Network + &Sieć + + + + Automatically open the Arepacoin client port on the router. This only works when your router supports UPnP and it is enabled. + + + + + Map port using &UPnP + Mapuj port używając &UPnP + + + + Connect to the Arepacoin network through a SOCKS proxy (e.g. when connecting through Tor). + + + + + &Connect through SOCKS proxy: + + + + + Proxy &IP: + Proxy &IP: + + + + IP address of the proxy (e.g. 127.0.0.1) + + + + + &Port: + &Port: + + + + Port of the proxy (e.g. 9050) + Port proxy (np. 9050) + + + + SOCKS &Version: + Wersja &SOCKS + + + + SOCKS version of the proxy (e.g. 5) + SOCKS wersja serwera proxy (np. 5) + + + + &Window + &Okno + + + + Show only a tray icon after minimizing the window. + Pokazuj tylko ikonę przy zegarku po zminimalizowaniu okna. + + + + &Minimize to the tray instead of the taskbar + &Minimalizuj do paska przy zegarku zamiast do paska zadań + + + + Minimize instead of exit the application when the window is closed. When this option is enabled, the application will be closed only after selecting Quit in the menu. + Minimalizuje zamiast zakończyć działanie programu przy zamykaniu okna. Kiedy ta opcja jest włączona, program zakończy działanie po wybieraniu Zamknij w menu. + + + + M&inimize on close + M&inimalizuj przy zamknięciu + + + + &Display + &Wyświetlanie + + + + User Interface &language: + Język &Użytkownika: + + + + The user interface language can be set here. This setting will take effect after restarting Arepacoin. + + + + + &Unit to show amounts in: + &Jednostka pokazywana przy kwocie: + + + + Choose the default subdivision unit to show in the interface and when sending coins. + Wybierz podział jednostki pokazywany w interfejsie oraz podczas wysyłania monet + + + + Whether to show Arepacoin addresses in the transaction list or not. + + + + + &Display addresses in transaction list + &Wyświetlaj adresy w liście transakcji + + + + Whether to show coin control features or not. + + + + + Display coin &control features (experts only!) + + + + + &OK + &OK + + + + &Cancel + &Anuluj + + + + &Apply + + + + + default + domyślny + + + + + Warning + + + + + + This setting will take effect after restarting Arepacoin. + + + + + The supplied proxy address is invalid. + Adres podanego proxy jest nieprawidłowy + + + + OverviewPage + + + Form + Formularz + + + + + The displayed information may be out of date. Your wallet automatically synchronizes with the Arepacoin network after a connection is established, but this process has not completed yet. + + + + + Stake: + + + + + Unconfirmed: + + + + + Wallet + Portfel + + + + Spendable: + + + + + Your current spendable balance + Twoje obecne saldo + + + + Immature: + Niedojrzały: + + + + Mined balance that has not yet matured + Balans wydobycia, który jeszcze nie dojrzał + + + + Total: + Wynosi ogółem: + + + + Your current total balance + Twoje obecne saldo + + + + <b>Recent transactions</b> + <b>Ostatnie transakcje</b> + + + + Total of transactions that have yet to be confirmed, and do not yet count toward the current balance + + + + + Total of coins that was staked, and do not yet count toward the current balance + + + + + + out of sync + desynchronizacja + + + + QRCodeDialog + + + QR Code Dialog + + + + + Request Payment + + + + + Amount: + + + + + Label: + + + + + Message: + + + + + &Save As... + + + + + Error encoding URI into QR Code. + + + + + The entered amount is invalid, please check. + + + + + Resulting URI too long, try to reduce the text for label / message. + + + + + Save QR Code + + + + + PNG Images (*.png) + + + + + RPCConsole + + + Client name + Nazwa klienta + + + + + + + + + + + + + N/A + NIEDOSTĘPNE + + + + Client version + Wersja klienta + + + + &Information + &Informacje + + + + Using OpenSSL version + Używana wersja OpenSSL + + + + Startup time + Czas uruchomienia + + + + Network + Sieć + + + + Number of connections + Liczba połączeń + + + + On testnet + + + + + Block chain + Ciąg bloków + + + + Current number of blocks + Aktualna liczba bloków + + + + Estimated total blocks + Szacowana ilość bloków + + + + Last block time + Czas ostatniego bloku + + + + &Open + &Otwórz + + + + Command-line options + + + + + Show the Arepacoin-Qt help message to get a list with possible Arepacoin command-line options. + + + + + &Show + + + + + &Console + &Konsola + + + + Build date + Data kompilacji + + + + Arepacoin - Debug window + + + + + Arepacoin Core + + + + + Debug log file + Plik logowania debugowania + + + + Open the Arepacoin debug log file from the current data directory. This can take a few seconds for large log files. + + + + + Clear console + Wyczyść konsolę + + + + Welcome to the Arepacoin RPC console. + + + + + Use up and down arrows to navigate history, and <b>Ctrl-L</b> to clear screen. + Użyj strzałek do przewijania historii i <b>Ctrl-L</b> aby wyczyścić ekran + + + + Type <b>help</b> for an overview of available commands. + Wpisz <b>help</b> aby uzyskać listę dostępnych komend + + + + SendCoinsDialog + + + + + + + + + + Send Coins + Wyślij Monety + + + + Coin Control Features + + + + + Inputs... + + + + + automatically selected + + + + + Insufficient funds! + + + + + Quantity: + Ilość: + + + + + 0 + + + + + Bytes: + Bajtów: + + + + Amount: + Kwota: + + + + + + + 0.00 BC + + + + + Priority: + Priorytet: + + + + medium + + + + + Fee: + Opłata: + + + + Low Output: + + + + + no + + + + + After Fee: + Po opłacie: + + + + Change + + + + + custom change address + + + + + Send to multiple recipients at once + Wyślij do wielu odbiorców na raz + + + + Add &Recipient + Dodaj Odbio&rce + + + + Remove all transaction fields + + + + + Clear &All + Wyczyść &wszystko + + + + Balance: + Saldo: + + + + 123.456 BC + + + + + Confirm the send action + Potwierdź akcję wysyłania + + + + S&end + Wy&syłka + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Copy quantity + Skopiuj ilość + + + + Copy amount + Kopiuj kwotę + + + + Copy fee + Skopiuj opłatę + + + + Copy after fee + Skopiuj ilość po opłacie + + + + Copy bytes + Skopiuj ilość bajtów + + + + Copy priority + Skopiuj priorytet + + + + Copy low output + + + + + Copy change + Skopiuj resztę + + + + <b>%1</b> to %2 (%3) + + + + + Confirm send coins + Potwierdź wysyłanie monet + + + + Are you sure you want to send %1? + + + + + and + + + + + The recipient address is not valid, please recheck. + Adres odbiorcy jest nieprawidłowy, proszę poprawić + + + + The amount to pay must be larger than 0. + Kwota do zapłacenia musi być większa od 0. + + + + The amount exceeds your balance. + Kwota przekracza twoje saldo. + + + + The total exceeds your balance when the %1 transaction fee is included. + Suma przekracza twoje saldo, gdy doliczymy %1 prowizji transakcyjnej. + + + + Duplicate address found, can only send to each address once per send operation. + Znaleziono powtórzony adres, można wysłać tylko raz na każdy adres podczas operacji wysyłania. + + + + Error: Transaction creation failed. + + + + + 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. + + + + + WARNING: Invalid Arepacoin address + + + + + (no label) + (bez etykiety) + + + + WARNING: unknown change address + + + + + SendCoinsEntry + + + Form + + + + + A&mount: + Su&ma: + + + + Pay &To: + Zapłać &dla: + + + + + Enter a label for this address to add it to your address book + Wprowadź etykietę dla tego adresu by dodać go do książki adresowej + + + + &Label: + &Etykieta: + + + + The address to send the payment to (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Choose address from address book + + + + + Alt+A + Alt+A + + + + Paste address from clipboard + Wklej adres ze schowka + + + + Alt+P + Alt+P + + + + Remove this recipient + + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + SignVerifyMessageDialog + + + Signatures - Sign / Verify a Message + Podpisy - Podpisz / zweryfikuj wiadomość + + + + + &Sign Message + Podpi&sz Wiadomość + + + + You can sign messages with your addresses to prove you own them. Be careful not to sign anything vague, as phishing attacks may try to trick you into signing your identity over to them. Only sign fully-detailed statements you agree to. + Możesz podpisywać wiadomości swoimi adresami aby udowodnić, że jesteś ich właścicielem. Uważaj, aby nie podpisywać niczego co wzbudza Twoje podejrzenia, ponieważ ktoś może stosować phishing próbując nakłonić Cię do ich podpisania. Akceptuj i podpisuj tylko w pełni zrozumiałe komunikaty i wiadomości. + + + + The address to sign the message with (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + + Choose an address from the address book + + + + + + Alt+A + Alt+A + + + + Paste address from clipboard + Wklej adres ze schowka + + + + Alt+P + Alt+P + + + + Enter the message you want to sign here + Wprowadź wiadomość, którą chcesz podpisać, tutaj + + + + Copy the current signature to the system clipboard + Kopiuje aktualny podpis do schowka systemowego + + + + Sign the message to prove you own this Arepacoin address + + + + + Reset all sign message fields + Zresetuj wszystkie pola podpisanej wiadomości + + + + + Clear &All + Wyczyść &wszystko + + + + + &Verify Message + &Zweryfikuj wiadomość + + + + Enter the signing address, message (ensure you copy line breaks, spaces, tabs, etc. exactly) and signature below to verify the message. Be careful not to read more into the signature than what is in the signed message itself, to avoid being tricked by a man-in-the-middle attack. + Wpisz adres podpisu, wiadomość (upewnij się, że dokładnie skopiujesz wszystkie zakończenia linii, spacje, tabulacje itp.) oraz podpis poniżej by sprawdzić wiadomość. Uważaj by nie dodać więcej do podpisu niż do samej podpisywanej wiadomości by uniknąć ataku man-in-the-middle (człowiek pośrodku) + + + + The address the message was signed with (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Verify the message to ensure it was signed with the specified Arepacoin address + + + + + Reset all verify message fields + Resetuje wszystkie pola weryfikacji wiadomości + + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Click "Sign Message" to generate signature + Kliknij "Podpisz Wiadomość" żeby uzyskać podpis + + + + Enter Arepacoin signature + + + + + + The entered address is invalid. + Podany adres jest nieprawidłowy. + + + + + + + Please check the address and try again. + Proszę sprawdzić adres i spróbować ponownie. + + + + + The entered address does not refer to a key. + Wprowadzony adres nie odnosi się do klucza. + + + + Wallet unlock was cancelled. + Odblokowanie portfela zostało anulowane. + + + + Private key for the entered address is not available. + Klucz prywatny dla podanego adresu nie jest dostępny + + + + Message signing failed. + Podpisanie wiadomości nie powiodło się + + + + Message signed. + Wiadomość podpisana. + + + + The signature could not be decoded. + Podpis nie może zostać zdekodowany. + + + + + Please check the signature and try again. + Sprawdź podpis i spróbuj ponownie. + + + + The signature did not match the message digest. + Podpis nie odpowiadał streszczeniu wiadomości + + + + Message verification failed. + Weryfikacja wiadomości nie powiodła się. + + + + Message verified. + Wiadomość zweryfikowana. + + + + TransactionDesc + + + Open until %1 + Otwórz do %1 + + + + Open for %n block(s) + + + + + conflicted + + + + + %1/offline + %1/offline + + + + %1/unconfirmed + %1/niezatwierdzone + + + + %1 confirmations + %1 potwierdzeń + + + + Status + Status + + + + , broadcast through %n node(s) + , emitowany przez %n węzeł, emitowany przez %n węzły, emitowany przez %n węzłów + + + + Date + Data + + + + Source + Źródło + + + + Generated + Wygenerowano + + + + + From + Od + + + + + + To + Do + + + + + own address + własny adres + + + + label + etykieta + + + + + + + + Credit + Przypisy + + + + matures in %n more block(s) + potwierdzona przy %n bloku więcejpotwierdzona przy %n blokach więcejpotwierdzona przy %n blokach więcej + + + + not accepted + niezaakceptowane + + + + + + + Debit + Debet + + + + Transaction fee + Prowizja transakcji + + + + Net amount + Kwota netto + + + + Message + Wiadomość + + + + Comment + Komentarz + + + + Transaction ID + ID transakcji + + + + Generated coins must mature 6 blocks before they can be spent. When you generated this block, it was broadcast to the network to be added to the block chain. If it fails to get into the chain, its state will change to "not accepted" and it won't be spendable. This may occasionally happen if another node generates a block within a few seconds of yours. + + + + + Debug information + Informacje debugowania + + + + Transaction + Transakcja + + + + Inputs + Wejścia + + + + Amount + Kwota + + + + true + prawda + + + + false + fałsz + + + + , has not been successfully broadcast yet + , nie został jeszcze pomyślnie wyemitowany + + + + unknown + nieznany + + + + TransactionDescDialog + + + Transaction details + Szczegóły transakcji + + + + This pane shows a detailed description of the transaction + Ten panel pokazuje szczegółowy opis transakcji + + + + TransactionTableModel + + + Date + Data + + + + Type + Typ + + + + Address + Adres + + + + Amount + Kwota + + + + Open until %1 + Otwórz do %1 + + + + Confirmed (%1 confirmations) + Zatwierdzony (%1 potwierdzeń) + + + + Open for %n more block(s) + + + + + Offline + + + + + Unconfirmed + Niepotwierdzone: + + + + Confirming (%1 of %2 recommended confirmations) + Potwierdzanie (%1 z %2 rekomendowanych potwierdzeń) + + + + Conflicted + + + + + Immature (%1 confirmations, will be available after %2) + + + + + This block was not received by any other nodes and will probably not be accepted! + Ten blok nie został odebrany przez jakikolwiek inny węzeł i prawdopodobnie nie zostanie zaakceptowany! + + + + Generated but not accepted + Wygenerowano ale nie zaakceptowano + + + + Received with + Otrzymane przez + + + + Received from + Odebrano od + + + + Sent to + Wysłano do + + + + Payment to yourself + Płatność do siebie + + + + Mined + Wydobyto + + + + (n/a) + (brak) + + + + Transaction status. Hover over this field to show number of confirmations. + Status transakcji. Najedź na pole, aby zobaczyć liczbę potwierdzeń. + + + + Date and time that the transaction was received. + Data i czas odebrania transakcji. + + + + Type of transaction. + Rodzaj transakcji. + + + + Destination address of transaction. + Adres docelowy transakcji. + + + + Amount removed from or added to balance. + Kwota usunięta z lub dodana do konta. + + + + TransactionView + + + + All + Wszystko + + + + Today + Dzisiaj + + + + This week + W tym tygodniu + + + + This month + W tym miesiącu + + + + Last month + W zeszłym miesiącu + + + + This year + W tym roku + + + + Range... + Zakres... + + + + Received with + Otrzymane przez + + + + Sent to + Wysłano do + + + + To yourself + Do siebie + + + + Mined + Wydobyto + + + + Other + Inne + + + + Enter address or label to search + Wprowadź adres albo etykietę żeby wyszukać + + + + Min amount + Min suma + + + + Copy address + Kopiuj adres + + + + Copy label + Kopiuj etykietę + + + + Copy amount + Kopiuj kwotę + + + + Copy transaction ID + Skopiuj ID transakcji + + + + Edit label + Edytuj etykietę + + + + Show transaction details + Pokaż szczegóły transakcji + + + + Export Transaction Data + + + + + Comma separated file (*.csv) + CSV (rozdzielany przecinkami) + + + + Confirmed + Potwierdzony + + + + Date + Data + + + + Type + Typ + + + + Label + Etykieta + + + + Address + Adres + + + + Amount + Kwota + + + + ID + ID + + + + Error exporting + + + + + Could not write to file %1. + + + + + Range: + Zakres: + + + + to + do + + + + WalletModel + + + Sending... + + + + + bitcoin-core + + + Arepacoin version + + + + + Usage: + Użycie: + + + + Send command to -server or arepacoind + + + + + List commands + Lista poleceń + + + + Get help for a command + Uzyskaj pomoc do polecenia + + + + Options: + Opcje: + + + + Specify configuration file (default: arepacoin.conf) + + + + + Specify pid file (default: arepacoind.pid) + + + + + Specify wallet file (within data directory) + Określ plik portfela (w obrębie folderu danych) + + + + Specify data directory + Wskaż folder danych + + + + Set database cache size in megabytes (default: 25) + Ustaw rozmiar w megabajtach cache-u bazy danych (domyślnie: 25) + + + + Set database disk log size in megabytes (default: 100) + + + + + Listen for connections on <port> (default: 9853 or testnet: 19853) + + + + + Maintain at most <n> connections to peers (default: 125) + Utrzymuj maksymalnie <n> połączeń z peerami (domyślnie: 125) + + + + Connect to a node to retrieve peer addresses, and disconnect + Podłącz się do węzła aby otrzymać adresy peerów i rozłącz + + + + Specify your own public address + Podaj swój publiczny adres + + + + Bind to given address. Use [host]:port notation for IPv6 + + + + + Stake your coins to support network and gain reward (default: 1) + + + + + Threshold for disconnecting misbehaving peers (default: 100) + Próg po którym nastąpi rozłączenie nietrzymających się zasad peerów (domyślnie: 100) + + + + Number of seconds to keep misbehaving peers from reconnecting (default: 86400) + Czas w sekundach, przez jaki nietrzymający się zasad peerzy nie będą mogli ponownie się podłączyć (domyślnie: 86400) + + + + An error occurred while setting up the RPC port %u for listening on IPv4: %s + Wystąpił błąd podczas ustawiania portu RPC %u w tryb nasłuchu: %s + + + + Detach block and address databases. Increases shutdown time (default: 0) + + + + + 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. + + + + + Error: This transaction requires a transaction fee of at least %s because of its amount, complexity, or use of recently received funds + + + + + Listen for JSON-RPC connections on <port> (default: 9852 or testnet: 19852) + + + + + Accept command line and JSON-RPC commands + Akceptuj linię poleceń oraz polecenia JSON-RPC + + + + Error: Transaction creation failed + + + + + Error: Wallet locked, unable to create transaction + + + + + Importing blockchain data file. + + + + + Importing bootstrap blockchain data file. + + + + + Run in the background as a daemon and accept commands + Uruchom w tle jako daemon i przyjmuj polecenia + + + + Use the test network + Użyj sieci testowej + + + + Accept connections from outside (default: 1 if no -proxy or -connect) + Akceptuj połączenia z zewnątrz (domyślnie: 1 jeśli nie ustawiono -proxy lub -connect) + + + + An error occurred while setting up the RPC port %u for listening on IPv6, falling back to IPv4: %s + Wystąpił błąd podczas ustawiania portu RPC %u w tryb nasłuchu dla IPv6, korzystam z IPv4: %s + + + + Error initializing database environment %s! To recover, BACKUP THAT DIRECTORY, then remove everything from it except for wallet.dat. + + + + + Set maximum size of high-priority/low-fee transactions in bytes (default: 27000) + + + + + Warning: -paytxfee is set very high! This is the transaction fee you will pay if you send a transaction. + Ostrzeżenie: -paytxfee jest bardzo duży. To jest prowizja za transakcje, którą płacisz, gdy wysyłasz monety. + + + + Warning: Please check that your computer's date and time are correct! If your clock is wrong Arepacoin will not work properly. + + + + + Warning: error reading wallet.dat! All keys read correctly, but transaction data or address book entries might be missing or incorrect. + Ostrzeżenie: błąd odczytu wallet.dat! Wszystkie klucze zostały odczytane, ale może brakować pewnych danych transakcji lub wpisów w książce adresowej lub mogą one być nieprawidłowe. + + + + Warning: wallet.dat corrupt, data salvaged! Original wallet.dat saved as wallet.{timestamp}.bak in %s; if your balance or transactions are incorrect you should restore from a backup. + Ostrzeżenie: Odtworzono dane z uszkodzonego pliku wallet.dat! Oryginalny wallet.dat został zapisany jako wallet.{timestamp}.bak w %s; jeśli twoje saldo lub transakcje są niepoprawne powinieneś odtworzyć kopię zapasową. + + + + Attempt to recover private keys from a corrupt wallet.dat + Próbuj odzyskać klucze prywatne z uszkodzonego wallet.dat + + + + Block creation options: + Opcje tworzenia bloku: + + + + Connect only to the specified node(s) + Łącz tylko do wskazanego węzła + + + + Discover own IP address (default: 1 when listening and no -externalip) + Odkryj własny adres IP (domyślnie: 1 kiedy w trybie nasłuchu i brak -externalip ) + + + + Failed to listen on any port. Use -listen=0 if you want this. + Próba otwarcia jakiegokolwiek portu nie powiodła się. Użyj -listen=0 jeśli tego chcesz. + + + + Find peers using DNS lookup (default: 1) + + + + + Sync checkpoints policy (default: strict) + + + + + Invalid -tor address: '%s' + + + + + Invalid amount for -reservebalance=<amount> + + + + + Maximum per-connection receive buffer, <n>*1000 bytes (default: 5000) + Maksymalny bufor odbioru na połączenie, <n>*1000 bajtów (domyślnie: 5000) + + + + Maximum per-connection send buffer, <n>*1000 bytes (default: 1000) + Maksymalny bufor wysyłu na połączenie, <n>*1000 bajtów (domyślnie: 1000) + + + + Only connect to nodes in network <net> (IPv4, IPv6 or Tor) + Łącz z węzłami tylko w sieci <net> (IPv4, IPv6 lub Tor) + + + + Output extra debugging information. Implies all other -debug* options + + + + + Output extra network debugging information + + + + + Prepend debug output with timestamp + + + + + SSL options: (see the Bitcoin Wiki for SSL setup instructions) + Opcje SSL: (odwiedź Bitcoin Wiki w celu uzyskania instrukcji) + + + + Select the version of socks proxy to use (4-5, default: 5) + + + + + Send trace/debug info to console instead of debug.log file + Wyślij informację/raport do konsoli zamiast do pliku debug.log. + + + + Send trace/debug info to debugger + + + + + Set maximum block size in bytes (default: 250000) + + + + + Set minimum block size in bytes (default: 0) + Ustaw minimalny rozmiar bloku w bajtach (domyślnie: 0) + + + + Shrink debug.log file on client startup (default: 1 when no -debug) + Zmniejsz plik debug.log przy starcie programu (domyślnie: 1 jeśli nie użyto -debug) + + + + Specify connection timeout in milliseconds (default: 5000) + Wskaż czas oczekiwania bezczynności połączenia w milisekundach (domyślnie: 5000) + + + + Unable to sign checkpoint, wrong checkpointkey? + + + + + + Use UPnP to map the listening port (default: 0) + Używaj UPnP do mapowania portu nasłuchu (domyślnie: 0) + + + + Use UPnP to map the listening port (default: 1 when listening) + Używaj UPnP do mapowania portu nasłuchu (domyślnie: 1 gdy nasłuchuje) + + + + Use proxy to reach tor hidden services (default: same as -proxy) + + + + + Username for JSON-RPC connections + Nazwa użytkownika dla połączeń JSON-RPC + + + + Verifying database integrity... + + + + + WARNING: syncronized checkpoint violation detected, but skipped! + + + + + Warning: Disk space is low! + + + + + Warning: This version is obsolete, upgrade required! + Uwaga: Ta wersja jest przestarzała, aktualizacja wymagana! + + + + wallet.dat corrupt, salvage failed + wallet.dat uszkodzony, odtworzenie się nie powiodło + + + + Password for JSON-RPC connections + Hasło do połączeń JSON-RPC + + + + %s, you must set a rpcpassword in the configuration file: + %s +It is recommended you use the following random password: +rpcuser=arepacoinrpc +rpcpassword=%s +(you do not need to remember this password) +The username and password MUST NOT be the same. +If the file does not exist, create it with owner-readable-only file permissions. +It is also recommended to set alertnotify so you are notified of problems; +for example: alertnotify=echo %%s | mail -s "Arepacoin Alert" admin@foo.com + + + + + + Find peers using internet relay chat (default: 0) + + + + + Sync time with other nodes. Disable if time on your system is precise e.g. syncing with NTP (default: 1) + + + + + When creating transactions, ignore inputs with value less than this (default: 0.01) + + + + + Allow JSON-RPC connections from specified IP address + Przyjmuj połączenia JSON-RPC ze wskazanego adresu IP + + + + Send commands to node running on <ip> (default: 127.0.0.1) + Wysyłaj polecenia do węzła działającego na <ip> (domyślnie: 127.0.0.1) + + + + Execute command when the best block changes (%s in cmd is replaced by block hash) + Wykonaj polecenie kiedy najlepszy blok ulegnie zmianie (%s w komendzie zastanie zastąpione przez hash bloku) + + + + Execute command when a wallet transaction changes (%s in cmd is replaced by TxID) + Wykonaj polecenie, kiedy transakcja portfela ulegnie zmianie (%s w poleceniu zostanie zastąpione przez TxID) + + + + Require a confirmations for change (default: 0) + + + + + Enforce transaction scripts to use canonical PUSH operators (default: 1) + + + + + Execute command when a relevant alert is received (%s in cmd is replaced by message) + + + + + Upgrade wallet to latest format + Zaktualizuj portfel do najnowszego formatu. + + + + Set key pool size to <n> (default: 100) + Ustaw rozmiar puli kluczy na <n> (domyślnie: 100) + + + + Rescan the block chain for missing wallet transactions + Przeskanuj blok łańcuchów żeby znaleźć zaginione transakcje portfela + + + + How many blocks to check at startup (default: 2500, 0 = all) + + + + + How thorough the block verification is (0-6, default: 1) + + + + + Imports blocks from external blk000?.dat file + + + + + Use OpenSSL (https) for JSON-RPC connections + Użyj OpenSSL (https) do połączeń JSON-RPC + + + + Server certificate file (default: server.cert) + Plik certyfikatu serwera (domyślnie: server.cert) + + + + Server private key (default: server.pem) + Klucz prywatny serwera (domyślnie: server.pem) + + + + Acceptable ciphers (default: TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH) + + + + + Error: Wallet unlocked for staking only, unable to create transaction. + + + + + WARNING: Invalid checkpoint found! Displayed transactions may not be correct! You may need to upgrade, or notify developers. + + + + + This help message + Ta wiadomość pomocy + + + + Wallet %s resides outside data directory %s. + + + + + Cannot obtain a lock on data directory %s. Arepacoin is probably already running. + + + + + Arepacoin + + + + + Unable to bind to %s on this computer (bind returned error %d, %s) + Nie można przywiązać %s na tym komputerze (bind returned error %d, %s) + + + + Connect through socks proxy + + + + + Allow DNS lookups for -addnode, -seednode and -connect + Zezwól -addnode, -seednode i -connect na łączenie się z serwerem DNS + + + + Loading addresses... + Wczytywanie adresów... + + + + Error loading blkindex.dat + + + + + Error loading wallet.dat: Wallet corrupted + Błąd ładowania wallet.dat: Uszkodzony portfel + + + + Error loading wallet.dat: Wallet requires newer version of Arepacoin + + + + + Wallet needed to be rewritten: restart Arepacoin to complete + + + + + Error loading wallet.dat + Błąd ładowania wallet.dat + + + + Invalid -proxy address: '%s' + Nieprawidłowy adres -proxy: '%s' + + + + Unknown network specified in -onlynet: '%s' + Nieznana sieć w -onlynet: '%s' + + + + Unknown -socks proxy version requested: %i + Nieznana wersja proxy w -socks: %i + + + + Cannot resolve -bind address: '%s' + Nie można uzyskać adresu -bind: '%s' + + + + Cannot resolve -externalip address: '%s' + Nie można uzyskać adresu -externalip: '%s' + + + + Invalid amount for -paytxfee=<amount>: '%s' + Nieprawidłowa kwota dla -paytxfee=<amount>: '%s' + + + + Error: could not start node + + + + + Sending... + + + + + Invalid amount + Nieprawidłowa kwota + + + + Insufficient funds + Niewystarczające środki + + + + Loading block index... + Ładowanie indeksu bloku... + + + + Add a node to connect to and attempt to keep the connection open + Dodaj węzeł do łączenia się and attempt to keep the connection open + + + + Unable to bind to %s on this computer. Arepacoin is probably already running. + + + + + Fee per KB to add to transactions you send + + + + + Invalid amount for -mininput=<amount>: '%s' + + + + + Loading wallet... + Wczytywanie portfela... + + + + Cannot downgrade wallet + Nie można dezaktualizować portfela + + + + Cannot initialize keypool + + + + + Cannot write default address + Nie można zapisać domyślnego adresu + + + + Rescanning... + Ponowne skanowanie... + + + + Done loading + Wczytywanie zakończone + + + + To use the %s option + Aby użyć opcji %s + + + + Error + Błąd + + + + You must set rpcpassword=<password> in the configuration file: +%s +If the file does not exist, create it with owner-readable-only file permissions. + Musisz ustawić rpcpassword=<hasło> w pliku configuracyjnym: +%s +Jeżeli plik nie istnieje, utwórz go z uprawnieniami właściciela-tylko-do-odczytu. + + + \ No newline at end of file diff --git a/src/qt/locale/bitcoin_pt_BR.ts b/src/qt/locale/bitcoin_pt_BR.ts new file mode 100755 index 0000000..9e7d526 --- /dev/null +++ b/src/qt/locale/bitcoin_pt_BR.ts @@ -0,0 +1,3285 @@ + + + AboutDialog + + + About Arepacoin + Sobre o Arepacoin + + + + <b>Arepacoin</b> version + <b>Arepacoin</b> versao + + + + Copyright © 2009-2014 The Bitcoin developers +Copyright © 2012-2014 The NovaCoin developers +Copyright © 2014 The Arepacoin developers + + + + + +This is experimental software. + +Distributed under the MIT/X11 software license, see the accompanying file COPYING or http://www.opensource.org/licenses/mit-license.php. + +This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit (http://www.openssl.org/) and cryptographic software written by Eric Young (eay@cryptsoft.com) and UPnP software written by Thomas Bernard. + ⏎ +Este é um software experimental.⏎ +⏎ +Distribuido sob a licença de software MIT/X11, veja o arquivo anexo COPYING ou http://www.opensource.org/licenses/mit-license.php.⏎ +⏎ +Este produto inclui software desenvolvido pelo Projeto OpenSSL para uso no OpenSSL Toolkit (http://www.openssl.org/), software de criptografia escrito por Eric Young (eay@cryptsoft.com) e sofware UPnP escrito por Thomas Bernard. + + + + AddressBookPage + + + Address Book + Livro de Endereços + + + + Double-click to edit address or label + Clique duas vezes para editar o endereço ou a etiqueta + + + + Create a new address + Criar um novo endereço + + + + Copy the currently selected address to the system clipboard + Copie o endereço selecionado para a área de transferência do sistema + + + + &New Address + &Novo Endereço + + + + These are your Arepacoin addresses for receiving payments. You may want to give a different one to each sender so you can keep track of who is paying you. + Estes são os seus endereços Arepacoin para receber pagamentos. Você pode dar um diferente a cada remetente para que você possa acompanhar quem está pagando. + + + + &Copy Address + &Copiar Endereço + + + + Show &QR Code + Mostrar &QR Code + + + + Sign a message to prove you own a Arepacoin address + Assine a mensagem para provar que você possui um endereço Arepacoin + + + + Sign &Message + Assinar &Mensagem + + + + Delete the currently selected address from the list + Excluir os endereços selecionados da lista + + + + Verify a message to ensure it was signed with a specified Arepacoin address + Verifique a mensagem para garantir que ela foi assinada com um endereço Arepacoin específico + + + + &Verify Message + &Verificar Mensagem + + + + &Delete + &Excluir + + + + Copy &Label + Copiar &Etiqueta + + + + &Edit + &Editar + + + + Export Address Book Data + Exportar Dados do Livro de Endereços + + + + Comma separated file (*.csv) + Arquivo separado por vírgulas (*. csv) + + + + Error exporting + Erro ao exportar + + + + Could not write to file %1. + Não foi possível escrever no arquivo %1. + + + + AddressTableModel + + + Label + Rótulo + + + + Address + Endereço + + + + (no label) + (Sem rótulo) + + + + AskPassphraseDialog + + + Passphrase Dialog + Janela da Frase de Segurança + + + + Enter passphrase + Digite a frase de segurança + + + + New passphrase + Nova frase de segurança + + + + Repeat new passphrase + Repita a nova frase de segurança + + + + Serves to disable the trivial sendmoney when OS account compromised. Provides no real security. + Serve para desativar o envio de dinheiro trivial quando conta do SO for comprometida. Não oferece segurança real. + + + + For staking only + Apenas para participação + + + + Enter the new passphrase to the wallet.<br/>Please use a passphrase of <b>10 or more random characters</b>, or <b>eight or more words</b>. + Digite a nova frase de seguraça da sua carteira. <br/> Por favor, use uma frase de <b>10 ou mais caracteres aleatórios,</b> ou <b>oito ou mais palavras.</b> + + + + Encrypt wallet + Criptografar carteira + + + + This operation needs your wallet passphrase to unlock the wallet. + Esta operação precisa de sua frase de segurança para desbloquear a carteira. + + + + Unlock wallet + Desbloquear carteira + + + + This operation needs your wallet passphrase to decrypt the wallet. + Esta operação precisa de sua frase de segurança para descriptografar a carteira. + + + + Decrypt wallet + Descriptografar carteira + + + + Change passphrase + Alterar frase de segurança + + + + Enter the old and new passphrase to the wallet. + Digite a frase de segurança antiga e nova para a carteira. + + + + Confirm wallet encryption + Confirmar criptografia da carteira + + + + Warning: If you encrypt your wallet and lose your passphrase, you will <b>LOSE ALL OF YOUR COINS</b>! + Aviso: Se você criptografar sua carteira e perder sua senha, você vai <b>PERDER TODAS AS SUAS MOEDAS</ b>! + + + + Are you sure you wish to encrypt your wallet? + Tem certeza de que deseja criptografar sua carteira? + + + + IMPORTANT: Any previous backups you have made of your wallet file should be replaced with the newly generated, encrypted wallet file. For security reasons, previous backups of the unencrypted wallet file will become useless as soon as you start using the new, encrypted wallet. + IMPORTANTE: Qualquer backup prévio que você tenha feito do seu arquivo wallet deve ser substituído pelo novo e encriptado arquivo wallet gerado. Por razões de segurança, qualquer backup do arquivo wallet não criptografado se tornará inútil assim que você começar a usar uma nova carteira criptografada. + + + + + Warning: The Caps Lock key is on! + Cuidado: A tecla Caps Lock está ligada! + + + + + Wallet encrypted + Carteira criptografada + + + + Arepacoin will close now to finish the encryption process. Remember that encrypting your wallet cannot fully protect your coins from being stolen by malware infecting your computer. + Arepacoin vai fechar agora para concluir o processo de criptografia. Lembre-se que a criptografia de sua carteira não pode proteger totalmente suas moedas de serem roubados por malwares infectem seu computador. + + + + + + + Wallet encryption failed + A criptografia da carteira falhou + + + + Wallet encryption failed due to an internal error. Your wallet was not encrypted. + A criptografia da carteira falhou devido a um erro interno. Sua carteira não estava criptografada. + + + + + The supplied passphrases do not match. + A frase de segurança fornecida não confere. + + + + Wallet unlock failed + A abertura da carteira falhou + + + + + + The passphrase entered for the wallet decryption was incorrect. + A frase de segurança digitada para a descriptografia da carteira estava incorreta. + + + + Wallet decryption failed + A descriptografia da carteira falhou + + + + Wallet passphrase was successfully changed. + A frase de segurança da carteira foi alterada com êxito. + + + + BitcoinGUI + + + Sign &message... + &Assinar Mensagem... + + + + Synchronizing with network... + Sincronizando com a rede... + + + + &Overview + &Visão geral + + + + Show general overview of wallet + Mostrar visão geral da carteira + + + + &Transactions + &Transações + + + + Browse transaction history + Navegar pelo histórico de transações + + + + &Address Book + &Livro de Endereços + + + + Edit the list of stored addresses and labels + Edite a lista de endereços armazenados e rótulos + + + + &Receive coins + &Receber moedas + + + + Show the list of addresses for receiving payments + Mostrar a lista de endereços para o recebimento de pagamentos + + + + &Send coins + &Enviar moedas + + + + E&xit + S&air + + + + Quit application + Sair da aplicação + + + + Show information about Arepacoin + Mostrar informações sobre o Arepacoin + + + + About &Qt + Sobre &Qt + + + + Show information about Qt + Mostrar informações sobre o Qt + + + + &Options... + &Opções... + + + + &Encrypt Wallet... + &Criptografar Carteira... + + + + &Backup Wallet... + &Backup Carteira... + + + + &Change Passphrase... + &Mudar frase de segurança... + + + + ~%n block(s) remaining + ~%n bloco faltando~%n blocos faltando + + + + Downloaded %1 of %2 blocks of transaction history (%3% done). + Baixados %1 de %2 blocos de histórico de transações (%3% completo). + + + + &Export... + &Exportar... + + + + Send coins to a Arepacoin address + Enviar moedas para um endereço Arepacoin + + + + Modify configuration options for Arepacoin + Modificar opções de configuração para Arepacoin + + + + Export the data in the current tab to a file + Exportar os dados da guia atual para um arquivo + + + + Encrypt or decrypt wallet + Cryptografar ou Decryptografar carteira + + + + Backup wallet to another location + Fazer cópia de segurança da carteira para uma outra localização + + + + Change the passphrase used for wallet encryption + Mudar a frase de segurança utilizada na criptografia da carteira + + + + &Debug window + Janela de &Depuração + + + + Open debugging and diagnostic console + Abrir console de depuração e diagnóstico + + + + &Verify message... + &Verificar mensagem... + + + + Arepacoin + Arepacoin + + + + Wallet + Carteira + + + + &About Arepacoin + Sobre o Arepacoin + + + + &Show / Hide + &Exibir/Ocultar + + + + Unlock wallet + Desbloquear carteira + + + + &Lock Wallet + &Bloquear Carteira + + + + Lock wallet + Bloquear Carteira + + + + &File + &Arquivo + + + + &Settings + &Configurações + + + + &Help + &Ajuda + + + + Tabs toolbar + Barra de ferramentas + + + + Actions toolbar + + + + + + [testnet] + [testnet] + + + + + Arepacoin client + + + + + %n active connection(s) to Arepacoin network + + + + + Downloaded %1 blocks of transaction history. + + + + + Staking.<br>Your weight is %1<br>Network weight is %2<br>Expected time to earn reward is %3 + + + + + Not staking because wallet is locked + + + + + Not staking because wallet is offline + + + + + Not staking because wallet is syncing + + + + + Not staking because you don't have mature coins + + + + + %n second(s) ago + + + + + &Unlock Wallet... + + + + + %n minute(s) ago + + + + + %n hour(s) ago + + + + + %n day(s) ago + + + + + Up to date + Atualizado + + + + Catching up... + Recuperando o atraso ... + + + + Last received block was generated %1. + + + + + This transaction is over the size limit. You can still send it for a fee of %1, which goes to the nodes that process your transaction and helps to support the network. Do you want to pay the fee? + + + + + Confirm transaction fee + + + + + Sent transaction + Transação enviada + + + + Incoming transaction + Transação recebida + + + + Date: %1 +Amount: %2 +Type: %3 +Address: %4 + + Data: %1 +Quantidade: %2 +Tipo: %3 +Endereço: %4 + + + + + URI handling + + + + + + URI can not be parsed! This can be caused by an invalid Arepacoin address or malformed URI parameters. + + + + + Wallet is <b>encrypted</b> and currently <b>unlocked</b> + Carteira está <b>criptografada</b> e atualmente <b>desbloqueada</b> + + + + Wallet is <b>encrypted</b> and currently <b>locked</b> + Carteira está <b>criptografada</b> e atualmente <b>bloqueada</b> + + + + Backup Wallet + + + + + Wallet Data (*.dat) + + + + + Backup Failed + + + + + There was an error trying to save the wallet data to the new location. + + + + + %n second(s) + + + + + %n minute(s) + + + + + %n hour(s) + %n hora%n horas + + + + %n day(s) + %n dia%n dias + + + + Not staking + + + + + A fatal error occurred. Arepacoin can no longer continue safely and will quit. + + + + + ClientModel + + + Network Alert + Alerta da Rede + + + + CoinControlDialog + + + Coin Control + + + + + Quantity: + Quantidade: + + + + Bytes: + Bytes: + + + + Amount: + Quantia: + + + + Priority: + Prioridade: + + + + Fee: + Taxa: + + + + Low Output: + Rendimento baixo: + + + + no + não + + + + After Fee: + Depois da taxa: + + + + Change: + trocar + + + + (un)select all + (de)selecionar tudo + + + + Tree mode + Modo árvore + + + + List mode + Modo lista + + + + Amount + Quantidade + + + + Label + + + + + Address + Endereço + + + + Date + Data + + + + Confirmations + Confirmações + + + + Confirmed + Confirmado + + + + Priority + Prioridade + + + + Copy address + Copiar endereço + + + + Copy label + Copiar etiqueta + + + + + Copy amount + Copiar quantia + + + + Copy transaction ID + Copiar ID da transação + + + + Copy quantity + Copiar quantidade + + + + Copy fee + Copiar taxa + + + + Copy after fee + Copia pós-taxa + + + + Copy bytes + Copiar bytes + + + + Copy priority + Copia prioridade + + + + Copy low output + Copia saída de pouco valor + + + + Copy change + Copia alteração + + + + highest + mais alta possível + + + + high + alta + + + + medium-high + média-alta + + + + medium + média + + + + low-medium + média-baixa + + + + low + baixa + + + + lowest + a mais baixa possível + + + + DUST + + + + + yes + sim + + + + This label turns red, if the transaction size is bigger than 10000 bytes. + + This means a fee of at least %1 per kb is required. + + Can vary +/- 1 Byte per input. + + + + + Transactions with higher priority get more likely into a block. + +This label turns red, if the priority is smaller than "medium". + + This means a fee of at least %1 per kb is required. + + + + + This label turns red, if any recipient receives an amount smaller than %1. + + This means a fee of at least %2 is required. + + Amounts below 0.546 times the minimum relay fee are shown as DUST. + + + + + This label turns red, if the change is smaller than %1. + + This means a fee of at least %2 is required. + + + + + + (no label) + (Sem rótulo) + + + + change from %1 (%2) + troco de %1 (%2) + + + + (change) + (troco) + + + + EditAddressDialog + + + Edit Address + Editar Endereço + + + + &Label + &Etiqueta + + + + The label associated with this address book entry + + + + + &Address + &Endereço + + + + The address associated with this address book entry. This can only be modified for sending addresses. + + + + + New receiving address + Novo endereço de recebimento + + + + New sending address + Novo endereço de envio + + + + Edit receiving address + Editar endereço de recebimento + + + + Edit sending address + Editar endereço de envio + + + + The entered address "%1" is already in the address book. + O endereço digitado "%1" já se encontra no catálogo de endereços. + + + + The entered address "%1" is not a valid Arepacoin address. + + + + + Could not unlock wallet. + Não foi possível destravar a carteira. + + + + New key generation failed. + A geração de nova chave falhou. + + + + GUIUtil::HelpMessageBox + + + + Arepacoin-Qt + + + + + version + + + + + Usage: + + + + + command-line options + + + + + UI options + + + + + Set language, for example "de_DE" (default: system locale) + + + + + Start minimized + + + + + Show splash screen on startup (default: 1) + + + + + OptionsDialog + + + Options + Opções + + + + &Main + Principal + + + + Optional transaction fee per kB that helps make sure your transactions are processed quickly. Most transactions are 1 kB. Fee 0.01 recommended. + + + + + Pay transaction &fee + Pagar taxa de &transação + + + + Reserved amount does not participate in staking and is therefore spendable at any time. + + + + + Reserve + + + + + Automatically start Arepacoin after logging in to the system. + + + + + &Start Arepacoin on system login + + + + + Detach block and address databases at shutdown. This means they can be moved to another data directory, but it slows down shutdown. The wallet is always detached. + + + + + &Detach databases at shutdown + + + + + &Network + Rede + + + + Automatically open the Arepacoin client port on the router. This only works when your router supports UPnP and it is enabled. + + + + + Map port using &UPnP + Mapear porta usando &UPnP + + + + Connect to the Arepacoin network through a SOCKS proxy (e.g. when connecting through Tor). + + + + + &Connect through SOCKS proxy: + + + + + Proxy &IP: + &IP do proxy: + + + + IP address of the proxy (e.g. 127.0.0.1) + + + + + &Port: + &Porta: + + + + Port of the proxy (e.g. 9050) + Porta do serviço de proxy (ex. 9050) + + + + SOCKS &Version: + &Versão do SOCKS: + + + + SOCKS version of the proxy (e.g. 5) + Versão do proxy SOCKS (ex. 5) + + + + &Window + &Janela + + + + Show only a tray icon after minimizing the window. + Mostrar apenas um ícone na bandeja ao minimizar a janela. + + + + &Minimize to the tray instead of the taskbar + &Minimizar para a bandeja em vez da barra de tarefas. + + + + Minimize instead of exit the application when the window is closed. When this option is enabled, the application will be closed only after selecting Quit in the menu. + Minimizar em vez de sair do aplicativo quando a janela for fechada. Quando esta opção é escolhida, o aplicativo só será fechado selecionando Sair no menu Arquivo. + + + + M&inimize on close + M&inimizar ao sair + + + + &Display + &Mostrar + + + + User Interface &language: + &Língua da interface com usuário: + + + + The user interface language can be set here. This setting will take effect after restarting Arepacoin. + + + + + &Unit to show amounts in: + &Unidade usada para mostrar quantidades: + + + + Choose the default subdivision unit to show in the interface and when sending coins. + Escolha a unidade padrão de subdivisão para interface mostrar quando enviar bitcoins. + + + + Whether to show Arepacoin addresses in the transaction list or not. + + + + + &Display addresses in transaction list + Mostrar en&dereços na lista de transações + + + + Whether to show coin control features or not. + Mostrar ou não opções de controle da moeda. + + + + Display coin &control features (experts only!) + + + + + &OK + &OK + + + + &Cancel + &Cancelar + + + + &Apply + + + + + default + padrão + + + + + Warning + + + + + + This setting will take effect after restarting Arepacoin. + + + + + The supplied proxy address is invalid. + O endereço proxy fornecido é inválido. + + + + OverviewPage + + + Form + Formulário + + + + + The displayed information may be out of date. Your wallet automatically synchronizes with the Arepacoin network after a connection is established, but this process has not completed yet. + + + + + Stake: + + + + + Unconfirmed: + + + + + Wallet + Carteira + + + + Spendable: + + + + + Your current spendable balance + Seu saldo atual spendable + + + + Immature: + Imaturo: + + + + Mined balance that has not yet matured + Saldo minerado que ainda não maturou + + + + Total: + Total: + + + + Your current total balance + Seu saldo total atual + + + + <b>Recent transactions</b> + <b>Transações recentes</b> + + + + Total of transactions that have yet to be confirmed, and do not yet count toward the current balance + + + + + Total of coins that was staked, and do not yet count toward the current balance + + + + + + out of sync + fora de sincronia + + + + QRCodeDialog + + + QR Code Dialog + + + + + Request Payment + + + + + Amount: + + + + + Label: + + + + + Message: + + + + + &Save As... + + + + + Error encoding URI into QR Code. + + + + + The entered amount is invalid, please check. + + + + + Resulting URI too long, try to reduce the text for label / message. + + + + + Save QR Code + + + + + PNG Images (*.png) + + + + + RPCConsole + + + Client name + Nome do cliente + + + + + + + + + + + + + N/A + N/A + + + + Client version + Versão do cliente + + + + &Information + &Informação + + + + Using OpenSSL version + Usando OpenSSL versão + + + + Startup time + Horário de inicialização + + + + Network + Rede + + + + Number of connections + Número de conexões + + + + On testnet + + + + + Block chain + Corrente de blocos + + + + Current number of blocks + Quantidade atual de blocos + + + + Estimated total blocks + Total estimado de blocos + + + + Last block time + Horário do último bloco + + + + &Open + &Abrir + + + + Command-line options + + + + + Show the Arepacoin-Qt help message to get a list with possible Arepacoin command-line options. + + + + + &Show + + + + + &Console + &Console + + + + Build date + Data do 'build' + + + + Arepacoin - Debug window + + + + + Arepacoin Core + + + + + Debug log file + Arquivo de log de Depuração + + + + Open the Arepacoin debug log file from the current data directory. This can take a few seconds for large log files. + + + + + Clear console + Limpar console + + + + Welcome to the Arepacoin RPC console. + + + + + Use up and down arrows to navigate history, and <b>Ctrl-L</b> to clear screen. + Use as setas para cima e para baixo para navegar pelo histórico, e <b>Ctrl-L</b> para limpar a tela. + + + + Type <b>help</b> for an overview of available commands. + Digite <b>help</b> para uma visão geral dos comandos disponíveis. + + + + SendCoinsDialog + + + + + + + + + + Send Coins + Enviar dinheiro + + + + Coin Control Features + Opções de Controle da Moeda + + + + Inputs... + Entradas... + + + + automatically selected + automaticamente selecionado + + + + Insufficient funds! + Saldo insuficiente! + + + + Quantity: + Quantidade: + + + + + 0 + + + + + Bytes: + Bytes: + + + + Amount: + Quantia: + + + + + + + 0.00 BC + + + + + Priority: + Prioridade: + + + + medium + + + + + Fee: + Taxa: + + + + Low Output: + Rendimento baixo: + + + + no + + + + + After Fee: + Depois da taxa: + + + + Change + + + + + custom change address + + + + + Send to multiple recipients at once + Enviar para vários destinatários de uma só vez + + + + Add &Recipient + Adicionar destinatário + + + + Remove all transaction fields + + + + + Clear &All + Limpar Tudo + + + + Balance: + Saldo: + + + + 123.456 BC + + + + + Confirm the send action + Confirmar o envio + + + + S&end + Enviar + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Copy quantity + Copiar quantidade + + + + Copy amount + Copiar quantia + + + + Copy fee + Copiar taxa + + + + Copy after fee + Copia pós-taxa + + + + Copy bytes + Copiar bytes + + + + Copy priority + Copia prioridade + + + + Copy low output + Copia saída de pouco valor + + + + Copy change + Copia alteração + + + + <b>%1</b> to %2 (%3) + + + + + Confirm send coins + Confirmar envio de dinheiro + + + + Are you sure you want to send %1? + + + + + and + + + + + The recipient address is not valid, please recheck. + O endereço do destinatário não é válido, favor verificar. + + + + The amount to pay must be larger than 0. + A quantidade a ser paga precisa ser maior que 0. + + + + The amount exceeds your balance. + A quantidade excede seu saldo. + + + + The total exceeds your balance when the %1 transaction fee is included. + O total excede seu saldo quando uma taxa de transação de %1 é incluída. + + + + Duplicate address found, can only send to each address once per send operation. + Endereço duplicado: pode-se enviar para cada endereço apenas uma vez por transação. + + + + Error: Transaction creation failed. + + + + + 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. + + + + + WARNING: Invalid Arepacoin address + + + + + (no label) + (Sem rótulo) + + + + WARNING: unknown change address + + + + + SendCoinsEntry + + + Form + + + + + A&mount: + Q&uantidade: + + + + Pay &To: + Pagar &Para: + + + + + Enter a label for this address to add it to your address book + Digite uma etiqueta para este endereço para adicioná-lo ao catálogo de endereços + + + + &Label: + &Etiqueta: + + + + The address to send the payment to (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Choose address from address book + + + + + Alt+A + Alt+A + + + + Paste address from clipboard + Colar o endereço da área de transferência + + + + Alt+P + Alt+P + + + + Remove this recipient + + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + SignVerifyMessageDialog + + + Signatures - Sign / Verify a Message + Assinaturas - Assinar / Verificar uma mensagem + + + + + &Sign Message + &Assinar Mensagem + + + + You can sign messages with your addresses to prove you own them. Be careful not to sign anything vague, as phishing attacks may try to trick you into signing your identity over to them. Only sign fully-detailed statements you agree to. + Você pode assinar mensagens com seus endereços para provar que você é o dono deles. Seja cuidadoso para não assinar algo vago, pois ataques de pishing podem tentar te enganar para dar sua assinatura de identidade para eles. Apenas assine afirmações completamente detalhadas com as quais você concorda. + + + + The address to sign the message with (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + + Choose an address from the address book + + + + + + Alt+A + Alt+A + + + + Paste address from clipboard + Colar o endereço da área de transferência + + + + Alt+P + Alt+P + + + + Enter the message you want to sign here + Entre a mensagem que você quer assinar aqui + + + + Copy the current signature to the system clipboard + Copiar a assinatura para a área de transferência do sistema + + + + Sign the message to prove you own this Arepacoin address + + + + + Reset all sign message fields + Limpar todos os campos de assinatura da mensagem + + + + + Clear &All + Limpar Tudo + + + + + &Verify Message + &Verificar Mensagem + + + + Enter the signing address, message (ensure you copy line breaks, spaces, tabs, etc. exactly) and signature below to verify the message. Be careful not to read more into the signature than what is in the signed message itself, to avoid being tricked by a man-in-the-middle attack. + Forneça o endereço da assinatura, a mensagem (se assegure que você copiou quebras de linha, espaços, tabs, etc. exatamente) e a assinatura abaixo para verificar a mensagem. Cuidado para não ler mais na assinatura do que está escrito na mensagem propriamente, para evitar ser vítima de uma ataque do tipo "man-in-the-middle". + + + + The address the message was signed with (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Verify the message to ensure it was signed with the specified Arepacoin address + + + + + Reset all verify message fields + Limpar todos os campos de assinatura da mensagem + + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Click "Sign Message" to generate signature + Clique em "Assinar Mensagem" para gerar a assinatura + + + + Enter Arepacoin signature + + + + + + The entered address is invalid. + O endereço fornecido é inválido. + + + + + + + Please check the address and try again. + Por favor, verifique o endereço e tente novamente. + + + + + The entered address does not refer to a key. + O endereço fornecido não se refere a uma chave. + + + + Wallet unlock was cancelled. + Destravamento da Carteira foi cancelado. + + + + Private key for the entered address is not available. + A chave privada para o endereço fornecido não está disponível. + + + + Message signing failed. + Assinatura da mensagem falhou. + + + + Message signed. + Mensagem assinada. + + + + The signature could not be decoded. + A assinatura não pode ser decodificada. + + + + + Please check the signature and try again. + Por favor, verifique a assinatura e tente novamente. + + + + The signature did not match the message digest. + A assinatura não corresponde ao "resumo da mensagem". + + + + Message verification failed. + Verificação da mensagem falhou. + + + + Message verified. + Mensagem verificada. + + + + TransactionDesc + + + Open until %1 + Aberto até %1 + + + + Open for %n block(s) + + + + + conflicted + em conflito + + + + %1/offline + %1/offline + + + + %1/unconfirmed + %1/não confirmadas + + + + %1 confirmations + %1 confirmações + + + + Status + Status + + + + , broadcast through %n node(s) + , difundir atráves de %n nó, difundir atráves de %n nós + + + + Date + Data + + + + Source + Fonte + + + + Generated + Gerados + + + + + From + De + + + + + + To + Para + + + + + own address + seu próprio endereço + + + + label + etiqueta + + + + + + + + Credit + Crédito + + + + matures in %n more block(s) + matura em mais %n blocomatura em mais %n blocos + + + + not accepted + não aceito + + + + + + + Debit + Débito + + + + Transaction fee + Taxa de transação + + + + Net amount + Valor líquido + + + + Message + Mensagem + + + + Comment + Comentário + + + + Transaction ID + ID da transação + + + + Generated coins must mature 6 blocks before they can be spent. When you generated this block, it was broadcast to the network to be added to the block chain. If it fails to get into the chain, its state will change to "not accepted" and it won't be spendable. This may occasionally happen if another node generates a block within a few seconds of yours. + + + + + Debug information + Informação de depuração + + + + Transaction + Transação + + + + Inputs + Entradas + + + + Amount + Quantidade + + + + true + verdadeiro + + + + false + falso + + + + , has not been successfully broadcast yet + , ainda não foi propagada na rede com sucesso. + + + + unknown + desconhecido + + + + TransactionDescDialog + + + Transaction details + Detalhes da transação + + + + This pane shows a detailed description of the transaction + Este painel mostra uma descrição detalhada da transação + + + + TransactionTableModel + + + Date + Data + + + + Type + Tipo + + + + Address + Endereço + + + + Amount + Quantidade + + + + Open until %1 + Aberto até %1 + + + + Confirmed (%1 confirmations) + Confirmado (%1 confirmações) + + + + Open for %n more block(s) + Abrir para mais %n blocoAbrir para mais %n blocos + + + + Offline + Offline + + + + Unconfirmed + Não confirmado + + + + Confirming (%1 of %2 recommended confirmations) + Confirmando (%1 de %2 confirmações recomendadas) + + + + Conflicted + Conflitou + + + + Immature (%1 confirmations, will be available after %2) + Recém-criado (%1 confirmações, disponível somente após %2) + + + + This block was not received by any other nodes and will probably not be accepted! + Este bloco não foi recebido por nenhum outro participante da rede e provavelmente não será aceito! + + + + Generated but not accepted + Gerado mas não aceito + + + + Received with + Recebido por + + + + Received from + Recebido de + + + + Sent to + Enviado para + + + + Payment to yourself + Pagamento para você mesmo + + + + Mined + Minerado + + + + (n/a) + (n/a) + + + + Transaction status. Hover over this field to show number of confirmations. + Status da transação. Passe o mouse sobre este campo para mostrar o número de confirmações. + + + + Date and time that the transaction was received. + Data e hora em que a transação foi recebida. + + + + Type of transaction. + Tipo de transação. + + + + Destination address of transaction. + Endereço de destino da transação. + + + + Amount removed from or added to balance. + Quantidade debitada ou creditada ao saldo. + + + + TransactionView + + + + All + Todos + + + + Today + Hoje + + + + This week + Esta semana + + + + This month + Este mês + + + + Last month + Mês passado + + + + This year + Este ano + + + + Range... + Intervalo... + + + + Received with + Recebido por + + + + Sent to + Enviado para + + + + To yourself + Para você mesmo + + + + Mined + Minerado + + + + Other + Outro + + + + Enter address or label to search + Procure um endereço ou etiqueta + + + + Min amount + Quantidade mínima + + + + Copy address + Copiar endereço + + + + Copy label + Copiar etiqueta + + + + Copy amount + Copiar quantia + + + + Copy transaction ID + Copiar ID da transação + + + + Edit label + Editar etiqueta + + + + Show transaction details + Mostrar detalhes da transação + + + + Export Transaction Data + + + + + Comma separated file (*.csv) + Arquivo separado por vírgulas (*. csv) + + + + Confirmed + Confirmado + + + + Date + Data + + + + Type + Tipo + + + + Label + Etiqueta + + + + Address + Endereço + + + + Amount + Quantidade + + + + ID + ID + + + + Error exporting + + + + + Could not write to file %1. + + + + + Range: + Intervalo: + + + + to + para + + + + WalletModel + + + Sending... + + + + + bitcoin-core + + + Arepacoin version + + + + + Usage: + Uso: + + + + Send command to -server or arepacoind + + + + + List commands + Lista de comandos + + + + Get help for a command + Obtenha ajuda sobre um comando + + + + Options: + Opções: + + + + Specify configuration file (default: arepacoin.conf) + + + + + Specify pid file (default: arepacoind.pid) + + + + + Specify wallet file (within data directory) + Especifique o arquivo da carteira (dentro do diretório de dados) + + + + Specify data directory + Especificar diretório de dados + + + + Set database cache size in megabytes (default: 25) + Definir o tamanho do cache do banco de dados em megabytes (padrão: 25) + + + + Set database disk log size in megabytes (default: 100) + + + + + Listen for connections on <port> (default: 9853 or testnet: 19853) + + + + + Maintain at most <n> connections to peers (default: 125) + Manter no máximo <n> conexões aos peers (padrão: 125) + + + + Connect to a node to retrieve peer addresses, and disconnect + Conectar a um nó para receber endereços de participantes, e desconectar. + + + + Specify your own public address + Especificar seu próprio endereço público + + + + Bind to given address. Use [host]:port notation for IPv6 + + + + + Stake your coins to support network and gain reward (default: 1) + + + + + Threshold for disconnecting misbehaving peers (default: 100) + Limite para desconectar peers mal comportados (padrão: 100) + + + + Number of seconds to keep misbehaving peers from reconnecting (default: 86400) + Número de segundos para impedir que peers mal comportados reconectem (padrão: 86400) + + + + An error occurred while setting up the RPC port %u for listening on IPv4: %s + Um erro ocorreu ao configurar a porta RPC %u para escuta em IPv4: %s + + + + Detach block and address databases. Increases shutdown time (default: 0) + + + + + 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. + + + + + Error: This transaction requires a transaction fee of at least %s because of its amount, complexity, or use of recently received funds + + + + + Listen for JSON-RPC connections on <port> (default: 9852 or testnet: 19852) + + + + + Accept command line and JSON-RPC commands + Aceitar linha de comando e comandos JSON-RPC + + + + Error: Transaction creation failed + + + + + Error: Wallet locked, unable to create transaction + + + + + Importing blockchain data file. + + + + + Importing bootstrap blockchain data file. + + + + + Run in the background as a daemon and accept commands + Rodar em segundo plano como serviço e aceitar comandos + + + + Use the test network + Usar rede de teste + + + + Accept connections from outside (default: 1 if no -proxy or -connect) + Aceitar conexões externas (padrão: 1 se opções -proxy ou -connect não estiverem presentes) + + + + An error occurred while setting up the RPC port %u for listening on IPv6, falling back to IPv4: %s + Um erro ocorreu ao configurar a porta RPC %u para escuta em IPv6, voltando ao IPv4: %s + + + + Error initializing database environment %s! To recover, BACKUP THAT DIRECTORY, then remove everything from it except for wallet.dat. + + + + + Set maximum size of high-priority/low-fee transactions in bytes (default: 27000) + + + + + Warning: -paytxfee is set very high! This is the transaction fee you will pay if you send a transaction. + Cuidado: valor de -paytxfee escolhido é muito alto! Este é o valor da taxa de transação que você irá pagar se enviar a transação. + + + + Warning: Please check that your computer's date and time are correct! If your clock is wrong Arepacoin will not work properly. + + + + + Warning: error reading wallet.dat! All keys read correctly, but transaction data or address book entries might be missing or incorrect. + Cuidado: erro ao ler arquivo wallet.dat! Todas as chaves foram lidas corretamente, mas dados transações e do catálogo de endereços podem estar faltando ou estar incorretas. + + + + Warning: wallet.dat corrupt, data salvaged! Original wallet.dat saved as wallet.{timestamp}.bak in %s; if your balance or transactions are incorrect you should restore from a backup. + Aviso: wallet.dat corrompido, dados recuperados! Arquivo wallet.dat original salvo como wallet.{timestamp}.bak em %s; se seu saldo ou transações estiverem incorretos, você deve restauras o backup. + + + + Attempt to recover private keys from a corrupt wallet.dat + Tentar recuperar chaves privadas de um arquivo wallet.dat corrompido + + + + Block creation options: + Opções de criação de blocos: + + + + Connect only to the specified node(s) + Conectar apenas a nó(s) específico(s) + + + + Discover own IP address (default: 1 when listening and no -externalip) + Descobrir os próprios endereços IP (padrão: 1 quando no modo listening e opção -externalip não estiver presente) + + + + Failed to listen on any port. Use -listen=0 if you want this. + Falha ao escutar em qualquer porta. Use -listen=0 se você quiser isso. + + + + Find peers using DNS lookup (default: 1) + + + + + Sync checkpoints policy (default: strict) + + + + + Invalid -tor address: '%s' + + + + + Invalid amount for -reservebalance=<amount> + + + + + Maximum per-connection receive buffer, <n>*1000 bytes (default: 5000) + Buffer máximo de recebimento por conexão, <n>*1000 bytes (padrão: 5000) + + + + Maximum per-connection send buffer, <n>*1000 bytes (default: 1000) + Buffer máximo de envio por conexão, <n>*1000 bytes (padrão: 1000) + + + + Only connect to nodes in network <net> (IPv4, IPv6 or Tor) + Apenas conectar em nós na rede <net> (IPv4, IPv6, ou Tor) + + + + Output extra debugging information. Implies all other -debug* options + + + + + Output extra network debugging information + + + + + Prepend debug output with timestamp + + + + + SSL options: (see the Bitcoin Wiki for SSL setup instructions) + Opções SSL: (veja a Wiki do Bitcoin para instruções de configuração SSL) + + + + Select the version of socks proxy to use (4-5, default: 5) + + + + + Send trace/debug info to console instead of debug.log file + Mandar informação de trace/debug para o console em vez de para o arquivo debug.log + + + + Send trace/debug info to debugger + + + + + Set maximum block size in bytes (default: 250000) + + + + + Set minimum block size in bytes (default: 0) + Determinar tamanho mínimo de bloco em bytes (padrão: 0) + + + + Shrink debug.log file on client startup (default: 1 when no -debug) + Encolher arquivo debug.log ao iniciar o cliente (padrão 1 se opção -debug não estiver presente) + + + + Specify connection timeout in milliseconds (default: 5000) + Especifique o tempo limite (timeout) da conexão em milissegundos (padrão: 5000) + + + + Unable to sign checkpoint, wrong checkpointkey? + + + + + + Use UPnP to map the listening port (default: 0) + Usar UPnP para mapear porta de escuta (padrão: 0) + + + + Use UPnP to map the listening port (default: 1 when listening) + Usar UPnP para mapear porta de escuta (padrão: 1 quando estiver escutando) + + + + Use proxy to reach tor hidden services (default: same as -proxy) + + + + + Username for JSON-RPC connections + Nome de usuário para conexões JSON-RPC + + + + Verifying database integrity... + + + + + WARNING: syncronized checkpoint violation detected, but skipped! + + + + + Warning: Disk space is low! + + + + + Warning: This version is obsolete, upgrade required! + Cuidado: Esta versão está obsoleta, atualização exigida! + + + + wallet.dat corrupt, salvage failed + wallet.dat corrompido, recuperação falhou + + + + Password for JSON-RPC connections + Senha para conexões JSON-RPC + + + + %s, you must set a rpcpassword in the configuration file: + %s +It is recommended you use the following random password: +rpcuser=arepacoinrpc +rpcpassword=%s +(you do not need to remember this password) +The username and password MUST NOT be the same. +If the file does not exist, create it with owner-readable-only file permissions. +It is also recommended to set alertnotify so you are notified of problems; +for example: alertnotify=echo %%s | mail -s "Arepacoin Alert" admin@foo.com + + + + + + Find peers using internet relay chat (default: 0) + + + + + Sync time with other nodes. Disable if time on your system is precise e.g. syncing with NTP (default: 1) + + + + + When creating transactions, ignore inputs with value less than this (default: 0.01) + + + + + Allow JSON-RPC connections from specified IP address + Permitir conexões JSON-RPC de endereços IP específicos + + + + Send commands to node running on <ip> (default: 127.0.0.1) + Enviar comando para nó rodando em <ip> (pardão: 127.0.0.1) + + + + Execute command when the best block changes (%s in cmd is replaced by block hash) + Executar comando quando o melhor bloco mudar (%s no comando será substituído pelo hash do bloco) + + + + Execute command when a wallet transaction changes (%s in cmd is replaced by TxID) + Executar comando quando uma transação da carteira mudar (%s no comando será substituído por TxID) + + + + Require a confirmations for change (default: 0) + + + + + Enforce transaction scripts to use canonical PUSH operators (default: 1) + + + + + Execute command when a relevant alert is received (%s in cmd is replaced by message) + + + + + Upgrade wallet to latest format + Atualizar carteira para o formato mais recente + + + + Set key pool size to <n> (default: 100) + Determinar tamanho do pool de endereços para <n> (padrão: 100) + + + + Rescan the block chain for missing wallet transactions + Re-escanear blocos procurando por transações perdidas da carteira + + + + How many blocks to check at startup (default: 2500, 0 = all) + + + + + How thorough the block verification is (0-6, default: 1) + + + + + Imports blocks from external blk000?.dat file + + + + + Use OpenSSL (https) for JSON-RPC connections + Usar OpenSSL (https) para conexões JSON-RPC + + + + Server certificate file (default: server.cert) + Arquivo de certificado do servidor (padrão: server.cert) + + + + Server private key (default: server.pem) + Chave privada do servidor (padrão: server.pem) + + + + Acceptable ciphers (default: TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH) + + + + + Error: Wallet unlocked for staking only, unable to create transaction. + + + + + WARNING: Invalid checkpoint found! Displayed transactions may not be correct! You may need to upgrade, or notify developers. + + + + + This help message + Esta mensagem de ajuda + + + + Wallet %s resides outside data directory %s. + + + + + Cannot obtain a lock on data directory %s. Arepacoin is probably already running. + + + + + Arepacoin + + + + + Unable to bind to %s on this computer (bind returned error %d, %s) + Impossível vincular a %s neste computador (bind retornou erro %d, %s) + + + + Connect through socks proxy + + + + + Allow DNS lookups for -addnode, -seednode and -connect + Permitir consultas DNS para -addnode, -seednode e -connect + + + + Loading addresses... + Carregando endereços... + + + + Error loading blkindex.dat + + + + + Error loading wallet.dat: Wallet corrupted + Erro ao carregar wallet.dat: Carteira corrompida + + + + Error loading wallet.dat: Wallet requires newer version of Arepacoin + + + + + Wallet needed to be rewritten: restart Arepacoin to complete + + + + + Error loading wallet.dat + Erro ao carregar wallet.dat + + + + Invalid -proxy address: '%s' + Endereço -proxy inválido: '%s' + + + + Unknown network specified in -onlynet: '%s' + Rede desconhecida especificada em -onlynet: '%s' + + + + Unknown -socks proxy version requested: %i + Versão desconhecida do proxy -socks requisitada: %i + + + + Cannot resolve -bind address: '%s' + Impossível encontrar o endereço -bind: '%s' + + + + Cannot resolve -externalip address: '%s' + Impossível encontrar endereço -externalip: '%s' + + + + Invalid amount for -paytxfee=<amount>: '%s' + Quantidade inválida para -paytxfee=<quantidade>: '%s' + + + + Error: could not start node + + + + + Sending... + + + + + Invalid amount + Quantidade inválida + + + + Insufficient funds + Saldo insuficiente + + + + Loading block index... + Carregando índice de blocos... + + + + Add a node to connect to and attempt to keep the connection open + Adicionar um nó com o qual se conectar e tentar manter a conexão ativa + + + + Unable to bind to %s on this computer. Arepacoin is probably already running. + + + + + Fee per KB to add to transactions you send + + + + + Invalid amount for -mininput=<amount>: '%s' + + + + + Loading wallet... + Carregando carteira... + + + + Cannot downgrade wallet + Não é possível fazer downgrade da carteira + + + + Cannot initialize keypool + + + + + Cannot write default address + Não foi possível escrever no endereço padrão + + + + Rescanning... + Re-escaneando... + + + + Done loading + Carregamento terminado + + + + To use the %s option + Para usar a opção %s + + + + Error + Erro + + + + You must set rpcpassword=<password> in the configuration file: +%s +If the file does not exist, create it with owner-readable-only file permissions. + Você precisa especificar rpcpassword=<senha> no arquivo de configurações:⏎ +%s⏎ +Se o arquivo não existir, crie um com permissão de leitura apenas pelo dono + + + \ No newline at end of file diff --git a/src/qt/locale/bitcoin_pt_PT.ts b/src/qt/locale/bitcoin_pt_PT.ts new file mode 100755 index 0000000..870f287 --- /dev/null +++ b/src/qt/locale/bitcoin_pt_PT.ts @@ -0,0 +1,3286 @@ + + + AboutDialog + + + About Arepacoin + + + + + <b>Arepacoin</b> version + + + + + Copyright © 2009-2014 The Bitcoin developers +Copyright © 2012-2014 The NovaCoin developers +Copyright © 2014 The Arepacoin developers + + + + + +This is experimental software. + +Distributed under the MIT/X11 software license, see the accompanying file COPYING or http://www.opensource.org/licenses/mit-license.php. + +This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit (http://www.openssl.org/) and cryptographic software written by Eric Young (eay@cryptsoft.com) and UPnP software written by Thomas Bernard. + +Este é um programa experimental. + +Distribuído sob uma licença de software MIT/X11, por favor verifique o ficheiro anexo license.txt ou http://www.opensource.org/licenses/mit-license.php. + +Este produto inclui software desenvolvido pelo Projecto OpenSSL para uso no OpenSSL Toolkit (http://www.openssl.org/), software criptográfico escrito por Eric Young (eay@cryptsoft.com) e software UPnP escrito por Thomas Bernard. + + + + AddressBookPage + + + Address Book + + + + + Double-click to edit address or label + Clique duas vezes para editar o endereço ou o rótulo + + + + Create a new address + Criar um novo endereço + + + + Copy the currently selected address to the system clipboard + Copie o endereço selecionado para a área de transferência + + + + &New Address + + + + + These are your Arepacoin addresses for receiving payments. You may want to give a different one to each sender so you can keep track of who is paying you. + + + + + &Copy Address + &Copiar Endereço + + + + Show &QR Code + + + + + Sign a message to prove you own a Arepacoin address + + + + + Sign &Message + + + + + Delete the currently selected address from the list + Apagar o endereço selecionado da lista + + + + Verify a message to ensure it was signed with a specified Arepacoin address + + + + + &Verify Message + + + + + &Delete + E&liminar + + + + Copy &Label + Copiar &Rótulo + + + + &Edit + &Editar + + + + Export Address Book Data + + + + + Comma separated file (*.csv) + Ficheiro separado por vírgulas (*.csv) + + + + Error exporting + + + + + Could not write to file %1. + + + + + AddressTableModel + + + Label + Rótulo + + + + Address + Endereço + + + + (no label) + (sem rótulo) + + + + AskPassphraseDialog + + + Passphrase Dialog + Diálogo de Frase-Passe + + + + Enter passphrase + Escreva a frase de segurança + + + + New passphrase + Nova frase de segurança + + + + Repeat new passphrase + Repita a nova frase de segurança + + + + Serves to disable the trivial sendmoney when OS account compromised. Provides no real security. + + + + + For staking only + + + + + Enter the new passphrase to the wallet.<br/>Please use a passphrase of <b>10 or more random characters</b>, or <b>eight or more words</b>. + Escreva a nova frase de seguraça da sua carteira. <br/> Por favor, use uma frase de <b>10 ou mais caracteres aleatórios,</b> ou <b>oito ou mais palavras</b>. + + + + Encrypt wallet + Encriptar carteira + + + + This operation needs your wallet passphrase to unlock the wallet. + A sua frase de segurança é necessária para desbloquear a carteira. + + + + Unlock wallet + Desbloquear carteira + + + + This operation needs your wallet passphrase to decrypt the wallet. + A sua frase de segurança é necessária para desencriptar a carteira. + + + + Decrypt wallet + Desencriptar carteira + + + + Change passphrase + Alterar frase de segurança + + + + Enter the old and new passphrase to the wallet. + Escreva a frase de segurança antiga seguida da nova para a carteira. + + + + Confirm wallet encryption + Confirmar encriptação da carteira + + + + Warning: If you encrypt your wallet and lose your passphrase, you will <b>LOSE ALL OF YOUR COINS</b>! + + + + + Are you sure you wish to encrypt your wallet? + Tem a certeza que deseja encriptar a carteira? + + + + IMPORTANT: Any previous backups you have made of your wallet file should be replaced with the newly generated, encrypted wallet file. For security reasons, previous backups of the unencrypted wallet file will become useless as soon as you start using the new, encrypted wallet. + IMPORTANTE: Qualquer cópia de segurança anterior da carteira deverá ser substituída com o novo, actualmente encriptado, ficheiro de carteira. Por razões de segurança, cópias de segurança não encriptadas efectuadas anteriormente do ficheiro da carteira tornar-se-ão inúteis assim que começar a usar a nova carteira encriptada. + + + + + Warning: The Caps Lock key is on! + Atenção: A tecla Caps Lock está activa! + + + + + Wallet encrypted + Carteira encriptada + + + + Arepacoin will close now to finish the encryption process. Remember that encrypting your wallet cannot fully protect your coins from being stolen by malware infecting your computer. + + + + + + + + Wallet encryption failed + A encriptação da carteira falhou + + + + Wallet encryption failed due to an internal error. Your wallet was not encrypted. + A encriptação da carteira falhou devido a um erro interno. A carteira não foi encriptada. + + + + + The supplied passphrases do not match. + As frases de segurança fornecidas não coincidem. + + + + Wallet unlock failed + O desbloqueio da carteira falhou + + + + + + The passphrase entered for the wallet decryption was incorrect. + A frase de segurança introduzida para a desencriptação da carteira estava incorreta. + + + + Wallet decryption failed + A desencriptação da carteira falhou + + + + Wallet passphrase was successfully changed. + A frase de segurança da carteira foi alterada com êxito. + + + + BitcoinGUI + + + Sign &message... + Assinar &mensagem... + + + + Synchronizing with network... + Sincronizando com a rede... + + + + &Overview + Visã&o geral + + + + Show general overview of wallet + Mostrar visão geral da carteira + + + + &Transactions + &Transações + + + + Browse transaction history + Navegar pelo histórico de transações + + + + &Address Book + + + + + Edit the list of stored addresses and labels + + + + + &Receive coins + + + + + Show the list of addresses for receiving payments + + + + + &Send coins + + + + + E&xit + Fec&har + + + + Quit application + Sair da aplicação + + + + Show information about Arepacoin + + + + + About &Qt + Sobre &Qt + + + + Show information about Qt + Mostrar informação sobre Qt + + + + &Options... + &Opções... + + + + &Encrypt Wallet... + E&ncriptar Carteira... + + + + &Backup Wallet... + &Guardar Carteira... + + + + &Change Passphrase... + Mudar &Palavra-passe... + + + + ~%n block(s) remaining + + + + + Downloaded %1 of %2 blocks of transaction history (%3% done). + + + + + &Export... + + + + + Send coins to a Arepacoin address + + + + + Modify configuration options for Arepacoin + + + + + Export the data in the current tab to a file + + + + + Encrypt or decrypt wallet + + + + + Backup wallet to another location + Faça uma cópia de segurança da carteira para outra localização + + + + Change the passphrase used for wallet encryption + Mudar a frase de segurança utilizada na encriptação da carteira + + + + &Debug window + Janela de &depuração + + + + Open debugging and diagnostic console + Abrir consola de diagnóstico e depuração + + + + &Verify message... + &Verificar mensagem... + + + + Arepacoin + + + + + Wallet + Carteira + + + + &About Arepacoin + + + + + &Show / Hide + Mo&strar / Ocultar + + + + Unlock wallet + + + + + &Lock Wallet + + + + + Lock wallet + + + + + &File + &Ficheiro + + + + &Settings + Con&figurações + + + + &Help + A&juda + + + + Tabs toolbar + Barra de separadores + + + + Actions toolbar + + + + + + [testnet] + [rede de testes] + + + + + Arepacoin client + + + + + %n active connection(s) to Arepacoin network + + + + + Downloaded %1 blocks of transaction history. + + + + + Staking.<br>Your weight is %1<br>Network weight is %2<br>Expected time to earn reward is %3 + + + + + Not staking because wallet is locked + + + + + Not staking because wallet is offline + + + + + Not staking because wallet is syncing + + + + + Not staking because you don't have mature coins + + + + + %n second(s) ago + + + + + &Unlock Wallet... + + + + + %n minute(s) ago + + + + + %n hour(s) ago + + + + + %n day(s) ago + + + + + Up to date + Atualizado + + + + Catching up... + Recuperando... + + + + Last received block was generated %1. + + + + + This transaction is over the size limit. You can still send it for a fee of %1, which goes to the nodes that process your transaction and helps to support the network. Do you want to pay the fee? + + + + + Confirm transaction fee + + + + + Sent transaction + Transação enviada + + + + Incoming transaction + Transação recebida + + + + Date: %1 +Amount: %2 +Type: %3 +Address: %4 + + Data: %1 +Quantia: %2 +Tipo: %3 +Endereço: %4 + + + + + + URI handling + + + + + + URI can not be parsed! This can be caused by an invalid Arepacoin address or malformed URI parameters. + + + + + Wallet is <b>encrypted</b> and currently <b>unlocked</b> + A carteira está <b>encriptada</b> e atualmente <b>desbloqueada</b> + + + + Wallet is <b>encrypted</b> and currently <b>locked</b> + A carteira está <b>encriptada</b> e atualmente <b>bloqueada</b> + + + + Backup Wallet + + + + + Wallet Data (*.dat) + + + + + Backup Failed + + + + + There was an error trying to save the wallet data to the new location. + + + + + %n second(s) + + + + + %n minute(s) + + + + + %n hour(s) + %n hora%n horas + + + + %n day(s) + %n dia%n dias + + + + Not staking + + + + + A fatal error occurred. Arepacoin can no longer continue safely and will quit. + + + + + ClientModel + + + Network Alert + Alerta da Rede + + + + CoinControlDialog + + + Coin Control + + + + + Quantity: + Quantidade: + + + + Bytes: + Bytes: + + + + Amount: + Quantia: + + + + Priority: + Prioridade: + + + + Fee: + Taxa: + + + + Low Output: + Saída Baixa: + + + + no + não + + + + After Fee: + Depois de taxas: + + + + Change: + Troco: + + + + (un)select all + (des)seleccionar todos + + + + Tree mode + Modo de árvore + + + + List mode + Modo lista + + + + Amount + Quantia + + + + Label + + + + + Address + Endereço + + + + Date + Data + + + + Confirmations + Confirmados + + + + Confirmed + Confirmada + + + + Priority + Prioridade + + + + Copy address + Copiar endereço + + + + Copy label + Copiar rótulo + + + + + Copy amount + Copiar quantia + + + + Copy transaction ID + Copiar ID da Transação + + + + Copy quantity + Copiar quantidade + + + + Copy fee + Taxa de cópia + + + + Copy after fee + Taxa depois de cópia + + + + Copy bytes + Copiar bytes + + + + Copy priority + Prioridade de Cópia + + + + Copy low output + Copiar output baixo + + + + Copy change + Copiar alteração + + + + highest + o maior + + + + high + alto + + + + medium-high + médio-alto + + + + medium + médio + + + + low-medium + baixo-médio + + + + low + baixo + + + + lowest + O mais baixo + + + + DUST + + + + + yes + sim + + + + This label turns red, if the transaction size is bigger than 10000 bytes. + + This means a fee of at least %1 per kb is required. + + Can vary +/- 1 Byte per input. + + + + + Transactions with higher priority get more likely into a block. + +This label turns red, if the priority is smaller than "medium". + + This means a fee of at least %1 per kb is required. + + + + + This label turns red, if any recipient receives an amount smaller than %1. + + This means a fee of at least %2 is required. + + Amounts below 0.546 times the minimum relay fee are shown as DUST. + + + + + This label turns red, if the change is smaller than %1. + + This means a fee of at least %2 is required. + + + + + + (no label) + (Sem rótulo) + + + + change from %1 (%2) + Alteração de %1 (%2) + + + + (change) + (Alteração) + + + + EditAddressDialog + + + Edit Address + Editar Endereço + + + + &Label + &Rótulo + + + + The label associated with this address book entry + + + + + &Address + E&ndereço + + + + The address associated with this address book entry. This can only be modified for sending addresses. + + + + + New receiving address + Novo endereço de entrada + + + + New sending address + Novo endereço de saída + + + + Edit receiving address + Editar endereço de entrada + + + + Edit sending address + Editar endereço de saída + + + + The entered address "%1" is already in the address book. + O endereço introduzido "%1" já se encontra no livro de endereços. + + + + The entered address "%1" is not a valid Arepacoin address. + + + + + Could not unlock wallet. + Impossível desbloquear carteira. + + + + New key generation failed. + Falha ao gerar nova chave. + + + + GUIUtil::HelpMessageBox + + + + Arepacoin-Qt + + + + + version + + + + + Usage: + + + + + command-line options + + + + + UI options + + + + + Set language, for example "de_DE" (default: system locale) + + + + + Start minimized + + + + + Show splash screen on startup (default: 1) + + + + + OptionsDialog + + + Options + Opções + + + + &Main + &Principal + + + + Optional transaction fee per kB that helps make sure your transactions are processed quickly. Most transactions are 1 kB. Fee 0.01 recommended. + + + + + Pay transaction &fee + Pagar &taxa de transação + + + + Reserved amount does not participate in staking and is therefore spendable at any time. + + + + + Reserve + + + + + Automatically start Arepacoin after logging in to the system. + + + + + &Start Arepacoin on system login + + + + + Detach block and address databases at shutdown. This means they can be moved to another data directory, but it slows down shutdown. The wallet is always detached. + + + + + &Detach databases at shutdown + + + + + &Network + &Rede + + + + Automatically open the Arepacoin client port on the router. This only works when your router supports UPnP and it is enabled. + + + + + Map port using &UPnP + Mapear porta usando &UPnP + + + + Connect to the Arepacoin network through a SOCKS proxy (e.g. when connecting through Tor). + + + + + &Connect through SOCKS proxy: + + + + + Proxy &IP: + &IP do proxy: + + + + IP address of the proxy (e.g. 127.0.0.1) + + + + + &Port: + &Porta: + + + + Port of the proxy (e.g. 9050) + Porta do proxy (p.ex. 9050) + + + + SOCKS &Version: + &Versão SOCKS: + + + + SOCKS version of the proxy (e.g. 5) + Versão do proxy SOCKS (p.ex. 5) + + + + &Window + &Janela + + + + Show only a tray icon after minimizing the window. + Apenas mostrar o ícone da bandeja após minimizar a janela. + + + + &Minimize to the tray instead of the taskbar + &Minimizar para a bandeja e não para a barra de ferramentas + + + + Minimize instead of exit the application when the window is closed. When this option is enabled, the application will be closed only after selecting Quit in the menu. + Minimize ao invés de sair da aplicação quando a janela é fechada. Com esta opção selecionada, a aplicação apenas será encerrada quando escolher Sair da aplicação no menú. + + + + M&inimize on close + M&inimizar ao fechar + + + + &Display + Vis&ualização + + + + User Interface &language: + &Linguagem da interface de utilizador: + + + + The user interface language can be set here. This setting will take effect after restarting Arepacoin. + + + + + &Unit to show amounts in: + &Unidade a usar em quantias: + + + + Choose the default subdivision unit to show in the interface and when sending coins. + Escolha a subdivisão unitária a ser mostrada por defeito na aplicação e ao enviar moedas. + + + + Whether to show Arepacoin addresses in the transaction list or not. + + + + + &Display addresses in transaction list + Mostrar en&dereços na lista de transações + + + + Whether to show coin control features or not. + Escolha para mostrar funcionalidades de controlo "coin" ou não. + + + + Display coin &control features (experts only!) + + + + + &OK + &OK + + + + &Cancel + &Cancelar + + + + &Apply + + + + + default + padrão + + + + + Warning + + + + + + This setting will take effect after restarting Arepacoin. + + + + + The supplied proxy address is invalid. + O endereço de proxy introduzido é inválido. + + + + OverviewPage + + + Form + Formulário + + + + + The displayed information may be out of date. Your wallet automatically synchronizes with the Arepacoin network after a connection is established, but this process has not completed yet. + + + + + Stake: + + + + + Unconfirmed: + + + + + Wallet + Carteira + + + + Spendable: + + + + + Your current spendable balance + O seu saldo disponível para gastar + + + + Immature: + Imaturo: + + + + Mined balance that has not yet matured + O saldo minado ainda não maturou + + + + Total: + Total: + + + + Your current total balance + O seu saldo total actual + + + + <b>Recent transactions</b> + <b>Transações recentes</b> + + + + Total of transactions that have yet to be confirmed, and do not yet count toward the current balance + + + + + Total of coins that was staked, and do not yet count toward the current balance + + + + + + out of sync + fora de sincronia + + + + QRCodeDialog + + + QR Code Dialog + + + + + Request Payment + + + + + Amount: + + + + + Label: + + + + + Message: + + + + + &Save As... + + + + + Error encoding URI into QR Code. + + + + + The entered amount is invalid, please check. + + + + + Resulting URI too long, try to reduce the text for label / message. + + + + + Save QR Code + + + + + PNG Images (*.png) + + + + + RPCConsole + + + Client name + Nome do Cliente + + + + + + + + + + + + + N/A + N/D + + + + Client version + Versão do Cliente + + + + &Information + &Informação + + + + Using OpenSSL version + Usando versão OpenSSL + + + + Startup time + Tempo de início + + + + Network + Rede + + + + Number of connections + Número de ligações + + + + On testnet + + + + + Block chain + Cadeia de blocos + + + + Current number of blocks + Número actual de blocos + + + + Estimated total blocks + Total estimado de blocos + + + + Last block time + Tempo do último bloco + + + + &Open + &Abrir + + + + Command-line options + + + + + Show the Arepacoin-Qt help message to get a list with possible Arepacoin command-line options. + + + + + &Show + + + + + &Console + &Consola + + + + Build date + Data de construção + + + + Arepacoin - Debug window + + + + + Arepacoin Core + + + + + Debug log file + Ficheiro de registo de depuração + + + + Open the Arepacoin debug log file from the current data directory. This can take a few seconds for large log files. + + + + + Clear console + Limpar consola + + + + Welcome to the Arepacoin RPC console. + + + + + Use up and down arrows to navigate history, and <b>Ctrl-L</b> to clear screen. + Use as setas para cima e para baixo para navegar no histórico e <b>Ctrl-L</b> para limpar o ecrã. + + + + Type <b>help</b> for an overview of available commands. + Digite <b>help</b> para visualizar os comandos disponíveis. + + + + SendCoinsDialog + + + + + + + + + + Send Coins + Enviar Moedas + + + + Coin Control Features + Funcionalidades de Coin Controlo: + + + + Inputs... + Entradas + + + + automatically selected + Selecção automática + + + + Insufficient funds! + Fundos insuficientes! + + + + Quantity: + Quantidade: + + + + + 0 + + + + + Bytes: + Bytes: + + + + Amount: + Quantia: + + + + + + + 0.00 BC + + + + + Priority: + Prioridade: + + + + medium + + + + + Fee: + Taxa: + + + + Low Output: + Output Baixo: + + + + no + + + + + After Fee: + Depois de taxas: + + + + Change + + + + + custom change address + + + + + Send to multiple recipients at once + Enviar para múltiplos destinatários de uma vez + + + + Add &Recipient + Adicionar &Destinatário + + + + Remove all transaction fields + + + + + Clear &All + &Limpar Tudo + + + + Balance: + Saldo: + + + + 123.456 BC + + + + + Confirm the send action + Confirme ação de envio + + + + S&end + &Enviar + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Copy quantity + Copiar quantidade + + + + Copy amount + Copiar quantia + + + + Copy fee + Taxa de cópia + + + + Copy after fee + Taxa depois de cópia + + + + Copy bytes + Copiar bytes + + + + Copy priority + Prioridade de Cópia + + + + Copy low output + Copiar output baixo + + + + Copy change + Copiar alteração + + + + <b>%1</b> to %2 (%3) + + + + + Confirm send coins + Confirme envio de moedas + + + + Are you sure you want to send %1? + + + + + and + + + + + The recipient address is not valid, please recheck. + O endereço de destino não é válido, por favor verifique. + + + + The amount to pay must be larger than 0. + A quantia a pagar deverá ser maior que 0. + + + + The amount exceeds your balance. + A quantia excede o seu saldo. + + + + The total exceeds your balance when the %1 transaction fee is included. + O total excede o seu saldo quando a taxa de transação de %1 for incluída. + + + + Duplicate address found, can only send to each address once per send operation. + Endereço duplicado encontrado, apenas poderá enviar uma vez para cada endereço por cada operação de envio. + + + + Error: Transaction creation failed. + + + + + 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. + + + + + WARNING: Invalid Arepacoin address + + + + + (no label) + (Sem rótulo) + + + + WARNING: unknown change address + + + + + SendCoinsEntry + + + Form + + + + + A&mount: + Qu&antia: + + + + Pay &To: + &Pagar A: + + + + + Enter a label for this address to add it to your address book + Escreva um rótulo para este endereço para o adicionar ao seu livro de endereços + + + + &Label: + Rótu&lo: + + + + The address to send the payment to (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Choose address from address book + + + + + Alt+A + Alt+A + + + + Paste address from clipboard + Cole endereço da área de transferência + + + + Alt+P + Alt+P + + + + Remove this recipient + + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + SignVerifyMessageDialog + + + Signatures - Sign / Verify a Message + Assinaturas - Assinar / Verificar uma Mensagem + + + + + &Sign Message + A&ssinar Mensagem + + + + You can sign messages with your addresses to prove you own them. Be careful not to sign anything vague, as phishing attacks may try to trick you into signing your identity over to them. Only sign fully-detailed statements you agree to. + Pode assinar mensagens com os seus endereços para provar que são seus. Tenha atenção ao assinar mensagens ambíguas, pois ataques de phishing podem tentar enganá-lo, de modo a assinar a sua identidade para os atacantes. Apenas assine declarações completamente detalhadas com as quais concorde. + + + + The address to sign the message with (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + + Choose an address from the address book + + + + + + Alt+A + Alt+A + + + + Paste address from clipboard + Cole endereço da área de transferência + + + + Alt+P + Alt+P + + + + Enter the message you want to sign here + Escreva aqui a mensagem que deseja assinar + + + + Copy the current signature to the system clipboard + Copiar a assinatura actual para a área de transferência + + + + Sign the message to prove you own this Arepacoin address + + + + + Reset all sign message fields + Repôr todos os campos de assinatura de mensagem + + + + + Clear &All + Limpar &Tudo + + + + + &Verify Message + &Verificar Mensagem + + + + Enter the signing address, message (ensure you copy line breaks, spaces, tabs, etc. exactly) and signature below to verify the message. Be careful not to read more into the signature than what is in the signed message itself, to avoid being tricked by a man-in-the-middle attack. + Introduza o endereço de assinatura, mensagem (assegure-se de copiar quebras de linha, espaços, tabuladores, etc. exactamente) e assinatura abaixo para verificar a mensagem. Tenha atenção para não ler mais na assinatura do que o que estiver na mensagem assinada, para evitar ser enganado por um atacante que se encontre entre si e quem assinou a mensagem. + + + + The address the message was signed with (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Verify the message to ensure it was signed with the specified Arepacoin address + + + + + Reset all verify message fields + Repôr todos os campos de verificação de mensagem + + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Click "Sign Message" to generate signature + Clique "Assinar mensagem" para gerar a assinatura + + + + Enter Arepacoin signature + + + + + + The entered address is invalid. + O endereço introduzido é inválido. + + + + + + + Please check the address and try again. + Por favor verifique o endereço e tente de novo. + + + + + The entered address does not refer to a key. + O endereço introduzido não refere a chave alguma. + + + + Wallet unlock was cancelled. + O desbloqueio da carteira foi cancelado. + + + + Private key for the entered address is not available. + A chave privada para o endereço introduzido não está disponível. + + + + Message signing failed. + Assinatura de mensagem falhou. + + + + Message signed. + Mensagem assinada. + + + + The signature could not be decoded. + A assinatura não pôde ser descodificada. + + + + + Please check the signature and try again. + Por favor verifique a assinatura e tente de novo. + + + + The signature did not match the message digest. + A assinatura não condiz com o conteúdo da mensagem. + + + + Message verification failed. + Verificação da mensagem falhou. + + + + Message verified. + Mensagem verificada. + + + + TransactionDesc + + + Open until %1 + Aberto até %1 + + + + Open for %n block(s) + + + + + conflicted + + + + + %1/offline + %1/desligado + + + + %1/unconfirmed + %1/não confirmada + + + + %1 confirmations + %1 confirmações + + + + Status + Estado + + + + , broadcast through %n node(s) + , transmitida através de %n nó, transmitida através de %n nós + + + + Date + Data + + + + Source + Origem + + + + Generated + Gerado + + + + + From + De + + + + + + To + Para + + + + + own address + endereço próprio + + + + label + rótulo + + + + + + + + Credit + Crédito + + + + matures in %n more block(s) + matura daqui por %n blocomatura daqui por %n blocos + + + + not accepted + não aceite + + + + + + + Debit + Débito + + + + Transaction fee + Taxa de transação + + + + Net amount + Valor líquido + + + + Message + Mensagem + + + + Comment + Comentário + + + + Transaction ID + ID da Transação + + + + Generated coins must mature 6 blocks before they can be spent. When you generated this block, it was broadcast to the network to be added to the block chain. If it fails to get into the chain, its state will change to "not accepted" and it won't be spendable. This may occasionally happen if another node generates a block within a few seconds of yours. + + + + + Debug information + Informação de depuração + + + + Transaction + Transação + + + + Inputs + Entradas + + + + Amount + Quantia + + + + true + verdadeiro + + + + false + falso + + + + , has not been successfully broadcast yet + , ainda não foi transmitida com sucesso + + + + unknown + desconhecido + + + + TransactionDescDialog + + + Transaction details + Detalhes da transação + + + + This pane shows a detailed description of the transaction + Esta janela mostra uma descrição detalhada da transação + + + + TransactionTableModel + + + Date + Data + + + + Type + Tipo + + + + Address + Endereço + + + + Amount + Quantia + + + + Open until %1 + Aberto até %1 + + + + Confirmed (%1 confirmations) + Confirmada (%1 confirmações) + + + + Open for %n more block(s) + Aberta por mais %n blocoAberta por mais %n blocos + + + + Offline + + + + + Unconfirmed + + + + + Confirming (%1 of %2 recommended confirmations) + + + + + Conflicted + + + + + Immature (%1 confirmations, will be available after %2) + + + + + This block was not received by any other nodes and will probably not be accepted! + Este bloco não foi recebido por outros nós e provavelmente não será aceite pela rede! + + + + Generated but not accepted + Gerado mas não aceite + + + + Received with + Recebido com + + + + Received from + Recebido de + + + + Sent to + Enviado para + + + + Payment to yourself + Pagamento ao próprio + + + + Mined + Minadas + + + + (n/a) + (n/d) + + + + Transaction status. Hover over this field to show number of confirmations. + Estado da transação. Pairar por cima deste campo para mostrar o número de confirmações. + + + + Date and time that the transaction was received. + Data e hora a que esta transação foi recebida. + + + + Type of transaction. + Tipo de transação. + + + + Destination address of transaction. + Endereço de destino da transação. + + + + Amount removed from or added to balance. + Quantia retirada ou adicionada ao saldo. + + + + TransactionView + + + + All + Todas + + + + Today + Hoje + + + + This week + Esta semana + + + + This month + Este mês + + + + Last month + Mês passado + + + + This year + Este ano + + + + Range... + Período... + + + + Received with + Recebida com + + + + Sent to + Enviada para + + + + To yourself + Para si + + + + Mined + Minadas + + + + Other + Outras + + + + Enter address or label to search + Escreva endereço ou rótulo a procurar + + + + Min amount + Quantia mínima + + + + Copy address + Copiar endereço + + + + Copy label + Copiar rótulo + + + + Copy amount + Copiar quantia + + + + Copy transaction ID + Copiar ID da Transação + + + + Edit label + Editar rótulo + + + + Show transaction details + Mostrar detalhes da transação + + + + Export Transaction Data + + + + + Comma separated file (*.csv) + Ficheiro separado por vírgula (*.csv) + + + + Confirmed + Confirmada + + + + Date + Data + + + + Type + Tipo + + + + Label + Rótulo + + + + Address + Endereço + + + + Amount + Quantia + + + + ID + ID + + + + Error exporting + + + + + Could not write to file %1. + + + + + Range: + Período: + + + + to + até + + + + WalletModel + + + Sending... + + + + + bitcoin-core + + + Arepacoin version + + + + + Usage: + Utilização: + + + + Send command to -server or arepacoind + + + + + List commands + Listar comandos + + + + Get help for a command + Obter ajuda para um comando + + + + Options: + Opções: + + + + Specify configuration file (default: arepacoin.conf) + + + + + Specify pid file (default: arepacoind.pid) + + + + + Specify wallet file (within data directory) + Especifique ficheiro de carteira (dentro da pasta de dados) + + + + Specify data directory + Especificar pasta de dados + + + + Set database cache size in megabytes (default: 25) + Definir o tamanho da cache de base de dados em megabytes (por defeito: 25) + + + + Set database disk log size in megabytes (default: 100) + + + + + Listen for connections on <port> (default: 9853 or testnet: 19853) + + + + + Maintain at most <n> connections to peers (default: 125) + Manter no máximo <n> ligações a outros nós da rede (por defeito: 125) + + + + Connect to a node to retrieve peer addresses, and disconnect + Ligar a um nó para recuperar endereços de pares, e desligar + + + + Specify your own public address + Especifique o seu endereço público + + + + Bind to given address. Use [host]:port notation for IPv6 + + + + + Stake your coins to support network and gain reward (default: 1) + + + + + Threshold for disconnecting misbehaving peers (default: 100) + Tolerância para desligar nós mal-formados (por defeito: 100) + + + + Number of seconds to keep misbehaving peers from reconnecting (default: 86400) + Número de segundos a impedir que nós mal-formados se liguem de novo (por defeito: 86400) + + + + An error occurred while setting up the RPC port %u for listening on IPv4: %s + Ocorreu um erro ao definir a porta %u do serviço RPC a escutar em IPv4: %s + + + + Detach block and address databases. Increases shutdown time (default: 0) + + + + + 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. + + + + + Error: This transaction requires a transaction fee of at least %s because of its amount, complexity, or use of recently received funds + + + + + Listen for JSON-RPC connections on <port> (default: 9852 or testnet: 19852) + + + + + Accept command line and JSON-RPC commands + Aceitar comandos da consola e JSON-RPC + + + + Error: Transaction creation failed + + + + + Error: Wallet locked, unable to create transaction + + + + + Importing blockchain data file. + + + + + Importing bootstrap blockchain data file. + + + + + Run in the background as a daemon and accept commands + Correr o processo como um daemon e aceitar comandos + + + + Use the test network + Utilizar a rede de testes - testnet + + + + Accept connections from outside (default: 1 if no -proxy or -connect) + Aceitar ligações externas (padrão: 1 sem -proxy ou -connect) + + + + An error occurred while setting up the RPC port %u for listening on IPv6, falling back to IPv4: %s + Ocorreu um erro ao definir a porta %u do serviço RPC a escutar em IPv6, a usar IPv4: %s + + + + Error initializing database environment %s! To recover, BACKUP THAT DIRECTORY, then remove everything from it except for wallet.dat. + + + + + Set maximum size of high-priority/low-fee transactions in bytes (default: 27000) + + + + + Warning: -paytxfee is set very high! This is the transaction fee you will pay if you send a transaction. + Atenção: -paytxfee está definida com um valor muito alto! Esta é a taxa que irá pagar se enviar uma transação. + + + + Warning: Please check that your computer's date and time are correct! If your clock is wrong Arepacoin will not work properly. + + + + + Warning: error reading wallet.dat! All keys read correctly, but transaction data or address book entries might be missing or incorrect. + Atenção: erro ao ler wallet.dat! Todas as chaves foram lidas correctamente, mas dados de transação ou do livro de endereços podem estar em falta ou incorrectos. + + + + Warning: wallet.dat corrupt, data salvaged! Original wallet.dat saved as wallet.{timestamp}.bak in %s; if your balance or transactions are incorrect you should restore from a backup. + Atenção: wallet.dat corrupto, dados recuperados! wallet.dat original salvo como wallet.{timestamp}.bak em %s; se o seu saldo ou transações estiverem incorrectos deverá recuperar de uma cópia de segurança. + + + + Attempt to recover private keys from a corrupt wallet.dat + Tentar recuperar chaves privadas de um wallet.dat corrupto + + + + Block creation options: + Opções de criação de bloco: + + + + Connect only to the specified node(s) + Apenas ligar ao(s) nó(s) especificado(s) + + + + Discover own IP address (default: 1 when listening and no -externalip) + Descobrir endereço IP próprio (padrão: 1 ao escutar e sem -externalip) + + + + Failed to listen on any port. Use -listen=0 if you want this. + Falhou a escutar em qualquer porta. Use -listen=0 se quer isto. + + + + Find peers using DNS lookup (default: 1) + + + + + Sync checkpoints policy (default: strict) + + + + + Invalid -tor address: '%s' + + + + + Invalid amount for -reservebalance=<amount> + + + + + Maximum per-connection receive buffer, <n>*1000 bytes (default: 5000) + Armazenamento intermédio de recepção por ligação, <n>*1000 bytes (por defeito: 5000) + + + + Maximum per-connection send buffer, <n>*1000 bytes (default: 1000) + Armazenamento intermédio de envio por ligação, <n>*1000 bytes (por defeito: 1000) + + + + Only connect to nodes in network <net> (IPv4, IPv6 or Tor) + Apenas ligar a nós na rede <net> (IPv4, IPv6 ou Tor) + + + + Output extra debugging information. Implies all other -debug* options + + + + + Output extra network debugging information + + + + + Prepend debug output with timestamp + + + + + SSL options: (see the Bitcoin Wiki for SSL setup instructions) + Opções SSL: (ver a Wiki Bitcoin para instruções de configuração SSL) + + + + Select the version of socks proxy to use (4-5, default: 5) + + + + + Send trace/debug info to console instead of debug.log file + Enviar informação de rastreio/depuração para a consola e não para o ficheiro debug.log + + + + Send trace/debug info to debugger + + + + + Set maximum block size in bytes (default: 250000) + + + + + Set minimum block size in bytes (default: 0) + Definir tamanho minímo de um bloco em bytes (por defeito: 0) + + + + Shrink debug.log file on client startup (default: 1 when no -debug) + Encolher ficheiro debug.log ao iniciar o cliente (por defeito: 1 sem -debug definido) + + + + Specify connection timeout in milliseconds (default: 5000) + Especificar tempo de espera da ligação em millisegundos (por defeito: 5000) + + + + Unable to sign checkpoint, wrong checkpointkey? + + + + + + Use UPnP to map the listening port (default: 0) + Usar UPnP para mapear a porta de escuta (padrão: 0) + + + + Use UPnP to map the listening port (default: 1 when listening) + Usar UPnP para mapear a porta de escuta (padrão: 1 ao escutar) + + + + Use proxy to reach tor hidden services (default: same as -proxy) + + + + + Username for JSON-RPC connections + Nome de utilizador para ligações JSON-RPC + + + + Verifying database integrity... + + + + + WARNING: syncronized checkpoint violation detected, but skipped! + + + + + Warning: Disk space is low! + + + + + Warning: This version is obsolete, upgrade required! + Atenção: Esta versão está obsoleta, é necessário actualizar! + + + + wallet.dat corrupt, salvage failed + wallet.dat corrupta, recuperação falhou + + + + Password for JSON-RPC connections + Palavra-passe para ligações JSON-RPC + + + + %s, you must set a rpcpassword in the configuration file: + %s +It is recommended you use the following random password: +rpcuser=arepacoinrpc +rpcpassword=%s +(you do not need to remember this password) +The username and password MUST NOT be the same. +If the file does not exist, create it with owner-readable-only file permissions. +It is also recommended to set alertnotify so you are notified of problems; +for example: alertnotify=echo %%s | mail -s "Arepacoin Alert" admin@foo.com + + + + + + Find peers using internet relay chat (default: 0) + + + + + Sync time with other nodes. Disable if time on your system is precise e.g. syncing with NTP (default: 1) + + + + + When creating transactions, ignore inputs with value less than this (default: 0.01) + + + + + Allow JSON-RPC connections from specified IP address + Permitir ligações JSON-RPC do endereço IP especificado + + + + Send commands to node running on <ip> (default: 127.0.0.1) + Enviar comandos para o nó a correr em <ip> (por defeito: 127.0.0.1) + + + + Execute command when the best block changes (%s in cmd is replaced by block hash) + Executar comando quando mudar o melhor bloco (no comando, %s é substituído pela hash do bloco) + + + + Execute command when a wallet transaction changes (%s in cmd is replaced by TxID) + Executar comando quando uma das transações na carteira mudar (no comando, %s é substituído pelo ID da Transação) + + + + Require a confirmations for change (default: 0) + + + + + Enforce transaction scripts to use canonical PUSH operators (default: 1) + + + + + Execute command when a relevant alert is received (%s in cmd is replaced by message) + + + + + Upgrade wallet to latest format + Atualize a carteira para o formato mais recente + + + + Set key pool size to <n> (default: 100) + Definir o tamanho da memória de chaves para <n> (por defeito: 100) + + + + Rescan the block chain for missing wallet transactions + Reexaminar a cadeia de blocos para transações em falta na carteira + + + + How many blocks to check at startup (default: 2500, 0 = all) + + + + + How thorough the block verification is (0-6, default: 1) + + + + + Imports blocks from external blk000?.dat file + + + + + Use OpenSSL (https) for JSON-RPC connections + Usar OpenSSL (https) para ligações JSON-RPC + + + + Server certificate file (default: server.cert) + Ficheiro de certificado do servidor (por defeito: server.cert) + + + + Server private key (default: server.pem) + Chave privada do servidor (por defeito: server.pem) + + + + Acceptable ciphers (default: TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH) + + + + + Error: Wallet unlocked for staking only, unable to create transaction. + + + + + WARNING: Invalid checkpoint found! Displayed transactions may not be correct! You may need to upgrade, or notify developers. + + + + + This help message + Esta mensagem de ajuda + + + + Wallet %s resides outside data directory %s. + + + + + Cannot obtain a lock on data directory %s. Arepacoin is probably already running. + + + + + Arepacoin + + + + + Unable to bind to %s on this computer (bind returned error %d, %s) + Incapaz de vincular a %s neste computador (vínculo retornou erro %d, %s) + + + + Connect through socks proxy + + + + + Allow DNS lookups for -addnode, -seednode and -connect + Permitir procuras DNS para -addnode, -seednode e -connect + + + + Loading addresses... + Carregar endereços... + + + + Error loading blkindex.dat + + + + + Error loading wallet.dat: Wallet corrupted + Erro ao carregar wallet.dat: Carteira danificada + + + + Error loading wallet.dat: Wallet requires newer version of Arepacoin + + + + + Wallet needed to be rewritten: restart Arepacoin to complete + + + + + Error loading wallet.dat + Erro ao carregar wallet.dat + + + + Invalid -proxy address: '%s' + Endereço -proxy inválido: '%s' + + + + Unknown network specified in -onlynet: '%s' + Rede desconhecida especificada em -onlynet: '%s' + + + + Unknown -socks proxy version requested: %i + Versão desconhecida de proxy -socks requisitada: %i + + + + Cannot resolve -bind address: '%s' + Não conseguiu resolver endereço -bind: '%s' + + + + Cannot resolve -externalip address: '%s' + Não conseguiu resolver endereço -externalip: '%s' + + + + Invalid amount for -paytxfee=<amount>: '%s' + Quantia inválida para -paytxfee=<amount>: '%s' + + + + Error: could not start node + + + + + Sending... + + + + + Invalid amount + Quantia inválida + + + + Insufficient funds + Fundos insuficientes + + + + Loading block index... + Carregar índice de blocos... + + + + Add a node to connect to and attempt to keep the connection open + Adicione um nó ao qual se ligar e tentar manter a ligação aberta + + + + Unable to bind to %s on this computer. Arepacoin is probably already running. + + + + + Fee per KB to add to transactions you send + + + + + Invalid amount for -mininput=<amount>: '%s' + + + + + Loading wallet... + Carregar carteira... + + + + Cannot downgrade wallet + Impossível mudar a carteira para uma versão anterior + + + + Cannot initialize keypool + + + + + Cannot write default address + Impossível escrever endereço por defeito + + + + Rescanning... + Reexaminando... + + + + Done loading + Carregamento completo + + + + To use the %s option + Para usar a opção %s + + + + Error + Erro + + + + You must set rpcpassword=<password> in the configuration file: +%s +If the file does not exist, create it with owner-readable-only file permissions. + Deverá definir rpcpassword=<password> no ficheiro de configuração: +%s +Se o ficheiro não existir, crie-o com permissões de leitura apenas para o dono. + + + \ No newline at end of file diff --git a/src/qt/locale/bitcoin_ro_RO.ts b/src/qt/locale/bitcoin_ro_RO.ts new file mode 100755 index 0000000..27f6f97 --- /dev/null +++ b/src/qt/locale/bitcoin_ro_RO.ts @@ -0,0 +1,3311 @@ + + + AboutDialog + + + About Arepacoin + Despre Arepacoin + + + + <b>Arepacoin</b> version + Versiune <b>Arepacoin</b> + + + + Copyright © 2009-2014 The Bitcoin developers +Copyright © 2012-2014 The NovaCoin developers +Copyright © 2014 The Arepacoin developers + Copyright © 2009-2014 The Bitcoin developers +Copyright © 2012-2014 The NovaCoin developers +Copyright © 2014 The Arepacoin developers + + + + +This is experimental software. + +Distributed under the MIT/X11 software license, see the accompanying file COPYING or http://www.opensource.org/licenses/mit-license.php. + +This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit (http://www.openssl.org/) and cryptographic software written by Eric Young (eay@cryptsoft.com) and UPnP software written by Thomas Bernard. + +Acesta este un software experimental. + +Distribuit sub licența MIT/X11, vezi fișierul însoțitor COPYING sau http://www.opensource.org/licenses/mit-license.php. + +Acest produs include programe dezvoltate de către OpenSSL Project pentru a fi folosite în OpenSSL Toolkit (http://www.openssl.org/) și programe criptografice scrise de către Eric Young (eay@cryptsoft.com) și programe UPnP scrise de către Thomas Bernard. + + + + AddressBookPage + + + Address Book + Agendă + + + + Double-click to edit address or label + Dublu-click pentru a edita adresa sau eticheta + + + + Create a new address + Creează o adresă nouă + + + + Copy the currently selected address to the system clipboard + Copiază adresa selectată în clipboard + + + + &New Address + Adresă nouă + + + + These are your Arepacoin addresses for receiving payments. You may want to give a different one to each sender so you can keep track of who is paying you. + Acestea sunt adresele Arepacoin pentru a primi plăți. Poate doriți sa dați o adresa noua fiecarui expeditor pentru a putea ține evidența la cine efectuează plăti. + + + + &Copy Address + &Copiază adresa + + + + Show &QR Code + Arată cod &QR + + + + Sign a message to prove you own a Arepacoin address + Semnează un mesaj pentru a dovedi că dețineti o adresă Arepacoin + + + + Sign &Message + Semnează &Mesajul + + + + Delete the currently selected address from the list + Sterge adresele curent selectate din lista + + + + Verify a message to ensure it was signed with a specified Arepacoin address + Verifică un mesaj pentru a vă asigura că a fost semnat cu o anumită adresă Arepacoin + + + + &Verify Message + &Verifică mesajul + + + + &Delete + Ște&rge + + + + Copy &Label + Copiază &eticheta + + + + &Edit + &Editează + + + + Export Address Book Data + Exportă datele din Agendă + + + + Comma separated file (*.csv) + Valori separate prin virgulă (*.csv) + + + + Error exporting + Eroare la exportare + + + + Could not write to file %1. + Nu s-a putut scrie în fișier %1. + + + + AddressTableModel + + + Label + Etichetă + + + + Address + Adresă + + + + (no label) + (fără etichetă) + + + + AskPassphraseDialog + + + Passphrase Dialog + Dialogul pentru fraza de acces + + + + Enter passphrase + Introdu fraza de acces + + + + New passphrase + Frază de acces nouă + + + + Repeat new passphrase + Repetă noua frază de acces + + + + Serves to disable the trivial sendmoney when OS account compromised. Provides no real security. + Servește pentru a dezactiva sendmoneyl atunci când sistemul de operare este compromis. Nu oferă nicio garanție reală. + + + + For staking only + Doar pentru staking + + + + Enter the new passphrase to the wallet.<br/>Please use a passphrase of <b>10 or more random characters</b>, or <b>eight or more words</b>. + Introdu noua parolă a portofelului electronic.<br/>Te rog folosește <b>minim 10 caractere aleatoare</b>, sau <b>minim 8 cuvinte</b>. + + + + Encrypt wallet + Criptează portofelul + + + + This operation needs your wallet passphrase to unlock the wallet. + Această acțiune necesită fraza ta de acces pentru deblocarea portofelului. + + + + Unlock wallet + Deblochează portofelul + + + + This operation needs your wallet passphrase to decrypt the wallet. + Această acțiune necesită fraza ta de acces pentru decriptarea portofelului. + + + + Decrypt wallet + Decriptează portofelul. + + + + Change passphrase + Schimbă fraza de acces + + + + Enter the old and new passphrase to the wallet. + Introdu vechea și noua parolă pentru portofel. + + + + Confirm wallet encryption + Confirmă criptarea portofelului + + + + Warning: If you encrypt your wallet and lose your passphrase, you will <b>LOSE ALL OF YOUR COINS</b>! + Atentie: Daca encriptezi portofelul si iti uiti parola, <b>VEI PIERDE TOATA MONEDELE</b>! + + + + Are you sure you wish to encrypt your wallet? + Sunteţi sigur că doriţi să criptaţi portofelul electronic? + + + + IMPORTANT: Any previous backups you have made of your wallet file should be replaced with the newly generated, encrypted wallet file. For security reasons, previous backups of the unencrypted wallet file will become useless as soon as you start using the new, encrypted wallet. + IMPORTANT: Orice copie de siguranta facuta in prealabil portofelului dumneavoastra ar trebui inlocuita cu cea generata cel mai recent fisier criptat al portofelului. Pentru siguranta, copiile de siguranta vechi ale portofelului ne-criptat vor deveni inutile de indata ce veti incepe folosirea noului fisier criptat al portofelului. + + + + + Warning: The Caps Lock key is on! + Atentie! Caps Lock este pornit + + + + + Wallet encrypted + Portofel criptat + + + + Arepacoin will close now to finish the encryption process. Remember that encrypting your wallet cannot fully protect your coins from being stolen by malware infecting your computer. + Arepacoin se va inchide pentru a termina procesul de encriptie. Amintiți-vă, criptarea portofelul dumneavoastră nu poate proteja pe deplin monedele dvs. de a fi furate de infectarea cu malware a computerului. + + + + + + + Wallet encryption failed + Criptarea portofelului a eșuat + + + + Wallet encryption failed due to an internal error. Your wallet was not encrypted. + Criptarea portofelului a eșuat din cauza unei erori interne. Portofelul tău nu a fost criptat. + + + + + The supplied passphrases do not match. + Frazele de acces introduse nu se potrivesc. + + + + Wallet unlock failed + Deblocarea portofelului a eșuat + + + + + + The passphrase entered for the wallet decryption was incorrect. + Fraza de acces introdusă pentru decriptarea portofelului a fost incorectă. + + + + Wallet decryption failed + Decriptarea portofelului a eșuat + + + + Wallet passphrase was successfully changed. + Parola portofelului electronic a fost schimbată. + + + + BitcoinGUI + + + Sign &message... + Semnează &mesaj... + + + + Synchronizing with network... + Se sincronizează cu rețeaua... + + + + &Overview + &Imagine de ansamblu + + + + Show general overview of wallet + Arată o stare generală de ansamblu a portofelului + + + + &Transactions + &Tranzacții + + + + Browse transaction history + Răsfoiește istoricul tranzacțiilor + + + + &Address Book + Agendă + + + + Edit the list of stored addresses and labels + Editează lista de adrese si etichete stocate + + + + &Receive coins + Primește monede + + + + Show the list of addresses for receiving payments + Arată lista de adrese pentru primire plăți + + + + &Send coins + &Trimite monede + + + + E&xit + &Ieșire + + + + Quit application + Închide aplicația + + + + Show information about Arepacoin + Arată informații despre Arepacoin + + + + About &Qt + Despre &Qt + + + + Show information about Qt + Arată informații despre Qt + + + + &Options... + &Setări... + + + + &Encrypt Wallet... + Criptează portofelul electronic... + + + + &Backup Wallet... + &Fă o copie de siguranță a portofelului... + + + + &Change Passphrase... + S&chimbă parola... + + + + ~%n block(s) remaining + ~%n bloc rămas~%n blocuri rămase~%n blocuri rămase + + + + Downloaded %1 of %2 blocks of transaction history (%3% done). + Descărcat %1 din %2 blocuri din istoricul tranzacțiilor(%3% terminat). + + + + &Export... + &Exportă + + + + Send coins to a Arepacoin address + Trimite monede către o adresă Arepacoin + + + + Modify configuration options for Arepacoin + Modifică opțiuni de configurare pentru Arepacoin + + + + Export the data in the current tab to a file + Exportă datele din tab-ul curent într-un fișier + + + + Encrypt or decrypt wallet + Criptează sau decriptează portofelul + + + + Backup wallet to another location + Creează o copie de rezervă a portofelului într-o locație diferită + + + + Change the passphrase used for wallet encryption + Schimbă fraza de acces folosită pentru criptarea portofelului + + + + &Debug window + Fereastră &debug + + + + Open debugging and diagnostic console + Deschide consola de debug și diagnosticare + + + + &Verify message... + &Verifică mesajul... + + + + Arepacoin + Arepacoin + + + + Wallet + Portofelul + + + + &About Arepacoin + Despre Arepacoin + + + + &Show / Hide + Arata/Ascunde + + + + Unlock wallet + Deblochează portofelul + + + + &Lock Wallet + Blochează portofelul + + + + Lock wallet + Blochează portofelul + + + + &File + &Fișier + + + + &Settings + &Setări + + + + &Help + A&jutor + + + + Tabs toolbar + Bara de file + + + + Actions toolbar + Bara de instrumente Actiuni + + + + + [testnet] + [testnet] + + + + + Arepacoin client + Clientul Arepacoin + + + + %n active connection(s) to Arepacoin network + %n conexiune activă la reteaua Arepacoin%n conexiuni active la reteaua Arepacoin%n conexiuni active la reteaua Arepacoin + + + + Downloaded %1 blocks of transaction history. + Descărcat %1 blocuri din istoricul tranzacțiilor. + + + + Staking.<br>Your weight is %1<br>Network weight is %2<br>Expected time to earn reward is %3 + Staking. <br>Greutatea este %1<br>Greutatea retelei este %2<br>Timp estimat pentru a castiga recompensa este %3 + + + + Not staking because wallet is locked + Nu este in modul stake deoarece portofelul este blocat + + + + Not staking because wallet is offline + Nu este in modul stake deoarece portofelul este offline + + + + Not staking because wallet is syncing + Nu este in modul stake deoarece portofelul se sincronizeaza + + + + Not staking because you don't have mature coins + Nu este in modul stake deoarece nu sunt destule monede maturate + + + + %n second(s) ago + %n secundă în urmă%n secunde în urmă%n secunde în urmă + + + + &Unlock Wallet... + &Deblochează portofelul + + + + %n minute(s) ago + %n minut în urmă%n minute în urmă%n minute în urmă + + + + %n hour(s) ago + %n oră în urmă%n ore în urmă%n ore în urmă + + + + %n day(s) ago + %n zi în urmă%n zile în urmă%n zile în urmă + + + + Up to date + Actualizat + + + + Catching up... + Se actualizează... + + + + Last received block was generated %1. + Ultimul bloc primit a fost generat %1. + + + + This transaction is over the size limit. You can still send it for a fee of %1, which goes to the nodes that process your transaction and helps to support the network. Do you want to pay the fee? + Această tranzactie este peste limita admisa. Puteți sa trimiteți pentru o taxa de 1%, care este pentru nodurile care proceseaza tranzactia si ajuta la sprijinirea retelei. Vrei să plătești taxa? + + + + Confirm transaction fee + Confirmă comisinoul tranzacției + + + + Sent transaction + Tranzacție expediată + + + + Incoming transaction + Tranzacție recepționată + + + + Date: %1 +Amount: %2 +Type: %3 +Address: %4 + + Data: %1 +Suma: %2 +Tipul: %3 +Adresa: %4 + + + + + + URI handling + Manipulare URI + + + + + URI can not be parsed! This can be caused by an invalid Arepacoin address or malformed URI parameters. + URI nu poate fi parsatt! Cauza poate fi o adresa Arepacoin invalidă sau parametrii URI malformați. + + + + Wallet is <b>encrypted</b> and currently <b>unlocked</b> + Portofelul este <b>criptat</b> iar în momentul de față este <b>deblocat</b> + + + + Wallet is <b>encrypted</b> and currently <b>locked</b> + Portofelul este <b>criptat</b> iar în momentul de față este <b>blocat</b> + + + + Backup Wallet + Fă o copie de siguranță a portofelului + + + + Wallet Data (*.dat) + Date portofel(*.dat) + + + + Backup Failed + Copia de rezerva a esuat + + + + There was an error trying to save the wallet data to the new location. + Eroare la încercarea de a salva datele portofelului în noua locaţie. + + + + %n second(s) + %n secundă%n secunde%n secunde + + + + %n minute(s) + %n minut%n minute%n minute + + + + %n hour(s) + %n oră%n ore%n ore + + + + %n day(s) + %n zi%n zile%n zile + + + + Not staking + Not staking + + + + A fatal error occurred. Arepacoin can no longer continue safely and will quit. + A apărut o eroare fatală. Arepacoin nu mai poate continua în condiții de siguranță și va iesi. + + + + ClientModel + + + Network Alert + Alertă rețea + + + + CoinControlDialog + + + Coin Control + Controlează moneda + + + + Quantity: + Cantitate: + + + + Bytes: + Octeţi: + + + + Amount: + Sumă: + + + + Priority: + Prioritate: + + + + Fee: + Taxa: + + + + Low Output: + Ieşire minimă: + + + + no + nu + + + + After Fee: + După taxe: + + + + Change: + Schimb: + + + + (un)select all + (de)selectaţi tot + + + + Tree mode + Modul arborescent + + + + List mode + Modul lista + + + + Amount + Sumă + + + + Label + Etichetă + + + + Address + Adresă + + + + Date + Data + + + + Confirmations + Confirmări + + + + Confirmed + Confirmat + + + + Priority + Prioritate + + + + Copy address + Copiază adresa + + + + Copy label + Copiază eticheta + + + + + Copy amount + Copiază suma + + + + Copy transaction ID + Copiază ID tranzacție + + + + Copy quantity + Copiaţi quantitea + + + + Copy fee + Copiaţi taxele + + + + Copy after fee + Copiaţi după taxe + + + + Copy bytes + Copiaţi octeţi + + + + Copy priority + Copiaţi prioritatea + + + + Copy low output + Copiaţi ieşire minimă: + + + + Copy change + Copiaţi schimb + + + + highest + cel mai mare + + + + high + mare + + + + medium-high + marime medie + + + + medium + mediu + + + + low-medium + mediu-scazut + + + + low + scazut + + + + lowest + cel mai scazut + + + + DUST + DUST + + + + yes + da + + + + This label turns red, if the transaction size is bigger than 10000 bytes. + + This means a fee of at least %1 per kb is required. + + Can vary +/- 1 Byte per input. + Aceasta eticheta se inroseste daca marimea tranzactiei este mai mare de 10000 bytes. + +Acest lucru inseamna ca este nevoie de o taxa de cel putin %1 pe kb + +Poate varia +/- 1 Byte pe imput. + + + + Transactions with higher priority get more likely into a block. + +This label turns red, if the priority is smaller than "medium". + + This means a fee of at least %1 per kb is required. + Tranzacțiile cu prioritate mai mare ajunge mult mai probabil într-un bloc + +Aceasta eticheta se inroseste daca prioritatea este mai mica decat "medium" + +Acest lucru inseamna ca este necesar un comision cel putin de %1 pe kB + + + + This label turns red, if any recipient receives an amount smaller than %1. + + This means a fee of at least %2 is required. + + Amounts below 0.546 times the minimum relay fee are shown as DUST. + Aceasta eticheta se inroseste daca oricare din contacte primeste o suma mai mica decat %1. + +Acest lucru inseamna ca un comision de cel putin %2 este necesar. + +Sume mai mici decat 0.546 ori minimul comisionului de relay sunt afisate ca DUST + + + + This label turns red, if the change is smaller than %1. + + This means a fee of at least %2 is required. + Această eticheta se înroseste dacă schimbul este mai mic de %1. + +Acest lucru înseamnă că o taxă de cel puțin %2 este necesară + + + + + (no label) + (fără etichetă) + + + + change from %1 (%2) + schimbă la %1(%2) + + + + (change) + (schimb) + + + + EditAddressDialog + + + Edit Address + Editează adresa + + + + &Label + &Etichetă + + + + The label associated with this address book entry + Eticheta asociată cu această intrare în agendă + + + + &Address + &Adresă + + + + The address associated with this address book entry. This can only be modified for sending addresses. + Adresa asociată cu această intrare în agendă. Acest lucru poate fi modificat numai pentru adresele de trimitere. + + + + New receiving address + Noua adresă de primire + + + + New sending address + Noua adresă de trimitere + + + + Edit receiving address + Editează adresa de primire + + + + Edit sending address + Editează adresa de trimitere + + + + The entered address "%1" is already in the address book. + Adresa introdusă "%1" se află deja în lista de adrese. + + + + The entered address "%1" is not a valid Arepacoin address. + Adresa introdusă "%1" nu este o adresă Arepacoin validă + + + + Could not unlock wallet. + Portofelul nu a putut fi deblocat. + + + + New key generation failed. + Generarea noii chei a eșuat. + + + + GUIUtil::HelpMessageBox + + + + Arepacoin-Qt + Arepacoin-Qt + + + + version + versiune + + + + Usage: + Utilizare: + + + + command-line options + Optiuni linie de comanda + + + + UI options + Setări UI + + + + Set language, for example "de_DE" (default: system locale) + Setează limba, de exemplu: "de_DE" (inițial: setare locală) + + + + Start minimized + Pornește miniaturizat + + + + Show splash screen on startup (default: 1) + Afișează ecran splash la pornire (implicit: 1) + + + + OptionsDialog + + + Options + Setări + + + + &Main + &Principal + + + + Optional transaction fee per kB that helps make sure your transactions are processed quickly. Most transactions are 1 kB. Fee 0.01 recommended. + Comision de tranzacție opțional pe kB, care vă ajută ca tranzacțiile sa fie procesate rapid. Majoritatea tranzactiilor sunt de 1 kB. Comision de 0.01 recomandat + + + + Pay transaction &fee + Plăteşte comision pentru tranzacţie &f + + + + Reserved amount does not participate in staking and is therefore spendable at any time. + Suma rezervată nu participă la maturare și, prin urmare, se poate cheltui în orice moment. + + + + Reserve + Rezervă + + + + Automatically start Arepacoin after logging in to the system. + Pornește Arepacoin imdiat după logarea în sistem + + + + &Start Arepacoin on system login + $Pornește Arepacoin la logarea în sistem + + + + Detach block and address databases at shutdown. This means they can be moved to another data directory, but it slows down shutdown. The wallet is always detached. + Detașați bloc și baze de date de adrese la închidere. Acest lucru înseamnă că pot fi mutate într-u alt director de date, dar incetineste închiderea. Portofelul este întotdeauna detașat. + + + + &Detach databases at shutdown + &Detasaza baza de date la inchidere + + + + &Network + &Retea + + + + Automatically open the Arepacoin client port on the router. This only works when your router supports UPnP and it is enabled. + Deschide automat portul pentru cientul Arepacoin pe router. Aces lucru este posibil doara daca routerul suporta UPnP si este activat + + + + Map port using &UPnP + Mapeaza portul folosind &UPnP + + + + Connect to the Arepacoin network through a SOCKS proxy (e.g. when connecting through Tor). + Conecteaza la reteaua Arepacoin prinr-un proxy SOCKS(ex. cand te conectezi prin Tor) + + + + &Connect through SOCKS proxy: + Conectează-te printr-un proxy socks + + + + Proxy &IP: + Proxy &IP: + + + + IP address of the proxy (e.g. 127.0.0.1) + Adresa IP a proxy-ului(ex. 127.0.0.1) + + + + &Port: + &Port: + + + + Port of the proxy (e.g. 9050) + Portul pe care se concetează proxy serverul (de exemplu: 9050) + + + + SOCKS &Version: + SOCKS &Versiune: + + + + SOCKS version of the proxy (e.g. 5) + Versiunea SOCKS a proxiului (ex. 5) + + + + &Window + &Fereastra + + + + Show only a tray icon after minimizing the window. + Afişează doar un icon in tray la ascunderea ferestrei + + + + &Minimize to the tray instead of the taskbar + &M Ascunde în tray în loc de taskbar + + + + Minimize instead of exit the application when the window is closed. When this option is enabled, the application will be closed only after selecting Quit in the menu. + Ascunde fereastra în locul părăsirii programului în momentul închiderii ferestrei. Când acestă opţiune e activă, aplicaţia se va opri doar în momentul selectării comenzii Quit din menu. + + + + M&inimize on close + &i Ascunde fereastra în locul închiderii programului + + + + &Display + &Afişare + + + + User Interface &language: + Interfata & limba userului + + + + The user interface language can be set here. This setting will take effect after restarting Arepacoin. + Limba interfeței utilizator poate fi setat aici. Această setare va avea efect după repornirea Arepacoin. + + + + &Unit to show amounts in: + &Unitatea de măsură pentru afişarea sumelor: + + + + Choose the default subdivision unit to show in the interface and when sending coins. + Alege subdiviziunea folosită la afişarea interfeţei şi la trimiterea de bitcoin. + + + + Whether to show Arepacoin addresses in the transaction list or not. + Dacă să arate adrese Arepacoin din lista de tranzacție sau nu. + + + + &Display addresses in transaction list + &Afişează adresele în lista de tranzacţii + + + + Whether to show coin control features or not. + Dacă să se afişeze controlul caracteristicilor monedei sau nu. + + + + Display coin &control features (experts only!) + Afiseaza &caracteristiclei de control ale monedei(numai experti!) + + + + &OK + & OK + + + + &Cancel + & Renunta + + + + &Apply + &Aplica + + + + default + Initial + + + + + Warning + Avertizare + + + + + This setting will take effect after restarting Arepacoin. + Aceasta setare va avea efect dupa repornirea Arepacoin. + + + + The supplied proxy address is invalid. + Adresa bitcoin pe care a-ti specificat-o este invalida + + + + OverviewPage + + + Form + Form + + + + + The displayed information may be out of date. Your wallet automatically synchronizes with the Arepacoin network after a connection is established, but this process has not completed yet. + Informatia afisata poate fi depasita. Portofel se sincronizează automat cu rețeaua Arepacoin după ce se stabilește o conexiune, dar acest proces nu s-a finalizat încă. + + + + Stake: + Stake: + + + + Unconfirmed: + Neconfirmat: + + + + Wallet + Portofel + + + + Spendable: + Cheltuibil: + + + + Your current spendable balance + Balanța ta curentă de cheltuieli + + + + Immature: + Nematurizat: + + + + Mined balance that has not yet matured + Balanta minata care nu s-a maturizat inca + + + + Total: + Total: + + + + Your current total balance + Balanța totală curentă + + + + <b>Recent transactions</b> + <b>Tranzacții recente</b> + + + + Total of transactions that have yet to be confirmed, and do not yet count toward the current balance + Total al tranzacțiilor care nu au fost confirmate încă și nu contează față de balanța curentă + + + + Total of coins that was staked, and do not yet count toward the current balance + Totalul de monede care au fost in stake si nu sunt numarate in balanta curenta + + + + + out of sync + Nu este sincronizat + + + + QRCodeDialog + + + QR Code Dialog + Dialog cod QR + + + + Request Payment + Cerere de plată + + + + Amount: + Cantitate: + + + + Label: + Etichetă + + + + Message: + Mesaj: + + + + &Save As... + &Salvează ca... + + + + Error encoding URI into QR Code. + Eroare la codarea URl-ului în cod QR. + + + + The entered amount is invalid, please check. + Suma introdusă nu este validă, vă rugăm să verificați. + + + + Resulting URI too long, try to reduce the text for label / message. + URI rezultat este prea lung, încearcă să reduci textul pentru etichetă / mesaj. + + + + Save QR Code + Salvează codul QR + + + + PNG Images (*.png) + Imagini PNG(*png) + + + + RPCConsole + + + Client name + Nume client + + + + + + + + + + + + + N/A + N/A + + + + Client version + Versiune client + + + + &Information + &Informație + + + + Using OpenSSL version + Foloseste versiunea OpenSSL + + + + Startup time + Durata pornirii + + + + Network + Rețea + + + + Number of connections + Numărul de conexiuni + + + + On testnet + Pe testnet + + + + Block chain + Lanț de blocuri + + + + Current number of blocks + Numărul curent de blocuri + + + + Estimated total blocks + Blocurile totale estimate + + + + Last block time + Data ultimului bloc + + + + &Open + &Deschide + + + + Command-line options + Optiuni linii de comandă + + + + Show the Arepacoin-Qt help message to get a list with possible Arepacoin command-line options. + Afișa mesajul de ajutor Arepacoin-Qt pentru a obține o listă cu posibile opțiuni de linie de comandă Arepacoin. + + + + &Show + &Arată + + + + &Console + &Consolă + + + + Build date + Construit la data + + + + Arepacoin - Debug window + Arepacoin - fereastră depanare + + + + Arepacoin Core + Arepacoin Core + + + + Debug log file + Loguri debug + + + + Open the Arepacoin debug log file from the current data directory. This can take a few seconds for large log files. + Deschideti fisierul de depanare Arepacoin din folderul curent. Acest lucru poate dura cateva secunde pentru fisiere de log mari. + + + + Clear console + Curăță consola + + + + Welcome to the Arepacoin RPC console. + Bine ati venit la consola Arepacoin RPC. + + + + Use up and down arrows to navigate history, and <b>Ctrl-L</b> to clear screen. + Foloseste sagetile sus si jos pentru a naviga in istoric si <b>Ctrl-L</b> pentru a curata. + + + + Type <b>help</b> for an overview of available commands. + Scrie <b>help</b> pentru a vedea comenzile disponibile + + + + SendCoinsDialog + + + + + + + + + + Send Coins + Trimite monede + + + + Coin Control Features + Caracteristici control ale monedei + + + + Inputs... + Intrări + + + + automatically selected + Selectie automatică + + + + Insufficient funds! + Fonduri insuficiente! + + + + Quantity: + Cantitate: + + + + + 0 + 0 + + + + Bytes: + Octeţi: + + + + Amount: + Sumă: + + + + + + + 0.00 BC + 123.456 BC {0.00 ?} + + + + Priority: + Prioritate: + + + + medium + mediu + + + + Fee: + Taxa: + + + + Low Output: + Ieşire minimă: + + + + no + nu + + + + After Fee: + După taxe: + + + + Change + Schimbă: + + + + custom change address + personalizează schimbarea adresei + + + + Send to multiple recipients at once + Trimite simultan către mai mulți destinatari + + + + Add &Recipient + &Adaugă destinatar + + + + Remove all transaction fields + Scoateți toate câmpuirile de tranzacții + + + + Clear &All + Șterge &tot + + + + Balance: + Balanță: + + + + 123.456 BC + 123.456 BC + + + + Confirm the send action + Confirmă operațiunea de trimitere + + + + S&end + &S Trimite + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + Introduceți o adresă Arepacoin(ex:AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + Copy quantity + Copiaţi quantitea + + + + Copy amount + Copiază suma + + + + Copy fee + Copiaţi taxele + + + + Copy after fee + Copiaţi după taxe + + + + Copy bytes + Copiaţi octeţi + + + + Copy priority + Copiaţi prioritatea + + + + Copy low output + Copiaţi ieşire minimă: + + + + Copy change + Copiaţi schimb + + + + <b>%1</b> to %2 (%3) + <b>%1</b> to %2 (%3) + + + + Confirm send coins + Confirmă trimiterea de monede + + + + Are you sure you want to send %1? + Sunteți sigur că doriți să trimiteți %1? + + + + and + și + + + + The recipient address is not valid, please recheck. + Adresa destinatarului nu este validă, vă rugăm să o verificaţi. + + + + The amount to pay must be larger than 0. + Suma de plată trebuie să fie mai mare decât 0. + + + + The amount exceeds your balance. + Suma depășește soldul contului. + + + + The total exceeds your balance when the %1 transaction fee is included. + Totalul depășește soldul contului dacă se include și plata comisionului de %1. + + + + Duplicate address found, can only send to each address once per send operation. + S-a descoperit o adresă care figurează de două ori. Expedierea se poate realiza către fiecare adresă doar o singură dată pe operațiune. + + + + Error: Transaction creation failed. + Eroare: crearea tranzacției a eșuat. + + + + 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. + Eroare: tranzacția a fost respinsă. Acest lucru s-ar putea întâmpla în cazul în care unele dintre monedele din portofel au fost deja cheltuite, cum si cum ați utilizat o copie a wallet.dat și monedele au fost cheltuite în copie dar nu au fost marcate ca și cheltuite aici. + + + + WARNING: Invalid Arepacoin address + Atenție: Adresă Arepacoin invalidă + + + + (no label) + (fără etichetă) + + + + WARNING: unknown change address + ATENTIE: adresa schimb necunoscuta + + + + SendCoinsEntry + + + Form + Formular + + + + A&mount: + Su&mă: + + + + Pay &To: + Plătește că&tre: + + + + + Enter a label for this address to add it to your address book + Introdu o etichetă pentru această adresă pentru a fi adăugată în lista ta de adrese + + + + &Label: + &Etichetă: + + + + The address to send the payment to (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + Adresa catre care trimiteti plata(ex. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + Choose address from address book + Alegeti adresa din agenda + + + + Alt+A + Alt+A + + + + Paste address from clipboard + Lipește adresa din clipboard + + + + Alt+P + Alt+P + + + + Remove this recipient + Scoateti acest destinatar + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + Introduceți o adresă Arepacoin(ex:AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + SignVerifyMessageDialog + + + Signatures - Sign / Verify a Message + Semnatura- Semneaza/verifica un mesaj + + + + + &Sign Message + Semneaza Mesajul + + + + You can sign messages with your addresses to prove you own them. Be careful not to sign anything vague, as phishing attacks may try to trick you into signing your identity over to them. Only sign fully-detailed statements you agree to. + Puteti semna mesaje cu adresa dumneavoastra pentru a demostra ca sunteti proprietarul lor. Aveti grija sa nu semnati nimic vag, deoarece atacurile de tip phishing va pot pacali sa le transferati identitatea. Semnati numai declaratiile detaliate cu care sunteti deacord. + + + + The address to sign the message with (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + Adresa cu care semnati mesajul(ex. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Choose an address from the address book + Alegeti o adresa din agenda + + + + + Alt+A + Alt+A + + + + Paste address from clipboard + Lipiţi adresa copiată in clipboard. + + + + Alt+P + Alt+P + + + + Enter the message you want to sign here + Introduce mesajul pe care vrei sa il semnezi, aici. + + + + Copy the current signature to the system clipboard + Copiaza semnatura curenta in clipboard-ul sistemului + + + + Sign the message to prove you own this Arepacoin address + Semnează un mesaj pentru a dovedi că dețineti o adresă Arepacoin + + + + Reset all sign message fields + Reseteaza toate spatiile mesajelor semnate. + + + + + Clear &All + Şterge &tot + + + + + &Verify Message + Verifica mesajul + + + + Enter the signing address, message (ensure you copy line breaks, spaces, tabs, etc. exactly) and signature below to verify the message. Be careful not to read more into the signature than what is in the signed message itself, to avoid being tricked by a man-in-the-middle attack. + Introduceti adresa de semnatura, mesajul (asigurati-va ca ati copiat spatiile, taburile etc. exact) si semnatura dedesubt pentru a verifica mesajul. Aveti grija sa nu cititi mai mult in semnatura decat mesajul in sine, pentru a evita sa fiti pacaliti de un atac de tip man-in-the-middle. + + + + The address the message was signed with (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + Adresa cu care a fost semnat mesajul(ex. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + Verify the message to ensure it was signed with the specified Arepacoin address + Verifică un mesaj pentru a vă asigura că a fost semnat cu o anumită adresă Arepacoin + + + + Reset all verify message fields + Reseteaza toate spatiile mesajelor semnate. + + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + Introduceți o adresă Arepacoin(ex:AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + Click "Sign Message" to generate signature + Click "Semneaza msajul" pentru a genera semnatura + + + + Enter Arepacoin signature + Introduceti semnatura Arepacoin + + + + + The entered address is invalid. + Adresa introdusa nu este valida + + + + + + + Please check the address and try again. + Te rugam verifica adresa si introduce-o din nou + + + + + The entered address does not refer to a key. + Adresa introdusa nu se refera la o cheie. + + + + Wallet unlock was cancelled. + Blocarea portofelului a fost intrerupta + + + + Private key for the entered address is not available. + Cheia privata pentru adresa introdusa nu este valida. + + + + Message signing failed. + Semnarea mesajului a esuat + + + + Message signed. + Mesaj Semnat! + + + + The signature could not be decoded. + Aceasta semnatura nu a putut fi decodata + + + + + Please check the signature and try again. + Verifica semnatura si incearca din nou + + + + The signature did not match the message digest. + Semnatura nu seamana! + + + + Message verification failed. + Verificarea mesajului a esuat + + + + Message verified. + Mesaj verificat + + + + TransactionDesc + + + Open until %1 + Deschis până la %1 + + + + Open for %n block(s) + Deschde pentru încă %1 blocDeschde pentru încă %1 blocuriDeschde pentru încă %1 blocuri + + + + conflicted + conflictual + + + + %1/offline + %1/deconectat + + + + %1/unconfirmed + %1/neconfirmat + + + + %1 confirmations + %1 confirmări + + + + Status + Stare + + + + , broadcast through %n node(s) + , distribuit prin %n nod, distribuit prin %n noduri, distribuit prin %n de noduri + + + + Date + Data + + + + Source + Sursa + + + + Generated + Generat + + + + + From + De la + + + + + + To + Către + + + + + own address + Adresa posedata + + + + label + etichetă + + + + + + + + Credit + Credit + + + + matures in %n more block(s) + se maturizează în încă %n blocse maturizează în încă %n blocurise maturizează în încă %n de blocuri + + + + not accepted + nu este acceptat + + + + + + + Debit + Debit + + + + Transaction fee + Comisionul tranzacţiei + + + + Net amount + Suma netă + + + + Message + Mesaj + + + + Comment + Comentarii + + + + Transaction ID + ID-ul tranzactiei + + + + Generated coins must mature 6 blocks before they can be spent. When you generated this block, it was broadcast to the network to be added to the block chain. If it fails to get into the chain, its state will change to "not accepted" and it won't be spendable. This may occasionally happen if another node generates a block within a few seconds of yours. + Monedele generate trebuie să se maturizeze 6 blocuri înainte de a fi cheltuite. Când ați generat acest bloc, a fost trimis la rețea pentru a fi adăugat la lanțul de blocuri. În cazul în care nu reușește să intre în lanț, starea sa se ​​va schimba in "nu a fost acceptat", și nu va putea fi cheltuit. Acest lucru se poate întâmpla din când în când, dacă un alt nod generează un bloc cu câteva secunde inaintea blocului tau. + + + + Debug information + Informatii pentru debug + + + + Transaction + Tranzacţie + + + + Inputs + Intrari + + + + Amount + Sumă + + + + true + Adevarat! + + + + false + Fals! + + + + , has not been successfully broadcast yet + , nu s-a propagat încă + + + + unknown + necunoscut + + + + TransactionDescDialog + + + Transaction details + Detaliile tranzacției + + + + This pane shows a detailed description of the transaction + Acest panou afișează o descriere detaliată a tranzacției + + + + TransactionTableModel + + + Date + Data + + + + Type + Tipul + + + + Address + Adresa + + + + Amount + Cantitate + + + + Open until %1 + Deschis până la %1 + + + + Confirmed (%1 confirmations) + Confirmat (%1 confirmări) + + + + Open for %n more block(s) + Deschis pentru încă %1 blocDeschis pentru încă %1 blocuriDeschis pentru încă %1 de blocuri + + + + Offline + Deconectat + + + + Unconfirmed + Neconfirmat + + + + Confirming (%1 of %2 recommended confirmations) + Confirmare (%1 dintre %2 confirmări recomandate) + + + + Conflicted + Conflictual + + + + Immature (%1 confirmations, will be available after %2) + Nematurate(%1 confirmari, vor fi valabile dupa %2) + + + + This block was not received by any other nodes and will probably not be accepted! + Acest bloc nu a fost recepționat de niciun alt nod și probabil nu va fi acceptat! + + + + Generated but not accepted + Generat dar neacceptat + + + + Received with + Recepționat cu + + + + Received from + Primit de la + + + + Sent to + Trimis către + + + + Payment to yourself + Plată către tine + + + + Mined + Produs + + + + (n/a) + (n/a) + + + + Transaction status. Hover over this field to show number of confirmations. + Starea tranzacției. Treci cu mausul peste acest câmp pentru afișarea numărului de confirmări. + + + + Date and time that the transaction was received. + Data și ora la care a fost recepționată tranzacția. + + + + Type of transaction. + Tipul tranzacției. + + + + Destination address of transaction. + Adresa de destinație a tranzacției. + + + + Amount removed from or added to balance. + Suma extrasă sau adăugată la sold. + + + + TransactionView + + + + All + Toate + + + + Today + Astăzi + + + + This week + Săptămâna aceasta + + + + This month + Luna aceasta + + + + Last month + Luna trecută + + + + This year + Anul acesta + + + + Range... + Între... + + + + Received with + Recepționat cu + + + + Sent to + Trimis către + + + + To yourself + Către tine + + + + Mined + Produs + + + + Other + Altele + + + + Enter address or label to search + Introdu adresa sau eticheta pentru căutare + + + + Min amount + Cantitatea minimă + + + + Copy address + Copiază adresa + + + + Copy label + Copiază eticheta + + + + Copy amount + Copiază suma + + + + Copy transaction ID + Copiază ID tranzacție + + + + Edit label + Editează eticheta + + + + Show transaction details + Arată detaliile tranzacției + + + + Export Transaction Data + Exporta datele trazactiei + + + + Comma separated file (*.csv) + Fișier text cu valori separate prin virgulă (*.csv) + + + + Confirmed + Confirmat + + + + Date + Data + + + + Type + Tipul + + + + Label + Etichetă + + + + Address + Adresă + + + + Amount + Sumă + + + + ID + ID + + + + Error exporting + Eroare la exportare + + + + Could not write to file %1. + Nu s-a putut scrie în fișier %1. + + + + Range: + Interval: + + + + to + către + + + + WalletModel + + + Sending... + Se trimite... + + + + bitcoin-core + + + Arepacoin version + Versiune Arepacoin + + + + Usage: + Uz: + + + + Send command to -server or arepacoind + Trimite comanda catre server sau arepacoind + + + + List commands + Listă de comenzi + + + + Get help for a command + Ajutor pentru o comandă + + + + Options: + Setări: + + + + Specify configuration file (default: arepacoin.conf) + Specifica fisier de configurare(implicit: arepacoin.conf) + + + + Specify pid file (default: arepacoind.pid) + Speficica fisier pid(implicit: arepacoin.pid) + + + + Specify wallet file (within data directory) + Specifică fișierul wallet (în dosarul de date) + + + + Specify data directory + Specifică dosarul de date + + + + Set database cache size in megabytes (default: 25) + Setează mărimea cache a bazei de date în megabiți (implicit: 25) + + + + Set database disk log size in megabytes (default: 100) + Setează mărimea cache a bazei de date în megabiți (implicit: 100) + + + + Listen for connections on <port> (default: 9853 or testnet: 19853) + Ascultă pentru conectări pe <port> (implicit: 9853 sau testnet: 19853) + + + + Maintain at most <n> connections to peers (default: 125) + Menține cel mult <n> conexiuni cu partenerii (implicit: 125) + + + + Connect to a node to retrieve peer addresses, and disconnect + Conectează-te la nod pentru a obține adresele partenerilor, și apoi deconectează-te + + + + Specify your own public address + Specifică adresa ta publică + + + + Bind to given address. Use [host]:port notation for IPv6 + Leaga la o adresa data. Utilizeaza notatie [host]:port pt IPv6 + + + + Stake your coins to support network and gain reward (default: 1) + Pune monedele in modul stake pentru a ajuta reteaua si a castiva bonusuri(implicit: 1) + + + + Threshold for disconnecting misbehaving peers (default: 100) + Prag pentru deconectarea partenerilor care nu funcționează corect (implicit: 100) + + + + Number of seconds to keep misbehaving peers from reconnecting (default: 86400) + Numărul de secunde pentru a preveni reconectarea partenerilor care nu funcționează corect (implicit: 86400) + + + + An error occurred while setting up the RPC port %u for listening on IPv4: %s + A intervenit o eroare in timp ce se seta portul RPC %u pentru ascultare pe IPv4: %s + + + + Detach block and address databases. Increases shutdown time (default: 0) + Detaseaza bloc si baza de date de adrese. Creste timpul de inchidere(implicit:0) + + + + 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. + Eroare: tranzacția a fost respinsă. Acest lucru s-ar putea întâmpla în cazul în care unele dintre monedele din portofel au fost deja cheltuite, cum si cum ați utilizat o copie a wallet.dat și monedele au fost cheltuite în copie dar nu au fost marcate ca și cheltuite aici. + + + + Error: This transaction requires a transaction fee of at least %s because of its amount, complexity, or use of recently received funds + Eroare: Această tranzacție necesită un comision de tranzacție de cel puțin %s din cauza valorii sale, complexitate, sau utilizarea de fonduri recent primite + + + + Listen for JSON-RPC connections on <port> (default: 9852 or testnet: 19852) + Ascultă pentru conexiuni JSON-RPC pe <port> (implicit:9852 sau testnet: 19852) + + + + Accept command line and JSON-RPC commands + Se acceptă comenzi din linia de comandă și comenzi JSON-RPC + + + + Error: Transaction creation failed + Eroare: crearea tranzacției a eșuat. + + + + Error: Wallet locked, unable to create transaction + Eroare: portofel blocat, tranzactia nu s-a creat + + + + Importing blockchain data file. + Se importa fisierul blockchain + + + + Importing bootstrap blockchain data file. + Se importa fisierul bootstrap blockchain + + + + Run in the background as a daemon and accept commands + Rulează în fundal ca un demon și acceptă comenzi + + + + Use the test network + Utilizează rețeaua de test + + + + Accept connections from outside (default: 1 if no -proxy or -connect) + Acceptă conexiuni din afară (implicit: 1 dacă nu se folosește -proxy sau -connect) + + + + An error occurred while setting up the RPC port %u for listening on IPv6, falling back to IPv4: %s + A intervenit o eroare in timp ce se seta portul RPC %u pentru ascultare pe IPv6, reintoarcere la IPv4: %s + + + + Error initializing database environment %s! To recover, BACKUP THAT DIRECTORY, then remove everything from it except for wallet.dat. + Eroare la inițializarea mediu de baze de date %s! Pentru a recupera, SALVATI ACEL DIRECTORr, apoi scoateți totul din el, cu excepția wallet.dat. + + + + Set maximum size of high-priority/low-fee transactions in bytes (default: 27000) + Setati valoarea maxima a prioritate mare/taxa scazuta in bytes(implicit: 27000) + + + + Warning: -paytxfee is set very high! This is the transaction fee you will pay if you send a transaction. + Atentie: setarea -paytxfee este foarte ridicata! Aceasta este taxa tranzactiei pe care o vei plati daca trimiti o tranzactie. + + + + Warning: Please check that your computer's date and time are correct! If your clock is wrong Arepacoin will not work properly. + Atentie: Va rugam verificati ca timpul si data calculatorului sunt corete. Daca timpul este gresit Arepacoin nu va functiona corect. + + + + Warning: error reading wallet.dat! All keys read correctly, but transaction data or address book entries might be missing or incorrect. + Atentie: eroare la citirea fisierului wallet.dat! Toate cheile sunt citite corect, dar datele tranzactiei sau anumite intrari din agenda sunt incorecte sau lipsesc. + + + + Warning: wallet.dat corrupt, data salvaged! Original wallet.dat saved as wallet.{timestamp}.bak in %s; if your balance or transactions are incorrect you should restore from a backup. + Atentie: fisierul wallet.dat este corupt, date salvate! Fisierul original wallet.dat a fost salvat ca wallet.{timestamp}.bak in %s; daca balansul sau tranzactiile sunt incorecte ar trebui sa restaurati dintr-o copie de siguranta. + + + + Attempt to recover private keys from a corrupt wallet.dat + Încearcă recuperarea cheilor private dintr-un wallet.dat corupt + + + + Block creation options: + Optiuni creare block + + + + Connect only to the specified node(s) + Conecteaza-te doar la nod(urile) specifice + + + + Discover own IP address (default: 1 when listening and no -externalip) + Descopera propria ta adresa IP (intial: 1) + + + + Failed to listen on any port. Use -listen=0 if you want this. + Am esuat ascultarea pe orice port. Folositi -listen=0 daca vreti asta. + + + + Find peers using DNS lookup (default: 1) + Gaseste peers folosind cautare DNS(implicit: 1) + + + + Sync checkpoints policy (default: strict) + Sincronizeaza politica checkpoint(implicit: strict) + + + + Invalid -tor address: '%s' + Adresa -tor invalida: '%s' + + + + Invalid amount for -reservebalance=<amount> + Suma invalida pentru -reservebalance=<amount> + + + + Maximum per-connection receive buffer, <n>*1000 bytes (default: 5000) + Tampon maxim pentru recepție per conexiune, <n>*1000 baiți (implicit: 5000) + + + + Maximum per-connection send buffer, <n>*1000 bytes (default: 1000) + Tampon maxim pentru transmitere per conexiune, <n>*1000 baiți (implicit: 1000) + + + + Only connect to nodes in network <net> (IPv4, IPv6 or Tor) + Efectuează conexiuni doar către nodurile din rețeaua <net> (IPv4, IPv6 sau Tor) + + + + Output extra debugging information. Implies all other -debug* options + Extra informatii despre depanare. Implica toate optiunile -debug* + + + + Output extra network debugging information + Extra informatii despre depanare retea. + + + + Prepend debug output with timestamp + Ataseaza output depanare cu log de timp + + + + SSL options: (see the Bitcoin Wiki for SSL setup instructions) + Optiuni SSl (vezi Bitcoin wiki pentru intructiunile de instalare) + + + + Select the version of socks proxy to use (4-5, default: 5) + Selectati versiunea de proxy socks(4-5, implicit: 5) + + + + Send trace/debug info to console instead of debug.log file + Trimite informațiile trace/debug la consolă în locul fișierului debug.log + + + + Send trace/debug info to debugger + Trimite informațiile trace/debug la consolă + + + + Set maximum block size in bytes (default: 250000) + Setează mărimea maxima a blocului în bytes (implicit: 250000) + + + + Set minimum block size in bytes (default: 0) + Setează mărimea minimă a blocului în baiți (implicit: 0) + + + + Shrink debug.log file on client startup (default: 1 when no -debug) + Micsorati fisierul debug.log la inceperea clientului (implicit: 1 cand nu -debug) + + + + Specify connection timeout in milliseconds (default: 5000) + Specifică intervalul maxim de conectare în milisecunde (implicit: 5000) + + + + Unable to sign checkpoint, wrong checkpointkey? + + În imposibilitatea de a semna checkpoint-ul, checkpointkey greșit? + + + + + Use UPnP to map the listening port (default: 0) + Foloseste UPnP pentru a vedea porturile (initial: 0) + + + + Use UPnP to map the listening port (default: 1 when listening) + Foloseste UPnP pentru a vedea porturile (initial: 1 cand listezi) + + + + Use proxy to reach tor hidden services (default: same as -proxy) + Utilizati proxy pentru a ajunge la serviciile tor (implicit: la fel ca proxy) + + + + Username for JSON-RPC connections + Utilizator pentru conexiunile JSON-RPC + + + + Verifying database integrity... + Se verifica integritatea bazei de date... + + + + WARNING: syncronized checkpoint violation detected, but skipped! + ATENTIONARE: s-a detectat o violare a checkpoint-ului sincronizat, dar s-a ignorat! + + + + Warning: Disk space is low! + Avertisment: spațiul pe disc este scăzut! + + + + Warning: This version is obsolete, upgrade required! + Atenție: această versiune este depășită, este necesară actualizarea! + + + + wallet.dat corrupt, salvage failed + wallet.dat corupt, recuperare eșuată + + + + Password for JSON-RPC connections + Parola pentru conexiunile JSON-RPC + + + + %s, you must set a rpcpassword in the configuration file: + %s +It is recommended you use the following random password: +rpcuser=arepacoinrpc +rpcpassword=%s +(you do not need to remember this password) +The username and password MUST NOT be the same. +If the file does not exist, create it with owner-readable-only file permissions. +It is also recommended to set alertnotify so you are notified of problems; +for example: alertnotify=echo %%s | mail -s "Arepacoin Alert" admin@foo.com + + %s, trebuie să configurați o parolă rpc în fișierul de configurare: %s +Este recomandat să folosiți următoarea parolă generată aleator: rpcuser=arepacoinrpc +rpcpassword=%s +(nu trebuie să țineți minte această parolă) +Username-ul și parola NU TREBUIE să fie aceleași. +Dacă fișierul nu există, creați-l cu drepturi de citire doar de către deținător. +Este deasemenea recomandat să setați alertnotify pentru a fi notificat de probleme; +de exemplu: alertnotify=echo %%s | mail -s "Arepacoin Alert" admin@foo.com + + + + + Find peers using internet relay chat (default: 0) + Gaseste noduri fosoling irc (implicit: 1) {0)?} + + + + Sync time with other nodes. Disable if time on your system is precise e.g. syncing with NTP (default: 1) + Sincronizează timp cu alte noduri. Dezactivează daca timpul de pe sistemul dumneavoastră este precis ex: sincronizare cu NTP (implicit: 1) + + + + When creating transactions, ignore inputs with value less than this (default: 0.01) + Când creați tranzacții, ignorați intrări cu valori mai mici decât aceasta (implicit: 0,01) + + + + Allow JSON-RPC connections from specified IP address + Permite conexiuni JSON-RPC de la adresa IP specificată + + + + Send commands to node running on <ip> (default: 127.0.0.1) + Trimite comenzi la nodul care rulează la <ip> (implicit: 127.0.0.1) + + + + Execute command when the best block changes (%s in cmd is replaced by block hash) + Execută comanda când cel mai bun bloc se modifică (%s în cmd este înlocuit cu hash-ul blocului) + + + + Execute command when a wallet transaction changes (%s in cmd is replaced by TxID) + Executati comanda cand o tranzactie a portofelului se schimba (%s in cmd este inlocuit de TxID) + + + + Require a confirmations for change (default: 0) + Necesita confirmari pentru schimbare (implicit: 0) + + + + Enforce transaction scripts to use canonical PUSH operators (default: 1) + Enforseaza tranzactiile script sa foloseasca operatori canonici PUSH(implicit: 1) + + + + Execute command when a relevant alert is received (%s in cmd is replaced by message) + Execută o comandă când o alerta relevantâ este primitâ(%s in cmd este înlocuit de mesaj) + + + + Upgrade wallet to latest format + Actualizează portofelul la ultimul format + + + + Set key pool size to <n> (default: 100) + Setează mărimea bazinului de chei la <n> (implicit: 100) + + + + Rescan the block chain for missing wallet transactions + Rescanează lanțul de bloc pentru tranzacțiile portofel lipsă + + + + How many blocks to check at startup (default: 2500, 0 = all) + Câte block-uri se verifică la initializare (implicit: 2500, 0 = toate) + + + + How thorough the block verification is (0-6, default: 1) + Cat de temeinica sa fie verificarea blocurilor( 0-6, implicit: 1) + + + + Imports blocks from external blk000?.dat file + Importă blocuri dintr-un fișier extern blk000?.dat + + + + Use OpenSSL (https) for JSON-RPC connections + Folosește OpenSSL (https) pentru conexiunile JSON-RPC + + + + Server certificate file (default: server.cert) + Certificatul serverului (implicit: server.cert) + + + + Server private key (default: server.pem) + Cheia privată a serverului (implicit: server.pem) + + + + Acceptable ciphers (default: TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH) + Cifruri acceptabile (implicit: TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH) + + + + Error: Wallet unlocked for staking only, unable to create transaction. + Eroare: portofel blocat doar pentru staking, tranzactia nu s-a creat. + + + + WARNING: Invalid checkpoint found! Displayed transactions may not be correct! You may need to upgrade, or notify developers. + ATENTIONARE: checkpoint invalid! Trazatiile afisate pot fi incorecte! Posibil să aveți nevoie să faceți upgrade, sau să notificati dezvoltatorii. + + + + This help message + Acest mesaj de ajutor + + + + Wallet %s resides outside data directory %s. + Portofelul %s este in afara directorului %s + + + + Cannot obtain a lock on data directory %s. Arepacoin is probably already running. + Nu se poate obtine un lock pe directorul de date &s. Blackoin probabil ruleaza deja. + + + + Arepacoin + Arepacoin + + + + Unable to bind to %s on this computer (bind returned error %d, %s) + Nu se poate folosi %s pe acest calculator (eroarea returnată este %d, %s) + + + + Connect through socks proxy + Conectează-te printr-un proxy socks + + + + Allow DNS lookups for -addnode, -seednode and -connect + Permite căutări DNS pentru -addnode, -seednode și -connect + + + + Loading addresses... + Încarc adrese... + + + + Error loading blkindex.dat + Eroare la încărcarea blkindex.dat + + + + Error loading wallet.dat: Wallet corrupted + Eroare la încărcarea wallet.dat: Portofel corupt + + + + Error loading wallet.dat: Wallet requires newer version of Arepacoin + Eroare la încărcarea wallet.dat: Portofelul necesita o versiune mai noua de Arepacoin + + + + Wallet needed to be rewritten: restart Arepacoin to complete + A fost nevoie de rescrierea portofelului: restartați Arepacoin pentru a finaliza + + + + Error loading wallet.dat + Eroare la încărcarea wallet.dat + + + + Invalid -proxy address: '%s' + Adresa -proxy nevalidă: '%s' + + + + Unknown network specified in -onlynet: '%s' + Rețeaua specificată în -onlynet este necunoscută: '%s' + + + + Unknown -socks proxy version requested: %i + S-a cerut o versiune necunoscută de proxy -socks: %i + + + + Cannot resolve -bind address: '%s' + Nu se poate rezolva adresa -bind: '%s' + + + + Cannot resolve -externalip address: '%s' + Nu se poate rezolva adresa -externalip: '%s' + + + + Invalid amount for -paytxfee=<amount>: '%s' + Suma nevalidă pentru -paytxfee=<amount>: '%s' + + + + Error: could not start node + Eroare: nodul nu a putut fi pornit + + + + Sending... + Se trimite... + + + + Invalid amount + Sumă nevalidă + + + + Insufficient funds + Fonduri insuficiente + + + + Loading block index... + Încarc indice bloc... + + + + Add a node to connect to and attempt to keep the connection open + Adaugă un nod la care te poți conecta pentru a menține conexiunea deschisă + + + + Unable to bind to %s on this computer. Arepacoin is probably already running. + Imposibil de conectat %s pe acest computer. Cel mai probabil Arepacoin ruleaza + + + + Fee per KB to add to transactions you send + Comision pe kB de adaugat la tranzactiile pe care le trimiti + + + + Invalid amount for -mininput=<amount>: '%s' + Suma invalida pentru -mininput=<amount>: '%s' + + + + Loading wallet... + Încarc portofel... + + + + Cannot downgrade wallet + Nu se poate retrograda portofelul + + + + Cannot initialize keypool + Nu se poate initializa keypool + + + + Cannot write default address + Nu se poate scrie adresa implicită + + + + Rescanning... + Rescanez... + + + + Done loading + Încărcare terminată + + + + To use the %s option + Pentru a folosi opțiunea %s + + + + Error + Eroare + + + + You must set rpcpassword=<password> in the configuration file: +%s +If the file does not exist, create it with owner-readable-only file permissions. + Trebuie sa setezi rpcpassword=<password> în fișierul de configurare:⏎ +%s⏎ +Dacă fișierul nu există, creează-l cu permisiuni de citire doar de către proprietar. + + + \ No newline at end of file diff --git a/src/qt/locale/bitcoin_ru.ts b/src/qt/locale/bitcoin_ru.ts new file mode 100755 index 0000000..cff107d --- /dev/null +++ b/src/qt/locale/bitcoin_ru.ts @@ -0,0 +1,3290 @@ + + + AboutDialog + + + About Arepacoin + О Arepacoin + + + + <b>Arepacoin</b> version + <b>Arepacoin</b> версия + + + + Copyright © 2009-2014 The Bitcoin developers +Copyright © 2012-2014 The NovaCoin developers +Copyright © 2014 The Arepacoin developers + Все права защищены © 2009-2014 Разработчики Bitcoin +Все права защищены © 2012-2014 Разработчики NovaCoin +Все права защищены © 2014 Разработчики Arepacoin + + + + +This is experimental software. + +Distributed under the MIT/X11 software license, see the accompanying file COPYING or http://www.opensource.org/licenses/mit-license.php. + +This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit (http://www.openssl.org/) and cryptographic software written by Eric Young (eay@cryptsoft.com) and UPnP software written by Thomas Bernard. + +Это экспериментальная программа. + +Распространяется на правах лицензии MIT/X11, см. файл license.txt или http://www.opensource.org/licenses/mit-license.php. + +Этот продукт включает ПО, разработанное OpenSSL Project для использования в OpenSSL Toolkit (http://www.openssl.org/) и криптографическое ПО, написанное Eric Young (eay@cryptsoft.com) и ПО для работы с UPnP, написанное Thomas Bernard. + + + + AddressBookPage + + + Address Book + Адресная книга + + + + Double-click to edit address or label + Для того, чтобы изменить адрес или метку давжды кликните по изменяемому объекту + + + + Create a new address + Создать новый адрес + + + + Copy the currently selected address to the system clipboard + Копировать текущий выделенный адрес в буфер обмена + + + + &New Address + &Новый адрес + + + + These are your Arepacoin addresses for receiving payments. You may want to give a different one to each sender so you can keep track of who is paying you. + Это Ваши адреса для получения платежей. Вы можете дать разные адреса отправителям, чтобы отслеживать, кто именно вам платит. + + + + &Copy Address + &Копировать адрес + + + + Show &QR Code + Показать &QR код + + + + Sign a message to prove you own a Arepacoin address + Подписать сообщение, чтобы доказать владение адресом Arepacoin + + + + Sign &Message + &Подписать сообщение + + + + Delete the currently selected address from the list + Удалить выбранный адрес из списка + + + + Verify a message to ensure it was signed with a specified Arepacoin address + Проверить сообщение, чтобы убедиться, что оно было подписано указанным адресом Arepacoin + + + + &Verify Message + &Проверить сообщение + + + + &Delete + &Удалить + + + + Copy &Label + Копировать &метку + + + + &Edit + &Правка + + + + Export Address Book Data + Экспортировать адресную книгу + + + + Comma separated file (*.csv) + Текст, разделённый запятыми (*.csv) + + + + Error exporting + Ошибка экспорта + + + + Could not write to file %1. + Невозможно записать в файл %1. + + + + AddressTableModel + + + Label + Метка + + + + Address + Адрес + + + + (no label) + [нет метки] + + + + AskPassphraseDialog + + + Passphrase Dialog + Диалог ввода пароля + + + + Enter passphrase + Введите пароль + + + + New passphrase + Новый пароль + + + + Repeat new passphrase + Повторите новый пароль + + + + Serves to disable the trivial sendmoney when OS account compromised. Provides no real security. + Служит для предотвращения тривиальной отправки монет, если ваша система скомпрометирована. Не предоставляет реальной безопасности. + + + + For staking only + Только для участия в доле + + + + Enter the new passphrase to the wallet.<br/>Please use a passphrase of <b>10 or more random characters</b>, or <b>eight or more words</b>. + Введите новый пароль для бумажника. <br/> Пожалуйста, используйте фразы из <b>10 или более случайных символов,</b> или <b>восьми и более слов.</b> + + + + Encrypt wallet + Зашифровать бумажник + + + + This operation needs your wallet passphrase to unlock the wallet. + Для выполнения операции требуется пароль вашего бумажника. + + + + Unlock wallet + Разблокировать бумажник + + + + This operation needs your wallet passphrase to decrypt the wallet. + Для выполнения операции требуется пароль вашего бумажника. + + + + Decrypt wallet + Расшифровать бумажник + + + + Change passphrase + Сменить пароль + + + + Enter the old and new passphrase to the wallet. + Введите старый и новый пароль для бумажника. + + + + Confirm wallet encryption + Подтвердите шифрование бумажника + + + + Warning: If you encrypt your wallet and lose your passphrase, you will <b>LOSE ALL OF YOUR COINS</b>! + Внимание: если вы зашифруете бумажник и потеряете пароль, вы <b>ПОТЕРЯЕТЕ ВСЕ ВАШИ МОНЕТЫ</b>! + + + + Are you sure you wish to encrypt your wallet? + Вы уверены, что хотите зашифровать ваш бумажник? + + + + IMPORTANT: Any previous backups you have made of your wallet file should be replaced with the newly generated, encrypted wallet file. For security reasons, previous backups of the unencrypted wallet file will become useless as soon as you start using the new, encrypted wallet. + ВАЖНО: все предыдущие резервные копии вашего кошелька должны быть заменены новым зашифрованным файлом. В целях безопасности предыдущие резервные копии нешифрованного кошелька станут бесполезны, как только вы начнёте использовать новый шифрованный кошелёк. + + + + + Warning: The Caps Lock key is on! + Внимание: Caps Lock включен! + + + + + Wallet encrypted + Бумажник зашифрован + + + + Arepacoin will close now to finish the encryption process. Remember that encrypting your wallet cannot fully protect your coins from being stolen by malware infecting your computer. + Сейчас программа закроется для завершения процесса шифрования. Помните, что шифрование вашего бумажника не может полностью защитить ваши монеты от кражи с помощью инфицирования вашего компьютера вредоносным ПО. + + + + + + + Wallet encryption failed + Не удалось зашифровать бумажник + + + + Wallet encryption failed due to an internal error. Your wallet was not encrypted. + Шифрование бумажника не удалось из-за внутренней ошибки. Ваш бумажник не был зашифрован. + + + + + The supplied passphrases do not match. + Введённые пароли не совпадают. + + + + Wallet unlock failed + Разблокировка бумажника не удалась + + + + + + The passphrase entered for the wallet decryption was incorrect. + Указанный пароль не подходит. + + + + Wallet decryption failed + Расшифрование бумажника не удалось + + + + Wallet passphrase was successfully changed. + Пароль бумажника успешно изменён. + + + + BitcoinGUI + + + Sign &message... + &Подписать сообщение + + + + Synchronizing with network... + Синхронизация с сетью... + + + + &Overview + О&бзор + + + + Show general overview of wallet + Показать общий обзор действий с бумажником + + + + &Transactions + &Транзакции + + + + Browse transaction history + Показать историю транзакций + + + + &Address Book + &Адресная книга + + + + Edit the list of stored addresses and labels + Изменить список сохранённых адресов и меток к ним + + + + &Receive coins + &Получение монет + + + + Show the list of addresses for receiving payments + Показать список адресов для получения платежей + + + + &Send coins + Отп&равка монет + + + + E&xit + В&ыход + + + + Quit application + Закрыть приложение + + + + Show information about Arepacoin + Показать информацию о Arepacoin'е + + + + About &Qt + О &Qt + + + + Show information about Qt + Показать информацию о Qt + + + + &Options... + Оп&ции... + + + + &Encrypt Wallet... + &Зашифровать бумажник + + + + &Backup Wallet... + &Сделать резервную копию бумажника + + + + &Change Passphrase... + &Изменить пароль + + + + ~%n block(s) remaining + остался ~%n блокосталось ~%n блоковосталось ~%n блоков + + + + Downloaded %1 of %2 blocks of transaction history (%3% done). + Загружено %1 из %2 блоков истории операций (%3% завершено). + + + + &Export... + &Экспорт... + + + + Send coins to a Arepacoin address + Отправить монеты на указанный адрес Arepacoin + + + + Modify configuration options for Arepacoin + Изменить параметры конфигурации Arepacoin + + + + Export the data in the current tab to a file + Экспортировать данные из вкладки в файл + + + + Encrypt or decrypt wallet + Зашифровать или расшифровать бумажник + + + + Backup wallet to another location + Сделать резервную копию бумажника в другом месте + + + + Change the passphrase used for wallet encryption + Изменить пароль шифрования бумажника + + + + &Debug window + &Окно отладки + + + + Open debugging and diagnostic console + Открыть консоль отладки и диагностики + + + + &Verify message... + &Проверить сообщение... + + + + Arepacoin + Arepacoin + + + + Wallet + Бумажник + + + + &About Arepacoin + &О Arepacoin + + + + &Show / Hide + &Показать / Скрыть + + + + Unlock wallet + Разблокировать бумажник + + + + &Lock Wallet + &Заблокировать бумажник + + + + Lock wallet + Заблокировать бумажник + + + + &File + &Файл + + + + &Settings + &Настройки + + + + &Help + &Помощь + + + + Tabs toolbar + Панель вкладок + + + + Actions toolbar + Панель действий + + + + + [testnet] + [тестовая сеть] + + + + + Arepacoin client + Arepacoin клиент + + + + %n active connection(s) to Arepacoin network + %n активное соединение с сетью%n активных соединений с сетью%n активных соединений с сетью + + + + Downloaded %1 blocks of transaction history. + Загружено %1 блоков истории транзакций. + + + + Staking.<br>Your weight is %1<br>Network weight is %2<br>Expected time to earn reward is %3 + Участвуем в доле.<br>Ваш вес %1<br>Вес сети %2<br>Ожидаемое время получения награды %3 + + + + Not staking because wallet is locked + Не участвуем в доле, так как кошелёк заблокирован + + + + Not staking because wallet is offline + Не участвуем в доле, так как кошелёк оффлайн + + + + Not staking because wallet is syncing + Не участвуем в доле, так как кошелёк синхронизируется + + + + Not staking because you don't have mature coins + Не участвуем в доле, так как нет зрелых монет + + + + %n second(s) ago + %n секунду назад%n секунды назад%n секунд назад + + + + &Unlock Wallet... + &Разблокировать бумажник + + + + %n minute(s) ago + %n минуту назад%n минуты назад%n минут назад + + + + %n hour(s) ago + %n час назад%n часа назад%n часов назад + + + + %n day(s) ago + %n день назад%n дня назад%n дней назад + + + + Up to date + Синхронизировано + + + + Catching up... + Синхронизируется... + + + + Last received block was generated %1. + Последний полученный блок был сгенерирован %1. + + + + This transaction is over the size limit. You can still send it for a fee of %1, which goes to the nodes that process your transaction and helps to support the network. Do you want to pay the fee? + Данная транзакция превышает предельно допустимый размер. Но Вы можете всё равно совершить её, добавив комиссию в %1, которая отправится тем узлам, которые обработают Вашу транзакцию, и поможет поддержать сеть. Вы хотите добавить комиссию? + + + + Confirm transaction fee + Подтвердите комиссию + + + + Sent transaction + Исходящая транзакция + + + + Incoming transaction + Входящая транзакция + + + + Date: %1 +Amount: %2 +Type: %3 +Address: %4 + + Дата: %1 +Количество: %2 +Тип: %3 +Адрес: %4 + + + + + + URI handling + Обработка URI + + + + + URI can not be parsed! This can be caused by an invalid Arepacoin address or malformed URI parameters. + Не удалось обработать URI! Это может быть связано с неверным адресом Arepacoin или неправильными параметрами URI. + + + + Wallet is <b>encrypted</b> and currently <b>unlocked</b> + Бумажник <b>зашифрован</b> и в настоящее время <b>разблокирован</b> + + + + Wallet is <b>encrypted</b> and currently <b>locked</b> + Бумажник <b>зашифрован</b> и в настоящее время <b>заблокирован</b> + + + + Backup Wallet + Сделать резервную копию бумажника + + + + Wallet Data (*.dat) + Данные бумажника (*.dat) + + + + Backup Failed + Резервное копирование не удалось + + + + There was an error trying to save the wallet data to the new location. + При попытке сохранения данных бумажника в новое место произошла ошибка. + + + + %n second(s) + %n секунда%n секунды%n секунд + + + + %n minute(s) + %n минута%n минуты%n минут + + + + %n hour(s) + %n час%n часа%n часов + + + + %n day(s) + %n день%n дня%n дней + + + + Not staking + Не участвуем в доле + + + + A fatal error occurred. Arepacoin can no longer continue safely and will quit. + Произошла неисправимая ошибка. Arepacoin не может безопасно продолжать работу и будет закрыт. + + + + ClientModel + + + Network Alert + Сетевая Тревога + + + + CoinControlDialog + + + Coin Control + Выбор входов + + + + Quantity: + Количество: + + + + Bytes: + Размер: + + + + Amount: + Сумма: + + + + Priority: + Приоритет: + + + + Fee: + Комиссия: + + + + Low Output: + Мелкие входы: + + + + no + нет + + + + After Fee: + С комиссией: + + + + Change: + Сдача: + + + + (un)select all + Выбрать все + + + + Tree mode + Дерево + + + + List mode + Список + + + + Amount + Сумма + + + + Label + Метка + + + + Address + Адрес + + + + Date + Дата + + + + Confirmations + Подтверждения + + + + Confirmed + Подтверждено + + + + Priority + Приоритет + + + + Copy address + Копировать адрес + + + + Copy label + Копировать метку + + + + + Copy amount + Копировать сумму + + + + Copy transaction ID + Скопировать ID транзакции + + + + Copy quantity + Копировать количество + + + + Copy fee + Копировать комиссию + + + + Copy after fee + Копировать с комиссией + + + + Copy bytes + Копировать объем + + + + Copy priority + Копировать приоритет + + + + Copy low output + + + + + Copy change + Копировать сдачу + + + + highest + наивысший + + + + high + высокий + + + + medium-high + выше среднего + + + + medium + средний + + + + low-medium + ниже среднего + + + + low + низкий + + + + lowest + наименьший + + + + DUST + + + + + yes + да + + + + This label turns red, if the transaction size is bigger than 10000 bytes. + + This means a fee of at least %1 per kb is required. + + Can vary +/- 1 Byte per input. + + + + + Transactions with higher priority get more likely into a block. + +This label turns red, if the priority is smaller than "medium". + + This means a fee of at least %1 per kb is required. + + + + + This label turns red, if any recipient receives an amount smaller than %1. + + This means a fee of at least %2 is required. + + Amounts below 0.546 times the minimum relay fee are shown as DUST. + + + + + This label turns red, if the change is smaller than %1. + + This means a fee of at least %2 is required. + + + + + + (no label) + (нет метки) + + + + change from %1 (%2) + + + + + (change) + (сдача) + + + + EditAddressDialog + + + Edit Address + Изменить адрес + + + + &Label + &Метка + + + + The label associated with this address book entry + Метка, связанная с данной записью + + + + &Address + &Адрес + + + + The address associated with this address book entry. This can only be modified for sending addresses. + Адрес, связанный с данной записью. + + + + New receiving address + Новый адрес для получения + + + + New sending address + Новый адрес для отправки + + + + Edit receiving address + Изменение адреса для получения + + + + Edit sending address + Изменение адреса для отправки + + + + The entered address "%1" is already in the address book. + Введённый адрес «%1» уже находится в адресной книге. + + + + The entered address "%1" is not a valid Arepacoin address. + Введённый адрес "%1" не является правильным Arepacoin-адресом. + + + + Could not unlock wallet. + Не удается разблокировать бумажник. + + + + New key generation failed. + Генерация нового ключа не удалась. + + + + GUIUtil::HelpMessageBox + + + + Arepacoin-Qt + Arepacoin-Qt + + + + version + версия + + + + Usage: + Использование: + + + + command-line options + параметры командной строки + + + + UI options + Опции интерфейса + + + + Set language, for example "de_DE" (default: system locale) + Выберите язык, например "de_DE" (по умолчанию: как в системе) + + + + Start minimized + Запускать свёрнутым + + + + Show splash screen on startup (default: 1) + Показывать сплэш при запуске (по умолчанию: 1) + + + + OptionsDialog + + + Options + Опции + + + + &Main + &Главная + + + + Optional transaction fee per kB that helps make sure your transactions are processed quickly. Most transactions are 1 kB. Fee 0.01 recommended. + Опциональная комиссия за каждый КБ транзакции, которая позволяет быть уверенным, что Ваша транзакция будет обработана быстро. Большинство транзакций занимают 1КБ. Рекомендуется комиссия 0.01. + + + + Pay transaction &fee + Заплатить ко&миссию + + + + Reserved amount does not participate in staking and is therefore spendable at any time. + Зарезервированная сумма не участвует в доле, и поэтому может быть потрачена в любое время. + + + + Reserve + Зарезервировать + + + + Automatically start Arepacoin after logging in to the system. + Автоматически запускать Arepacoin после входа в систему + + + + &Start Arepacoin on system login + &Запускать Arepacoin при входе в систему + + + + Detach block and address databases at shutdown. This means they can be moved to another data directory, but it slows down shutdown. The wallet is always detached. + Отключить базы данных блоков и адресов при выходе. Это означает, что их можно будет переместить в другой каталог данных, но завершение работы будет медленнее. Бумажник всегда отключается. + + + + &Detach databases at shutdown + &Отключать базы данных при выходе + + + + &Network + &Сеть + + + + Automatically open the Arepacoin client port on the router. This only works when your router supports UPnP and it is enabled. + Автоматически открыть порт для Arepacoin-клиента на роутере. Работает только если Ваш роутер поддерживает UPnP, и данная функция включена. + + + + Map port using &UPnP + Пробросить порт через &UPnP + + + + Connect to the Arepacoin network through a SOCKS proxy (e.g. when connecting through Tor). + Подключаться к сети Arepacoin через прокси SOCKS (например, при подключении через Tor). + + + + &Connect through SOCKS proxy: + &Подключаться через SOCKS прокси: + + + + Proxy &IP: + &IP Прокси: + + + + IP address of the proxy (e.g. 127.0.0.1) + IP-адрес прокси (например 127.0.0.1) + + + + &Port: + По&рт: + + + + Port of the proxy (e.g. 9050) + Порт прокси-сервера (например, 9050) + + + + SOCKS &Version: + &Версия SOCKS: + + + + SOCKS version of the proxy (e.g. 5) + Версия SOCKS-прокси (например, 5) + + + + &Window + &Окно + + + + Show only a tray icon after minimizing the window. + Показывать только иконку в системном лотке после сворачивания окна. + + + + &Minimize to the tray instead of the taskbar + &Cворачивать в системный лоток вместо панели задач + + + + Minimize instead of exit the application when the window is closed. When this option is enabled, the application will be closed only after selecting Quit in the menu. + Сворачивать вместо закрытия. Если данная опция будет выбрана — приложение закроется только после выбора соответствующего пункта в меню. + + + + M&inimize on close + С&ворачивать при закрытии + + + + &Display + О&тображение + + + + User Interface &language: + &Язык интерфейса: + + + + The user interface language can be set here. This setting will take effect after restarting Arepacoin. + Здесь можно выбрать язык интерфейса. Настройки вступят в силу после перезапуска Arepacoin. + + + + &Unit to show amounts in: + &Отображать суммы в единицах: + + + + Choose the default subdivision unit to show in the interface and when sending coins. + Выберите единицу измерения монет при отображении и отправке. + + + + Whether to show Arepacoin addresses in the transaction list or not. + Показывать ли адреса Arepacoin в списке транзакций. + + + + &Display addresses in transaction list + &Показывать адреса в списке транзакций + + + + Whether to show coin control features or not. + Выключает и включает отображение панели выбора входов. + + + + Display coin &control features (experts only!) + Управление &входами (только для продвинутых пользователей!) + + + + &OK + О&К + + + + &Cancel + &Отмена + + + + &Apply + &Применить + + + + default + по умолчанию + + + + + Warning + Внимание + + + + + This setting will take effect after restarting Arepacoin. + Эта настройка вступит в силу после перезапуска Arepacoin + + + + The supplied proxy address is invalid. + Адрес прокси неверен. + + + + OverviewPage + + + Form + Форма + + + + + The displayed information may be out of date. Your wallet automatically synchronizes with the Arepacoin network after a connection is established, but this process has not completed yet. + Отображаемая информация может быть устаревшей. Ваш бумажник автоматически синхронизируется с сетью Arepacoin после подключения, но этот процесс пока не завершён. + + + + Stake: + Доля: + + + + Unconfirmed: + Не подтверждено: + + + + Wallet + Бумажник + + + + Spendable: + Доступно: + + + + Your current spendable balance + Баланс, доступный в настоящее время + + + + Immature: + Незрелые: + + + + Mined balance that has not yet matured + Баланс добытых монет, который ещё не созрел + + + + Total: + Итого: + + + + Your current total balance + Ваш суммарный баланс + + + + <b>Recent transactions</b> + <b>Последние транзакции</b> + + + + Total of transactions that have yet to be confirmed, and do not yet count toward the current balance + Общая сумма всех транзакций, которые до сих пор не подтверждены, и до сих пор не учитываются в текущем балансе + + + + Total of coins that was staked, and do not yet count toward the current balance + Общая сумма всех монет, используемых для Proof-of-Stake, и не учитывающихся на балансе + + + + + out of sync + не синхронизировано + + + + QRCodeDialog + + + QR Code Dialog + Диалог QR-кода + + + + Request Payment + Запросить платёж + + + + Amount: + Количество: + + + + Label: + Метка: + + + + Message: + Сообщение: + + + + &Save As... + &Сохранить как... + + + + Error encoding URI into QR Code. + Ошибка кодирования URI в QR-код + + + + The entered amount is invalid, please check. + Введено неверное количество, проверьте ещё раз. + + + + Resulting URI too long, try to reduce the text for label / message. + Получившийся URI слишком длинный, попробуйте сократить текст метки / сообщения. + + + + Save QR Code + Сохранить QR-код + + + + PNG Images (*.png) + PNG Изображения (*.png) + + + + RPCConsole + + + Client name + Имя клиента + + + + + + + + + + + + + N/A + Н/Д + + + + Client version + Версия клиента + + + + &Information + &Информация + + + + Using OpenSSL version + Используется версия OpenSSL + + + + Startup time + Время запуска + + + + Network + Сеть + + + + Number of connections + Число подключений + + + + On testnet + В тестовой сети + + + + Block chain + Цепь блоков + + + + Current number of blocks + Текущее число блоков + + + + Estimated total blocks + Расчётное число блоков + + + + Last block time + Время последнего блока + + + + &Open + &Открыть + + + + Command-line options + Параметры командной строки + + + + Show the Arepacoin-Qt help message to get a list with possible Arepacoin command-line options. + Показать помощь по Arepacoin-Qt, чтобы получить список доступных параметров командной строки. + + + + &Show + &Показать + + + + &Console + Консоль + + + + Build date + Дата сборки + + + + Arepacoin - Debug window + Arepacoin - Окно отладки + + + + Arepacoin Core + Ядро Arepacoin + + + + Debug log file + Отладочный лог-файл + + + + Open the Arepacoin debug log file from the current data directory. This can take a few seconds for large log files. + Открыть отладочный лог-файл Arepacoin из текущего каталога данных. Это может занять несколько секунд для больших лог-файлов. + + + + Clear console + Очистить консоль + + + + Welcome to the Arepacoin RPC console. + Добро пожаловать в RPC-консоль Arepacoin. + + + + Use up and down arrows to navigate history, and <b>Ctrl-L</b> to clear screen. + Используйте стрелки вверх и вниз для просмотра истории и <b>Ctrl-L</b> для очистки экрана. + + + + Type <b>help</b> for an overview of available commands. + Напишите <b>help</b> для просмотра доступных команд. + + + + SendCoinsDialog + + + + + + + + + + Send Coins + Отправка + + + + Coin Control Features + Выбор входов + + + + Inputs... + Входы... + + + + automatically selected + автоматический выбор + + + + Insufficient funds! + Недостаточно средств! + + + + Quantity: + Количество: + + + + + 0 + + + + + Bytes: + + + + + Amount: + Сумма: + + + + + + + 0.00 BC + + + + + Priority: + Приоритет: + + + + medium + средний + + + + Fee: + Комиссия: + + + + Low Output: + + + + + no + нет + + + + After Fee: + + + + + Change + + + + + custom change address + адрес для сдачи + + + + Send to multiple recipients at once + Отправить нескольким получателям одновременно + + + + Add &Recipient + &Добавить получателя + + + + Remove all transaction fields + Удалить все поля транзакции + + + + Clear &All + Очистить &всё + + + + Balance: + Баланс: + + + + 123.456 BC + 123.456 BC + + + + Confirm the send action + Подтвердить отправку + + + + S&end + &Отправить + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + Введите Arepacoin-адрес (например AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + Copy quantity + Копировать количество + + + + Copy amount + Копировать сумму + + + + Copy fee + Копировать комиссию + + + + Copy after fee + + + + + Copy bytes + Копировать количество байтов + + + + Copy priority + Копировать приоритет + + + + Copy low output + + + + + Copy change + Копировать сдачу + + + + <b>%1</b> to %2 (%3) + <b>%1</b> адресату %2 (%3) + + + + Confirm send coins + Подтвердите отправку монет + + + + Are you sure you want to send %1? + Вы уверены, что хотите отправить %1? + + + + and + и + + + + The recipient address is not valid, please recheck. + Адрес получателя неверный, пожалуйста, перепроверьте. + + + + The amount to pay must be larger than 0. + Количество монет для отправки должно быть больше 0. + + + + The amount exceeds your balance. + Количество отправляемых монет превышает Ваш баланс + + + + The total exceeds your balance when the %1 transaction fee is included. + Сумма превысит Ваш баланс, если комиссия в размере %1 будет добавлена к транзакции + + + + Duplicate address found, can only send to each address once per send operation. + Обнаружен дублирующийся адрес. Отправка на один и тот же адрес возможна только один раз за одну операцию отправки + + + + Error: Transaction creation failed. + Ошибка: не удалось создать транзакцию. + + + + 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. + Ошибка: В транзакции отказано. Такое может произойти, если некоторые монеты уже были потрачены, например, если Вы используете одну копию файла wallet.dat, а монеты были потрачены из другой копии, но не были отмечены как потраченные в этой. + + + + WARNING: Invalid Arepacoin address + + + + + (no label) + (нет метки) + + + + WARNING: unknown change address + ПРЕДУПРЕЖДЕНИЕ: неизвестный адрес для сдачи + + + + SendCoinsEntry + + + Form + Форма + + + + A&mount: + Ко&личество: + + + + Pay &To: + Полу&чатель: + + + + + Enter a label for this address to add it to your address book + Введите метку для данного адреса (для добавления в адресную книгу) + + + + &Label: + &Метка: + + + + The address to send the payment to (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + Адрес получателя платежа (например AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + Choose address from address book + Выберите адрес из адресной книги + + + + Alt+A + Alt+A + + + + Paste address from clipboard + Вставить адрес из буфера обмена + + + + Alt+P + Alt+P + + + + Remove this recipient + Удалить этого получателя + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + Введите Arepacoin-адрес (например AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + SignVerifyMessageDialog + + + Signatures - Sign / Verify a Message + Подписи - подписать/проверить сообщение + + + + + &Sign Message + &Подписать сообщение + + + + You can sign messages with your addresses to prove you own them. Be careful not to sign anything vague, as phishing attacks may try to trick you into signing your identity over to them. Only sign fully-detailed statements you agree to. + Вы можете подписывать сообщения своими адресами, чтобы доказать владение ими. Будьте осторожны, не подписывайте что-то неопределённое, так как фишинговые атаки могут обманным путём заставить вас подписать нежелательные сообщения. Подписывайте только те сообщения, с которыми вы согласны вплоть до мелочей. + + + + The address to sign the message with (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + Адрес, которым вы хотите подписать сообщение (напр. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Choose an address from the address book + Выберите адрес из адресной книги + + + + + Alt+A + Alt+A + + + + Paste address from clipboard + Вставить адрес из буфера обмена + + + + Alt+P + Alt+P + + + + Enter the message you want to sign here + Введите сообщение для подписи + + + + Copy the current signature to the system clipboard + Скопировать текущую подпись в системный буфер обмена + + + + Sign the message to prove you own this Arepacoin address + Подписать сообщение, чтобы доказать владение адресом Arepacoin + + + + Reset all sign message fields + Сбросить значения всех полей подписывания сообщений + + + + + Clear &All + Очистить &всё + + + + + &Verify Message + &Проверить сообщение + + + + Enter the signing address, message (ensure you copy line breaks, spaces, tabs, etc. exactly) and signature below to verify the message. Be careful not to read more into the signature than what is in the signed message itself, to avoid being tricked by a man-in-the-middle attack. + Введите ниже адрес для подписи, сообщение (убедитесь, что переводы строк, пробелы, табы и т.п. в точности скопированы) и подпись, чтобы проверить сообщение. Убедитесь, что не скопировали лишнего в подпись, по сравнению с самим подписываемым сообщением, чтобы не стать жертвой атаки "man-in-the-middle". + + + + The address the message was signed with (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + Адрес, которым было подписано сообщение (напр. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + Verify the message to ensure it was signed with the specified Arepacoin address + Проверить сообщение, чтобы убедиться, что оно было подписано указанным адресом Arepacoin + + + + Reset all verify message fields + Сбросить все поля проверки сообщения + + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + Введите адрес Arepacoin (напр. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + Click "Sign Message" to generate signature + Нажмите "Подписать сообщение" для создания подписи + + + + Enter Arepacoin signature + Введите подпись Arepacoin + + + + + The entered address is invalid. + Введённый адрес неверен + + + + + + + Please check the address and try again. + Пожалуйста, проверьте адрес и попробуйте ещё раз. + + + + + The entered address does not refer to a key. + Введённый адрес не связан с ключом + + + + Wallet unlock was cancelled. + Разблокировка бумажника была отменена. + + + + Private key for the entered address is not available. + Для введённого адреса недоступен закрытый ключ + + + + Message signing failed. + Не удалось подписать сообщение + + + + Message signed. + Сообщение подписано + + + + The signature could not be decoded. + Подпись не может быть раскодирована. + + + + + Please check the signature and try again. + Пожалуйста, проверьте подпись и попробуйте ещё раз. + + + + The signature did not match the message digest. + Подпись не соответствует отпечатку сообщения. + + + + Message verification failed. + Проверка сообщения не удалась. + + + + Message verified. + Сообщение проверено. + + + + TransactionDesc + + + Open until %1 + Открыто до %1 + + + + Open for %n block(s) + Открыто для %n блокаОткрыто для %n блоковОткрыто для %n блоков + + + + conflicted + конфликт + + + + %1/offline + %1/оффлайн + + + + %1/unconfirmed + %1/не подтверждено + + + + %1 confirmations + %1 подтверждений + + + + Status + Статус + + + + , broadcast through %n node(s) + , разослано через %n узел, разослано через %n узла, разослано через %n узлов + + + + Date + Дата + + + + Source + Источник + + + + Generated + Сгенерировано + + + + + From + От + + + + + + To + Для + + + + + own address + свой адрес + + + + label + метка + + + + + + + + Credit + Кредит + + + + matures in %n more block(s) + будет доступно через %n блокбудет доступно через %n блокабудет доступно через %n блоков + + + + not accepted + не принято + + + + + + + Debit + Дебет + + + + Transaction fee + Комиссия + + + + Net amount + Чистая сумма + + + + Message + Сообщение + + + + Comment + Комментарий + + + + Transaction ID + ID транзакции + + + + Generated coins must mature 6 blocks before they can be spent. When you generated this block, it was broadcast to the network to be added to the block chain. If it fails to get into the chain, its state will change to "not accepted" and it won't be spendable. This may occasionally happen if another node generates a block within a few seconds of yours. + Сгенерированные монеты должны подождать 6 блоков, прежде чем они могут быть потрачены. Когда Вы сгенерировали этот блок, он был отправлен в сеть для добавления в цепочку блоков. Если данная процедура не удастся, статус изменится на «не подтверждено», и монеты будут недействительны. Это иногда происходит в случае, если другой узел сгенерирует блок на несколько секунд раньше вас. + + + + Debug information + Отладочная информация + + + + Transaction + Транзакция + + + + Inputs + Входы + + + + Amount + Количество + + + + true + истина + + + + false + ложь + + + + , has not been successfully broadcast yet + , ещё не было успешно разослано + + + + unknown + неизвестно + + + + TransactionDescDialog + + + Transaction details + Детали транзакции + + + + This pane shows a detailed description of the transaction + Данный диалог показывает детализированную статистику по выбранной транзакции + + + + TransactionTableModel + + + Date + Дата + + + + Type + Тип + + + + Address + Адрес + + + + Amount + Количество + + + + Open until %1 + Открыто до %1 + + + + Confirmed (%1 confirmations) + Подтверждено (%1 подтверждений) + + + + Open for %n more block(s) + Открыто для ещё %n блокаОткрыто для ещё %n блоковОткрыто для ещё %n блоков + + + + Offline + Оффлайн + + + + Unconfirmed + Не подтверждено + + + + Confirming (%1 of %2 recommended confirmations) + Подтверждается (%1 из %2 рекомендованных подтверждений) + + + + Conflicted + Конфликт + + + + Immature (%1 confirmations, will be available after %2) + Незрелые (%1 подтверждений, будут доступны после %2) + + + + This block was not received by any other nodes and will probably not be accepted! + Этот блок не был получен другими узлами и, возможно, не будет принят! + + + + Generated but not accepted + Сгенерировано, но не принято + + + + Received with + Получено + + + + Received from + Получено от + + + + Sent to + Отправлено + + + + Payment to yourself + Отправлено себе + + + + Mined + Добыто + + + + (n/a) + [не доступно] + + + + Transaction status. Hover over this field to show number of confirmations. + Статус транзакции. Подведите курсор к нужному полю для того, чтобы увидеть количество подтверждений. + + + + Date and time that the transaction was received. + Дата и время, когда транзакция была получена. + + + + Type of transaction. + Тип транзакции. + + + + Destination address of transaction. + Адрес назначения транзакции. + + + + Amount removed from or added to balance. + Сумма, добавленная, или снятая с баланса. + + + + TransactionView + + + + All + Все + + + + Today + Сегодня + + + + This week + На этой неделе + + + + This month + В этом месяце + + + + Last month + За последний месяц + + + + This year + В этом году + + + + Range... + Промежуток... + + + + Received with + Получено на + + + + Sent to + Отправлено на + + + + To yourself + Отправленные себе + + + + Mined + Добытые + + + + Other + Другое + + + + Enter address or label to search + Введите адрес или метку для поиска + + + + Min amount + Мин. сумма + + + + Copy address + Копировать адрес + + + + Copy label + Копировать метку + + + + Copy amount + Скопировать сумму + + + + Copy transaction ID + Скопировать ID транзакции + + + + Edit label + Изменить метку + + + + Show transaction details + Показать подробности транзакции + + + + Export Transaction Data + Экспортировать данные транзакций + + + + Comma separated file (*.csv) + Текст, разделённый запятыми (*.csv) + + + + Confirmed + Подтверждено + + + + Date + Дата + + + + Type + Тип + + + + Label + Метка + + + + Address + Адрес + + + + Amount + Количество + + + + ID + ID + + + + Error exporting + Ошибка экспорта + + + + Could not write to file %1. + Невозможно записать в файл %1. + + + + Range: + Промежуток от: + + + + to + до + + + + WalletModel + + + Sending... + Отправка.... + + + + bitcoin-core + + + Arepacoin version + Версия + + + + Usage: + Использование: + + + + Send command to -server or arepacoind + Отправить команду на -server или arepacoind + + + + List commands + Список команд + + + + + Get help for a command + Получить помощь по команде + + + + Options: + Опции: + + + + Specify configuration file (default: arepacoin.conf) + Указать конфигурационный файл (по умолчанию: arepacoin.conf) + + + + Specify pid file (default: arepacoind.pid) + Указать pid-файл (по умолчанию: arepacoind.pid) + + + + Specify wallet file (within data directory) + Указать файл кошелька (в пределах DATA директории) + + + + Specify data directory + Укажите каталог данных + + + + Set database cache size in megabytes (default: 25) + Установить размер кэша базы данных в мегабайтах (по умолчанию: 25) + + + + Set database disk log size in megabytes (default: 100) + Установить размер лога базы данных в мегабайтах (по умолчанию: 100) + + + + Listen for connections on <port> (default: 9853 or testnet: 19853) + Принимать входящие подключения на <port> (по умолчанию: 9853 или 19853 в тестовой сети) + + + + Maintain at most <n> connections to peers (default: 125) + Поддерживать не более <n> подключений к узлам (по умолчанию: 125) + + + + Connect to a node to retrieve peer addresses, and disconnect + Подключиться к узлу, чтобы получить список адресов других участников и отключиться + + + + Specify your own public address + Укажите ваш собственный публичный адрес + + + + Bind to given address. Use [host]:port notation for IPv6 + Привязаться (bind) к указанному адресу. Используйте запись вида [хост]:порт для IPv6 + + + + Stake your coins to support network and gain reward (default: 1) + + + + + Threshold for disconnecting misbehaving peers (default: 100) + Порог для отключения неправильно ведущих себя узлов (по умолчанию: 100) + + + + Number of seconds to keep misbehaving peers from reconnecting (default: 86400) + Число секунд блокирования неправильно ведущих себя узлов (по умолчанию: 86400) + + + + An error occurred while setting up the RPC port %u for listening on IPv4: %s + Произошла ошибка при открытии RPC-порта %u для прослушивания на IPv4: %s + + + + Detach block and address databases. Increases shutdown time (default: 0) + Отключить базы данных блоков и адресов. Увеличивает время завершения работы (по умолчанию: 0) + + + + 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. + Ошибка: В транзакции отказано. Такое может произойти, если некоторые монеты уже были потрачены, например, если Вы используете одну копию файла wallet.dat, а монеты были потрачены из другой копии, но не были отмечены как потраченные в этой. + + + + Error: This transaction requires a transaction fee of at least %s because of its amount, complexity, or use of recently received funds + Ошибка: эта транзакция требует комиссию в размере как минимум %s из-за её объёма, сложности или использования недавно полученных средств + + + + Listen for JSON-RPC connections on <port> (default: 9852 or testnet: 19852) + Прослушивать подключения JSON-RPC на <порту> (по умолчанию: 9852 или для testnet: 19852) + + + + Accept command line and JSON-RPC commands + Принимать командную строку и команды JSON-RPC + + + + Error: Transaction creation failed + Ошибка: Создание транзакции не удалось + + + + Error: Wallet locked, unable to create transaction + Ошибка: бумажник заблокирован, невозможно создать транзакцию + + + + Importing blockchain data file. + Импортируется файл цепи блоков. + + + + Importing bootstrap blockchain data file. + Импортируется bootstrap-файл цепи блоков. + + + + Run in the background as a daemon and accept commands + Запускаться в фоне как демон и принимать команды + + + + Use the test network + Использовать тестовую сеть + + + + Accept connections from outside (default: 1 if no -proxy or -connect) + Принимать подключения извне (по умолчанию: 1, если не используется -proxy или -connect) + + + + An error occurred while setting up the RPC port %u for listening on IPv6, falling back to IPv4: %s + Произошла ошибка при открытии на прослушивание IPv6 RCP-порта %u, возвращаемся к IPv4: %s + + + + Error initializing database environment %s! To recover, BACKUP THAT DIRECTORY, then remove everything from it except for wallet.dat. + Ошибка инициализации окружения БД %s! Для восстановления СДЕЛАЙТЕ РЕЗЕРВНУЮ КОПИЮ этой директории, затем удалите из нее все, кроме wallet.dat. + + + + Set maximum size of high-priority/low-fee transactions in bytes (default: 27000) + Максимальный размер высокоприоритетных/низкокомиссионных транзакций в байтах (по умолчанию: 27000) + + + + Warning: -paytxfee is set very high! This is the transaction fee you will pay if you send a transaction. + Внимание: установлено очень большое значение -paytxfee. Это комиссия, которую вы заплатите при проведении транзакции. + + + + Warning: Please check that your computer's date and time are correct! If your clock is wrong Arepacoin will not work properly. + Внимание: убедитесь, что дата и время на Вашем компьютере выставлены верно. Если Ваши часы идут неправильно, Arepacoin будет работать некорректно. + + + + Warning: error reading wallet.dat! All keys read correctly, but transaction data or address book entries might be missing or incorrect. + Внимание: ошибка чтения wallet.dat! Все ключи восстановлены, но записи в адресной книге и истории транзакций могут быть некорректными. + + + + Warning: wallet.dat corrupt, data salvaged! Original wallet.dat saved as wallet.{timestamp}.bak in %s; if your balance or transactions are incorrect you should restore from a backup. + Внимание: wallet.dat был поврежден, данные восстановлены! Оригинальный wallet.dat сохранен как wallet.{timestamp}.bak в %s;, если ваши транзакции или баланс отображаются неправильно, следует восстановить его из данной копии. + + + + Attempt to recover private keys from a corrupt wallet.dat + Попытка восстановления ключей из поврежденного wallet.dat + + + + Block creation options: + Параметры создания блоков: + + + + Connect only to the specified node(s) + Подключаться только к указанному узлу(ам) + + + + Discover own IP address (default: 1 when listening and no -externalip) + Определить свой IP (по умолчанию: 1 при прослушивании и если не используется -externalip) + + + + Failed to listen on any port. Use -listen=0 if you want this. + Не удалось начать прослушивание на порту. Используйте -listen=0 если вас это устраивает. + + + + Find peers using DNS lookup (default: 1) + Искать узлы с помощью DNS (по умолчанию: 1) + + + + Sync checkpoints policy (default: strict) + Политика синхронизированных меток (по умолчанию: strict) + + + + Invalid -tor address: '%s' + Неверный адрес -tor: '%s' + + + + Invalid amount for -reservebalance=<amount> + + + + + Maximum per-connection receive buffer, <n>*1000 bytes (default: 5000) + Максимальный размер буфера приёма на соединение, <n>*1000 байт (по умолчанию: 5000) + + + + Maximum per-connection send buffer, <n>*1000 bytes (default: 1000) + Максимальный размер буфера отправки на соединение, <n>*1000 байт (по умолчанию: 1000) + + + + Only connect to nodes in network <net> (IPv4, IPv6 or Tor) + Подключаться только к узлам из сети <net> (IPv4, IPv6 или Tor) + + + + Output extra debugging information. Implies all other -debug* options + Выводить больше отладочной информации. Включает все остальные опции -debug* + + + + Output extra network debugging information + Выводить дополнительную сетевую отладочную информацию + + + + Prepend debug output with timestamp + Дописывать отметки времени к отладочному выводу + + + + SSL options: (see the Bitcoin Wiki for SSL setup instructions) + +Параметры SSL: (см. Bitcoin Wiki для инструкций по настройке SSL) + + + + Select the version of socks proxy to use (4-5, default: 5) + Выберите версию SOCKS-прокси (4-5, по умолчанию: 5) + + + + Send trace/debug info to console instead of debug.log file + Выводить информацию трассировки/отладки на консоль вместо файла debug.log + + + + Send trace/debug info to debugger + Отправлять информацию трассировки/отладки в отладчик + + + + Set maximum block size in bytes (default: 250000) + Максимальный размер блока в байтах (по умолчанию: 250000) + + + + Set minimum block size in bytes (default: 0) + Минимальный размер блока в байтах (по умолчанию: 0) + + + + Shrink debug.log file on client startup (default: 1 when no -debug) + Сжимать файл debug.log при запуске клиента (по умолчанию: 1, если нет -debug) + + + + Specify connection timeout in milliseconds (default: 5000) + Таймаут соединения в миллисекундах (по умолчанию: 5000) + + + + Unable to sign checkpoint, wrong checkpointkey? + + + + + + Use UPnP to map the listening port (default: 0) + Использовать UPnP для проброса порта (по умолчанию: 0) + + + + Use UPnP to map the listening port (default: 1 when listening) + Использовать UPnP для проброса порта (по умолчанию: 1, если используется прослушивание) + + + + Use proxy to reach tor hidden services (default: same as -proxy) + Использовать прокси для скрытых сервисов (по умолчанию: тот же, что и в -proxy) + + + + Username for JSON-RPC connections + Имя для подключений JSON-RPC + + + + Verifying database integrity... + Проверка целостности базы данных... + + + + WARNING: syncronized checkpoint violation detected, but skipped! + + + + + Warning: Disk space is low! + Внимание: мало места на диске! + + + + Warning: This version is obsolete, upgrade required! + Внимание: эта версия устарела, требуется обновление! + + + + wallet.dat corrupt, salvage failed + wallet.dat поврежден, восстановление не удалось + + + + Password for JSON-RPC connections + Пароль для подключений JSON-RPC + + + + %s, you must set a rpcpassword in the configuration file: + %s +It is recommended you use the following random password: +rpcuser=arepacoinrpc +rpcpassword=%s +(you do not need to remember this password) +The username and password MUST NOT be the same. +If the file does not exist, create it with owner-readable-only file permissions. +It is also recommended to set alertnotify so you are notified of problems; +for example: alertnotify=echo %%s | mail -s "Arepacoin Alert" admin@foo.com + + + + + + Find peers using internet relay chat (default: 0) + + + + + Sync time with other nodes. Disable if time on your system is precise e.g. syncing with NTP (default: 1) + + + + + When creating transactions, ignore inputs with value less than this (default: 0.01) + + + + + Allow JSON-RPC connections from specified IP address + Разрешить подключения JSON-RPC с указанного IP + + + + Send commands to node running on <ip> (default: 127.0.0.1) + Посылать команды узлу, запущенному на <ip> (по умолчанию: 127.0.0.1) + + + + Execute command when the best block changes (%s in cmd is replaced by block hash) + Выполнить команду, когда появляется новый блок (%s в команде заменяется на хэш блока) + + + + Execute command when a wallet transaction changes (%s in cmd is replaced by TxID) + Выполнить команду, когда получена новая транзакция (%s в команде заменяется на ID транзакции) + + + + Require a confirmations for change (default: 0) + Требовать подтверждения для сдачи (по умолчанию: 0) + + + + Enforce transaction scripts to use canonical PUSH operators (default: 1) + + + + + Execute command when a relevant alert is received (%s in cmd is replaced by message) + + + + + Upgrade wallet to latest format + Обновить бумажник до последнего формата + + + + Set key pool size to <n> (default: 100) + Установить размер запаса ключей в <n> (по умолчанию: 100) + + + + Rescan the block chain for missing wallet transactions + Перепроверить цепь блоков на предмет отсутствующих в бумажнике транзакций + + + + How many blocks to check at startup (default: 2500, 0 = all) + Сколько блоков проверять при запуске (по умолчанию: 2500, 0 = все) + + + + How thorough the block verification is (0-6, default: 1) + Насколько тщательно проверять блоки (0-6, по умолчанию: 1) + + + + Imports blocks from external blk000?.dat file + Импортировать блоки из внешнего файла blk000?.dat + + + + Use OpenSSL (https) for JSON-RPC connections + Использовать OpenSSL (https) для подключений JSON-RPC + + + + Server certificate file (default: server.cert) + Файл серверного сертификата (по умолчанию: server.cert) + + + + Server private key (default: server.pem) + Приватный ключ сервера (по умолчанию: server.pem) + + + + Acceptable ciphers (default: TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH) + Разрешённые алгоритмы (по умолчанию: TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH) + + + + Error: Wallet unlocked for staking only, unable to create transaction. + + + + + WARNING: Invalid checkpoint found! Displayed transactions may not be correct! You may need to upgrade, or notify developers. + + + + + This help message + Эта справка + + + + Wallet %s resides outside data directory %s. + Кошелек %s находится вне рабочей директории %s. + + + + Cannot obtain a lock on data directory %s. Arepacoin is probably already running. + Невозможно установить блокировку на рабочую директорию %s. Возможно, бумажник уже запущен. + + + + Arepacoin + Arepacoin + + + + Unable to bind to %s on this computer (bind returned error %d, %s) + Невозможно привязаться к %s на этом компьютере (bind вернул ошибку %d, %s) + + + + Connect through socks proxy + Подключаться через socks прокси + + + + Allow DNS lookups for -addnode, -seednode and -connect + Разрешить поиск в DNS для -addnode, -seednode и -connect + + + + Loading addresses... + Загрузка адресов... + + + + Error loading blkindex.dat + Ошибка чтения blkindex.dat + + + + Error loading wallet.dat: Wallet corrupted + Ошибка загрузки wallet.dat: Бумажник поврежден + + + + Error loading wallet.dat: Wallet requires newer version of Arepacoin + Ошибка загрузки wallet.dat: бумажник требует более новую версию Arepacoin + + + + Wallet needed to be rewritten: restart Arepacoin to complete + Необходимо перезаписать бумажник, перезапустите Arepacoin для завершения операции + + + + Error loading wallet.dat + Ошибка при загрузке wallet.dat + + + + Invalid -proxy address: '%s' + Неверный адрес -proxy: '%s' + + + + Unknown network specified in -onlynet: '%s' + В параметре -onlynet указана неизвестная сеть: '%s' + + + + Unknown -socks proxy version requested: %i + В параметре -socks запрошена неизвестная версия: %i + + + + Cannot resolve -bind address: '%s' + Не удаётся разрешить адрес в параметре -bind: '%s' + + + + Cannot resolve -externalip address: '%s' + Не удаётся разрешить адрес в параметре -externalip: '%s' + + + + Invalid amount for -paytxfee=<amount>: '%s' + Неверное количество в параметре -paytxfee=<кол-во>: '%s' + + + + Error: could not start node + Ошибка: не удалось запустить узел + + + + Sending... + Отправка... + + + + Invalid amount + Неверное количество + + + + Insufficient funds + Недостаточно монет + + + + Loading block index... + Загрузка индекса блоков... + + + + Add a node to connect to and attempt to keep the connection open + Добавить узел для подключения и пытаться поддерживать соединение открытым + + + + Unable to bind to %s on this computer. Arepacoin is probably already running. + Невозможно привязаться к %s на этом компьютере. Возможно, Arepacoin уже работает. + + + + Fee per KB to add to transactions you send + Комиссия на килобайт, добавляемая к вашим транзакциям + + + + Invalid amount for -mininput=<amount>: '%s' + + + + + Loading wallet... + Загрузка бумажника... + + + + Cannot downgrade wallet + Не удаётся понизить версию бумажника + + + + Cannot initialize keypool + Не удаётся инициализировать массив ключей + + + + Cannot write default address + Не удаётся записать адрес по умолчанию + + + + Rescanning... + Сканирование... + + + + Done loading + Загрузка завершена + + + + To use the %s option + Чтобы использовать опцию %s + + + + Error + Ошибка + + + + You must set rpcpassword=<password> in the configuration file: +%s +If the file does not exist, create it with owner-readable-only file permissions. + Вы должны установить rpcpassword=<password> в конфигурационном файле: +%s +Если файл не существует, создайте его и установите права доступа только для владельца. + + + \ No newline at end of file diff --git a/src/qt/locale/bitcoin_sah.ts b/src/qt/locale/bitcoin_sah.ts new file mode 100755 index 0000000..b69e6a9 --- /dev/null +++ b/src/qt/locale/bitcoin_sah.ts @@ -0,0 +1,3275 @@ + + + AboutDialog + + + About Arepacoin + + + + + <b>Arepacoin</b> version + + + + + Copyright © 2009-2014 The Bitcoin developers +Copyright © 2012-2014 The NovaCoin developers +Copyright © 2014 The Arepacoin developers + + + + + +This is experimental software. + +Distributed under the MIT/X11 software license, see the accompanying file COPYING or http://www.opensource.org/licenses/mit-license.php. + +This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit (http://www.openssl.org/) and cryptographic software written by Eric Young (eay@cryptsoft.com) and UPnP software written by Thomas Bernard. + + + + + AddressBookPage + + + Address Book + + + + + Double-click to edit address or label + Аадырыскын уларытаргар иккитэ баттаа + + + + Create a new address + + + + + Copy the currently selected address to the system clipboard + + + + + &New Address + + + + + These are your Arepacoin addresses for receiving payments. You may want to give a different one to each sender so you can keep track of who is paying you. + + + + + &Copy Address + + + + + Show &QR Code + + + + + Sign a message to prove you own a Arepacoin address + + + + + Sign &Message + + + + + Delete the currently selected address from the list + + + + + Verify a message to ensure it was signed with a specified Arepacoin address + + + + + &Verify Message + + + + + &Delete + + + + + Copy &Label + + + + + &Edit + + + + + Export Address Book Data + + + + + Comma separated file (*.csv) + + + + + Error exporting + + + + + Could not write to file %1. + + + + + AddressTableModel + + + Label + + + + + Address + + + + + (no label) + + + + + AskPassphraseDialog + + + Passphrase Dialog + + + + + Enter passphrase + + + + + New passphrase + + + + + Repeat new passphrase + + + + + Serves to disable the trivial sendmoney when OS account compromised. Provides no real security. + + + + + For staking only + + + + + Enter the new passphrase to the wallet.<br/>Please use a passphrase of <b>10 or more random characters</b>, or <b>eight or more words</b>. + + + + + Encrypt wallet + + + + + This operation needs your wallet passphrase to unlock the wallet. + + + + + Unlock wallet + + + + + This operation needs your wallet passphrase to decrypt the wallet. + + + + + Decrypt wallet + + + + + Change passphrase + + + + + Enter the old and new passphrase to the wallet. + + + + + Confirm wallet encryption + + + + + Warning: If you encrypt your wallet and lose your passphrase, you will <b>LOSE ALL OF YOUR COINS</b>! + + + + + Are you sure you wish to encrypt your wallet? + + + + + IMPORTANT: Any previous backups you have made of your wallet file should be replaced with the newly generated, encrypted wallet file. For security reasons, previous backups of the unencrypted wallet file will become useless as soon as you start using the new, encrypted wallet. + + + + + + Warning: The Caps Lock key is on! + + + + + + Wallet encrypted + + + + + Arepacoin will close now to finish the encryption process. Remember that encrypting your wallet cannot fully protect your coins from being stolen by malware infecting your computer. + + + + + + + + Wallet encryption failed + + + + + Wallet encryption failed due to an internal error. Your wallet was not encrypted. + + + + + + The supplied passphrases do not match. + + + + + Wallet unlock failed + + + + + + + The passphrase entered for the wallet decryption was incorrect. + + + + + Wallet decryption failed + + + + + Wallet passphrase was successfully changed. + + + + + BitcoinGUI + + + Sign &message... + + + + + Synchronizing with network... + + + + + &Overview + + + + + Show general overview of wallet + + + + + &Transactions + + + + + Browse transaction history + + + + + &Address Book + + + + + Edit the list of stored addresses and labels + + + + + &Receive coins + + + + + Show the list of addresses for receiving payments + + + + + &Send coins + + + + + E&xit + + + + + Quit application + + + + + Show information about Arepacoin + + + + + About &Qt + + + + + Show information about Qt + + + + + &Options... + + + + + &Encrypt Wallet... + + + + + &Backup Wallet... + + + + + &Change Passphrase... + + + + + ~%n block(s) remaining + + + + + Downloaded %1 of %2 blocks of transaction history (%3% done). + + + + + &Export... + + + + + Send coins to a Arepacoin address + + + + + Modify configuration options for Arepacoin + + + + + Export the data in the current tab to a file + + + + + Encrypt or decrypt wallet + + + + + Backup wallet to another location + + + + + Change the passphrase used for wallet encryption + + + + + &Debug window + + + + + Open debugging and diagnostic console + + + + + &Verify message... + + + + + Arepacoin + + + + + Wallet + + + + + &About Arepacoin + + + + + &Show / Hide + + + + + Unlock wallet + + + + + &Lock Wallet + + + + + Lock wallet + + + + + &File + + + + + &Settings + + + + + &Help + + + + + Tabs toolbar + + + + + Actions toolbar + + + + + + [testnet] + + + + + + Arepacoin client + + + + + %n active connection(s) to Arepacoin network + + + + + Downloaded %1 blocks of transaction history. + + + + + Staking.<br>Your weight is %1<br>Network weight is %2<br>Expected time to earn reward is %3 + + + + + Not staking because wallet is locked + + + + + Not staking because wallet is offline + + + + + Not staking because wallet is syncing + + + + + Not staking because you don't have mature coins + + + + + %n second(s) ago + + + + + &Unlock Wallet... + + + + + %n minute(s) ago + + + + + %n hour(s) ago + + + + + %n day(s) ago + + + + + Up to date + + + + + Catching up... + + + + + Last received block was generated %1. + + + + + This transaction is over the size limit. You can still send it for a fee of %1, which goes to the nodes that process your transaction and helps to support the network. Do you want to pay the fee? + + + + + Confirm transaction fee + + + + + Sent transaction + + + + + Incoming transaction + + + + + Date: %1 +Amount: %2 +Type: %3 +Address: %4 + + + + + + + URI handling + + + + + + URI can not be parsed! This can be caused by an invalid Arepacoin address or malformed URI parameters. + + + + + Wallet is <b>encrypted</b> and currently <b>unlocked</b> + + + + + Wallet is <b>encrypted</b> and currently <b>locked</b> + + + + + Backup Wallet + + + + + Wallet Data (*.dat) + + + + + Backup Failed + + + + + There was an error trying to save the wallet data to the new location. + + + + + %n second(s) + + + + + %n minute(s) + + + + + %n hour(s) + + + + + %n day(s) + + + + + Not staking + + + + + A fatal error occurred. Arepacoin can no longer continue safely and will quit. + + + + + ClientModel + + + Network Alert + + + + + CoinControlDialog + + + Coin Control + + + + + Quantity: + + + + + Bytes: + + + + + Amount: + + + + + Priority: + + + + + Fee: + + + + + Low Output: + + + + + no + + + + + After Fee: + + + + + Change: + + + + + (un)select all + + + + + Tree mode + + + + + List mode + + + + + Amount + + + + + Label + + + + + Address + + + + + Date + + + + + Confirmations + + + + + Confirmed + + + + + Priority + + + + + Copy address + + + + + Copy label + + + + + + Copy amount + + + + + Copy transaction ID + + + + + Copy quantity + + + + + Copy fee + + + + + Copy after fee + + + + + Copy bytes + + + + + Copy priority + + + + + Copy low output + + + + + Copy change + + + + + highest + + + + + high + + + + + medium-high + + + + + medium + + + + + low-medium + + + + + low + + + + + lowest + + + + + DUST + + + + + yes + + + + + This label turns red, if the transaction size is bigger than 10000 bytes. + + This means a fee of at least %1 per kb is required. + + Can vary +/- 1 Byte per input. + + + + + Transactions with higher priority get more likely into a block. + +This label turns red, if the priority is smaller than "medium". + + This means a fee of at least %1 per kb is required. + + + + + This label turns red, if any recipient receives an amount smaller than %1. + + This means a fee of at least %2 is required. + + Amounts below 0.546 times the minimum relay fee are shown as DUST. + + + + + This label turns red, if the change is smaller than %1. + + This means a fee of at least %2 is required. + + + + + + (no label) + + + + + change from %1 (%2) + + + + + (change) + + + + + EditAddressDialog + + + Edit Address + + + + + &Label + + + + + The label associated with this address book entry + + + + + &Address + + + + + The address associated with this address book entry. This can only be modified for sending addresses. + + + + + New receiving address + + + + + New sending address + + + + + Edit receiving address + + + + + Edit sending address + + + + + The entered address "%1" is already in the address book. + + + + + The entered address "%1" is not a valid Arepacoin address. + + + + + Could not unlock wallet. + + + + + New key generation failed. + + + + + GUIUtil::HelpMessageBox + + + + Arepacoin-Qt + + + + + version + + + + + Usage: + + + + + command-line options + + + + + UI options + + + + + Set language, for example "de_DE" (default: system locale) + + + + + Start minimized + + + + + Show splash screen on startup (default: 1) + + + + + OptionsDialog + + + Options + + + + + &Main + + + + + Optional transaction fee per kB that helps make sure your transactions are processed quickly. Most transactions are 1 kB. Fee 0.01 recommended. + + + + + Pay transaction &fee + + + + + Reserved amount does not participate in staking and is therefore spendable at any time. + + + + + Reserve + + + + + Automatically start Arepacoin after logging in to the system. + + + + + &Start Arepacoin on system login + + + + + Detach block and address databases at shutdown. This means they can be moved to another data directory, but it slows down shutdown. The wallet is always detached. + + + + + &Detach databases at shutdown + + + + + &Network + + + + + Automatically open the Arepacoin client port on the router. This only works when your router supports UPnP and it is enabled. + + + + + Map port using &UPnP + + + + + Connect to the Arepacoin network through a SOCKS proxy (e.g. when connecting through Tor). + + + + + &Connect through SOCKS proxy: + + + + + Proxy &IP: + + + + + IP address of the proxy (e.g. 127.0.0.1) + + + + + &Port: + + + + + Port of the proxy (e.g. 9050) + + + + + SOCKS &Version: + + + + + SOCKS version of the proxy (e.g. 5) + + + + + &Window + + + + + Show only a tray icon after minimizing the window. + + + + + &Minimize to the tray instead of the taskbar + + + + + Minimize instead of exit the application when the window is closed. When this option is enabled, the application will be closed only after selecting Quit in the menu. + + + + + M&inimize on close + + + + + &Display + + + + + User Interface &language: + + + + + The user interface language can be set here. This setting will take effect after restarting Arepacoin. + + + + + &Unit to show amounts in: + + + + + Choose the default subdivision unit to show in the interface and when sending coins. + + + + + Whether to show Arepacoin addresses in the transaction list or not. + + + + + &Display addresses in transaction list + + + + + Whether to show coin control features or not. + + + + + Display coin &control features (experts only!) + + + + + &OK + + + + + &Cancel + + + + + &Apply + + + + + default + + + + + + Warning + + + + + + This setting will take effect after restarting Arepacoin. + + + + + The supplied proxy address is invalid. + + + + + OverviewPage + + + Form + + + + + + The displayed information may be out of date. Your wallet automatically synchronizes with the Arepacoin network after a connection is established, but this process has not completed yet. + + + + + Stake: + + + + + Unconfirmed: + + + + + Wallet + + + + + Spendable: + + + + + Your current spendable balance + + + + + Immature: + + + + + Mined balance that has not yet matured + + + + + Total: + + + + + Your current total balance + + + + + <b>Recent transactions</b> + + + + + Total of transactions that have yet to be confirmed, and do not yet count toward the current balance + + + + + Total of coins that was staked, and do not yet count toward the current balance + + + + + + out of sync + + + + + QRCodeDialog + + + QR Code Dialog + + + + + Request Payment + + + + + Amount: + + + + + Label: + + + + + Message: + + + + + &Save As... + + + + + Error encoding URI into QR Code. + + + + + The entered amount is invalid, please check. + + + + + Resulting URI too long, try to reduce the text for label / message. + + + + + Save QR Code + + + + + PNG Images (*.png) + + + + + RPCConsole + + + Client name + + + + + + + + + + + + + + N/A + + + + + Client version + + + + + &Information + + + + + Using OpenSSL version + + + + + Startup time + + + + + Network + + + + + Number of connections + + + + + On testnet + + + + + Block chain + + + + + Current number of blocks + + + + + Estimated total blocks + + + + + Last block time + + + + + &Open + + + + + Command-line options + + + + + Show the Arepacoin-Qt help message to get a list with possible Arepacoin command-line options. + + + + + &Show + + + + + &Console + + + + + Build date + + + + + Arepacoin - Debug window + + + + + Arepacoin Core + + + + + Debug log file + + + + + Open the Arepacoin debug log file from the current data directory. This can take a few seconds for large log files. + + + + + Clear console + + + + + Welcome to the Arepacoin RPC console. + + + + + Use up and down arrows to navigate history, and <b>Ctrl-L</b> to clear screen. + + + + + Type <b>help</b> for an overview of available commands. + + + + + SendCoinsDialog + + + + + + + + + + Send Coins + + + + + Coin Control Features + + + + + Inputs... + + + + + automatically selected + + + + + Insufficient funds! + + + + + Quantity: + + + + + + 0 + + + + + Bytes: + + + + + Amount: + + + + + + + + 0.00 BC + + + + + Priority: + + + + + medium + + + + + Fee: + + + + + Low Output: + + + + + no + + + + + After Fee: + + + + + Change + + + + + custom change address + + + + + Send to multiple recipients at once + + + + + Add &Recipient + + + + + Remove all transaction fields + + + + + Clear &All + + + + + Balance: + + + + + 123.456 BC + + + + + Confirm the send action + + + + + S&end + + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Copy quantity + + + + + Copy amount + + + + + Copy fee + + + + + Copy after fee + + + + + Copy bytes + + + + + Copy priority + + + + + Copy low output + + + + + Copy change + + + + + <b>%1</b> to %2 (%3) + + + + + Confirm send coins + + + + + Are you sure you want to send %1? + + + + + and + + + + + The recipient address is not valid, please recheck. + + + + + The amount to pay must be larger than 0. + + + + + The amount exceeds your balance. + + + + + The total exceeds your balance when the %1 transaction fee is included. + + + + + Duplicate address found, can only send to each address once per send operation. + + + + + Error: Transaction creation failed. + + + + + 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. + + + + + WARNING: Invalid Arepacoin address + + + + + (no label) + + + + + WARNING: unknown change address + + + + + SendCoinsEntry + + + Form + + + + + A&mount: + + + + + Pay &To: + + + + + + Enter a label for this address to add it to your address book + + + + + &Label: + + + + + The address to send the payment to (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Choose address from address book + + + + + Alt+A + + + + + Paste address from clipboard + + + + + Alt+P + + + + + Remove this recipient + + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + SignVerifyMessageDialog + + + Signatures - Sign / Verify a Message + + + + + + &Sign Message + + + + + You can sign messages with your addresses to prove you own them. Be careful not to sign anything vague, as phishing attacks may try to trick you into signing your identity over to them. Only sign fully-detailed statements you agree to. + + + + + The address to sign the message with (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + + Choose an address from the address book + + + + + + Alt+A + + + + + Paste address from clipboard + + + + + Alt+P + + + + + Enter the message you want to sign here + + + + + Copy the current signature to the system clipboard + + + + + Sign the message to prove you own this Arepacoin address + + + + + Reset all sign message fields + + + + + + Clear &All + + + + + + &Verify Message + + + + + Enter the signing address, message (ensure you copy line breaks, spaces, tabs, etc. exactly) and signature below to verify the message. Be careful not to read more into the signature than what is in the signed message itself, to avoid being tricked by a man-in-the-middle attack. + + + + + The address the message was signed with (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Verify the message to ensure it was signed with the specified Arepacoin address + + + + + Reset all verify message fields + + + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Click "Sign Message" to generate signature + + + + + Enter Arepacoin signature + + + + + + The entered address is invalid. + + + + + + + + Please check the address and try again. + + + + + + The entered address does not refer to a key. + + + + + Wallet unlock was cancelled. + + + + + Private key for the entered address is not available. + + + + + Message signing failed. + + + + + Message signed. + + + + + The signature could not be decoded. + + + + + + Please check the signature and try again. + + + + + The signature did not match the message digest. + + + + + Message verification failed. + + + + + Message verified. + + + + + TransactionDesc + + + Open until %1 + + + + + Open for %n block(s) + + + + + conflicted + + + + + %1/offline + + + + + %1/unconfirmed + + + + + %1 confirmations + + + + + Status + + + + + , broadcast through %n node(s) + + + + + Date + + + + + Source + + + + + Generated + + + + + + From + + + + + + + To + + + + + + own address + + + + + label + + + + + + + + + Credit + + + + + matures in %n more block(s) + + + + + not accepted + + + + + + + + Debit + + + + + Transaction fee + + + + + Net amount + + + + + Message + + + + + Comment + + + + + Transaction ID + + + + + Generated coins must mature 6 blocks before they can be spent. When you generated this block, it was broadcast to the network to be added to the block chain. If it fails to get into the chain, its state will change to "not accepted" and it won't be spendable. This may occasionally happen if another node generates a block within a few seconds of yours. + + + + + Debug information + + + + + Transaction + + + + + Inputs + + + + + Amount + + + + + true + + + + + false + + + + + , has not been successfully broadcast yet + + + + + unknown + + + + + TransactionDescDialog + + + Transaction details + + + + + This pane shows a detailed description of the transaction + + + + + TransactionTableModel + + + Date + + + + + Type + + + + + Address + + + + + Amount + + + + + Open until %1 + + + + + Confirmed (%1 confirmations) + + + + + Open for %n more block(s) + + + + + Offline + + + + + Unconfirmed + + + + + Confirming (%1 of %2 recommended confirmations) + + + + + Conflicted + + + + + Immature (%1 confirmations, will be available after %2) + + + + + This block was not received by any other nodes and will probably not be accepted! + + + + + Generated but not accepted + + + + + Received with + + + + + Received from + + + + + Sent to + + + + + Payment to yourself + + + + + Mined + + + + + (n/a) + + + + + Transaction status. Hover over this field to show number of confirmations. + + + + + Date and time that the transaction was received. + + + + + Type of transaction. + + + + + Destination address of transaction. + + + + + Amount removed from or added to balance. + + + + + TransactionView + + + + All + + + + + Today + + + + + This week + + + + + This month + + + + + Last month + + + + + This year + + + + + Range... + + + + + Received with + + + + + Sent to + + + + + To yourself + + + + + Mined + + + + + Other + + + + + Enter address or label to search + + + + + Min amount + + + + + Copy address + + + + + Copy label + + + + + Copy amount + + + + + Copy transaction ID + + + + + Edit label + + + + + Show transaction details + + + + + Export Transaction Data + + + + + Comma separated file (*.csv) + + + + + Confirmed + + + + + Date + + + + + Type + + + + + Label + + + + + Address + + + + + Amount + + + + + ID + + + + + Error exporting + + + + + Could not write to file %1. + + + + + Range: + + + + + to + + + + + WalletModel + + + Sending... + + + + + bitcoin-core + + + Arepacoin version + + + + + Usage: + + + + + Send command to -server or arepacoind + + + + + List commands + + + + + Get help for a command + + + + + Options: + + + + + Specify configuration file (default: arepacoin.conf) + + + + + Specify pid file (default: arepacoind.pid) + + + + + Specify wallet file (within data directory) + + + + + Specify data directory + + + + + Set database cache size in megabytes (default: 25) + + + + + Set database disk log size in megabytes (default: 100) + + + + + Listen for connections on <port> (default: 9853 or testnet: 19853) + + + + + Maintain at most <n> connections to peers (default: 125) + + + + + Connect to a node to retrieve peer addresses, and disconnect + + + + + Specify your own public address + + + + + Bind to given address. Use [host]:port notation for IPv6 + + + + + Stake your coins to support network and gain reward (default: 1) + + + + + Threshold for disconnecting misbehaving peers (default: 100) + + + + + Number of seconds to keep misbehaving peers from reconnecting (default: 86400) + + + + + An error occurred while setting up the RPC port %u for listening on IPv4: %s + + + + + Detach block and address databases. Increases shutdown time (default: 0) + + + + + 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. + + + + + Error: This transaction requires a transaction fee of at least %s because of its amount, complexity, or use of recently received funds + + + + + Listen for JSON-RPC connections on <port> (default: 9852 or testnet: 19852) + + + + + Accept command line and JSON-RPC commands + + + + + Error: Transaction creation failed + + + + + Error: Wallet locked, unable to create transaction + + + + + Importing blockchain data file. + + + + + Importing bootstrap blockchain data file. + + + + + Run in the background as a daemon and accept commands + + + + + Use the test network + + + + + Accept connections from outside (default: 1 if no -proxy or -connect) + + + + + An error occurred while setting up the RPC port %u for listening on IPv6, falling back to IPv4: %s + + + + + Error initializing database environment %s! To recover, BACKUP THAT DIRECTORY, then remove everything from it except for wallet.dat. + + + + + Set maximum size of high-priority/low-fee transactions in bytes (default: 27000) + + + + + Warning: -paytxfee is set very high! This is the transaction fee you will pay if you send a transaction. + + + + + Warning: Please check that your computer's date and time are correct! If your clock is wrong Arepacoin will not work properly. + + + + + Warning: error reading wallet.dat! All keys read correctly, but transaction data or address book entries might be missing or incorrect. + + + + + Warning: wallet.dat corrupt, data salvaged! Original wallet.dat saved as wallet.{timestamp}.bak in %s; if your balance or transactions are incorrect you should restore from a backup. + + + + + Attempt to recover private keys from a corrupt wallet.dat + + + + + Block creation options: + + + + + Connect only to the specified node(s) + + + + + Discover own IP address (default: 1 when listening and no -externalip) + + + + + Failed to listen on any port. Use -listen=0 if you want this. + + + + + Find peers using DNS lookup (default: 1) + + + + + Sync checkpoints policy (default: strict) + + + + + Invalid -tor address: '%s' + + + + + Invalid amount for -reservebalance=<amount> + + + + + Maximum per-connection receive buffer, <n>*1000 bytes (default: 5000) + + + + + Maximum per-connection send buffer, <n>*1000 bytes (default: 1000) + + + + + Only connect to nodes in network <net> (IPv4, IPv6 or Tor) + + + + + Output extra debugging information. Implies all other -debug* options + + + + + Output extra network debugging information + + + + + Prepend debug output with timestamp + + + + + SSL options: (see the Bitcoin Wiki for SSL setup instructions) + + + + + Select the version of socks proxy to use (4-5, default: 5) + + + + + Send trace/debug info to console instead of debug.log file + + + + + Send trace/debug info to debugger + + + + + Set maximum block size in bytes (default: 250000) + + + + + Set minimum block size in bytes (default: 0) + + + + + Shrink debug.log file on client startup (default: 1 when no -debug) + + + + + Specify connection timeout in milliseconds (default: 5000) + + + + + Unable to sign checkpoint, wrong checkpointkey? + + + + + + Use UPnP to map the listening port (default: 0) + + + + + Use UPnP to map the listening port (default: 1 when listening) + + + + + Use proxy to reach tor hidden services (default: same as -proxy) + + + + + Username for JSON-RPC connections + + + + + Verifying database integrity... + + + + + WARNING: syncronized checkpoint violation detected, but skipped! + + + + + Warning: Disk space is low! + + + + + Warning: This version is obsolete, upgrade required! + + + + + wallet.dat corrupt, salvage failed + + + + + Password for JSON-RPC connections + + + + + %s, you must set a rpcpassword in the configuration file: + %s +It is recommended you use the following random password: +rpcuser=arepacoinrpc +rpcpassword=%s +(you do not need to remember this password) +The username and password MUST NOT be the same. +If the file does not exist, create it with owner-readable-only file permissions. +It is also recommended to set alertnotify so you are notified of problems; +for example: alertnotify=echo %%s | mail -s "Arepacoin Alert" admin@foo.com + + + + + + Find peers using internet relay chat (default: 0) + + + + + Sync time with other nodes. Disable if time on your system is precise e.g. syncing with NTP (default: 1) + + + + + When creating transactions, ignore inputs with value less than this (default: 0.01) + + + + + Allow JSON-RPC connections from specified IP address + + + + + Send commands to node running on <ip> (default: 127.0.0.1) + + + + + Execute command when the best block changes (%s in cmd is replaced by block hash) + + + + + Execute command when a wallet transaction changes (%s in cmd is replaced by TxID) + + + + + Require a confirmations for change (default: 0) + + + + + Enforce transaction scripts to use canonical PUSH operators (default: 1) + + + + + Execute command when a relevant alert is received (%s in cmd is replaced by message) + + + + + Upgrade wallet to latest format + + + + + Set key pool size to <n> (default: 100) + + + + + Rescan the block chain for missing wallet transactions + + + + + How many blocks to check at startup (default: 2500, 0 = all) + + + + + How thorough the block verification is (0-6, default: 1) + + + + + Imports blocks from external blk000?.dat file + + + + + Use OpenSSL (https) for JSON-RPC connections + + + + + Server certificate file (default: server.cert) + + + + + Server private key (default: server.pem) + + + + + Acceptable ciphers (default: TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH) + + + + + Error: Wallet unlocked for staking only, unable to create transaction. + + + + + WARNING: Invalid checkpoint found! Displayed transactions may not be correct! You may need to upgrade, or notify developers. + + + + + This help message + + + + + Wallet %s resides outside data directory %s. + + + + + Cannot obtain a lock on data directory %s. Arepacoin is probably already running. + + + + + Arepacoin + + + + + Unable to bind to %s on this computer (bind returned error %d, %s) + + + + + Connect through socks proxy + + + + + Allow DNS lookups for -addnode, -seednode and -connect + + + + + Loading addresses... + + + + + Error loading blkindex.dat + + + + + Error loading wallet.dat: Wallet corrupted + + + + + Error loading wallet.dat: Wallet requires newer version of Arepacoin + + + + + Wallet needed to be rewritten: restart Arepacoin to complete + + + + + Error loading wallet.dat + + + + + Invalid -proxy address: '%s' + + + + + Unknown network specified in -onlynet: '%s' + + + + + Unknown -socks proxy version requested: %i + + + + + Cannot resolve -bind address: '%s' + + + + + Cannot resolve -externalip address: '%s' + + + + + Invalid amount for -paytxfee=<amount>: '%s' + + + + + Error: could not start node + + + + + Sending... + + + + + Invalid amount + + + + + Insufficient funds + + + + + Loading block index... + + + + + Add a node to connect to and attempt to keep the connection open + + + + + Unable to bind to %s on this computer. Arepacoin is probably already running. + + + + + Fee per KB to add to transactions you send + + + + + Invalid amount for -mininput=<amount>: '%s' + + + + + Loading wallet... + + + + + Cannot downgrade wallet + + + + + Cannot initialize keypool + + + + + Cannot write default address + + + + + Rescanning... + + + + + Done loading + + + + + To use the %s option + + + + + Error + + + + + You must set rpcpassword=<password> in the configuration file: +%s +If the file does not exist, create it with owner-readable-only file permissions. + + + + \ No newline at end of file diff --git a/src/qt/locale/bitcoin_sk.ts b/src/qt/locale/bitcoin_sk.ts new file mode 100755 index 0000000..4a14b2d --- /dev/null +++ b/src/qt/locale/bitcoin_sk.ts @@ -0,0 +1,3311 @@ + + + AboutDialog + + + About Arepacoin + O Arepacoine + + + + <b>Arepacoin</b> version + verzia <b>Arepacoinu</b> + + + + Copyright © 2009-2014 The Bitcoin developers +Copyright © 2012-2014 The NovaCoin developers +Copyright © 2014 The Arepacoin developers + Copyright © 2009-2014 The Bitcoin developers +Copyright © 2012-2014 The NovaCoin developers +Copyright © 2014 The Arepacoin developers + + + + +This is experimental software. + +Distributed under the MIT/X11 software license, see the accompanying file COPYING or http://www.opensource.org/licenses/mit-license.php. + +This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit (http://www.openssl.org/) and cryptographic software written by Eric Young (eay@cryptsoft.com) and UPnP software written by Thomas Bernard. + +Toto je experimentálny softvér. + +Distribuovaný pod softvérovou licenciou MIT/X11, viď priložený súbor COPYING alebo http://www.opensource.org/licenses/mit-license.php. + +Tento produkt obsahuje softvér vyvinutý projektom OpenSSL Project pre použitie v sade OpenSSL Toolkit (http://www.openssl.org/) a šifrovací softvér, ktorý napísal Eric Young (eay@cryptsoft.com) a UPnP softvér ktorý napísaný Thomas Bernard. + + + + AddressBookPage + + + Address Book + Adresár + + + + Double-click to edit address or label + Dvojklikom editovať adresu alebo popis + + + + Create a new address + Vytvoriť novú adresu + + + + Copy the currently selected address to the system clipboard + Kopírovať práve zvolenú adresu do systémovej schránky + + + + &New Address + &Nová adresa + + + + These are your Arepacoin addresses for receiving payments. You may want to give a different one to each sender so you can keep track of who is paying you. + Toto sú vaše Arepacoin adresy pre príjem platieb. Možno budete chcieť dať inú každému odosielateľovi, aby ste mohli sledovať, kto Vám platí. + + + + &Copy Address + &Kopírovať adresu + + + + Show &QR Code + Ukáž &QR kód + + + + Sign a message to prove you own a Arepacoin address + Podpísať správu ako dôkaz, že vlastníte túto Arepacoin adresu + + + + Sign &Message + Podpísať &správu + + + + Delete the currently selected address from the list + Vymazať aktuálne vybranú adresu zo zoznamu + + + + Verify a message to ensure it was signed with a specified Arepacoin address + Overte správu, aby ste zabezpečili, že bola podpísaná s určitou Arepacoin adresou + + + + &Verify Message + &Overte správu + + + + &Delete + &Zmazať + + + + Copy &Label + Kopírovať &Popis + + + + &Edit + &Upraviť + + + + Export Address Book Data + Exportovať dáta z adresára + + + + Comma separated file (*.csv) + Čiarkou oddelený súbor (*.csv) + + + + Error exporting + Chyba pri exporte + + + + Could not write to file %1. + Nie je možné zapísať do súboru %1. + + + + AddressTableModel + + + Label + Popis + + + + Address + Adresa + + + + (no label) + (bez popisu) + + + + AskPassphraseDialog + + + Passphrase Dialog + Dialóg hesla + + + + Enter passphrase + Zadajte heslo + + + + New passphrase + Nové heslo + + + + Repeat new passphrase + Zopakujte nové heslo + + + + Serves to disable the trivial sendmoney when OS account compromised. Provides no real security. + Slúži na vypnutie trivial sendmoney keď je ohrozený OS účet. Neposkytuje žiadnu skutočnú istotu. + + + + For staking only + Len pre stávkovanie + + + + Enter the new passphrase to the wallet.<br/>Please use a passphrase of <b>10 or more random characters</b>, or <b>eight or more words</b>. + Zadajte nové heslo k peňaženke.<br/>Prosím použite heslo s dĺžkou aspon <b>10 a viac náhodných znakov</b>, alebo <b>8 a viac slov</b>. + + + + Encrypt wallet + Zašifrovať peňaženku + + + + This operation needs your wallet passphrase to unlock the wallet. + Táto operácia potrebuje heslo k vašej peňaženke aby ju mohla odomknúť. + + + + Unlock wallet + Odomknúť peňaženku + + + + This operation needs your wallet passphrase to decrypt the wallet. + Táto operácia potrebuje heslo k vašej peňaženke na dešifrovanie peňaženky. + + + + Decrypt wallet + Dešifrovať peňaženku + + + + Change passphrase + Zmena hesla + + + + Enter the old and new passphrase to the wallet. + Zadajte staré a nové heslo k peňaženke. + + + + Confirm wallet encryption + Potvrďte zašifrovanie peňaženky + + + + Warning: If you encrypt your wallet and lose your passphrase, you will <b>LOSE ALL OF YOUR COINS</b>! + Upozornenie: Ak zašifrujete vašu peňaženku a stratíte prístupové heslo, potom <b>prídete o všetky svoje MINCE</b>! + + + + Are you sure you wish to encrypt your wallet? + Ste si istí, že si želáte zašifrovať peňaženku? + + + + IMPORTANT: Any previous backups you have made of your wallet file should be replaced with the newly generated, encrypted wallet file. For security reasons, previous backups of the unencrypted wallet file will become useless as soon as you start using the new, encrypted wallet. + DÔLEŽITÉ: Všetky predchádzajúce zálohy vašej peňaženky, ktoré ste vykonali by mali byť nahradené novo vytvorenou, zašifrovanou peňaženkou. Z bezpečnostných dôvodov bude predchádzajúca záloha nezašifrovanej peňaženky k ničomu, akonáhle začnete používať novú, zašifrovanú peňaženku. + + + + + Warning: The Caps Lock key is on! + Upozornenie: Máte zapnutý Caps Lock! + + + + + Wallet encrypted + Peňaženka zašifrovaná + + + + Arepacoin will close now to finish the encryption process. Remember that encrypting your wallet cannot fully protect your coins from being stolen by malware infecting your computer. + Arepacoin sa teraz zavrie aby dokončil proces zašifrovania. Nezabudnite, že zašifrovanie vašej peňaženky nemôže plne chrániť vaše mince pred krádežou malwarom napadnutím vašeho počítača. + + + + + + + Wallet encryption failed + Šifrovanie peňaženky zlyhalo + + + + Wallet encryption failed due to an internal error. Your wallet was not encrypted. + Šifrovanie peňaženky zlyhalo kôli internej chybe. Vaša peňaženka nebola zašifrovaná. + + + + + The supplied passphrases do not match. + Zadané heslá nesúhlasia. + + + + Wallet unlock failed + Odomykanie peňaženky zlyhalo + + + + + + The passphrase entered for the wallet decryption was incorrect. + Zadané heslo pre dešifrovanie peňaženky bolo nesprávne. + + + + Wallet decryption failed + Zlyhalo šifrovanie peňaženky. + + + + Wallet passphrase was successfully changed. + Heslo k peňaženke bolo úspešne zmenené. + + + + BitcoinGUI + + + Sign &message... + Podpísať &správu... + + + + Synchronizing with network... + Synchronizácia so sieťou... + + + + &Overview + &Prehľad + + + + Show general overview of wallet + Zobraziť celkový prehľad o peňaženke + + + + &Transactions + &Transakcie + + + + Browse transaction history + Prechádzať históriu transakcií + + + + &Address Book + &Adresár + + + + Edit the list of stored addresses and labels + Úprava zoznamu uložených adries a popisov + + + + &Receive coins + &Prijať mince + + + + Show the list of addresses for receiving payments + Zobraziť zoznam adries pre príjem platieb + + + + &Send coins + &Poslať mince + + + + E&xit + &Ukončiť + + + + Quit application + Ukončiť program + + + + Show information about Arepacoin + Zobraziť informácie o Arepacoin + + + + About &Qt + O &Qt + + + + Show information about Qt + Zobrazit informácie o Qt + + + + &Options... + &Možnosti... + + + + &Encrypt Wallet... + &Zašifrovať peňaženku... + + + + &Backup Wallet... + &Zálohovať peňaženku... + + + + &Change Passphrase... + &Zmena hesla... + + + + ~%n block(s) remaining + ~%n blok zostáva~%n blokov zostávaZostáva ~%n blokov + + + + Downloaded %1 of %2 blocks of transaction history (%3% done). + Stiahnutých %1 z %2 blokov transakčnej histórie (%3% hotových). + + + + &Export... + &Export... + + + + Send coins to a Arepacoin address + Poslať mince na Arepacoin adresu + + + + Modify configuration options for Arepacoin + Upraviť možnosti konfigurácie pre Arepacoin + + + + Export the data in the current tab to a file + Exportovať dáta v aktuálnej karte do súboru + + + + Encrypt or decrypt wallet + Zašifrovať alebo dešifrovať peňaženku + + + + Backup wallet to another location + Zálohovať peňaženku na iné miesto + + + + Change the passphrase used for wallet encryption + Zmeniť heslo použité na šifrovanie peňaženky + + + + &Debug window + &Ladiace okno + + + + Open debugging and diagnostic console + Otvor konzolu pre ladenie a diagnostiku + + + + &Verify message... + Overiť správu + + + + Arepacoin + Arepacoin + + + + Wallet + Peňaženka + + + + &About Arepacoin + &O Arepacoin + + + + &Show / Hide + Zobraziť / skryť + + + + Unlock wallet + Odomknúť peňaženku + + + + &Lock Wallet + &Zamknúť peňaženku + + + + Lock wallet + Zamknúť peňaženku + + + + &File + &Súbor + + + + &Settings + &Nastavenia + + + + &Help + &Pomoc + + + + Tabs toolbar + Lišta záložiek + + + + Actions toolbar + Lišta činností + + + + + [testnet] + [testovacia sieť] + + + + + Arepacoin client + Arepacoin klient + + + + %n active connection(s) to Arepacoin network + %n aktívne spojenie s Arepacoin sieťov%n aktívnych spojení s Arepacoin sieťov%n aktívnych spojení s Arepacoin sieťou + + + + Downloaded %1 blocks of transaction history. + Stiahnutých %1 blokov z transakčnej histórie. + + + + Staking.<br>Your weight is %1<br>Network weight is %2<br>Expected time to earn reward is %3 + Stávkovanie.<br>Vaša váha je %1<br>Váha siete je %2<br>Odhadovaný čas pre získanie odmeny je %3 + + + + Not staking because wallet is locked + Nestávkujem pretože peňaženka je zamknutá + + + + Not staking because wallet is offline + Nestávkujem pretože peňaženka je offline + + + + Not staking because wallet is syncing + Nestávkujem pretože peňaženka sa synchronizuje + + + + Not staking because you don't have mature coins + Nestávkujem pretože nemáte odležané mince + + + + %n second(s) ago + pred %n sekundoupred %n sekundamipred %n sekundami + + + + &Unlock Wallet... + &Odomknúť peňaženku... + + + + %n minute(s) ago + pred %n minutoupred %n minutamipred %n minutami + + + + %n hour(s) ago + pred %n hodinoupred %n hodinamipred %n hodinami + + + + %n day(s) ago + pred %n dňompred %n dňamipred %n dňami + + + + Up to date + Aktualizovaný + + + + Catching up... + Sťahujem... + + + + Last received block was generated %1. + Posledný prijatý blok bol vytvorený %1. + + + + This transaction is over the size limit. You can still send it for a fee of %1, which goes to the nodes that process your transaction and helps to support the network. Do you want to pay the fee? + Táto transakcia je nad veľkostný limit. Stále ju môžete poslať za poplatok %1, ktorý ide uzlom spracujúcim vaše transakcie, čím pomáhate podporovať sieť. Chcete zaplatiť poplatok? + + + + Confirm transaction fee + Potvrďte transakčný poplatok + + + + Sent transaction + Odoslané transakcie + + + + Incoming transaction + Prijaté transakcie + + + + Date: %1 +Amount: %2 +Type: %3 +Address: %4 + + Dátum: %1 +Suma: %2 +Typ: %3 +Adresa: %4 + + + + + URI handling + URI manipulácia + + + + + URI can not be parsed! This can be caused by an invalid Arepacoin address or malformed URI parameters. + URI nemožno analyzovať! Toto môže byť spôsobené neplatnou Arepacoin adresu alebo chybnými URI parametrami. + + + + Wallet is <b>encrypted</b> and currently <b>unlocked</b> + Peňaženka je <b>zašifrovaná</b> a momentálne <b>odomknutá</b> + + + + Wallet is <b>encrypted</b> and currently <b>locked</b> + Peňaženka je <b>zašifrovaná</b> a momentálne <b>zamknutá</b> + + + + Backup Wallet + Zálohovanie peňaženky + + + + Wallet Data (*.dat) + Dáta peňaženky (*.dat) + + + + Backup Failed + Zálohovanie zlyhalo + + + + There was an error trying to save the wallet data to the new location. + Došlo k chybe pri pokuse o uloženie dát peňaženky do nového umiestnenia. + + + + %n second(s) + %n sekunda%n sekúnd%n sekúnd + + + + %n minute(s) + %n minúta%n minút%n minút + + + + %n hour(s) + %n hodina%n hodiny%n hodín + + + + %n day(s) + %n deň%n dni%n dní + + + + Not staking + Nestávkuje sa + + + + A fatal error occurred. Arepacoin can no longer continue safely and will quit. + Došlo k závažnej chybe. Arepacoin už nemôže pokračovať bezpečne a bude ukončený. + + + + ClientModel + + + Network Alert + Výstraha siete + + + + CoinControlDialog + + + Coin Control + Kontrola mincí + + + + Quantity: + Množstvo: + + + + Bytes: + Bajty: + + + + Amount: + Suma: + + + + Priority: + Priorita: + + + + Fee: + Poplatok: + + + + Low Output: + Nízky výstup: + + + + no + nie + + + + After Fee: + Po poplatku: + + + + Change: + Zmena: + + + + (un)select all + (ne)označiť všetko + + + + Tree mode + Stromový režim + + + + List mode + Zoznamový režim + + + + Amount + Suma + + + + Label + Menovka + + + + Address + Adresa + + + + Date + Dátum + + + + Confirmations + Potvrdenia + + + + Confirmed + Potvrdené + + + + Priority + Priorita + + + + Copy address + Kopírovať adresu + + + + Copy label + Kopírovať popis + + + + + Copy amount + Kopírovať sumu + + + + Copy transaction ID + Kopírovať ID transakcie + + + + Copy quantity + Kopírovať množstvo + + + + Copy fee + Kopírovať poplatok + + + + Copy after fee + Kopírovať po poplatku + + + + Copy bytes + Kopírovať bajty + + + + Copy priority + Kopírovať prioritu + + + + Copy low output + Kopírovať nízky výstup + + + + Copy change + Kopírovať zmenu + + + + highest + najvyššie + + + + high + vysoké + + + + medium-high + stredne vysoké + + + + medium + stredné + + + + low-medium + stredne nízke + + + + low + nízke + + + + lowest + najnižšie + + + + DUST + PRACH + + + + yes + áno + + + + This label turns red, if the transaction size is bigger than 10000 bytes. + + This means a fee of at least %1 per kb is required. + + Can vary +/- 1 Byte per input. + Tento popis sčervená, v prípade, že veľkosť transakcie je väčšia ako 10000 bajtov. + + To znamená, že je potrebný poplatok vo výške najmenej %1 za kb. + +Môže sa líšiť +/- 1 bajt za vstup. + + + + Transactions with higher priority get more likely into a block. + +This label turns red, if the priority is smaller than "medium". + + This means a fee of at least %1 per kb is required. + Transakcie s vyššou prioritou sa dostanú s väčšou pravdepodobnosťou do bloku. + +Tento popis sčervenie, ak je priorita menšia ako "stredná". + +To znamená, že je nutný poplatok vo výške aspoň %1 za kb. + + + + This label turns red, if any recipient receives an amount smaller than %1. + + This means a fee of at least %2 is required. + + Amounts below 0.546 times the minimum relay fee are shown as DUST. + Tento popis sčervenie, ak príjemca dostane sumu menšiu ako %1. + +To znamená, že je potrebný poplatok aspoň %2. + +Sumy nižšie ako 0,546 násobok minimálneho poplatku sú zobrazené ako PRACH. + + + + This label turns red, if the change is smaller than %1. + + This means a fee of at least %2 is required. + Tento popis sčervenie, ak je zmena menšia než %1. + +To znamená, že je potrebný poplatok aspoň %2. + + + + + (no label) + (bez popisu) + + + + change from %1 (%2) + zmena od %1 (%2) + + + + (change) + (zmena) + + + + EditAddressDialog + + + Edit Address + Upraviť adresu + + + + &Label + &Popis + + + + The label associated with this address book entry + Popis spojený s touto položkou v adresáry + + + + &Address + &Adresa + + + + The address associated with this address book entry. This can only be modified for sending addresses. + Adresa spojená s položkou v tomto adresári. Toto môže byť zmenené iba pre odosielané adresy. + + + + New receiving address + Nová adresa pre prijímanie + + + + New sending address + Nová adresa pre odoslanie + + + + Edit receiving address + Upraviť adresu pre prijímanie + + + + Edit sending address + Upraviť adresu pre odosielanie + + + + The entered address "%1" is already in the address book. + Zadaná adresa "%1" sa už nachádza v adresári. + + + + The entered address "%1" is not a valid Arepacoin address. + Zadaná adresa "%1" nie je platnou Arepacoin adresou. + + + + Could not unlock wallet. + Nepodarilo sa odomknúť peňaženku. + + + + New key generation failed. + Generovanie nového kľúča zlyhalo. + + + + GUIUtil::HelpMessageBox + + + + Arepacoin-Qt + Arepacoin-Qt + + + + version + verzia + + + + Usage: + Použitie: + + + + command-line options + možnosti príkazového riadka + + + + UI options + Možnosti používateľského rozhrania + + + + Set language, for example "de_DE" (default: system locale) + Nastavenie jazyka, napr "de_DE" (predvolené: miestne nastavenie systému) + + + + Start minimized + Spustiť minimalizované + + + + Show splash screen on startup (default: 1) + Zobraziť úvodnú obrazovku pri štarte (predvolené: 1) + + + + OptionsDialog + + + Options + Možnosti + + + + &Main + &Hlavné + + + + Optional transaction fee per kB that helps make sure your transactions are processed quickly. Most transactions are 1 kB. Fee 0.01 recommended. + Voliteľný transakčný poplatok za kB, ktorý pomáha zaistiť, že vaše transakcie sú spracované rýchlo. Väčšina transakcií je 1 kB. Poplatok 0.01 je odporúčaný. + + + + Pay transaction &fee + Zaplatiť transakčné &poplatky + + + + Reserved amount does not participate in staking and is therefore spendable at any time. + Rezervované množstvo sa nepodieľa na stávkovaní a preto je použiteľné kedykoľvek. + + + + Reserve + Rezerva + + + + Automatically start Arepacoin after logging in to the system. + Automaticky spustiť Arepacoin po prihlásení sa do systému. + + + + &Start Arepacoin on system login + &Spustiť Arepacoin pri prihlásení do systému + + + + Detach block and address databases at shutdown. This means they can be moved to another data directory, but it slows down shutdown. The wallet is always detached. + Odpojiť blok a databázy z adresami pri vypnutí počítača. To znamená, že môžu byť presunuté do iného adresára dát, ale to spomaľuje vypnutie. Peňaženka je vždy odpojená. + + + + &Detach databases at shutdown + &Odpojiť databázy pri vypnutí + + + + &Network + Sieť + + + + Automatically open the Arepacoin client port on the router. This only works when your router supports UPnP and it is enabled. + Automaticky otvoriť port klienta Arepacoin na routeri. To funguje iba vtedy, ak váš router podporuje UPnP a je povolené. + + + + Map port using &UPnP + Mapovať port pomocou &UPnP + + + + Connect to the Arepacoin network through a SOCKS proxy (e.g. when connecting through Tor). + Pripojenie k sieti Arepacoin cez SOCKS proxy server (napr. pri pripojení cez Tor). + + + + &Connect through SOCKS proxy: + &Pripojenie cez SOCKS proxy server: + + + + Proxy &IP: + Proxy &IP: + + + + IP address of the proxy (e.g. 127.0.0.1) + IP adresa proxy servera (napr. 127.0.0.1) + + + + &Port: + &Port: + + + + Port of the proxy (e.g. 9050) + Port proxy (napr. 9050) + + + + SOCKS &Version: + Verzia SOCKS: + + + + SOCKS version of the proxy (e.g. 5) + SOCKS verzia proxy (napr. 5) + + + + &Window + Okno + + + + Show only a tray icon after minimizing the window. + Zobraziť len ikonu na lište po minimalizovaní okna. + + + + &Minimize to the tray instead of the taskbar + Minimalizovať na lištu namiesto panelu úloh + + + + Minimize instead of exit the application when the window is closed. When this option is enabled, the application will be closed only after selecting Quit in the menu. + Minimalizovať namiesto ukončenia aplikácie keď sa zatvorí okno. Keď je zvolená táto možnosť, aplikácia sa zatvorí len po zvolení Ukončiť v menu. + + + + M&inimize on close + M&inimalizovať pri zatvorení + + + + &Display + &Displej + + + + User Interface &language: + Jazyk používateľského rozhrania: + + + + The user interface language can be set here. This setting will take effect after restarting Arepacoin. + Tu môžete nastaviť jazyk používateľského rozhrania. Toto nastavenie sa prejaví až po reštartovaní Arepacoin. + + + + &Unit to show amounts in: + &Zobrazovať hodnoty v jednotkách: + + + + Choose the default subdivision unit to show in the interface and when sending coins. + Vyberte si predvolené delenie jednotiek zobrazované v rozhraní a pri odosielaní mincí. + + + + Whether to show Arepacoin addresses in the transaction list or not. + Či chcete zobraziť Arepacoin adresy v zozname transakcií alebo nie. + + + + &Display addresses in transaction list + &Zobraziť adresy v zozname transakcií + + + + Whether to show coin control features or not. + Či sa majú zobraziť coin control features alebo nie. + + + + Display coin &control features (experts only!) + Zobraziť coin &control features (len pre odborníkov!) + + + + &OK + &OK + + + + &Cancel + Zrušiť + + + + &Apply + &Použiť + + + + default + predvolené + + + + + Warning + Upozornenie + + + + + This setting will take effect after restarting Arepacoin. + Toto nastavenie sa prejaví až po reštartovaní Arepacoin. + + + + The supplied proxy address is invalid. + Zadaná proxy adresa je neplatná. + + + + OverviewPage + + + Form + Forma + + + + + The displayed information may be out of date. Your wallet automatically synchronizes with the Arepacoin network after a connection is established, but this process has not completed yet. + Zobrazené informácie môžu byť zastaralé. Vaša peňaženka sa automaticky synchronizuje so sieťou Arepacoin po nadviazaní spojenia, ale tento proces nie je ešte dokončený. + + + + Stake: + V stávke: + + + + Unconfirmed: + Nepotvrdené: + + + + Wallet + Peňaženka + + + + Spendable: + Použiteľné: + + + + Your current spendable balance + Váš aktuálny použiteľný zostatok + + + + Immature: + Nezrelé: + + + + Mined balance that has not yet matured + Vyťažený zostatok, ktorý nebol ešte dozretý + + + + Total: + Celkovo: + + + + Your current total balance + Váš súčasný celkový zostatok + + + + <b>Recent transactions</b> + <b>Nedávne transakcie</b> + + + + Total of transactions that have yet to be confirmed, and do not yet count toward the current balance + Súčet transakcií, ktoré neboli ešte potvrdené, a ešte nezapočítané do aktuálneho zostatku + + + + Total of coins that was staked, and do not yet count toward the current balance + Súčet mincí, ktoré sú v stávke a ešte neboli započítané do aktuálneho zostatku + + + + + out of sync + nezosynchronizované + + + + QRCodeDialog + + + QR Code Dialog + QR Code Dialóg + + + + Request Payment + Vyžiadať Platbu + + + + Amount: + Čiastka: + + + + Label: + Popis: + + + + Message: + Správa: + + + + &Save As... + &Uložiť ako... + + + + Error encoding URI into QR Code. + Chyba kódovania URI do QR Code. + + + + The entered amount is invalid, please check. + Zadaná suma je neplatná, prosím skontrolujte. + + + + Resulting URI too long, try to reduce the text for label / message. + Výsledná URI príliš dlhá, skúste skrátiť text popisu / správy. + + + + Save QR Code + Uložiť QR Code + + + + PNG Images (*.png) + PNG Obrázky (*.png) + + + + RPCConsole + + + Client name + Meno klienta + + + + + + + + + + + + + N/A + nie je k dispozícii + + + + Client version + Verzia klienta + + + + &Information + &Informácie + + + + Using OpenSSL version + Používa OpenSSL verziu + + + + Startup time + Čas spustenia + + + + Network + Sieť + + + + Number of connections + Počet pripojení + + + + On testnet + Na testovacej sieti + + + + Block chain + Reťazec blokov + + + + Current number of blocks + Aktuálny počet blokov + + + + Estimated total blocks + Očakávaných blokov celkovo + + + + Last block time + Čas posledného bloku + + + + &Open + &Otvoriť + + + + Command-line options + Možnosti príkazového riadka + + + + Show the Arepacoin-Qt help message to get a list with possible Arepacoin command-line options. + Zobraziť Arepacoin-Qt nápovedu k získaniu zoznamu pre možnosti príkazového riadku Arepacoin. + + + + &Show + &Zobraziť + + + + &Console + &Konzola + + + + Build date + Dátum zostavenia + + + + Arepacoin - Debug window + Arepacoin - Ladiace okno + + + + Arepacoin Core + Jadro Arepacoin + + + + Debug log file + Súbor denníka ladenia + + + + Open the Arepacoin debug log file from the current data directory. This can take a few seconds for large log files. + Otvorte Arepacoin súbor denníku ladenia z aktuálneho adresára dát. To môže trvať niekoľko sekúnd pre veľké súbory denníka. + + + + Clear console + Vymazať konzolu + + + + Welcome to the Arepacoin RPC console. + Vitajte v konzole Arepacoin RPC. + + + + Use up and down arrows to navigate history, and <b>Ctrl-L</b> to clear screen. + Použite šípky hore a dole pre navigáciu históriou, a <b> Ctrl-L </ b> pre vymazanie obrazovky. + + + + Type <b>help</b> for an overview of available commands. + Zadajte <b>help</b> pre prehľad dostupných príkazov. + + + + SendCoinsDialog + + + + + + + + + + Send Coins + Poslať mince + + + + Coin Control Features + Coin Control Features + + + + Inputs... + Vstupy... + + + + automatically selected + automaticky vybrané + + + + Insufficient funds! + Nedostatok prostriedkov! + + + + Quantity: + Množstvo: + + + + + 0 + 0 + + + + Bytes: + Bajtov: + + + + Amount: + Suma: + + + + + + + 0.00 BC + 123.456 BC {0.00 ?} + + + + Priority: + Priorita: + + + + medium + stredne + + + + Fee: + Poplatok: + + + + Low Output: + Nízky výstup: + + + + no + nie + + + + After Fee: + Po poplatkoch: + + + + Change + Zmeniť + + + + custom change address + vlastná zmena adresy + + + + Send to multiple recipients at once + Poslať viacerým príjemcom naraz + + + + Add &Recipient + &Pridať príjemcu + + + + Remove all transaction fields + Odstráňte všetky transakčné polia + + + + Clear &All + Zmazať &všetko + + + + Balance: + Zostatok: + + + + 123.456 BC + 123.456 BC + + + + Confirm the send action + Potvrďte odoslanie + + + + S&end + &Odoslať + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + Zadajte Arepacoin adresu (napr. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + Copy quantity + Kopírovať množstvo + + + + Copy amount + Kopírovať sumu + + + + Copy fee + Kopírovať poplatok + + + + Copy after fee + Kopírovať po poplatkoch + + + + Copy bytes + Kopírovať bajty + + + + Copy priority + Kopírovať prioritu + + + + Copy low output + Kopírovať nízky výstup + + + + Copy change + Kopírovať zmenu + + + + <b>%1</b> to %2 (%3) + <b>%1</b> do %2 (%3) + + + + Confirm send coins + Potvrdiť odoslanie mincí + + + + Are you sure you want to send %1? + Ste si istý, že chcete poslať %1? + + + + and + a + + + + The recipient address is not valid, please recheck. + Adresa príjemcu je neplatná, overte ju prosím. + + + + The amount to pay must be larger than 0. + Suma na úhradu musí byť väčšia ako 0. + + + + The amount exceeds your balance. + Suma je vyššia ako Váš zostatok. + + + + The total exceeds your balance when the %1 transaction fee is included. + Celková suma prevyšuje Váš zostatok ak sú započítané aj transakčné poplatky %1. + + + + Duplicate address found, can only send to each address once per send operation. + Objavený duplikát adresy, na každú adresu je možné poslať len raz v jednej odchádzajúcej transakcii. + + + + Error: Transaction creation failed. + Chyba: Vytvorenie transakcie zlyhalo. + + + + 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. + Chyba: Transakcia bola zamietnutá. To môže nastať, ak niektoré z mincí vo vašej peňaženke sa už použili, ako napríklad, ak ste použili kópiu wallet.dat a mince boli použité v kópii, ale neboli označené tu ako použité. + + + + WARNING: Invalid Arepacoin address + UPOZORNENIE: Neplatná Arepacoin adresa + + + + (no label) + (bez popisu) + + + + WARNING: unknown change address + UPOZORNENIE: Neznáma zmena adresy + + + + SendCoinsEntry + + + Form + Formulár + + + + A&mount: + Su&ma: + + + + Pay &To: + Zapla&tiť: + + + + + Enter a label for this address to add it to your address book + Vložte popis pre túto adresu aby sa pridala do adresára + + + + &Label: + &Popis: + + + + The address to send the payment to (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + Adresa pre poslanie platby (napr. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + Choose address from address book + Vybrať adresu z adresára + + + + Alt+A + Alt+A + + + + Paste address from clipboard + Vložiť adresu zo schránky + + + + Alt+P + Alt+P + + + + Remove this recipient + Odstrániť tohto príjemcu + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + Zadajte Arepacoin adresu (napr. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + SignVerifyMessageDialog + + + Signatures - Sign / Verify a Message + Podpisy - Prihlásiť sa / Overiť správu + + + + + &Sign Message + &Podpísať správu + + + + You can sign messages with your addresses to prove you own them. Be careful not to sign anything vague, as phishing attacks may try to trick you into signing your identity over to them. Only sign fully-detailed statements you agree to. + Môžete podpísať správy svojimi adresami a dokázať tak, že ich vlastníte. Buďte opatrní a podpíšte len prehlásenia s ktorými plne súhlasíte, nakoľko útoky typu "phishing" Vás môžu lákať k ich podpísaniu. Podpisujete iba plne detailné vyhlásenia s ktorými súhlasíte. + + + + The address to sign the message with (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + Adresa na podpísanie správy (napr. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Choose an address from the address book + Vyberte adresu z adresára + + + + + Alt+A + Alt+A + + + + Paste address from clipboard + Vložiť adresu zo schránky + + + + Alt+P + Alt+P + + + + Enter the message you want to sign here + Sem vložte správu ktorú chcete podpísať + + + + Copy the current signature to the system clipboard + Skopírujte aktuálny podpis do schránky + + + + Sign the message to prove you own this Arepacoin address + Podpísať správu ako dôkaz, že vlastníte túto Arepacoin adresu + + + + Reset all sign message fields + Obnoviť všetky polia podpísania správy + + + + + Clear &All + Zmazať &všetko + + + + + &Verify Message + Overiť správu... + + + + Enter the signing address, message (ensure you copy line breaks, spaces, tabs, etc. exactly) and signature below to verify the message. Be careful not to read more into the signature than what is in the signed message itself, to avoid being tricked by a man-in-the-middle attack. + Zadajte podpisovú adresu správy (uistite sa že presne kopírujete konce riadkov, medzier, tabulátorov, atď.) a podpis nižšie pre overenie správy. Dávajte pozor, aby ste nedali viac do podpisu, než to, čo je v podpísanej správe samotnej, aby ste sa vyhli oklamaniu útokom typu man-in-the-middle. + + + + The address the message was signed with (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + Adresa správy bola podpísaná (napr. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + Verify the message to ensure it was signed with the specified Arepacoin address + Overte správu, aby ste sa ubezpečili, že bola podpísaná s danou Arepacoin adresou + + + + Reset all verify message fields + Obnoviť všetky polia pre overenie správy + + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + Zadajte Arepacoin adresu (napr. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + Click "Sign Message" to generate signature + Kliknite "Podpísať správu" pre získanie podpisu + + + + Enter Arepacoin signature + Zadajte Arepacoin podpis + + + + + The entered address is invalid. + Zadaná adresa je neplatná. + + + + + + + Please check the address and try again. + Prosím skontrolujte adresu a skúste znova. + + + + + The entered address does not refer to a key. + Zadaná adresa sa nevzťahuje na kľúč. + + + + Wallet unlock was cancelled. + Odomknutie peňaženky bolo zrušené. + + + + Private key for the entered address is not available. + Súkromný kľúč k zadanej adrese nie je k dispozícii. + + + + Message signing failed. + Podpísanie správy zlyhalo. + + + + Message signed. + Správa podpísaná. + + + + The signature could not be decoded. + Podpis nie je možné dekódovať. + + + + + Please check the signature and try again. + Prosím skontrolujte podpis a skúste znova. + + + + The signature did not match the message digest. + Podpis nezodpovedá súhrnu správy. + + + + Message verification failed. + Overenie správy zlyhalo. + + + + Message verified. + Správa overená. + + + + TransactionDesc + + + Open until %1 + Otvorené do %1 + + + + Open for %n block(s) + Otvoriť pre %n blokOtvoriť pre %n blokovOtvoriť pre %n blokov + + + + conflicted + v rozpore + + + + %1/offline + %1/offline + + + + %1/unconfirmed + %1/nepotvrdené + + + + %1 confirmations + %1 potvrdení + + + + Status + Stav + + + + , broadcast through %n node(s) + , vysielanie cez %n uzol, vysielanie cez %n uzlov, vysielanie cez %n uzlov + + + + Date + Dátum + + + + Source + Zdroj + + + + Generated + Vygenerované + + + + + From + Od + + + + + + To + Pre + + + + + own address + vlastná adresa + + + + label + popis + + + + + + + + Credit + Kredit + + + + matures in %n more block(s) + dozreje o ďalší %n blokdozreje o ďalších %n blokovdozreje o ďalších %n blokov + + + + not accepted + neprijaté + + + + + + + Debit + Debet + + + + Transaction fee + Transakčný poplatok + + + + Net amount + Čiastka netto + + + + Message + Správa + + + + Comment + Komentár + + + + Transaction ID + ID transakcie + + + + Generated coins must mature 6 blocks before they can be spent. When you generated this block, it was broadcast to the network to be added to the block chain. If it fails to get into the chain, its state will change to "not accepted" and it won't be spendable. This may occasionally happen if another node generates a block within a few seconds of yours. + Generované mince musia zrieť 6 blokov pred tým, než môžu byť použité. Keď sa vygeneroval tento blok, bol vysielaný do siete, kde má byť pridaný do reťazca blokov. Ak sa nepodarí dostať ho do reťazca blokov, jeho stav sa zmení na "Neprijatý", a nebude použiteľný. Toto sa môže občas stať, ak iný uzol generuje blok v priebehu niekoľkých sekúnd pred Vami. + + + + Debug information + Ladiace informácie + + + + Transaction + Transakcie + + + + Inputs + Vstupy + + + + Amount + Suma + + + + true + pravda + + + + false + nepravda + + + + , has not been successfully broadcast yet + , ešte nebola úspešne odoslaná + + + + unknown + neznámy + + + + TransactionDescDialog + + + Transaction details + Detaily transakcie + + + + This pane shows a detailed description of the transaction + Táto časť obrazovky zobrazuje detailný popis transakcie + + + + TransactionTableModel + + + Date + Dátum + + + + Type + Typ + + + + Address + Adresa + + + + Amount + Hodnota + + + + Open until %1 + Otvorené do %1 + + + + Confirmed (%1 confirmations) + Potvrdené (%1 potvrdení) + + + + Open for %n more block(s) + Otvoriť pre %n ďalší blokOtvoriť pre %n ďalšie blokyOtvoriť pre %n ďalšie bloky + + + + Offline + Offline + + + + Unconfirmed + Nepotvrdené + + + + Confirming (%1 of %2 recommended confirmations) + Potvrdzujem (%1 z %2 doporučených potvrdení) + + + + Conflicted + V rozpore + + + + Immature (%1 confirmations, will be available after %2) + Nezrelé (%1 potvrdení, bude k dispozícii po %2) + + + + This block was not received by any other nodes and will probably not be accepted! + Ten blok nebol prijatý žiadnym iným uzlom a pravdepodobne nebude akceptovaný! + + + + Generated but not accepted + Vypočítané ale neakceptované + + + + Received with + Prijaté s + + + + Received from + Prijaté od: + + + + Sent to + Odoslané na + + + + Payment to yourself + Platba sebe samému + + + + Mined + Vyťažené + + + + (n/a) + (n/a) + + + + Transaction status. Hover over this field to show number of confirmations. + Status transakcie. Presuňte myš nad toto pole a zobrazí sa počet potvrdení. + + + + Date and time that the transaction was received. + Dátum a čas prijatia transakcie. + + + + Type of transaction. + Typ transakcie. + + + + Destination address of transaction. + Cieľová adresa transakcie. + + + + Amount removed from or added to balance. + Suma pridaná alebo odobraná k zostatku. + + + + TransactionView + + + + All + Všetko + + + + Today + Dnes + + + + This week + Tento týždeň + + + + This month + Tento mesiac + + + + Last month + Minulý mesiac + + + + This year + Tento rok + + + + Range... + Rozsah... + + + + Received with + Prijaté s + + + + Sent to + Odoslané na + + + + To yourself + Samému sebe + + + + Mined + Vyťažené + + + + Other + Iné + + + + Enter address or label to search + Vložte adresu alebo popis pre vyhľadávanie + + + + Min amount + Min. množstvo + + + + Copy address + Kopírovať adresu + + + + Copy label + Kopírovať popis + + + + Copy amount + Kopírovať sumu + + + + Copy transaction ID + Kopírovať ID transakcie + + + + Edit label + Editovať popis + + + + Show transaction details + Zobraziť podrobnosti transakcie + + + + Export Transaction Data + Export transakčných údajov + + + + Comma separated file (*.csv) + Čiarkou oddelovaný súbor (*.csv) + + + + Confirmed + Potvrdené + + + + Date + Dátum + + + + Type + Typ + + + + Label + Popis + + + + Address + Adresa + + + + Amount + Suma + + + + ID + ID + + + + Error exporting + Chyba pri exporte + + + + Could not write to file %1. + Nemožno zapisovať do súboru %1. + + + + Range: + Rozsah: + + + + to + do + + + + WalletModel + + + Sending... + Posielam... + + + + bitcoin-core + + + Arepacoin version + Arepacoin verzia + + + + Usage: + Použitie: + + + + Send command to -server or arepacoind + Pošli príkaz na -server alebo arepacoind + + + + List commands + Zoznam príkazov + + + + Get help for a command + Získať pomoc pre príkaz + + + + Options: + Možnosti: + + + + Specify configuration file (default: arepacoin.conf) + Zadajte konfiguračný súbor (predvolené: arepacoin.conf) + + + + Specify pid file (default: arepacoind.pid) + Zadajte pid súbor (predvolené: arepacoind.pid) + + + + Specify wallet file (within data directory) + Zadajte súbor peňaženky (v rámci dátového adresára) + + + + Specify data directory + Zadajte priečinok s dátami + + + + Set database cache size in megabytes (default: 25) + Nastaviť veľkosť vyrovnávajúcej pamäte pre databázu v megabytoch (predvolené: 25) + + + + Set database disk log size in megabytes (default: 100) + Nastaviť veľkosť databázového denníka na disku v MB (predvolené: 100) + + + + Listen for connections on <port> (default: 9853 or testnet: 19853) + Počúvať pripojenia na <port> (predvolené: 9853 alebo testovacia sieť: 19853) + + + + Maintain at most <n> connections to peers (default: 125) + Udržiavať maximálne <n> spojení (predvolené: 125) + + + + Connect to a node to retrieve peer addresses, and disconnect + Pre načítanie peer adresy sa pripojte k uzlu, a odpojte + + + + Specify your own public address + Určite vašu vlastnú verejnú adresu + + + + Bind to given address. Use [host]:port notation for IPv6 + Spojiť do danej adresy. Použite [host]:port zápis pre IPv6 + + + + Stake your coins to support network and gain reward (default: 1) + Nechajte stávkovať vaše mince pre podporu siete a získajte odmenu (predvolené: 1) + + + + Threshold for disconnecting misbehaving peers (default: 100) + Hranica pre odpojenie zle sa správajúcich peerov (predvolené: 100) + + + + Number of seconds to keep misbehaving peers from reconnecting (default: 86400) + Počet sekúnd kedy sa zabráni zle sa správajúcim peerom znovupripojenie (predvolené: 86400) + + + + An error occurred while setting up the RPC port %u for listening on IPv4: %s + Pri nastavovaní portu RPC %u pre počúvanie na IPv4 došlo k chybe: %s + + + + Detach block and address databases. Increases shutdown time (default: 0) + Odpojiť blok a databázy adries. Zvyšuje vypínací čas (predvolené: 0) + + + + 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. + Chyba: Transakcia bola zamietnutá. To môže nastať, ak niektoré z mincí vo vašej peňaženke sa už použili, ako napríklad, ak ste použili kópiu wallet.dat a mince boli použité v kópii, ale neboli označené ako použité tu. + + + + Error: This transaction requires a transaction fee of at least %s because of its amount, complexity, or use of recently received funds + Chyba: Táto operácia vyžaduje transakčný poplatok vo výške aspoň %s, pretože jeho množstvo, zložitosť, alebo použitím nedávno prijatých finančných prostriedkov + + + + Listen for JSON-RPC connections on <port> (default: 9852 or testnet: 19852) + Počúvajte pre JSON-RPC spojenie na <port> (predvolené: 9852 alebo testovaciasieť: 19852) + + + + Accept command line and JSON-RPC commands + Prijímať príkazy z príkazového riadku a JSON-RPC + + + + Error: Transaction creation failed + Chyba: Vytvorenie transakcie zlyhalo + + + + Error: Wallet locked, unable to create transaction + Chyba: Peňaženka je zamknutá, nie je možné vytvoriť transakciu + + + + Importing blockchain data file. + Importovanie dátového súboru reťazca blokov. + + + + Importing bootstrap blockchain data file. + Import zavádzacej časti blockchain dátového súbora. + + + + Run in the background as a daemon and accept commands + Bežať na pozadí ako démon a prijímať príkazy + + + + Use the test network + Použiť testovaciu sieť + + + + Accept connections from outside (default: 1 if no -proxy or -connect) + Prijímať pripojenie z vonka (predvolené: 1, ak nie -proxy alebo -connect) + + + + An error occurred while setting up the RPC port %u for listening on IPv6, falling back to IPv4: %s + Pri nastavovaní portu RPC %u pre počúvanie na IPv6, spadne späť do IPv4 došlo k chybe: %s + + + + Error initializing database environment %s! To recover, BACKUP THAT DIRECTORY, then remove everything from it except for wallet.dat. + Chyba pri inicializácii databázy prostredie %s! Ak chcete obnoviť, ZÁLOHUJTE TENTO ADRESÁR, potom všetko z neho odstránte okrem wallet.dat. + + + + Set maximum size of high-priority/low-fee transactions in bytes (default: 27000) + Nastavte maximálnu veľkosť high-priority/low-fee transakcií v bajtoch (predvolené: 27000) + + + + Warning: -paytxfee is set very high! This is the transaction fee you will pay if you send a transaction. + Upozornenie: -paytxfee je nastavené veľmi vysoko. Toto sú transakčné poplatky ktoré zaplatíte ak odošlete transakciu. + + + + Warning: Please check that your computer's date and time are correct! If your clock is wrong Arepacoin will not work properly. + Upozornenie: Skontrolujte, že dátum a čas počítača sú správne! Ak je Váš čas nesprávny Arepacoin nebude pracovať správne. + + + + Warning: error reading wallet.dat! All keys read correctly, but transaction data or address book entries might be missing or incorrect. + Upozornenie: Chyba pri čítaní wallet.dat! Všetky kľúče načítané správne, ale transakčné dáta alebo položky adresára môže chýbať alebo byť nesprávne. + + + + Warning: wallet.dat corrupt, data salvaged! Original wallet.dat saved as wallet.{timestamp}.bak in %s; if your balance or transactions are incorrect you should restore from a backup. + Upozornenie: wallet.dat poškodený, údaje zachránené! Pôvodný wallet.dat bol uložený ako wallet.{timestamp}.bak v %s; ak váš zostatok alebo transakcie nie sú správne, mali by ste obnoviť zo zálohy. + + + + Attempt to recover private keys from a corrupt wallet.dat + Pokus obnoviť súkromné kľúče z poškodeného wallet.dat + + + + Block creation options: + Voľby vytvorenia bloku: + + + + Connect only to the specified node(s) + Pripojiť sa len k určenému uzlu(om) + + + + Discover own IP address (default: 1 when listening and no -externalip) + Objavte vlastnú IP adresa (predvolené: 1 pri počúvaní a nie -externalip) + + + + Failed to listen on any port. Use -listen=0 if you want this. + Nepodarilo sa počúvať žiadnom porte. Použite -listen=0 ak to chcete. + + + + Find peers using DNS lookup (default: 1) + Nájsť peerov pomocou vyhľadávania DNS (predvolené: 1) + + + + Sync checkpoints policy (default: strict) + Sync checkpoints policy (predvolené: strict) + + + + Invalid -tor address: '%s' + Neplatná -tor adresa: '%s' + + + + Invalid amount for -reservebalance=<amount> + Neplatná suma pre -reservebalance=<množstvo> + + + + Maximum per-connection receive buffer, <n>*1000 bytes (default: 5000) + Maximum pre-pripojenie prijímacej vyrovnávacej pamäti, <n>*1000 bajtov (predvolené: 5000) + + + + Maximum per-connection send buffer, <n>*1000 bytes (default: 1000) + Maximum pre-pripojenie posielacej vyrovnávacej pamäti, <n>*1000 bajtov (predvolené: 1000) + + + + Only connect to nodes in network <net> (IPv4, IPv6 or Tor) + Pripojiť len k uzlom siete <net> (IPv4, IPv6 alebo Tor) + + + + Output extra debugging information. Implies all other -debug* options + Výstupné ďalšie informácie o ladení. Znamená všetky -debug* možnosti + + + + Output extra network debugging information + Výstupné ďalšie sieťové informácie o ladení + + + + Prepend debug output with timestamp + Pred debug výstup s časovou pečiatkou + + + + SSL options: (see the Bitcoin Wiki for SSL setup instructions) + SSL možnosť: (pozrite Bitcoin Wiki pre návod na nastavenie SSL) + + + + Select the version of socks proxy to use (4-5, default: 5) + Vyberte verziu SOCKS proxy pre používanie (4-5, predvolené: 5) + + + + Send trace/debug info to console instead of debug.log file + Odoslať trace/debug informácie na konzolu namiesto debug.info žurnálu + + + + Send trace/debug info to debugger + Poslať stopy/ladiace informácie do debuggera + + + + Set maximum block size in bytes (default: 250000) + Nastavte maximálnu veľkosť bloku v bajtoch (predvolené: 250000) + + + + Set minimum block size in bytes (default: 0) + Nastavte minimálnu veľkosť bloku v bajtoch (predvolené: 0) + + + + Shrink debug.log file on client startup (default: 1 when no -debug) + Stlačiť debug.log súbor na spustenie klienta (predvolené: 1, keď nie -debug) + + + + Specify connection timeout in milliseconds (default: 5000) + Určiť aut spojenia v milisekundách (predvolené: 5000) + + + + Unable to sign checkpoint, wrong checkpointkey? + + Nemožno podpísať kontrolný bod, zlý checkpointkey? + + + + + Use UPnP to map the listening port (default: 0) + Skúsiť použiť UPnP pre mapovanie počúvajúceho portu (default: 0) + + + + Use UPnP to map the listening port (default: 1 when listening) + Skúsiť použiť UPnP pre mapovanie počúvajúceho portu (default: 1 when listening) + + + + Use proxy to reach tor hidden services (default: same as -proxy) + Použiť proxy server k získaniu Tor skrytých služieb (predvolené: rovnaká ako -proxy) + + + + Username for JSON-RPC connections + Užívateľské meno pre JSON-RPC spojenia + + + + Verifying database integrity... + Overenie integrity databázy ... + + + + WARNING: syncronized checkpoint violation detected, but skipped! + UPOZORNENIE: detekovaný synchronizovaný porušený checkpoint, ale preskočený! + + + + Warning: Disk space is low! + Upozornenie: Nedostatok miesta na disku! + + + + Warning: This version is obsolete, upgrade required! + Upozornenie: Táto verzia je zastaraná, vyžaduje sa aktualizácia! + + + + wallet.dat corrupt, salvage failed + wallet.dat je poškodený, záchrana zlyhala + + + + Password for JSON-RPC connections + Heslo pre JSON-rPC spojenia + + + + %s, you must set a rpcpassword in the configuration file: + %s +It is recommended you use the following random password: +rpcuser=arepacoinrpc +rpcpassword=%s +(you do not need to remember this password) +The username and password MUST NOT be the same. +If the file does not exist, create it with owner-readable-only file permissions. +It is also recommended to set alertnotify so you are notified of problems; +for example: alertnotify=echo %%s | mail -s "Arepacoin Alert" admin@foo.com + + %s, musíte nastaviť rpcpassword v konfiguračnom súbore: + %s +Je odporúčané použiť nasledujúce náhodné heslo: +rpcuser=arepacoinrpc +rpcpassword=%s +(Nemusíte si pamätať toto heslo) +Užívateľské meno a heslo nesmú byť rovnaké. +Ak súbor neexistuje, vytvorte ho s oprávneniami súborov vlastníkov iba na čítatanie. +Odporúča sa tiež nastaviť alertnotify, takže budete upozornení na problémy; +napríklad: alertnotify=echo %%s | mail -s "Arepacoin Alert" admin@foo.com + + + + Find peers using internet relay chat (default: 0) + Nájsť peerov pomocou Internet Relay Chat (predvolené: 1) {0)?} + + + + Sync time with other nodes. Disable if time on your system is precise e.g. syncing with NTP (default: 1) + Synchronizácia času s ostatnými uzlami. Zakázať ak čas na vašom systéme je presný, napr synchronizáciu s NTP (predvolené: 1) + + + + When creating transactions, ignore inputs with value less than this (default: 0.01) + Pri vytváraní transakcií, ignorovať vstupy s hodnotou nižšou než táto (predvolené: 0.01) + + + + Allow JSON-RPC connections from specified IP address + Povoliť JSON-RPC spojenia z určenej IP adresy. + + + + Send commands to node running on <ip> (default: 127.0.0.1) + Poslať príkaz nóde bežiacej na <ip> (predvolené: 127.0.0.1) + + + + Execute command when the best block changes (%s in cmd is replaced by block hash) + Vykonaj príkaz, ak zmeny v najlepšom bloku (%s v príkaze nahradí blok hash) + + + + Execute command when a wallet transaction changes (%s in cmd is replaced by TxID) + Spustiť príkaz ak sa zmení transakcia v peňaženke (%s v cmd sa nahrádza TxID) + + + + Require a confirmations for change (default: 0) + Požadovať potvrdenie pre zmenu (predvolené: 0) + + + + Enforce transaction scripts to use canonical PUSH operators (default: 1) + Presadzovať transakčné skripty k používaniu kanonických PUSH operátorov (predvolené: 1) + + + + Execute command when a relevant alert is received (%s in cmd is replaced by message) + Spustiť príkaz, keď je prijaté príslušné upozornenie (%s v cmd je nahradený správou) + + + + Upgrade wallet to latest format + Aktualizuj peňaženku na najnovší formát. + + + + Set key pool size to <n> (default: 100) + Nastaviť zásobu adries na <n> (predvolené: 100) + + + + Rescan the block chain for missing wallet transactions + Znovu skenovať reťaz blokov pre chýbajúce transakcie + + + + How many blocks to check at startup (default: 2500, 0 = all) + Koľko blokov na kontrolu pri štarte (predvolené: 2500, 0 = všetky) + + + + How thorough the block verification is (0-6, default: 1) + Ako dôkladné overenie bloku je (0-6, predvolené: 1) + + + + Imports blocks from external blk000?.dat file + Importovať bloky z externého blk000?.dat súbora + + + + Use OpenSSL (https) for JSON-RPC connections + Použiť OpenSSL (https) pre JSON-RPC spojenia + + + + Server certificate file (default: server.cert) + Súbor s certifikátom servra (predvolené: server.cert) + + + + Server private key (default: server.pem) + Súkromný kľúč servra (predvolené: server.pem) + + + + Acceptable ciphers (default: TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH) + Akceptovateľné ciphers (predvolené: TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH) + + + + Error: Wallet unlocked for staking only, unable to create transaction. + Chyba: Peňaženka odomknuté len pre stávkovanie, nemožné vytvoriť transakciu. + + + + WARNING: Invalid checkpoint found! Displayed transactions may not be correct! You may need to upgrade, or notify developers. + UPOZORNENIE: Neplatný checkpoint nájdený! Uvedené transakcie nemusia byť správne! Možno budete musieť upgradovať, alebo upozorniť vývojárov. + + + + This help message + Táto pomocná správa + + + + Wallet %s resides outside data directory %s. + Peňaženka %s bydlisko mimo dátový adresár %s. + + + + Cannot obtain a lock on data directory %s. Arepacoin is probably already running. + Nemožno získať zámok na dátový adresár %s. Arepacoin už pravdepodobne beží. + + + + Arepacoin + Arepacoin + + + + Unable to bind to %s on this computer (bind returned error %d, %s) + Nemôžem sa pripojiť k %s na tomto počítači (bind vrátil chybu %d, %s) + + + + Connect through socks proxy + Pripojenie cez SOCKS proxy + + + + Allow DNS lookups for -addnode, -seednode and -connect + Povoliť vyhľadávanie DNS pre pridanie nódy a spojenie + + + + Loading addresses... + Načítavanie adries... + + + + Error loading blkindex.dat + Chyba pri načítaní blkindex.dat + + + + Error loading wallet.dat: Wallet corrupted + Chyba načítania wallet.dat: Peňaženka je poškodená + + + + Error loading wallet.dat: Wallet requires newer version of Arepacoin + Chyba pri načítaní wallet.dat: Peňaženka vyžaduje novšiu verziu Arepacoin + + + + Wallet needed to be rewritten: restart Arepacoin to complete + Peňaženka potrebuje byť prepísaná: reštartujte Arepacoin k dokončeniu + + + + Error loading wallet.dat + Chyba načítania wallet.dat + + + + Invalid -proxy address: '%s' + Neplatná adresa proxy: '%s' + + + + Unknown network specified in -onlynet: '%s' + Neznámy siete je uvedené v -onlynet: '%s' + + + + Unknown -socks proxy version requested: %i + Neznáma požadovaná SOCKS proxy verzia:% i + + + + Cannot resolve -bind address: '%s' + Nemožno rozložiť -bind adresu: '%s' + + + + Cannot resolve -externalip address: '%s' + Nemožno rozložiť -externalip adresu: '%s' + + + + Invalid amount for -paytxfee=<amount>: '%s' + Neplatná suma pre -paytxfee=<amount>: '%s' + + + + Error: could not start node + Chyba: nemožno spustiť uzol + + + + Sending... + Posielam... + + + + Invalid amount + Neplatná suma + + + + Insufficient funds + Nedostatok prostriedkov + + + + Loading block index... + Načítavanie zoznamu blokov... + + + + Add a node to connect to and attempt to keep the connection open + Pridať nód na pripojenie a pokus o udržanie pripojenia otvoreného + + + + Unable to bind to %s on this computer. Arepacoin is probably already running. + Nemôžem sa pripojiť na %s na tomto počítači. Arepacoin je pravdepodobne už beží. + + + + Fee per KB to add to transactions you send + Poplatok za KB pridať do transakcií, ktoré odosielate + + + + Invalid amount for -mininput=<amount>: '%s' + Neplatná suma pre -mininput=<amount>: '%s' + + + + Loading wallet... + Načítavam peňaženku... + + + + Cannot downgrade wallet + Nie je možné prejsť na nižšiu verziu peňaženky + + + + Cannot initialize keypool + Nemožno inicializovať keypool + + + + Cannot write default address + Nie je možné zapísať predvolenú adresu. + + + + Rescanning... + Nové prehľadávanie... + + + + Done loading + Dokončené načítavanie + + + + To use the %s option + Použiť %s možnosť. + + + + Error + Chyba + + + + You must set rpcpassword=<password> in the configuration file: +%s +If the file does not exist, create it with owner-readable-only file permissions. + Musíš nastaviť rpcpassword=<heslo> v konfiguračnom súbore: +%s +Ak súbor neexistuje, vytvorte ho s oprávnením pre čítanie len vlastníkom (owner-readable-only) + + + \ No newline at end of file diff --git a/src/qt/locale/bitcoin_sl_SI.ts b/src/qt/locale/bitcoin_sl_SI.ts new file mode 100755 index 0000000..572bdbb --- /dev/null +++ b/src/qt/locale/bitcoin_sl_SI.ts @@ -0,0 +1,3311 @@ + + + AboutDialog + + + About Arepacoin + O Arepacoin + + + + <b>Arepacoin</b> version + <b>Arepacoin</b> verzija + + + + Copyright © 2009-2014 The Bitcoin developers +Copyright © 2012-2014 The NovaCoin developers +Copyright © 2014 The Arepacoin developers + + + + + +This is experimental software. + +Distributed under the MIT/X11 software license, see the accompanying file COPYING or http://www.opensource.org/licenses/mit-license.php. + +This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit (http://www.openssl.org/) and cryptographic software written by Eric Young (eay@cryptsoft.com) and UPnP software written by Thomas Bernard. + +To je poizkusen softver. + +Distribuiran pod MIT/X11 softversko licenco, glej priloženo datoteko COPYING ali http://www.opensource.org/licenses/mit-license.php. + +Ta proizvod vključuje softver razvit s strani projekta OpenSSL za uporabo v OpenSSL Toolkit (http://www.openssl.org/) in kriptografski softver, ki ga je napisal Eric Young (eay@cryptsoft.com), ter UPnP softver, ki ga je napisal Thomas Bernard. + + + + AddressBookPage + + + Address Book + Imenik + + + + Double-click to edit address or label + Dvakrat kliknite za urejanje naslovov ali oznak + + + + Create a new address + Ustvari nov naslov + + + + Copy the currently selected address to the system clipboard + Kopiraj trenutno izbrani naslov v odložišče + + + + &New Address + &Nov naslov + + + + These are your Arepacoin addresses for receiving payments. You may want to give a different one to each sender so you can keep track of who is paying you. + To so vaši Arepacoin naslovi za prejemanje plačil. Priporočeno je da vsakemu pošiljatelju namenite drugega in tako dobite večji pregled nad svojimi nakazili. + + + + &Copy Address + &Kopiraj naslov + + + + Show &QR Code + Prikaži &QR kodo + + + + Sign a message to prove you own a Arepacoin address + Podpišite sporočilo, kot dokazilo lastništva Arepacoin naslova + + + + Sign &Message + Podpiši &sporočilo + + + + Delete the currently selected address from the list + Izbriši izbran naslov iz seznama + + + + Verify a message to ensure it was signed with a specified Arepacoin address + Potrdi sporočilo, da zagotovite, da je bilo podpisano z izbranim Arepacoin naslovom + + + + &Verify Message + &Potrdi sporočilo + + + + &Delete + &Izbriši + + + + Copy &Label + Kopiraj &oznako + + + + &Edit + &Uredi + + + + Export Address Book Data + Izvozi podatke imenika + + + + Comma separated file (*.csv) + Datoteka s podatki, ločenimi z vejico (*.csv) + + + + Error exporting + Napaka pri izvozu datoteke + + + + Could not write to file %1. + Napaka pri pisanju na datoteko %1. + + + + AddressTableModel + + + Label + Oznaka + + + + Address + Naslov + + + + (no label) + (ni oznake) + + + + AskPassphraseDialog + + + Passphrase Dialog + Poziv gesla + + + + Enter passphrase + Vnesite geslo + + + + New passphrase + Novo geslo + + + + Repeat new passphrase + Ponovite novo geslo + + + + Serves to disable the trivial sendmoney when OS account compromised. Provides no real security. + Služi kot onemogočenje pošiljanja prostega denarja, v primerih okužbe operacijskega sistema. Ne ponuja prave zaščite. + + + + For staking only + Samo za staking. + + + + Enter the new passphrase to the wallet.<br/>Please use a passphrase of <b>10 or more random characters</b>, or <b>eight or more words</b>. + Vnesite novo geslo za vstop v denarnico.<br/>Prosimo, da geslo sestavite iz <b> 10 ali več naključnih znakov</b> oz. <b>osem ali več besed</b>. + + + + Encrypt wallet + Šifriraj denarnico + + + + This operation needs your wallet passphrase to unlock the wallet. + To dejanje zahteva geslo za odklepanje vaše denarnice. + + + + Unlock wallet + Odkleni denarnico + + + + This operation needs your wallet passphrase to decrypt the wallet. + To dejanje zahteva geslo za dešifriranje vaše denarnice. + + + + Decrypt wallet + Dešifriraj denarnico + + + + Change passphrase + Zamenjaj geslo + + + + Enter the old and new passphrase to the wallet. + Vnesite staro in novo geslo denarnice. + + + + Confirm wallet encryption + Potrdi šifriranje denarnice + + + + Warning: If you encrypt your wallet and lose your passphrase, you will <b>LOSE ALL OF YOUR COINS</b>! + Opozorilo: Če šifrirate svojo denarnico in izgubite svoje geslo, boste <b> IZGUBILI VSE SVOJE KOVANCE</b>! + + + + Are you sure you wish to encrypt your wallet? + Ali ste prepričani, da želite šifrirati vašo denarnico? + + + + IMPORTANT: Any previous backups you have made of your wallet file should be replaced with the newly generated, encrypted wallet file. For security reasons, previous backups of the unencrypted wallet file will become useless as soon as you start using the new, encrypted wallet. + POMEMBNO: Vsaka predhodna varnostna kopija datoteke denarnice mora biti nadomeščena z novo datoteko šifrirane denarnice. Zaradi varnostnih razlogov bodo namreč prejšnje varnostne kopije datoteke nešifrirane denarnice postale neuporabne takoj ko boste pričeli uporabljati novo, šifrirano denarnico. + + + + + Warning: The Caps Lock key is on! + Opozorilo: imate prižgan Cap Lock + + + + + Wallet encrypted + Denarnica šifrirana + + + + Arepacoin will close now to finish the encryption process. Remember that encrypting your wallet cannot fully protect your coins from being stolen by malware infecting your computer. + Arepacoin se bo sedaj zaprl, da dokonča proces šifriranje. Pomnite, da tudi šifriranje vaše denarnice ne more v celoti zaščititi vaših kovancev pred krajo z zlonamernimi programi in računalniškimi virusi, če ti okužijo vaš računalnik. + + + + + + + Wallet encryption failed + Šifriranje denarnice je spodletelo + + + + Wallet encryption failed due to an internal error. Your wallet was not encrypted. + Šifriranje denarnice spodletelo je zaradi notranje napake. Vaša denarnica ni šifrirana. + + + + + The supplied passphrases do not match. + Vnešeno geslo se ne ujema + + + + Wallet unlock failed + Odklep denarnice spodletel + + + + + + The passphrase entered for the wallet decryption was incorrect. + Geslo za dešifriranje denarnice, ki ste ga vnesli, ni pravilno. + + + + Wallet decryption failed + Dešifriranje denarnice je spodletelo + + + + Wallet passphrase was successfully changed. + Geslo denarnice je bilo uspešno spremenjeno. + + + + BitcoinGUI + + + Sign &message... + Podpiši &sporočilo ... + + + + Synchronizing with network... + Sinhroniziranje z omrežjem ... + + + + &Overview + &Pregled + + + + Show general overview of wallet + Pokaži splošen pregled denarnice + + + + &Transactions + &Transakcije + + + + Browse transaction history + Brskaj po zgodovini transakcij + + + + &Address Book + &Imenik + + + + Edit the list of stored addresses and labels + Uredi seznam shranjenih naslovov in oznak + + + + &Receive coins + &Prejmi kovance + + + + Show the list of addresses for receiving payments + Prikaži seznam naslovov za prejemanje plačil. + + + + &Send coins + &Pošlji kovance + + + + E&xit + I&zhod + + + + Quit application + Izhod iz aplikacije + + + + Show information about Arepacoin + Pokaži informacije o Arepacoin + + + + About &Qt + O &Qt + + + + Show information about Qt + Prikaži informacije o Qt + + + + &Options... + &Možnosti ... + + + + &Encrypt Wallet... + &Šifriraj denarnico ... + + + + &Backup Wallet... + &Ustvari varnostno kopijo denarnice ... + + + + &Change Passphrase... + &Spremeni geslo ... + + + + ~%n block(s) remaining + Ostaja ~%n bloka Ostaja ~%n blokovOstaja ~%n blokovOstaja ~%n blokov + + + + Downloaded %1 of %2 blocks of transaction history (%3% done). + Prenešen %1 od %2 blokov transakcijske zgodovine (%3% opravljeno). + + + + &Export... + &Izvozi... + + + + Send coins to a Arepacoin address + Pošlji kovance na Arepacoin naslov + + + + Modify configuration options for Arepacoin + Spremeni nastavitve za Arepacoin + + + + Export the data in the current tab to a file + Izvozi podatke v izbranem zavihku v datoteko + + + + Encrypt or decrypt wallet + Šifriraj ali dešifriraj denarnico + + + + Backup wallet to another location + Napravi varnostno kopijo denarnice na drugo lokacijo + + + + Change the passphrase used for wallet encryption + Spremeni šifrirno geslo denarnice + + + + &Debug window + &Razhroščevalno okno + + + + Open debugging and diagnostic console + Odpri razhroščevalno in diagnostično konzolo + + + + &Verify message... + %Potrdi sporočilo ... + + + + Arepacoin + Arepacoin + + + + Wallet + Denarnica + + + + &About Arepacoin + &O Arepacoin + + + + &Show / Hide + &Prikaži / Skrij + + + + Unlock wallet + Odkleni denarnico + + + + &Lock Wallet + &Zakleni denarnico + + + + Lock wallet + Zakleni denarnico + + + + &File + &Datoteka + + + + &Settings + &Nastavitve + + + + &Help + &Pomoč + + + + Tabs toolbar + Orodna vrstica zavihkov + + + + Actions toolbar + Orodna vrsticai + + + + + [testnet] + [testnet] + + + + + Arepacoin client + Arepacoin program + + + + %n active connection(s) to Arepacoin network + %n aktivne povezave na Arepacoin omrežje%n aktivnih povezav na Arepacoin omrežje%n aktivnih povezav na Arepacoin omrežje%n aktivnih povezav na Arepacoin omrežje + + + + Downloaded %1 blocks of transaction history. + Prenešenih %1 blokov transakcijske zgodovine. + + + + Staking.<br>Your weight is %1<br>Network weight is %2<br>Expected time to earn reward is %3 + Deležeje [Staking].<br>Teža vašega deleženja je %1<br>Teža celotne mreže deleženja je %2<br>Pričakovan čas do prejema nagrade %3 + + + + Not staking because wallet is locked + Ne deležite ker je denarnica zakljenjena + + + + Not staking because wallet is offline + Ne deležite ker denarnica ni povezana + + + + Not staking because wallet is syncing + Ne deležite ker se denarnica sinhronizira z omrežjem + + + + Not staking because you don't have mature coins + Ne deležite ker nimate zrelih kovancev. + + + + %n second(s) ago + pred %n sekundopred %n sekundamapred %n sekundamipred %n sekundami + + + + &Unlock Wallet... + &Odkleni denarnico... + + + + %n minute(s) ago + Pred %n minutoPred %n minutamaPred %n minutamiPred %n minutami + + + + %n hour(s) ago + Pred %n uro.Pred %n urama.Pred %n urami.Pred %n urami. + + + + %n day(s) ago + Pred %n dnevom.Pred %n dnevoma.Pred %n dnevi.Pred %n dnevi. + + + + Up to date + Posodobljeno + + + + Catching up... + Pridobivanje ... + + + + Last received block was generated %1. + Zadnji prejeti blok je bil ustvarjen %1. + + + + This transaction is over the size limit. You can still send it for a fee of %1, which goes to the nodes that process your transaction and helps to support the network. Do you want to pay the fee? + Ta transakcija je prekoračila limit. Še vedno jo lahko pošljete za plačilo %1 transakcije, ki je plačano vsem delom omrežja kot deležnina in pomaga zagotavljati njegovo varnost. Ali želite plačati provizijo? + + + + Confirm transaction fee + Potrdi transakcijsko provizijo + + + + Sent transaction + Odlivi + + + + Incoming transaction + Prilivi + + + + Date: %1 +Amount: %2 +Type: %3 +Address: %4 + + Datum: %1 +Količina: %2 +Vrsta: %3 +Naslov: %4 + + + + + + URI handling + Rokovanje z URI + + + + + URI can not be parsed! This can be caused by an invalid Arepacoin address or malformed URI parameters. + URI ne more biti razčlenjen! To se lahko zgodi zaradi neveljavnega Arepacoin naslova ali slabih parametrov URI. + + + + Wallet is <b>encrypted</b> and currently <b>unlocked</b> + Denarnica je <b>šifrirana</b> in trenutno <b>odklenjena</b> + + + + Wallet is <b>encrypted</b> and currently <b>locked</b> + Denarnica je <b>šifrirana</b> in trenutno <b>zaklenjena</b> + + + + Backup Wallet + Napravi varnostno kopijo denarnice + + + + Wallet Data (*.dat) + Datoteka denarnice (*.dat) + + + + Backup Failed + Ustvarjanje varnostne kopije je spodeltelo + + + + There was an error trying to save the wallet data to the new location. + Prišlo je do napake ob poskušanju shranjevanja datoteke denarnice na novo lokacijo. + + + + %n second(s) + %n sekundo%n sekundama%n sekund%n sekund + + + + %n minute(s) + %n minuto%n minutama%n minut%n minut + + + + %n hour(s) + %n ura%n uri%n ure%n ura + + + + %n day(s) + %n dan%n dneva%n dnevi%n dni + + + + Not staking + Ne deležite + + + + A fatal error occurred. Arepacoin can no longer continue safely and will quit. + Prišlo je do usodne napake. Program Arepacoin se ne more več varno nadaljevati in se bo zato zaprl. + + + + ClientModel + + + Network Alert + Omrežno Opozorilo + + + + CoinControlDialog + + + Coin Control + Kontrola kovancev + + + + Quantity: + Količina: + + + + Bytes: + Biti: + + + + Amount: + Količina: + + + + Priority: + Prednostno mesto: + + + + Fee: + Provizija: + + + + Low Output: + Nizek output: + + + + no + ne + + + + After Fee: + Po proviziji: + + + + Change: + Sprememba: + + + + (un)select all + od/obkljukaj vse + + + + Tree mode + Drevo + + + + List mode + Seznam + + + + Amount + Količina + + + + Label + Oznaka + + + + Address + Naslov + + + + Date + Datum + + + + Confirmations + Potrdila + + + + Confirmed + Potrjeno + + + + Priority + Prednostno mesto + + + + Copy address + Kopiraj naslov + + + + Copy label + Kopiraj oznako + + + + + Copy amount + Kopiraj količino + + + + Copy transaction ID + Kopiraj ID transakcije + + + + Copy quantity + Kopiraj količino + + + + Copy fee + Kopiraj provizijo + + + + Copy after fee + Kopiraj po proviziji + + + + Copy bytes + Kopiraj bite + + + + Copy priority + Kopiraj prednostno mesto + + + + Copy low output + Kopiraj nizek output: + + + + Copy change + Kopiraj spremembo + + + + highest + najvišja + + + + high + visoka + + + + medium-high + srednje visoka + + + + medium + srednje + + + + low-medium + srednje nizka + + + + low + nizka + + + + lowest + najnižja + + + + DUST + PRAH + + + + yes + da + + + + This label turns red, if the transaction size is bigger than 10000 bytes. + + This means a fee of at least %1 per kb is required. + + Can vary +/- 1 Byte per input. + Ta oznakla se obarva rdeče, če je transakcija večja od 10000 bajtov. + + To pomeni, da je zahtevana provizija vsaj %1 na kb. + + Lahko variira +/- 1 Bajt na vnos. + + + + Transactions with higher priority get more likely into a block. + +This label turns red, if the priority is smaller than "medium". + + This means a fee of at least %1 per kb is required. + Transakcije z višjo prioriteto imajo višjo verjetnost, da so vključene v blok. + +Ta oznaka se obarva rdeče, če je prioriteta manjša kot "srednja". + + To pomeni, da je zahtevana provizija vsaj %1 na kb. + + + + This label turns red, if any recipient receives an amount smaller than %1. + + This means a fee of at least %2 is required. + + Amounts below 0.546 times the minimum relay fee are shown as DUST. + Ta oznaka se obarva rdeče, če prejemnik dobi količino manjšo od %1. + + To pomeni, da je potrebna vsaj %2 provizija. + + Zneski pod 0.546 krat minimalna transakcijska provizija so prikazani kot PRAH. + + + + This label turns red, if the change is smaller than %1. + + This means a fee of at least %2 is required. + Ta oznakla se obarva rdeče, če je sprememba manjša od %1. + + To pomeni, da je zahtevana provizija vsaj %2. + + + + + (no label) + (ni oznake) + + + + change from %1 (%2) + spremeni iz %1 (%2) + + + + (change) + (spremeni) + + + + EditAddressDialog + + + Edit Address + Uredi naslov + + + + &Label + &Oznaka + + + + The label associated with this address book entry + Oznaka povezana s tem vnosom v imeniku + + + + &Address + &Naslov + + + + The address associated with this address book entry. This can only be modified for sending addresses. + Naslov povezan s tem vnosom v imeniku. Spremenite ga lahko le za naslove odlivov. + + + + New receiving address + Nov naslov za prilive + + + + New sending address + Nov naslov za odlive + + + + Edit receiving address + Uredi naslov za prilive + + + + Edit sending address + Uredi naslov za odlive + + + + The entered address "%1" is already in the address book. + Vnešeni naslov "&1" je že v imeniku. + + + + The entered address "%1" is not a valid Arepacoin address. + Vneseni naslov "%1" ni veljaven Arepacoin naslov. + + + + Could not unlock wallet. + Denarnice ni bilo mogoče odkleniti. + + + + New key generation failed. + Ustvarjanje novega ključa je spodletelo. + + + + GUIUtil::HelpMessageBox + + + + Arepacoin-Qt + Arepacoin-Qt + + + + version + različica + + + + Usage: + Uporaba: + + + + command-line options + možnosti ukazne vrstice + + + + UI options + možnosti uporabniškega vmesnika + + + + Set language, for example "de_DE" (default: system locale) + Nastavi jezik, npr. "sl_SI" (privzeto: jezikovna oznaka sistema) + + + + Start minimized + Zaženi pomanjšano + + + + Show splash screen on startup (default: 1) + Prikaži splash screen ob zagonu (default: 1) + + + + OptionsDialog + + + Options + Možnosti + + + + &Main + &Glavno + + + + Optional transaction fee per kB that helps make sure your transactions are processed quickly. Most transactions are 1 kB. Fee 0.01 recommended. + Izbirne transakcijske provizije za kB, ki pomagajo pri tem, da so vaše transakcije procesirane hitreje. Večina transakcij je velikih 1 kB. Priporočena je provizija 0.01. + + + + Pay transaction &fee + Nakazilo plačila & provizija + + + + Reserved amount does not participate in staking and is therefore spendable at any time. + Rezervirana količina ne deleži in je tako na voljo za potrošnjo. + + + + Reserve + Rezerva + + + + Automatically start Arepacoin after logging in to the system. + Avtomatično zaženi Arepacoin ob zagonu sistema. + + + + &Start Arepacoin on system login + &Zaženi Arepacoin ob prijavi v sistem + + + + Detach block and address databases at shutdown. This means they can be moved to another data directory, but it slows down shutdown. The wallet is always detached. + Loči podatkovne baze blokov in naslovov ob zaustavitvi. To pomeni da jih lahko prenesete na drugo lokacijo, a upočasni zaustavitev. Denarnica je vedno ločena. + + + + &Detach databases at shutdown + &Loči podatkovne baze ob zaustavitvi + + + + &Network + &Omrežje + + + + Automatically open the Arepacoin client port on the router. This only works when your router supports UPnP and it is enabled. + Avtomatično odpri vrata na routerju za Arepacoin program. To deluje le če vaš router podpira UPnP in je ta omogočen. + + + + Map port using &UPnP + Začrtaj vrata z &UPnP + + + + Connect to the Arepacoin network through a SOCKS proxy (e.g. when connecting through Tor). + Poveži se na Arepacoin omrežje skozi SOCKS proxy (npr. ko se povezujete prek Tora) + + + + &Connect through SOCKS proxy: + &Poveži se skozi SOCKS proxy: + + + + Proxy &IP: + Proxy &IP: + + + + IP address of the proxy (e.g. 127.0.0.1) + IP naslov proxy strežnika (npr. 127.0.0.1) + + + + &Port: + &Vrata: + + + + Port of the proxy (e.g. 9050) + Vrata strežnika (npr.: 9050) + + + + SOCKS &Version: + SOCKS &različica: + + + + SOCKS version of the proxy (e.g. 5) + SOCKS različica proxya (npr.: 5) + + + + &Window + &Okno + + + + Show only a tray icon after minimizing the window. + Ob pomanjšanju okna prikaži le ikono v odlagališču. + + + + &Minimize to the tray instead of the taskbar + &Pomanjšaj v odlagališče namesto v opravilno vrstico + + + + Minimize instead of exit the application when the window is closed. When this option is enabled, the application will be closed only after selecting Quit in the menu. + Pomanjšaj aplikacijo, ko je okno zaprto. Ko je omogočena ta možnost lahko aplikacijo zaprete le tako, da izberete Izhod v meniju. + + + + M&inimize on close + P&omanjšaj ko zapreš + + + + &Display + &Prikaz + + + + User Interface &language: + Uporabniški vmesnik &jezik: + + + + The user interface language can be set here. This setting will take effect after restarting Arepacoin. + Tu lahko nastavite jezik uporabniškega vmesnika. Nastavitve bodo pričele delovati ob ponovnem zagonu Arepacoin aplikacije. + + + + &Unit to show amounts in: + &Enota prikaza količin: + + + + Choose the default subdivision unit to show in the interface and when sending coins. + Izberite privzeto delitev enot, ki naj bodo prikazane v vmesniku ob pošiljanju kovancev. + + + + Whether to show Arepacoin addresses in the transaction list or not. + Izbira prikaza Arepacoin naslovov v seznamu transakcij. + + + + &Display addresses in transaction list + &Prikaz naslovov v seznamu transakcij + + + + Whether to show coin control features or not. + Izbira prikaza lastnosti kontrole kovancev. + + + + Display coin &control features (experts only!) + Prikaži lastnosti &kontrole kovancev (samo za strokovnjake!) + + + + &OK + &Potrdi + + + + &Cancel + &Prekini + + + + &Apply + &Uporabi + + + + default + privzeto + + + + + Warning + Opozorilo + + + + + This setting will take effect after restarting Arepacoin. + Ta nastavitev bo pričela delovati ob ponovnem zagonu Arepacoin aplikacije + + + + The supplied proxy address is invalid. + Podan naslov proxy strežnika je neveljaven. + + + + OverviewPage + + + Form + Oblika + + + + + The displayed information may be out of date. Your wallet automatically synchronizes with the Arepacoin network after a connection is established, but this process has not completed yet. + Prikazane informacije so morda zastarele. Vaša denarnica se avtomatično sinhronizira z Arepacoin omrežjem, ko je vzpostavljena povezava, toda ta proces še ni bil zaključen. + + + + Stake: + Deleženje: + + + + Unconfirmed: + Nepotrjeni: + + + + Wallet + Denarnica + + + + Spendable: + Razpoložljivi: + + + + Your current spendable balance + Vaše trenutno razpoložljivo stanje + + + + Immature: + Nezreli: + + + + Mined balance that has not yet matured + Z deleženjem pridobljeni kovanci, ki še niso dozoreli. + + + + Total: + Skupaj: + + + + Your current total balance + Vaše trenutno skupno stanje + + + + <b>Recent transactions</b> + <b>Pogoste transakcije</> + + + + Total of transactions that have yet to be confirmed, and do not yet count toward the current balance + Znesek transakcij, ki še niso bile potrjene in se še ne upoštevajo v trenutnem stanju na računu. + + + + Total of coins that was staked, and do not yet count toward the current balance + Znesek kovancev, ki so bili v deleženju in se še ne upoštevajo v trenutnem stanju na računu. + + + + + out of sync + nesinhronizirano + + + + QRCodeDialog + + + QR Code Dialog + QR koda + + + + Request Payment + Zahtevaj plačilo + + + + Amount: + Znesek: + + + + Label: + Oznaka: + + + + Message: + Sporočilo: + + + + &Save As... + &Shrani kot... + + + + Error encoding URI into QR Code. + Napaka pri šifriranju URI v QR kodo. + + + + The entered amount is invalid, please check. + Vnesen znesek je neveljaven, prosimo preverite vnos. + + + + Resulting URI too long, try to reduce the text for label / message. + URI predolg, skušajte zmanjšati besedilo oznake/sporočila. + + + + Save QR Code + Shrani QR kodo + + + + PNG Images (*.png) + PNG slike (*.png) + + + + RPCConsole + + + Client name + Ime odjemalca + + + + + + + + + + + + + N/A + Neznano + + + + Client version + Različica odjemalca + + + + &Information + &Informacije + + + + Using OpenSSL version + OpenSSL različica v rabi + + + + Startup time + Čas zagona + + + + Network + Omrežje + + + + Number of connections + Število povezav + + + + On testnet + Na testnet + + + + Block chain + veriga blokov + + + + Current number of blocks + Trenutno število blokov + + + + Estimated total blocks + Ocena vseh blokov + + + + Last block time + Čas zadnjega bloka + + + + &Open + &Odpri + + + + Command-line options + Možnosti ukazne vrstice. + + + + Show the Arepacoin-Qt help message to get a list with possible Arepacoin command-line options. + Prikaži Arepacoin-Qt sporočilo za pomoč , ki prikaže vse možnosti ukazne vrstice Arepacoin aplikacije + + + + &Show + &Prikaži + + + + &Console + &Konzola + + + + Build date + Datum izgradnje + + + + Arepacoin - Debug window + Arepacoin - okno za odpravljanje napak + + + + Arepacoin Core + Arepacoin jedro + + + + Debug log file + Razhroščevalna dnevniška datoteka + + + + Open the Arepacoin debug log file from the current data directory. This can take a few seconds for large log files. + Odpri Arepacoin datoteko zapisov odpravljanja napak iz trenutnega direktorija podatkov. Če so datoteke zapisov velike, to lahko traja nekaj sekund. + + + + Clear console + Počisti konzolo + + + + Welcome to the Arepacoin RPC console. + Dobrodošli v Arepacoin RPC konzoli. + + + + Use up and down arrows to navigate history, and <b>Ctrl-L</b> to clear screen. + Za navigiranje po zgodovini uporabite puščici gor in dol, in <b>Ctrl-L</b> za izpraznjenje zaslona. + + + + Type <b>help</b> for an overview of available commands. + Vtipkaj <b>pomoč</b> za vpogled v razpožljive ukaze. + + + + SendCoinsDialog + + + + + + + + + + Send Coins + Pošlji kovance + + + + Coin Control Features + Funkcije kontrole kovancev + + + + Inputs... + Vnosi... + + + + automatically selected + samodejno izbran + + + + Insufficient funds! + Premalo sredstev! + + + + Quantity: + Količina: + + + + + 0 + 0 + + + + Bytes: + Biti: + + + + Amount: + Znesek: + + + + + + + 0.00 BC + 123.456 BC {0.00 ?} + + + + Priority: + Prednostno mesto: + + + + medium + srednje + + + + Fee: + Provizija: + + + + Low Output: + Nizek output: + + + + no + ne + + + + After Fee: + Po proviziji: + + + + Change + Sprememba + + + + custom change address + izbira spremembe naslova + + + + Send to multiple recipients at once + Pošlji več prejemnikom hkrati + + + + Add &Recipient + Dodaj &prejemnika + + + + Remove all transaction fields + Odstrani vsa polja transakcij + + + + Clear &All + Počisti &vse + + + + Balance: + Dobroimetje: + + + + 123.456 BC + 123.456 BC + + + + Confirm the send action + Potrdi odlivno dejanje + + + + S&end + P&ošlji + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + Vnesite Arepacoin naslov (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + Copy quantity + Kopiraj količino + + + + Copy amount + Kopiraj količino + + + + Copy fee + Kopiraj provizijo + + + + Copy after fee + Kopiraj po proviziji + + + + Copy bytes + Kopiraj bite + + + + Copy priority + Kopiraj prednostno mesto + + + + Copy low output + Kopiraj nizek output + + + + Copy change + Kopiraj spremembo + + + + <b>%1</b> to %2 (%3) + <b>%1</b> to %2 (%3) + + + + Confirm send coins + Potrdi odliv kovancev + + + + Are you sure you want to send %1? + Ali ste prepričani, da želite poslati %1? + + + + and + in + + + + The recipient address is not valid, please recheck. + Prejemnikov naslov ni veljaven, prosimo če ga ponovno preverite. + + + + The amount to pay must be larger than 0. + Količina za plačilo mora biti večja od 0. + + + + The amount exceeds your balance. + Količina presega vaše dobroimetje + + + + The total exceeds your balance when the %1 transaction fee is included. + Seštevek presega vaše stanje na računu ko je vključen %1 provizije na transakcijo. + + + + Duplicate address found, can only send to each address once per send operation. + Najdena kopija naslova, možnost pošiljanja na vsakega izmed naslov le enkrat ob pošiljanju. + + + + Error: Transaction creation failed. + Napaka: Ustvarjanje transakcije spodletelo + + + + 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. + Napaka: Transakcija je bila zavrnjena. To se je lahko zgodilo, če so bili kovanci v vaši denarnici že zapravljeni, na primer če ste uporabili kopijo wallet.dat in so bili kovanci zapravljeni v kopiji, a tu še niso bili označeni kot zapravljeni. + + + + WARNING: Invalid Arepacoin address + OPOZORILO: Neveljaven Arepacoin naslov + + + + (no label) + (ni oznake) + + + + WARNING: unknown change address + OPOZORILO: neznana sprememba naslova + + + + SendCoinsEntry + + + Form + Oblika + + + + A&mount: + K&oličina: + + + + Pay &To: + Prejemnik &plačila: + + + + + Enter a label for this address to add it to your address book + Vnesite oznako za ta naslov, ki bo shranjena v imenik + + + + &Label: + &Oznaka: + + + + The address to send the payment to (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + Naslov kamor želite poslati plačilo (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + Choose address from address book + Izberite naslov iz imenika + + + + Alt+A + Alt+A + + + + Paste address from clipboard + Prilepi naslov iz odložišča + + + + Alt+P + Alt+P + + + + Remove this recipient + Odstrani tega prejemnika + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + Vnesite Arepacoin naslov (npr. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + SignVerifyMessageDialog + + + Signatures - Sign / Verify a Message + Podpisi - Podpiši/potrdi sporočilo + + + + + &Sign Message + &Podpiši sporočilo + + + + You can sign messages with your addresses to prove you own them. Be careful not to sign anything vague, as phishing attacks may try to trick you into signing your identity over to them. Only sign fully-detailed statements you agree to. + Sporočila lahko podpišete s svojim naslovom, da dokažete lastništvo. Bodite previdni, saj vas lahko phishing napadi skušajo pretentati v to, da jim prepišete svojo identiteto. Podpisujte le jasne in razločne izjave, s katerimi se strinjate. + + + + The address to sign the message with (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + Naslov s katerim želite podpisati sporočilo (npr. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Choose an address from the address book + Izberite naslov iz imenika + + + + + Alt+A + Alt+A + + + + Paste address from clipboard + Prilepi naslov iz odložišča + + + + Alt+P + Alt+P + + + + Enter the message you want to sign here + Vnesite sporočilo, ki ga želite podpisati + + + + Copy the current signature to the system clipboard + Kopiraj trenutno izbrani naslov v odložišče + + + + Sign the message to prove you own this Arepacoin address + Podpišite sporočilo, kot dokazilo lastništva Arepacoin naslova + + + + Reset all sign message fields + Ponastavite vse polja sporočila s podpisom + + + + + Clear &All + Počisti &vse + + + + + &Verify Message + &Potrdi sporočilo + + + + Enter the signing address, message (ensure you copy line breaks, spaces, tabs, etc. exactly) and signature below to verify the message. Be careful not to read more into the signature than what is in the signed message itself, to avoid being tricked by a man-in-the-middle attack. + Vnesite naslov za podpis, sporočilo (poskribte da točno skopirate presledke med vrsticami, črkami, itd.) in podpis spodaj, da potrdite sporočilo Da se ognete napadom posrednika, bodite pozorni, da ne boste v podpisu ugledali več, kot je v podpisanemu sporočilu samem. + + + + The address the message was signed with (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + Naslov s katerim je bilo podpisano sporočilo (npr. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + Verify the message to ensure it was signed with the specified Arepacoin address + Potrdite sporočilo, da zagotovite, da je bilo podpisano z izbranim Arepacoin naslovom + + + + Reset all verify message fields + Ponastavite vse polja sporočila potrditve + + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + Vnesite Arepacoin naslov (npr. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + Click "Sign Message" to generate signature + Kliknite "Podpiši sporočilo" za ustvaritev podpisa + + + + Enter Arepacoin signature + Vnesite Arepacoin podpis + + + + + The entered address is invalid. + Vnešeni naslov ni veljaven. + + + + + + + Please check the address and try again. + Prosimo preverite naslov in poizkusite znova. + + + + + The entered address does not refer to a key. + Vnešen naslov se ne nanaša na ključ. + + + + Wallet unlock was cancelled. + Odklepanje denarnice je bilo prekinjeno. + + + + Private key for the entered address is not available. + Zasebni ključ vnešenega naslov ni na voljo. + + + + Message signing failed. + Podpisovanje sporočila spodletelo. + + + + Message signed. + Sporočilo podpisano. + + + + The signature could not be decoded. + Ni bilo mogoče dešifrirati podpisa. + + + + + Please check the signature and try again. + Prosimo preverite podpis in poizkusite znova. + + + + The signature did not match the message digest. + Podpis se ni ujemal s povzetkom sporočila. + + + + Message verification failed. + Pregledovanje sporočila spodletelo. + + + + Message verified. + Sporočilo pregledano. + + + + TransactionDesc + + + Open until %1 + Odpri enoto %1 + + + + Open for %n block(s) + Odprt za %n blokOdprt za %n blokaOdprt za %n blokovOdprt za %n blokov + + + + conflicted + sporen + + + + %1/offline + %1/offline + + + + %1/unconfirmed + %1/nepotrjeno + + + + %1 confirmations + %1 potrdil + + + + Status + Stanje + + + + , broadcast through %n node(s) + , predvajanje skozi %n vozlišče, predvajanje skozi %n vozlišči, predvajanje skozi %n vozlišč, predvajanje skozi %n vozlišč + + + + Date + Datum + + + + Source + Izvor + + + + Generated + Generirano + + + + + From + Pošiljatelj + + + + + + To + Prejemnik + + + + + own address + lasten naslov + + + + label + oznaka + + + + + + + + Credit + Kredit + + + + matures in %n more block(s) + dozori čez %n blokdozori čez %n blokadozori čez %n blokovdozori čez %n blokov + + + + not accepted + ni bilo sprejeto + + + + + + + Debit + Dolg + + + + Transaction fee + Provizija transakcije + + + + Net amount + Neto količina + + + + Message + Sporočilo + + + + Comment + Opomba + + + + Transaction ID + ID transakcije + + + + Generated coins must mature 6 blocks before they can be spent. When you generated this block, it was broadcast to the network to be added to the block chain. If it fails to get into the chain, its state will change to "not accepted" and it won't be spendable. This may occasionally happen if another node generates a block within a few seconds of yours. + Ustvarjeni kovanci morajo zoreti 6 blokov preden so lahko potrošeni. Ko ustvarite ta blok, je predvajan po mreži in nanizan v verigo blokov. Če mu priključitev na verigo spodleti, se bo njegovo stanje spremenilo v "ni sprejet" in ne bo razpoložljiv. To se lahko občasno zgodi, če drugo vozlišče ustvari blok par sekund pred vami. + + + + Debug information + Razhroščevalna informacija + + + + Transaction + Transakcija + + + + Inputs + Vnosi + + + + Amount + Količina + + + + true + pravilno + + + + false + nepravilno + + + + , has not been successfully broadcast yet + , še ni bil uspešno predvajan + + + + unknown + neznano + + + + TransactionDescDialog + + + Transaction details + Podrobnosti transakcije + + + + This pane shows a detailed description of the transaction + To podokno prikazuje podroben opis transakcije + + + + TransactionTableModel + + + Date + Datum + + + + Type + Vrsta + + + + Address + Naslov + + + + Amount + Količina + + + + Open until %1 + Odpri enoto %1 + + + + Confirmed (%1 confirmations) + Potrjeno (%1 potrdil) + + + + Open for %n more block(s) + Odprt še %n blokOdprt še %n blokaOdprt še %n blokovOdprt še %n blokov + + + + Offline + Nepovezan + + + + Unconfirmed + Nepotrjeno + + + + Confirming (%1 of %2 recommended confirmations) + Potrjuje (%1 od %2 priporočenih potrditev) + + + + Conflicted + Sporen + + + + Immature (%1 confirmations, will be available after %2) + Nezrel (%1 potrditev, na voljo bo po %2) + + + + This block was not received by any other nodes and will probably not be accepted! + Ta blok ni prejelo še nobeno vozlišče. Najverjetneje ne bo sprejet! + + + + Generated but not accepted + Generirano, toda ne sprejeto + + + + Received with + Prejeto z + + + + Received from + Prejeto od + + + + Sent to + Poslano + + + + Payment to yourself + Izplačilo sebi + + + + Mined + Minirano + + + + (n/a) + (ni na voljo) + + + + Transaction status. Hover over this field to show number of confirmations. + Stanje transakcije. Zapeljite z miško čez to polje za prikaz števila potrdil. + + + + Date and time that the transaction was received. + Datum in čas, ko je transakcija bila prejeta. + + + + Type of transaction. + Vrsta transakcije. + + + + Destination address of transaction. + Naslov prejemnika transakcije. + + + + Amount removed from or added to balance. + Količina odlita ali prilita dobroimetju. + + + + TransactionView + + + + All + Vse + + + + Today + Danes + + + + This week + Ta teden + + + + This month + Ta mesec + + + + Last month + Prejšnji mesec + + + + This year + To leto + + + + Range... + Območje ... + + + + Received with + Prejeto z + + + + Sent to + Poslano + + + + To yourself + Samemu sebi + + + + Mined + Minirano + + + + Other + Drugo + + + + Enter address or label to search + Vnesite naslov ali oznako za iskanje + + + + Min amount + Minimalna količina + + + + Copy address + Kopiraj naslov + + + + Copy label + Kopiraj oznako + + + + Copy amount + Kopiraj količino + + + + Copy transaction ID + Kopiraj ID transakcije + + + + Edit label + Uredi oznako + + + + Show transaction details + Prikaži podrobnosti transakcije + + + + Export Transaction Data + Izvozi podatke transakcij + + + + Comma separated file (*.csv) + Datoteka s podatki, ločenimi z vejico (*.csv) + + + + Confirmed + Potrjeno + + + + Date + Datum + + + + Type + Vrsta + + + + Label + Oznaka + + + + Address + Naslov + + + + Amount + Količina + + + + ID + ID + + + + Error exporting + Napaka pri izvažanju podatkov + + + + Could not write to file %1. + Napaka pri pisanju na datoteko %1. + + + + Range: + Območje: + + + + to + za + + + + WalletModel + + + Sending... + Pošiljanje... + + + + bitcoin-core + + + Arepacoin version + Arepacoin različica + + + + Usage: + Uporaba: + + + + Send command to -server or arepacoind + Pošlji ukaz na -server ali blackoind + + + + List commands + Prikaži ukaze + + + + Get help for a command + Prikaži pomoč za ukaz + + + + Options: + Možnosti: + + + + Specify configuration file (default: arepacoin.conf) + Določi konfiguracijsko datoteko (privzeto: arepacoin.conf) + + + + Specify pid file (default: arepacoind.pid) + Določi pid datoteko (privzeto: arepacoin.pid) + + + + Specify wallet file (within data directory) + Določi datoteko denarnice (znotraj imenika s podatki) + + + + Specify data directory + Določi podatkovni imenik + + + + Set database cache size in megabytes (default: 25) + Nastavi pomnilnik podatkovne zbirke v megabajtih (privzeto: 25) + + + + Set database disk log size in megabytes (default: 100) + Nastavi velikost zapisa podatkovne baze na disku v megabajtih (privzeto: 100) + + + + Listen for connections on <port> (default: 9853 or testnet: 19853) + Sprejmi povezave na <port> (privzeta vrata: 9853 ali testnet: 19853) + + + + Maintain at most <n> connections to peers (default: 125) + Obdrži maksimalno število <n> povezav (privzeto: 125) + + + + Connect to a node to retrieve peer addresses, and disconnect + Poveži se na vozlišče da pridobiš naslove soležnikov in prekini povezavo + + + + Specify your own public address + Določite vaš lasten javni naslov + + + + Bind to given address. Use [host]:port notation for IPv6 + Naveži na dani naslov. Uporabi [host]:port ukaz za IPv6 + + + + Stake your coins to support network and gain reward (default: 1) + Deleži svoje kovance za podporo omrežja in pridobi nagrado (default: 1) + + + + Threshold for disconnecting misbehaving peers (default: 100) + Prag za prekinitev povezav s slabimi odjemalci (privzeto: 1000) + + + + Number of seconds to keep misbehaving peers from reconnecting (default: 86400) + Število sekund preden se ponovno povežejo neodzivni soležniki (privzeto: 86400) + + + + An error occurred while setting up the RPC port %u for listening on IPv4: %s + Prišlo je do napake pri nastavljanju RPC porta %u za vhodne povezave na IPv4: %s + + + + Detach block and address databases. Increases shutdown time (default: 0) + Loči podatkovne baze blokov in naslovov. Podaljša čas zaustavitve (privzeto: 0) + + + + 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. + Napaka: Transakcija je bila zavrnjena. To se je lahko zgodilo, če so bili kovanci v vaši denarnici že zapravljeni, na primer če ste uporabili kopijo wallet.dat in so bili kovanci zapravljeni v kopiji, a tu še niso bili označeni kot zapravljeni. + + + + Error: This transaction requires a transaction fee of at least %s because of its amount, complexity, or use of recently received funds + Napaka: Ta transakcija zahteva transakcijsko provizijo vsaj %s zaradi svoje količine, kompleksnosti ali uporabo sredstev, ki ste jih prejeli pred kratkim. + + + + Listen for JSON-RPC connections on <port> (default: 9852 or testnet: 19852) + Sprejmi povezave na <port> (privzeta vrata: 9853 ali testnet: 19853) + + + + Accept command line and JSON-RPC commands + Sprejmi ukaze iz ukazne vrstice in JSON-RPC + + + + Error: Transaction creation failed + Napaka: Ustvarjanje transakcije spodletelo + + + + Error: Wallet locked, unable to create transaction + Napaka: Zaklenjena denarnica, ni mogoče opraviti transakcije + + + + Importing blockchain data file. + Uvažanje blockchain podatkovne datoteke. + + + + Importing bootstrap blockchain data file. + Uvažanje podatkovne datoteke verige blokov. + + + + Run in the background as a daemon and accept commands + Teci v ozadju in sprejemaj ukaze + + + + Use the test network + Uporabi testno omrežje + + + + Accept connections from outside (default: 1 if no -proxy or -connect) + Sprejmi zunanje povezave (privzeto: 1 če ni nastavljen -proxy ali -connect) + + + + An error occurred while setting up the RPC port %u for listening on IPv6, falling back to IPv4: %s + Prišlo je do napake pri nastavljanju RPC porta %u za vhodne povezave na IPv6: %s + + + + Error initializing database environment %s! To recover, BACKUP THAT DIRECTORY, then remove everything from it except for wallet.dat. + Napaka pri zagonu podatkovne baze okolja %s! Za popravilo, NAPRAVITE VARNOSTNO KOPIJO IMENIKA, in iz njega odstranite vse razen datoteke wallet.dat + + + + Set maximum size of high-priority/low-fee transactions in bytes (default: 27000) + Nastavi maksimalno velikost visoke-prioritete/nizke-provizije transakcij v bajtih (privzeto: 27000) + + + + Warning: -paytxfee is set very high! This is the transaction fee you will pay if you send a transaction. + Opozorilo: -paytxfee je nastavljen zelo visoko! To je transakcijska provizija, ki jo boste plačali ob pošiljanju transakcije. + + + + Warning: Please check that your computer's date and time are correct! If your clock is wrong Arepacoin will not work properly. + Opozorilo: Prosimo preverite svoj datum in čas svojega računalnika! Če je vaša ura nastavljena napačno Arepacoin ne bo deloval. + + + + Warning: error reading wallet.dat! All keys read correctly, but transaction data or address book entries might be missing or incorrect. + Opozorilo: napaka pri branju wallet.dat! Vsi ključi so bili pravilno prebrani, podatki o transakciji ali imenik vnešenih naslovov so morda izgubljeni ali nepravilni. + + + + Warning: wallet.dat corrupt, data salvaged! Original wallet.dat saved as wallet.{timestamp}.bak in %s; if your balance or transactions are incorrect you should restore from a backup. + Opozorilo: wallet.dat je pokvarjena, podatki rešeni! Originalna wallet.dat je bila shranjena kot denarnica. {timestamp}.bak v %s; če imate napačno prikazano stanje na računu ali v transakcijah prenovite datoteko z varnostno kopijo. + + + + Attempt to recover private keys from a corrupt wallet.dat + Poizkusi rešiti zasebni ključ iz pokvarjene wallet.dat + + + + Block creation options: + Možnosti ustvarjanja blokov: + + + + Connect only to the specified node(s) + Poveži se samo na določena vozlišče(a) + + + + Discover own IP address (default: 1 when listening and no -externalip) + Odkrij svoj IP naslov (privzeto: 1 ob poslušanju, ko ni aktiviran -externalip) + + + + Failed to listen on any port. Use -listen=0 if you want this. + Poslušanje za vrata je spodletelo. Če želite lahko uporabite ukaz -listen=0. + + + + Find peers using DNS lookup (default: 1) + Najdi soležnike z uporabno DNS vpogleda (privzeto: 1) + + + + Sync checkpoints policy (default: strict) + Sinhronizacija načina točk preverjanja (privzeto: strogo) + + + + Invalid -tor address: '%s' + Neveljaven -tor naslov: '%s' + + + + Invalid amount for -reservebalance=<amount> + Neveljavni znesek za -reservebalance=<amount> + + + + Maximum per-connection receive buffer, <n>*1000 bytes (default: 5000) + Največji sprejemni medpomnilnik glede na povezavo, <n>*1000 bytov (privzeto: 5000) + + + + Maximum per-connection send buffer, <n>*1000 bytes (default: 1000) + Največji oddajni medpomnilnik glede na povezavo, <n>*1000 bytov (privzeto: 1000) + + + + Only connect to nodes in network <net> (IPv4, IPv6 or Tor) + Poveži se samo z vozlišči v omrežju <net> (IPv4, IPv6 in Tor) + + + + Output extra debugging information. Implies all other -debug* options + Output dodatnih informacij razhroščevanja. Obsega vse druge -debug* možnosti. + + + + Output extra network debugging information + Output dodatnih informacij razhroščevanja omrežja. + + + + Prepend debug output with timestamp + Opremi output rahroščevanja s časovnim žigom. + + + + SSL options: (see the Bitcoin Wiki for SSL setup instructions) + SSL možnosti: (glejte Bitcoin Wiki za navodla, kako nastaviti SSL) + + + + Select the version of socks proxy to use (4-5, default: 5) + Izberi verzijo socks proxya za uporabo (4-5, privzeto: 5) + + + + Send trace/debug info to console instead of debug.log file + Pošlji sledilne/razhroščevalne informacije v konzolo namesto jih shraniti v debug.log datoteko + + + + Send trace/debug info to debugger + Pošlji sledilne/razhroščevalne informacije v razhroščevalnik + + + + Set maximum block size in bytes (default: 250000) + Nastavi največjo velikost bloka v bajtih (privzeto: 250000) + + + + Set minimum block size in bytes (default: 0) + Nastavi najmanjšo velikost bloka v bajtih (privzeto: 0) + + + + Shrink debug.log file on client startup (default: 1 when no -debug) + Skrči debug.log datoteko ob zagonu aplikacije (privzeto: 1 ko ni aktiviran -debug) + + + + Specify connection timeout in milliseconds (default: 5000) + Določi čas pavze povezovanja v milisekundah (privzeto: 5000) + + + + Unable to sign checkpoint, wrong checkpointkey? + + Ni bilo mogoče vpisati točke preverjanja, napačen ključ za točko preverjanja? + + + + + Use UPnP to map the listening port (default: 0) + Uporabi UPnP za mapiranje vrat poslušanja (privzeto: 0) + + + + Use UPnP to map the listening port (default: 1 when listening) + Uporabi UPnP za mapiranje vrat poslušanja (privzeto: 1 med poslušanjem) + + + + Use proxy to reach tor hidden services (default: same as -proxy) + Uporabi proxy za povezavo s skritimi storitvami tora (privzeto: isto kot -proxy) + + + + Username for JSON-RPC connections + Uporabniško ime za JSON-RPC povezave + + + + Verifying database integrity... + Potrdite neoporečnost baze podatkov... + + + + WARNING: syncronized checkpoint violation detected, but skipped! + OPOZORILO: zaznana je bila kršitev s sinhronizirami točkami preverjanja, a je bila izpuščena. + + + + Warning: Disk space is low! + Opozorilo: Malo prostora na disku! + + + + Warning: This version is obsolete, upgrade required! + Opozorilo: ta različica je zastarela, potrebna je nadgradnja! + + + + wallet.dat corrupt, salvage failed + wallet.dat poškodovana, neuspešna obnova + + + + Password for JSON-RPC connections + Geslo za JSON-RPC povezave + + + + %s, you must set a rpcpassword in the configuration file: + %s +It is recommended you use the following random password: +rpcuser=arepacoinrpc +rpcpassword=%s +(you do not need to remember this password) +The username and password MUST NOT be the same. +If the file does not exist, create it with owner-readable-only file permissions. +It is also recommended to set alertnotify so you are notified of problems; +for example: alertnotify=echo %%s | mail -s "Arepacoin Alert" admin@foo.com + + %s, nastaviti morate rpcgeslo v konfiguracijski datoteki: + %s +Priporočeno je, da uporabite naslednje naključno geslo: +rpcuser=arepacoinrpc +rpcpassword=%s +(tega gesla si vam ni potrebno zapomniti) +Uporabniško ime in geslo NE SMETA biti ista. +Če datoteka ne obstaja, jo ustvarite z lastniškimi dovoljenji za datoteke. +Prav tako je priporočeno, da nastavite alernotify, tkako da vas opozori na probleme; +na primer: alertnotify=echo %%s | mail -s "Arepacoin Alarm" admin@foo.com + + + + + Find peers using internet relay chat (default: 0) + Najdi soležnike prek irca (privzeto: 0) + + + + Sync time with other nodes. Disable if time on your system is precise e.g. syncing with NTP (default: 1) + Sinhroniziraj čas z drugimi vozlišči. Onemogoči, če je čas na vašem sistemu točno nastavljen, npr. sinhroniziranje z NTP (privzeto: 1) + + + + When creating transactions, ignore inputs with value less than this (default: 0.01) + Ob ustvarjanju transakcij, prezri vnose z manjšo vrednostjo kot (privzeto: 0.01) + + + + Allow JSON-RPC connections from specified IP address + Dovoli JSON-RPC povezave z določenega IP naslova + + + + Send commands to node running on <ip> (default: 127.0.0.1) + Pošlji ukaze vozlišču na <ip> (privzet: 127.0.0.1) + + + + Execute command when the best block changes (%s in cmd is replaced by block hash) + Izvrši ukaz, ko se najboljši blok spremeni (%s je v cmd programu nadomeščen z zgoščenimi bloki). + + + + Execute command when a wallet transaction changes (%s in cmd is replaced by TxID) + Izvedi ukaz, ko bo transakcija denarnice se spremenila (V cmd je bil TxID zamenjan za %s) + + + + Require a confirmations for change (default: 0) + Zahtevaj potrditve za spremembo (default: 0) + + + + Enforce transaction scripts to use canonical PUSH operators (default: 1) + Zahtevaj da transakcijske skripte uporabljajo operatorje canonical PUSH (privzeto: 1) + + + + Execute command when a relevant alert is received (%s in cmd is replaced by message) + Izvrši ukaz, ko je prejet relevanten alarm (%s je v cmd programu nadomeščen s sporočilom) + + + + Upgrade wallet to latest format + Posodobi denarnico v najnovejši zapis + + + + Set key pool size to <n> (default: 100) + Nastavi velikost ključa bazena na <n> (privzeto: 100) + + + + Rescan the block chain for missing wallet transactions + Ponovno preglej verigo blokov za manjkajoče transakcije denarnice + + + + How many blocks to check at startup (default: 2500, 0 = all) + Koliko blokov naj preveri ob zagonu aplikacije (privzeto: 2500, 0 = vse) + + + + How thorough the block verification is (0-6, default: 1) + Kako temeljito naj bo preverjanje blokov (0-6, privzeto: 1) + + + + Imports blocks from external blk000?.dat file + Uvozi bloke iz zunanje blk000?.dat datoteke + + + + Use OpenSSL (https) for JSON-RPC connections + Uporabi OpenSSL (https) za JSON-RPC povezave + + + + Server certificate file (default: server.cert) + Datoteka potrdila strežnika (privzeta: server.cert) + + + + Server private key (default: server.pem) + Zasebni ključ strežnika (privzet: server.pem) + + + + Acceptable ciphers (default: TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH) + Dovoljeni kodirniki (privzeti: TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH) + + + + Error: Wallet unlocked for staking only, unable to create transaction. + + + + + WARNING: Invalid checkpoint found! Displayed transactions may not be correct! You may need to upgrade, or notify developers. + OPOZORILO: Najdene so bile neveljavne točke preverjanja! Prikazane transakcije so morda napačne! Poiščite novo različico aplikacije ali pa obvestite razvijalce. + + + + This help message + To sporočilo pomoči + + + + Wallet %s resides outside data directory %s. + Denarnica %s se nahaja zunaj datotečnega imenika %s. + + + + Cannot obtain a lock on data directory %s. Arepacoin is probably already running. + Ni bilo mogoče najti podatkovnega imenika %s. Aplikacija Arepacoin je verjetno že zagnana. + + + + Arepacoin + Arepacoin + + + + Unable to bind to %s on this computer (bind returned error %d, %s) + Na tem računalniku je bilo nemogoče vezati na %s (bind returned error %d, %s) + + + + Connect through socks proxy + Poveži se skozi socks proxy + + + + Allow DNS lookups for -addnode, -seednode and -connect + Omogoči DNS povezave za -addnode, -seednode in -connect + + + + Loading addresses... + Nalaganje naslovov ... + + + + Error loading blkindex.dat + Napaka pri nalaganju blkindex.dat + + + + Error loading wallet.dat: Wallet corrupted + Napaka pri nalaganju wallet.dat: denarnica pokvarjena + + + + Error loading wallet.dat: Wallet requires newer version of Arepacoin + Napaka pri nalaganju wallet.dat: denarnica zahteva novejšo verzijo Arepacoin + + + + Wallet needed to be rewritten: restart Arepacoin to complete + Denarnica mora biti prepisana: ponovno odprite Arepacoin za dokončanje + + + + Error loading wallet.dat + Napaka pri nalaganju wallet.dat + + + + Invalid -proxy address: '%s' + Neveljaven -proxy naslov: '%s' + + + + Unknown network specified in -onlynet: '%s' + Neznano omrežje določeno v -onlynet: '%s' + + + + Unknown -socks proxy version requested: %i + Zahtevana neznana -socks proxy različica: %i + + + + Cannot resolve -bind address: '%s' + Ni mogoče določiti -bind naslova: '%s' + + + + Cannot resolve -externalip address: '%s' + Ni mogoče določiti -externalip naslova: '%s' + + + + Invalid amount for -paytxfee=<amount>: '%s' + Neveljavni znesek za -paytxfee=<amount>: '%s' + + + + Error: could not start node + Napaka: ni mogoče zagnati vozlišča + + + + Sending... + Pošiljanje... + + + + Invalid amount + Neveljavna količina + + + + Insufficient funds + Premalo sredstev + + + + Loading block index... + Nalaganje indeksa blokov ... + + + + Add a node to connect to and attempt to keep the connection open + Dodaj vozlišče za povezavo nanj in skušaj le to obdržati odprto + + + + Unable to bind to %s on this computer. Arepacoin is probably already running. + Navezava v %s na tem računalniku ni mogoča Arepacoin aplikacija je verjetno že zagnana. + + + + Fee per KB to add to transactions you send + Provizija na KB ki jo morate dodati transakcijam, ki jih pošiljate + + + + Invalid amount for -mininput=<amount>: '%s' + Neveljavni znesek za -miniput=<amount>: '%s' + + + + Loading wallet... + Nalaganje denarnice ... + + + + Cannot downgrade wallet + Ne morem + + + + Cannot initialize keypool + Ni mogoče zagnati keypoola + + + + Cannot write default address + Ni mogoče zapisati privzetega naslova + + + + Rescanning... + Ponovno pregledovanje ... + + + + Done loading + Nalaganje končano + + + + To use the %s option + Za uporabo %s opcije + + + + Error + Napaka + + + + You must set rpcpassword=<password> in the configuration file: +%s +If the file does not exist, create it with owner-readable-only file permissions. + Nastaviti morate rpcpassword=<password> v konfiguracijski datoteki: +%s +Če datoteka ne obstaja, jo ustvarite z lastniškimi dovoljenji za datoteke. + + + \ No newline at end of file diff --git a/src/qt/locale/bitcoin_sq.ts b/src/qt/locale/bitcoin_sq.ts new file mode 100755 index 0000000..5d36012 --- /dev/null +++ b/src/qt/locale/bitcoin_sq.ts @@ -0,0 +1,3275 @@ + + + AboutDialog + + + About Arepacoin + + + + + <b>Arepacoin</b> version + + + + + Copyright © 2009-2014 The Bitcoin developers +Copyright © 2012-2014 The NovaCoin developers +Copyright © 2014 The Arepacoin developers + + + + + +This is experimental software. + +Distributed under the MIT/X11 software license, see the accompanying file COPYING or http://www.opensource.org/licenses/mit-license.php. + +This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit (http://www.openssl.org/) and cryptographic software written by Eric Young (eay@cryptsoft.com) and UPnP software written by Thomas Bernard. + + + + + AddressBookPage + + + Address Book + + + + + Double-click to edit address or label + Klikoni 2 herë për të ndryshuar adressën ose etiketën + + + + Create a new address + Krijo një adresë të re + + + + Copy the currently selected address to the system clipboard + Kopjo adresën e zgjedhur në memorjen e sistemit + + + + &New Address + + + + + These are your Arepacoin addresses for receiving payments. You may want to give a different one to each sender so you can keep track of who is paying you. + + + + + &Copy Address + + + + + Show &QR Code + + + + + Sign a message to prove you own a Arepacoin address + + + + + Sign &Message + + + + + Delete the currently selected address from the list + + + + + Verify a message to ensure it was signed with a specified Arepacoin address + + + + + &Verify Message + + + + + &Delete + &Fshi + + + + Copy &Label + + + + + &Edit + + + + + Export Address Book Data + + + + + Comma separated file (*.csv) + Skedar i ndarë me pikëpresje(*.csv) + + + + Error exporting + + + + + Could not write to file %1. + + + + + AddressTableModel + + + Label + Etiketë + + + + Address + Adresë + + + + (no label) + (pa etiketë) + + + + AskPassphraseDialog + + + Passphrase Dialog + + + + + Enter passphrase + Futni frazkalimin + + + + New passphrase + Frazkalim i ri + + + + Repeat new passphrase + Përsërisni frazkalimin e ri + + + + Serves to disable the trivial sendmoney when OS account compromised. Provides no real security. + + + + + For staking only + + + + + Enter the new passphrase to the wallet.<br/>Please use a passphrase of <b>10 or more random characters</b>, or <b>eight or more words</b>. + Futni frazkalimin e ri në portofol.<br/>Ju lutemi përdorni një frazkalim prej<b>10 ose më shumë shkronjash të rastësishme<b/>, ose tetë apo më shumë fjalë</b>. + + + + Encrypt wallet + Enkripto portofolin + + + + This operation needs your wallet passphrase to unlock the wallet. + Ky veprim ka nevojë per frazkalimin e portofolit tuaj që të ç'kyç portofolin. + + + + Unlock wallet + ç'kyç portofolin. + + + + This operation needs your wallet passphrase to decrypt the wallet. + Ky veprim kërkon frazkalimin e portofolit tuaj që të dekriptoj portofolin. + + + + Decrypt wallet + Dekripto portofolin + + + + Change passphrase + Ndrysho frazkalimin + + + + Enter the old and new passphrase to the wallet. + Futni frazkalimin e vjetër dhe të ri në portofol. + + + + Confirm wallet encryption + Konfirmoni enkriptimin e portofolit + + + + Warning: If you encrypt your wallet and lose your passphrase, you will <b>LOSE ALL OF YOUR COINS</b>! + + + + + Are you sure you wish to encrypt your wallet? + + + + + IMPORTANT: Any previous backups you have made of your wallet file should be replaced with the newly generated, encrypted wallet file. For security reasons, previous backups of the unencrypted wallet file will become useless as soon as you start using the new, encrypted wallet. + + + + + + Warning: The Caps Lock key is on! + + + + + + Wallet encrypted + Portofoli u enkriptua + + + + Arepacoin will close now to finish the encryption process. Remember that encrypting your wallet cannot fully protect your coins from being stolen by malware infecting your computer. + + + + + + + + Wallet encryption failed + Enkriptimi i portofolit dështoi + + + + Wallet encryption failed due to an internal error. Your wallet was not encrypted. + Enkriptimi i portofolit dështoi për shkak të një gabimi të brëndshëm. portofoli juaj nuk u enkriptua. + + + + + The supplied passphrases do not match. + Frazkalimet e plotësuara nuk përputhen. + + + + Wallet unlock failed + ç'kyçja e portofolit dështoi + + + + + + The passphrase entered for the wallet decryption was incorrect. + Frazkalimi i futur për dekriptimin e portofolit nuk ishte i saktë. + + + + Wallet decryption failed + Dekriptimi i portofolit dështoi + + + + Wallet passphrase was successfully changed. + + + + + BitcoinGUI + + + Sign &message... + + + + + Synchronizing with network... + Duke u sinkronizuar me rrjetin... + + + + &Overview + &Përmbledhje + + + + Show general overview of wallet + Trego një përmbledhje te përgjithshme të portofolit + + + + &Transactions + &Transaksionet + + + + Browse transaction history + Shfleto historinë e transaksioneve + + + + &Address Book + + + + + Edit the list of stored addresses and labels + + + + + &Receive coins + + + + + Show the list of addresses for receiving payments + + + + + &Send coins + + + + + E&xit + + + + + Quit application + Mbyllni aplikacionin + + + + Show information about Arepacoin + + + + + About &Qt + + + + + Show information about Qt + + + + + &Options... + &Opsione + + + + &Encrypt Wallet... + + + + + &Backup Wallet... + + + + + &Change Passphrase... + + + + + ~%n block(s) remaining + + + + + Downloaded %1 of %2 blocks of transaction history (%3% done). + + + + + &Export... + + + + + Send coins to a Arepacoin address + + + + + Modify configuration options for Arepacoin + + + + + Export the data in the current tab to a file + + + + + Encrypt or decrypt wallet + + + + + Backup wallet to another location + + + + + Change the passphrase used for wallet encryption + Ndrysho frazkalimin e përdorur per enkriptimin e portofolit + + + + &Debug window + + + + + Open debugging and diagnostic console + + + + + &Verify message... + + + + + Arepacoin + + + + + Wallet + + + + + &About Arepacoin + + + + + &Show / Hide + + + + + Unlock wallet + + + + + &Lock Wallet + + + + + Lock wallet + + + + + &File + &Skedar + + + + &Settings + &Konfigurimet + + + + &Help + &Ndihmë + + + + Tabs toolbar + Shiriti i mjeteve + + + + Actions toolbar + + + + + + [testnet] + [testo rrjetin] + + + + + Arepacoin client + + + + + %n active connection(s) to Arepacoin network + + + + + Downloaded %1 blocks of transaction history. + + + + + Staking.<br>Your weight is %1<br>Network weight is %2<br>Expected time to earn reward is %3 + + + + + Not staking because wallet is locked + + + + + Not staking because wallet is offline + + + + + Not staking because wallet is syncing + + + + + Not staking because you don't have mature coins + + + + + %n second(s) ago + + + + + &Unlock Wallet... + + + + + %n minute(s) ago + + + + + %n hour(s) ago + + + + + %n day(s) ago + + + + + Up to date + I azhornuar + + + + Catching up... + Duke u azhornuar... + + + + Last received block was generated %1. + + + + + This transaction is over the size limit. You can still send it for a fee of %1, which goes to the nodes that process your transaction and helps to support the network. Do you want to pay the fee? + + + + + Confirm transaction fee + + + + + Sent transaction + Dërgo transaksionin + + + + Incoming transaction + Transaksion në ardhje + + + + Date: %1 +Amount: %2 +Type: %3 +Address: %4 + + + + + + + URI handling + + + + + + URI can not be parsed! This can be caused by an invalid Arepacoin address or malformed URI parameters. + + + + + Wallet is <b>encrypted</b> and currently <b>unlocked</b> + Portofoli po <b> enkriptohet</b> dhe është <b> i ç'kyçur</b> + + + + Wallet is <b>encrypted</b> and currently <b>locked</b> + Portofoli po <b> enkriptohet</b> dhe është <b> i kyçur</b> + + + + Backup Wallet + + + + + Wallet Data (*.dat) + + + + + Backup Failed + + + + + There was an error trying to save the wallet data to the new location. + + + + + %n second(s) + + + + + %n minute(s) + + + + + %n hour(s) + + + + + %n day(s) + + + + + Not staking + + + + + A fatal error occurred. Arepacoin can no longer continue safely and will quit. + + + + + ClientModel + + + Network Alert + + + + + CoinControlDialog + + + Coin Control + + + + + Quantity: + + + + + Bytes: + + + + + Amount: + + + + + Priority: + + + + + Fee: + + + + + Low Output: + + + + + no + + + + + After Fee: + + + + + Change: + + + + + (un)select all + + + + + Tree mode + + + + + List mode + + + + + Amount + Sasia + + + + Label + + + + + Address + Adresë + + + + Date + Data + + + + Confirmations + + + + + Confirmed + + + + + Priority + + + + + Copy address + + + + + Copy label + + + + + + Copy amount + + + + + Copy transaction ID + + + + + Copy quantity + + + + + Copy fee + + + + + Copy after fee + + + + + Copy bytes + + + + + Copy priority + + + + + Copy low output + + + + + Copy change + + + + + highest + + + + + high + + + + + medium-high + + + + + medium + + + + + low-medium + + + + + low + + + + + lowest + + + + + DUST + + + + + yes + + + + + This label turns red, if the transaction size is bigger than 10000 bytes. + + This means a fee of at least %1 per kb is required. + + Can vary +/- 1 Byte per input. + + + + + Transactions with higher priority get more likely into a block. + +This label turns red, if the priority is smaller than "medium". + + This means a fee of at least %1 per kb is required. + + + + + This label turns red, if any recipient receives an amount smaller than %1. + + This means a fee of at least %2 is required. + + Amounts below 0.546 times the minimum relay fee are shown as DUST. + + + + + This label turns red, if the change is smaller than %1. + + This means a fee of at least %2 is required. + + + + + + (no label) + (pa etiketë) + + + + change from %1 (%2) + + + + + (change) + + + + + EditAddressDialog + + + Edit Address + Ndrysho Adresën + + + + &Label + &Etiketë + + + + The label associated with this address book entry + + + + + &Address + &Adresa + + + + The address associated with this address book entry. This can only be modified for sending addresses. + + + + + New receiving address + Adresë e re pritëse + + + + New sending address + Adresë e re dërgimi + + + + Edit receiving address + Ndrysho adresën pritëse + + + + Edit sending address + ndrysho adresën dërguese + + + + The entered address "%1" is already in the address book. + Adresa e dhënë "%1" është e zënë në librin e adresave. + + + + The entered address "%1" is not a valid Arepacoin address. + + + + + Could not unlock wallet. + Nuk mund të ç'kyçet portofoli. + + + + New key generation failed. + Krijimi i çelësit të ri dështoi. + + + + GUIUtil::HelpMessageBox + + + + Arepacoin-Qt + + + + + version + + + + + Usage: + + + + + command-line options + + + + + UI options + + + + + Set language, for example "de_DE" (default: system locale) + + + + + Start minimized + + + + + Show splash screen on startup (default: 1) + + + + + OptionsDialog + + + Options + Opsionet + + + + &Main + + + + + Optional transaction fee per kB that helps make sure your transactions are processed quickly. Most transactions are 1 kB. Fee 0.01 recommended. + + + + + Pay transaction &fee + + + + + Reserved amount does not participate in staking and is therefore spendable at any time. + + + + + Reserve + + + + + Automatically start Arepacoin after logging in to the system. + + + + + &Start Arepacoin on system login + + + + + Detach block and address databases at shutdown. This means they can be moved to another data directory, but it slows down shutdown. The wallet is always detached. + + + + + &Detach databases at shutdown + + + + + &Network + + + + + Automatically open the Arepacoin client port on the router. This only works when your router supports UPnP and it is enabled. + + + + + Map port using &UPnP + + + + + Connect to the Arepacoin network through a SOCKS proxy (e.g. when connecting through Tor). + + + + + &Connect through SOCKS proxy: + + + + + Proxy &IP: + + + + + IP address of the proxy (e.g. 127.0.0.1) + + + + + &Port: + + + + + Port of the proxy (e.g. 9050) + + + + + SOCKS &Version: + + + + + SOCKS version of the proxy (e.g. 5) + + + + + &Window + + + + + Show only a tray icon after minimizing the window. + + + + + &Minimize to the tray instead of the taskbar + + + + + Minimize instead of exit the application when the window is closed. When this option is enabled, the application will be closed only after selecting Quit in the menu. + + + + + M&inimize on close + + + + + &Display + + + + + User Interface &language: + + + + + The user interface language can be set here. This setting will take effect after restarting Arepacoin. + + + + + &Unit to show amounts in: + + + + + Choose the default subdivision unit to show in the interface and when sending coins. + + + + + Whether to show Arepacoin addresses in the transaction list or not. + + + + + &Display addresses in transaction list + + + + + Whether to show coin control features or not. + + + + + Display coin &control features (experts only!) + + + + + &OK + + + + + &Cancel + + + + + &Apply + + + + + default + + + + + + Warning + + + + + + This setting will take effect after restarting Arepacoin. + + + + + The supplied proxy address is invalid. + + + + + OverviewPage + + + Form + Formilarë + + + + + The displayed information may be out of date. Your wallet automatically synchronizes with the Arepacoin network after a connection is established, but this process has not completed yet. + + + + + Stake: + + + + + Unconfirmed: + + + + + Wallet + + + + + Spendable: + + + + + Your current spendable balance + + + + + Immature: + + + + + Mined balance that has not yet matured + + + + + Total: + + + + + Your current total balance + + + + + <b>Recent transactions</b> + <b>Transaksionet e fundit</b> + + + + Total of transactions that have yet to be confirmed, and do not yet count toward the current balance + + + + + Total of coins that was staked, and do not yet count toward the current balance + + + + + + out of sync + + + + + QRCodeDialog + + + QR Code Dialog + + + + + Request Payment + + + + + Amount: + + + + + Label: + + + + + Message: + + + + + &Save As... + + + + + Error encoding URI into QR Code. + + + + + The entered amount is invalid, please check. + + + + + Resulting URI too long, try to reduce the text for label / message. + + + + + Save QR Code + + + + + PNG Images (*.png) + + + + + RPCConsole + + + Client name + + + + + + + + + + + + + + N/A + + + + + Client version + + + + + &Information + + + + + Using OpenSSL version + + + + + Startup time + + + + + Network + + + + + Number of connections + + + + + On testnet + + + + + Block chain + + + + + Current number of blocks + + + + + Estimated total blocks + + + + + Last block time + + + + + &Open + + + + + Command-line options + + + + + Show the Arepacoin-Qt help message to get a list with possible Arepacoin command-line options. + + + + + &Show + + + + + &Console + + + + + Build date + + + + + Arepacoin - Debug window + + + + + Arepacoin Core + + + + + Debug log file + + + + + Open the Arepacoin debug log file from the current data directory. This can take a few seconds for large log files. + + + + + Clear console + + + + + Welcome to the Arepacoin RPC console. + + + + + Use up and down arrows to navigate history, and <b>Ctrl-L</b> to clear screen. + + + + + Type <b>help</b> for an overview of available commands. + + + + + SendCoinsDialog + + + + + + + + + + Send Coins + Dërgo Monedha + + + + Coin Control Features + + + + + Inputs... + + + + + automatically selected + + + + + Insufficient funds! + + + + + Quantity: + + + + + + 0 + + + + + Bytes: + + + + + Amount: + + + + + + + + 0.00 BC + + + + + Priority: + + + + + medium + + + + + Fee: + + + + + Low Output: + + + + + no + + + + + After Fee: + + + + + Change + + + + + custom change address + + + + + Send to multiple recipients at once + Dërgo marrësve të ndryshëm njëkohësisht + + + + Add &Recipient + + + + + Remove all transaction fields + + + + + Clear &All + + + + + Balance: + Balanca: + + + + 123.456 BC + + + + + Confirm the send action + Konfirmo veprimin e dërgimit + + + + S&end + + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Copy quantity + + + + + Copy amount + + + + + Copy fee + + + + + Copy after fee + + + + + Copy bytes + + + + + Copy priority + + + + + Copy low output + + + + + Copy change + + + + + <b>%1</b> to %2 (%3) + + + + + Confirm send coins + konfirmo dërgimin e monedhave + + + + Are you sure you want to send %1? + + + + + and + + + + + The recipient address is not valid, please recheck. + + + + + The amount to pay must be larger than 0. + Shuma e paguar duhet të jetë më e madhe se 0. + + + + The amount exceeds your balance. + + + + + The total exceeds your balance when the %1 transaction fee is included. + + + + + Duplicate address found, can only send to each address once per send operation. + + + + + Error: Transaction creation failed. + + + + + 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. + + + + + WARNING: Invalid Arepacoin address + + + + + (no label) + (pa etiketë) + + + + WARNING: unknown change address + + + + + SendCoinsEntry + + + Form + + + + + A&mount: + Sh&uma: + + + + Pay &To: + Paguaj &drejt: + + + + + Enter a label for this address to add it to your address book + Krijoni një etiketë për këtë adresë që t'ja shtoni librit të adresave + + + + &Label: + &Etiketë: + + + + The address to send the payment to (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Choose address from address book + + + + + Alt+A + Alt+A + + + + Paste address from clipboard + Ngjit nga memorja e sistemit + + + + Alt+P + Alt+P + + + + Remove this recipient + + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + SignVerifyMessageDialog + + + Signatures - Sign / Verify a Message + + + + + + &Sign Message + + + + + You can sign messages with your addresses to prove you own them. Be careful not to sign anything vague, as phishing attacks may try to trick you into signing your identity over to them. Only sign fully-detailed statements you agree to. + + + + + The address to sign the message with (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + + Choose an address from the address book + + + + + + Alt+A + Alt+A + + + + Paste address from clipboard + Ngjit nga memorja e sistemit + + + + Alt+P + Alt+P + + + + Enter the message you want to sign here + + + + + Copy the current signature to the system clipboard + + + + + Sign the message to prove you own this Arepacoin address + + + + + Reset all sign message fields + + + + + + Clear &All + + + + + + &Verify Message + + + + + Enter the signing address, message (ensure you copy line breaks, spaces, tabs, etc. exactly) and signature below to verify the message. Be careful not to read more into the signature than what is in the signed message itself, to avoid being tricked by a man-in-the-middle attack. + + + + + The address the message was signed with (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Verify the message to ensure it was signed with the specified Arepacoin address + + + + + Reset all verify message fields + + + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Click "Sign Message" to generate signature + + + + + Enter Arepacoin signature + + + + + + The entered address is invalid. + + + + + + + + Please check the address and try again. + + + + + + The entered address does not refer to a key. + + + + + Wallet unlock was cancelled. + + + + + Private key for the entered address is not available. + + + + + Message signing failed. + + + + + Message signed. + + + + + The signature could not be decoded. + + + + + + Please check the signature and try again. + + + + + The signature did not match the message digest. + + + + + Message verification failed. + + + + + Message verified. + + + + + TransactionDesc + + + Open until %1 + Hapur deri më %1 + + + + Open for %n block(s) + + + + + conflicted + + + + + %1/offline + + + + + %1/unconfirmed + %1/I pakonfirmuar + + + + %1 confirmations + %1 konfirmimet + + + + Status + + + + + , broadcast through %n node(s) + + + + + Date + Data + + + + Source + + + + + Generated + + + + + + From + + + + + + + To + + + + + + own address + + + + + label + + + + + + + + + Credit + + + + + matures in %n more block(s) + + + + + not accepted + + + + + + + + Debit + + + + + Transaction fee + + + + + Net amount + + + + + Message + + + + + Comment + + + + + Transaction ID + + + + + Generated coins must mature 6 blocks before they can be spent. When you generated this block, it was broadcast to the network to be added to the block chain. If it fails to get into the chain, its state will change to "not accepted" and it won't be spendable. This may occasionally happen if another node generates a block within a few seconds of yours. + + + + + Debug information + + + + + Transaction + + + + + Inputs + + + + + Amount + Sasia + + + + true + + + + + false + + + + + , has not been successfully broadcast yet + , nuk është transmetuar me sukses deri tani + + + + unknown + i/e panjohur + + + + TransactionDescDialog + + + Transaction details + Detajet e transaksionit + + + + This pane shows a detailed description of the transaction + Ky panel tregon një përshkrim të detajuar të transaksionit + + + + TransactionTableModel + + + Date + Data + + + + Type + Lloji + + + + Address + Adresë + + + + Amount + Sasia + + + + Open until %1 + Hapur deri më %1 + + + + Confirmed (%1 confirmations) + I/E konfirmuar(%1 konfirmime) + + + + Open for %n more block(s) + + + + + Offline + + + + + Unconfirmed + + + + + Confirming (%1 of %2 recommended confirmations) + + + + + Conflicted + + + + + Immature (%1 confirmations, will be available after %2) + + + + + This block was not received by any other nodes and will probably not be accepted! + Ky bllok është marrë nga ndonjë nyje dhe ka shumë mundësi të mos pranohet! + + + + Generated but not accepted + I krijuar por i papranuar + + + + Received with + Marrë me + + + + Received from + + + + + Sent to + Dërguar drejt + + + + Payment to yourself + Pagesë ndaj vetvetes + + + + Mined + Minuar + + + + (n/a) + (p/a) + + + + Transaction status. Hover over this field to show number of confirmations. + + + + + Date and time that the transaction was received. + + + + + Type of transaction. + + + + + Destination address of transaction. + + + + + Amount removed from or added to balance. + + + + + TransactionView + + + + All + + + + + Today + + + + + This week + + + + + This month + + + + + Last month + + + + + This year + + + + + Range... + + + + + Received with + Marrë me + + + + Sent to + Dërguar drejt + + + + To yourself + + + + + Mined + Minuar + + + + Other + + + + + Enter address or label to search + + + + + Min amount + + + + + Copy address + + + + + Copy label + + + + + Copy amount + + + + + Copy transaction ID + + + + + Edit label + + + + + Show transaction details + + + + + Export Transaction Data + + + + + Comma separated file (*.csv) + Skedar i ndarë me pikëpresje(*.csv) + + + + Confirmed + + + + + Date + Data + + + + Type + Lloji + + + + Label + Etiketë + + + + Address + Adresë + + + + Amount + Sasia + + + + ID + + + + + Error exporting + + + + + Could not write to file %1. + + + + + Range: + + + + + to + + + + + WalletModel + + + Sending... + + + + + bitcoin-core + + + Arepacoin version + + + + + Usage: + + + + + Send command to -server or arepacoind + + + + + List commands + + + + + Get help for a command + + + + + Options: + + + + + Specify configuration file (default: arepacoin.conf) + + + + + Specify pid file (default: arepacoind.pid) + + + + + Specify wallet file (within data directory) + + + + + Specify data directory + + + + + Set database cache size in megabytes (default: 25) + + + + + Set database disk log size in megabytes (default: 100) + + + + + Listen for connections on <port> (default: 9853 or testnet: 19853) + + + + + Maintain at most <n> connections to peers (default: 125) + + + + + Connect to a node to retrieve peer addresses, and disconnect + + + + + Specify your own public address + + + + + Bind to given address. Use [host]:port notation for IPv6 + + + + + Stake your coins to support network and gain reward (default: 1) + + + + + Threshold for disconnecting misbehaving peers (default: 100) + + + + + Number of seconds to keep misbehaving peers from reconnecting (default: 86400) + + + + + An error occurred while setting up the RPC port %u for listening on IPv4: %s + + + + + Detach block and address databases. Increases shutdown time (default: 0) + + + + + 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. + + + + + Error: This transaction requires a transaction fee of at least %s because of its amount, complexity, or use of recently received funds + + + + + Listen for JSON-RPC connections on <port> (default: 9852 or testnet: 19852) + + + + + Accept command line and JSON-RPC commands + + + + + Error: Transaction creation failed + + + + + Error: Wallet locked, unable to create transaction + + + + + Importing blockchain data file. + + + + + Importing bootstrap blockchain data file. + + + + + Run in the background as a daemon and accept commands + + + + + Use the test network + + + + + Accept connections from outside (default: 1 if no -proxy or -connect) + + + + + An error occurred while setting up the RPC port %u for listening on IPv6, falling back to IPv4: %s + + + + + Error initializing database environment %s! To recover, BACKUP THAT DIRECTORY, then remove everything from it except for wallet.dat. + + + + + Set maximum size of high-priority/low-fee transactions in bytes (default: 27000) + + + + + Warning: -paytxfee is set very high! This is the transaction fee you will pay if you send a transaction. + + + + + Warning: Please check that your computer's date and time are correct! If your clock is wrong Arepacoin will not work properly. + + + + + Warning: error reading wallet.dat! All keys read correctly, but transaction data or address book entries might be missing or incorrect. + + + + + Warning: wallet.dat corrupt, data salvaged! Original wallet.dat saved as wallet.{timestamp}.bak in %s; if your balance or transactions are incorrect you should restore from a backup. + + + + + Attempt to recover private keys from a corrupt wallet.dat + + + + + Block creation options: + + + + + Connect only to the specified node(s) + + + + + Discover own IP address (default: 1 when listening and no -externalip) + + + + + Failed to listen on any port. Use -listen=0 if you want this. + + + + + Find peers using DNS lookup (default: 1) + + + + + Sync checkpoints policy (default: strict) + + + + + Invalid -tor address: '%s' + + + + + Invalid amount for -reservebalance=<amount> + + + + + Maximum per-connection receive buffer, <n>*1000 bytes (default: 5000) + + + + + Maximum per-connection send buffer, <n>*1000 bytes (default: 1000) + + + + + Only connect to nodes in network <net> (IPv4, IPv6 or Tor) + + + + + Output extra debugging information. Implies all other -debug* options + + + + + Output extra network debugging information + + + + + Prepend debug output with timestamp + + + + + SSL options: (see the Bitcoin Wiki for SSL setup instructions) + + + + + Select the version of socks proxy to use (4-5, default: 5) + + + + + Send trace/debug info to console instead of debug.log file + + + + + Send trace/debug info to debugger + + + + + Set maximum block size in bytes (default: 250000) + + + + + Set minimum block size in bytes (default: 0) + + + + + Shrink debug.log file on client startup (default: 1 when no -debug) + + + + + Specify connection timeout in milliseconds (default: 5000) + + + + + Unable to sign checkpoint, wrong checkpointkey? + + + + + + Use UPnP to map the listening port (default: 0) + + + + + Use UPnP to map the listening port (default: 1 when listening) + + + + + Use proxy to reach tor hidden services (default: same as -proxy) + + + + + Username for JSON-RPC connections + + + + + Verifying database integrity... + + + + + WARNING: syncronized checkpoint violation detected, but skipped! + + + + + Warning: Disk space is low! + + + + + Warning: This version is obsolete, upgrade required! + + + + + wallet.dat corrupt, salvage failed + + + + + Password for JSON-RPC connections + + + + + %s, you must set a rpcpassword in the configuration file: + %s +It is recommended you use the following random password: +rpcuser=arepacoinrpc +rpcpassword=%s +(you do not need to remember this password) +The username and password MUST NOT be the same. +If the file does not exist, create it with owner-readable-only file permissions. +It is also recommended to set alertnotify so you are notified of problems; +for example: alertnotify=echo %%s | mail -s "Arepacoin Alert" admin@foo.com + + + + + + Find peers using internet relay chat (default: 0) + + + + + Sync time with other nodes. Disable if time on your system is precise e.g. syncing with NTP (default: 1) + + + + + When creating transactions, ignore inputs with value less than this (default: 0.01) + + + + + Allow JSON-RPC connections from specified IP address + + + + + Send commands to node running on <ip> (default: 127.0.0.1) + + + + + Execute command when the best block changes (%s in cmd is replaced by block hash) + + + + + Execute command when a wallet transaction changes (%s in cmd is replaced by TxID) + + + + + Require a confirmations for change (default: 0) + + + + + Enforce transaction scripts to use canonical PUSH operators (default: 1) + + + + + Execute command when a relevant alert is received (%s in cmd is replaced by message) + + + + + Upgrade wallet to latest format + + + + + Set key pool size to <n> (default: 100) + + + + + Rescan the block chain for missing wallet transactions + + + + + How many blocks to check at startup (default: 2500, 0 = all) + + + + + How thorough the block verification is (0-6, default: 1) + + + + + Imports blocks from external blk000?.dat file + + + + + Use OpenSSL (https) for JSON-RPC connections + + + + + Server certificate file (default: server.cert) + + + + + Server private key (default: server.pem) + + + + + Acceptable ciphers (default: TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH) + + + + + Error: Wallet unlocked for staking only, unable to create transaction. + + + + + WARNING: Invalid checkpoint found! Displayed transactions may not be correct! You may need to upgrade, or notify developers. + + + + + This help message + + + + + Wallet %s resides outside data directory %s. + + + + + Cannot obtain a lock on data directory %s. Arepacoin is probably already running. + + + + + Arepacoin + + + + + Unable to bind to %s on this computer (bind returned error %d, %s) + + + + + Connect through socks proxy + + + + + Allow DNS lookups for -addnode, -seednode and -connect + + + + + Loading addresses... + + + + + Error loading blkindex.dat + + + + + Error loading wallet.dat: Wallet corrupted + + + + + Error loading wallet.dat: Wallet requires newer version of Arepacoin + + + + + Wallet needed to be rewritten: restart Arepacoin to complete + + + + + Error loading wallet.dat + + + + + Invalid -proxy address: '%s' + + + + + Unknown network specified in -onlynet: '%s' + + + + + Unknown -socks proxy version requested: %i + + + + + Cannot resolve -bind address: '%s' + + + + + Cannot resolve -externalip address: '%s' + + + + + Invalid amount for -paytxfee=<amount>: '%s' + + + + + Error: could not start node + + + + + Sending... + + + + + Invalid amount + + + + + Insufficient funds + + + + + Loading block index... + + + + + Add a node to connect to and attempt to keep the connection open + + + + + Unable to bind to %s on this computer. Arepacoin is probably already running. + + + + + Fee per KB to add to transactions you send + + + + + Invalid amount for -mininput=<amount>: '%s' + + + + + Loading wallet... + + + + + Cannot downgrade wallet + + + + + Cannot initialize keypool + + + + + Cannot write default address + + + + + Rescanning... + + + + + Done loading + + + + + To use the %s option + + + + + Error + + + + + You must set rpcpassword=<password> in the configuration file: +%s +If the file does not exist, create it with owner-readable-only file permissions. + + + + \ No newline at end of file diff --git a/src/qt/locale/bitcoin_sr.ts b/src/qt/locale/bitcoin_sr.ts new file mode 100755 index 0000000..2848381 --- /dev/null +++ b/src/qt/locale/bitcoin_sr.ts @@ -0,0 +1,3276 @@ + + + AboutDialog + + + About Arepacoin + О Arepacoin-u + + + + <b>Arepacoin</b> version + + + + + Copyright © 2009-2014 The Bitcoin developers +Copyright © 2012-2014 The NovaCoin developers +Copyright © 2014 The Arepacoin developers + + + + + +This is experimental software. + +Distributed under the MIT/X11 software license, see the accompanying file COPYING or http://www.opensource.org/licenses/mit-license.php. + +This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit (http://www.openssl.org/) and cryptographic software written by Eric Young (eay@cryptsoft.com) and UPnP software written by Thomas Bernard. + + + + + AddressBookPage + + + Address Book + Адресар + + + + Double-click to edit address or label + Кликните два пута да промените адресу и/или етикету + + + + Create a new address + Прави нову адресу + + + + Copy the currently selected address to the system clipboard + Копира изабрану адресу на системски клипборд + + + + &New Address + &Нова адреса + + + + These are your Arepacoin addresses for receiving payments. You may want to give a different one to each sender so you can keep track of who is paying you. + + + + + &Copy Address + &Прекопирај адресу + + + + Show &QR Code + Прикажи &QR код + + + + Sign a message to prove you own a Arepacoin address + + + + + Sign &Message + + + + + Delete the currently selected address from the list + Уклони обележену адресу из листе + + + + Verify a message to ensure it was signed with a specified Arepacoin address + + + + + &Verify Message + &Потврди поруку + + + + &Delete + &Избриши + + + + Copy &Label + Копирај &етикету + + + + &Edit + &Измени + + + + Export Address Book Data + + + + + Comma separated file (*.csv) + Зарезом одвојене вредности (*.csv) + + + + Error exporting + + + + + Could not write to file %1. + + + + + AddressTableModel + + + Label + Етикета + + + + Address + Адреса + + + + (no label) + (без етикете) + + + + AskPassphraseDialog + + + Passphrase Dialog + + + + + Enter passphrase + Унесите лозинку + + + + New passphrase + Нова лозинка + + + + Repeat new passphrase + Поновите нову лозинку + + + + Serves to disable the trivial sendmoney when OS account compromised. Provides no real security. + + + + + For staking only + + + + + Enter the new passphrase to the wallet.<br/>Please use a passphrase of <b>10 or more random characters</b>, or <b>eight or more words</b>. + Унесите нову лозинку за приступ новчанику.<br/>Молимо Вас да лозинка буде <b>10 или више насумице одабраних знакова</b>, или <b>осам или више речи</b>. + + + + Encrypt wallet + Шифровање новчаника + + + + This operation needs your wallet passphrase to unlock the wallet. + Ова акција захтева лозинку Вашег новчаника да би га откључала. + + + + Unlock wallet + Откључавање новчаника + + + + This operation needs your wallet passphrase to decrypt the wallet. + Ова акција захтева да унесете лозинку да би дешифловала новчаник. + + + + Decrypt wallet + Дешифровање новчаника + + + + Change passphrase + Промена лозинке + + + + Enter the old and new passphrase to the wallet. + Унесите стару и нову лозинку за шифровање новчаника. + + + + Confirm wallet encryption + Одобрите шифровање новчаника + + + + Warning: If you encrypt your wallet and lose your passphrase, you will <b>LOSE ALL OF YOUR COINS</b>! + + + + + Are you sure you wish to encrypt your wallet? + Да ли сте сигурни да желите да се новчаник шифује? + + + + IMPORTANT: Any previous backups you have made of your wallet file should be replaced with the newly generated, encrypted wallet file. For security reasons, previous backups of the unencrypted wallet file will become useless as soon as you start using the new, encrypted wallet. + + + + + + Warning: The Caps Lock key is on! + + + + + + Wallet encrypted + Новчаник је шифрован + + + + Arepacoin will close now to finish the encryption process. Remember that encrypting your wallet cannot fully protect your coins from being stolen by malware infecting your computer. + + + + + + + + Wallet encryption failed + Неуспело шифровање новчаника + + + + Wallet encryption failed due to an internal error. Your wallet was not encrypted. + Настала је унутрашња грешка током шифровања новчаника. Ваш новчаник није шифрован. + + + + + The supplied passphrases do not match. + Лозинке које сте унели се не подударају. + + + + Wallet unlock failed + Неуспело откључавање новчаника + + + + + + The passphrase entered for the wallet decryption was incorrect. + Лозинка коју сте унели за откључавање новчаника је нетачна. + + + + Wallet decryption failed + Неуспело дешифровање новчаника + + + + Wallet passphrase was successfully changed. + Лозинка за приступ новчанику је успешно промењена. + + + + BitcoinGUI + + + Sign &message... + + + + + Synchronizing with network... + Синхронизација са мрежом у току... + + + + &Overview + &Општи преглед + + + + Show general overview of wallet + Погледајте општи преглед новчаника + + + + &Transactions + &Трансакције + + + + Browse transaction history + Претражите историјат трансакција + + + + &Address Book + + + + + Edit the list of stored addresses and labels + + + + + &Receive coins + + + + + Show the list of addresses for receiving payments + + + + + &Send coins + + + + + E&xit + I&zlaz + + + + Quit application + Напустите програм + + + + Show information about Arepacoin + + + + + About &Qt + О &Qt-у + + + + Show information about Qt + Прегледајте информације о Qt-у + + + + &Options... + П&оставке... + + + + &Encrypt Wallet... + &Шифровање новчаника... + + + + &Backup Wallet... + &Backup новчаника + + + + &Change Passphrase... + Промени &лозинку... + + + + ~%n block(s) remaining + + + + + Downloaded %1 of %2 blocks of transaction history (%3% done). + + + + + &Export... + + + + + Send coins to a Arepacoin address + + + + + Modify configuration options for Arepacoin + + + + + Export the data in the current tab to a file + + + + + Encrypt or decrypt wallet + + + + + Backup wallet to another location + + + + + Change the passphrase used for wallet encryption + Мењање лозинке којом се шифрује новчаник + + + + &Debug window + + + + + Open debugging and diagnostic console + + + + + &Verify message... + + + + + Arepacoin + + + + + Wallet + новчаник + + + + &About Arepacoin + + + + + &Show / Hide + + + + + Unlock wallet + + + + + &Lock Wallet + + + + + Lock wallet + + + + + &File + &Фајл + + + + &Settings + &Подешавања + + + + &Help + П&омоћ + + + + Tabs toolbar + Трака са картицама + + + + Actions toolbar + + + + + + [testnet] + [testnet] + + + + + Arepacoin client + + + + + %n active connection(s) to Arepacoin network + + + + + Downloaded %1 blocks of transaction history. + + + + + Staking.<br>Your weight is %1<br>Network weight is %2<br>Expected time to earn reward is %3 + + + + + Not staking because wallet is locked + + + + + Not staking because wallet is offline + + + + + Not staking because wallet is syncing + + + + + Not staking because you don't have mature coins + + + + + %n second(s) ago + + + + + &Unlock Wallet... + + + + + %n minute(s) ago + + + + + %n hour(s) ago + + + + + %n day(s) ago + + + + + Up to date + Ажурно + + + + Catching up... + Ажурирање у току... + + + + Last received block was generated %1. + + + + + This transaction is over the size limit. You can still send it for a fee of %1, which goes to the nodes that process your transaction and helps to support the network. Do you want to pay the fee? + + + + + Confirm transaction fee + + + + + Sent transaction + Послана трансакција + + + + Incoming transaction + Придошла трансакција + + + + Date: %1 +Amount: %2 +Type: %3 +Address: %4 + + Datum: %1⏎ Iznos: %2⏎ Tip: %3⏎ Adresa: %4⏎ + + + + + URI handling + + + + + + URI can not be parsed! This can be caused by an invalid Arepacoin address or malformed URI parameters. + + + + + Wallet is <b>encrypted</b> and currently <b>unlocked</b> + Новчаник јс <b>шифрован</b> и тренутно <b>откључан</b> + + + + Wallet is <b>encrypted</b> and currently <b>locked</b> + Новчаник јс <b>шифрован</b> и тренутно <b>закључан</b> + + + + Backup Wallet + + + + + Wallet Data (*.dat) + + + + + Backup Failed + + + + + There was an error trying to save the wallet data to the new location. + + + + + %n second(s) + + + + + %n minute(s) + + + + + %n hour(s) + + + + + %n day(s) + + + + + Not staking + + + + + A fatal error occurred. Arepacoin can no longer continue safely and will quit. + + + + + ClientModel + + + Network Alert + + + + + CoinControlDialog + + + Coin Control + + + + + Quantity: + + + + + Bytes: + + + + + Amount: + Iznos: + + + + Priority: + + + + + Fee: + + + + + Low Output: + + + + + no + + + + + After Fee: + + + + + Change: + + + + + (un)select all + + + + + Tree mode + + + + + List mode + + + + + Amount + iznos + + + + Label + + + + + Address + Адреса + + + + Date + datum + + + + Confirmations + + + + + Confirmed + Potvrdjen + + + + Priority + + + + + Copy address + kopiraj adresu + + + + Copy label + kopiraj naziv + + + + + Copy amount + kopiraj iznos + + + + Copy transaction ID + + + + + Copy quantity + + + + + Copy fee + + + + + Copy after fee + + + + + Copy bytes + + + + + Copy priority + + + + + Copy low output + + + + + Copy change + + + + + highest + + + + + high + + + + + medium-high + + + + + medium + + + + + low-medium + + + + + low + + + + + lowest + + + + + DUST + + + + + yes + + + + + This label turns red, if the transaction size is bigger than 10000 bytes. + + This means a fee of at least %1 per kb is required. + + Can vary +/- 1 Byte per input. + + + + + Transactions with higher priority get more likely into a block. + +This label turns red, if the priority is smaller than "medium". + + This means a fee of at least %1 per kb is required. + + + + + This label turns red, if any recipient receives an amount smaller than %1. + + This means a fee of at least %2 is required. + + Amounts below 0.546 times the minimum relay fee are shown as DUST. + + + + + This label turns red, if the change is smaller than %1. + + This means a fee of at least %2 is required. + + + + + + (no label) + (без етикете) + + + + change from %1 (%2) + + + + + (change) + + + + + EditAddressDialog + + + Edit Address + Измени адресу + + + + &Label + &Етикета + + + + The label associated with this address book entry + + + + + &Address + &Адреса + + + + The address associated with this address book entry. This can only be modified for sending addresses. + + + + + New receiving address + + + + + New sending address + + + + + Edit receiving address + + + + + Edit sending address + + + + + The entered address "%1" is already in the address book. + Унешена адреса "%1" се већ налази у адресару. + + + + The entered address "%1" is not a valid Arepacoin address. + + + + + Could not unlock wallet. + Немогуће откључати новчаник. + + + + New key generation failed. + + + + + GUIUtil::HelpMessageBox + + + + Arepacoin-Qt + + + + + version + + + + + Usage: + + + + + command-line options + + + + + UI options + + + + + Set language, for example "de_DE" (default: system locale) + + + + + Start minimized + + + + + Show splash screen on startup (default: 1) + + + + + OptionsDialog + + + Options + Поставке + + + + &Main + + + + + Optional transaction fee per kB that helps make sure your transactions are processed quickly. Most transactions are 1 kB. Fee 0.01 recommended. + + + + + Pay transaction &fee + + + + + Reserved amount does not participate in staking and is therefore spendable at any time. + + + + + Reserve + + + + + Automatically start Arepacoin after logging in to the system. + + + + + &Start Arepacoin on system login + + + + + Detach block and address databases at shutdown. This means they can be moved to another data directory, but it slows down shutdown. The wallet is always detached. + + + + + &Detach databases at shutdown + + + + + &Network + + + + + Automatically open the Arepacoin client port on the router. This only works when your router supports UPnP and it is enabled. + + + + + Map port using &UPnP + + + + + Connect to the Arepacoin network through a SOCKS proxy (e.g. when connecting through Tor). + + + + + &Connect through SOCKS proxy: + + + + + Proxy &IP: + + + + + IP address of the proxy (e.g. 127.0.0.1) + + + + + &Port: + + + + + Port of the proxy (e.g. 9050) + + + + + SOCKS &Version: + + + + + SOCKS version of the proxy (e.g. 5) + + + + + &Window + + + + + Show only a tray icon after minimizing the window. + + + + + &Minimize to the tray instead of the taskbar + + + + + Minimize instead of exit the application when the window is closed. When this option is enabled, the application will be closed only after selecting Quit in the menu. + + + + + M&inimize on close + + + + + &Display + + + + + User Interface &language: + + + + + The user interface language can be set here. This setting will take effect after restarting Arepacoin. + + + + + &Unit to show amounts in: + &Јединица за приказивање износа: + + + + Choose the default subdivision unit to show in the interface and when sending coins. + + + + + Whether to show Arepacoin addresses in the transaction list or not. + + + + + &Display addresses in transaction list + + + + + Whether to show coin control features or not. + + + + + Display coin &control features (experts only!) + + + + + &OK + &OK + + + + &Cancel + + + + + &Apply + + + + + default + + + + + + Warning + + + + + + This setting will take effect after restarting Arepacoin. + + + + + The supplied proxy address is invalid. + + + + + OverviewPage + + + Form + Форма + + + + + The displayed information may be out of date. Your wallet automatically synchronizes with the Arepacoin network after a connection is established, but this process has not completed yet. + + + + + Stake: + + + + + Unconfirmed: + + + + + Wallet + новчаник + + + + Spendable: + + + + + Your current spendable balance + + + + + Immature: + + + + + Mined balance that has not yet matured + + + + + Total: + + + + + Your current total balance + + + + + <b>Recent transactions</b> + <b>Недавне трансакције</b> + + + + Total of transactions that have yet to be confirmed, and do not yet count toward the current balance + + + + + Total of coins that was staked, and do not yet count toward the current balance + + + + + + out of sync + + + + + QRCodeDialog + + + QR Code Dialog + + + + + Request Payment + + + + + Amount: + + + + + Label: + + + + + Message: + + + + + &Save As... + + + + + Error encoding URI into QR Code. + + + + + The entered amount is invalid, please check. + + + + + Resulting URI too long, try to reduce the text for label / message. + + + + + Save QR Code + + + + + PNG Images (*.png) + + + + + RPCConsole + + + Client name + + + + + + + + + + + + + + N/A + + + + + Client version + + + + + &Information + + + + + Using OpenSSL version + + + + + Startup time + + + + + Network + + + + + Number of connections + + + + + On testnet + + + + + Block chain + + + + + Current number of blocks + + + + + Estimated total blocks + + + + + Last block time + + + + + &Open + + + + + Command-line options + + + + + Show the Arepacoin-Qt help message to get a list with possible Arepacoin command-line options. + + + + + &Show + + + + + &Console + + + + + Build date + + + + + Arepacoin - Debug window + + + + + Arepacoin Core + + + + + Debug log file + + + + + Open the Arepacoin debug log file from the current data directory. This can take a few seconds for large log files. + + + + + Clear console + + + + + Welcome to the Arepacoin RPC console. + + + + + Use up and down arrows to navigate history, and <b>Ctrl-L</b> to clear screen. + + + + + Type <b>help</b> for an overview of available commands. + + + + + SendCoinsDialog + + + + + + + + + + Send Coins + Слање новца + + + + Coin Control Features + + + + + Inputs... + + + + + automatically selected + + + + + Insufficient funds! + + + + + Quantity: + + + + + + 0 + + + + + Bytes: + + + + + Amount: + Iznos: + + + + + + + 0.00 BC + + + + + Priority: + + + + + medium + + + + + Fee: + + + + + Low Output: + + + + + no + + + + + After Fee: + + + + + Change + + + + + custom change address + + + + + Send to multiple recipients at once + + + + + Add &Recipient + + + + + Remove all transaction fields + + + + + Clear &All + + + + + Balance: + + + + + 123.456 BC + + + + + Confirm the send action + Потврди акцију слања + + + + S&end + &Пошаљи + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Copy quantity + + + + + Copy amount + kopiraj iznos + + + + Copy fee + + + + + Copy after fee + + + + + Copy bytes + + + + + Copy priority + + + + + Copy low output + + + + + Copy change + + + + + <b>%1</b> to %2 (%3) + + + + + Confirm send coins + + + + + Are you sure you want to send %1? + + + + + and + + + + + The recipient address is not valid, please recheck. + + + + + The amount to pay must be larger than 0. + + + + + The amount exceeds your balance. + + + + + The total exceeds your balance when the %1 transaction fee is included. + + + + + Duplicate address found, can only send to each address once per send operation. + + + + + Error: Transaction creation failed. + + + + + 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. + + + + + WARNING: Invalid Arepacoin address + + + + + (no label) + (без етикете) + + + + WARNING: unknown change address + + + + + SendCoinsEntry + + + Form + + + + + A&mount: + + + + + Pay &To: + + + + + + Enter a label for this address to add it to your address book + + + + + &Label: + &Етикета + + + + The address to send the payment to (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Choose address from address book + + + + + Alt+A + Alt+ + + + + Paste address from clipboard + + + + + Alt+P + Alt+П + + + + Remove this recipient + + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + SignVerifyMessageDialog + + + Signatures - Sign / Verify a Message + + + + + + &Sign Message + + + + + You can sign messages with your addresses to prove you own them. Be careful not to sign anything vague, as phishing attacks may try to trick you into signing your identity over to them. Only sign fully-detailed statements you agree to. + + + + + The address to sign the message with (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + + Choose an address from the address book + + + + + + Alt+A + Alt+A + + + + Paste address from clipboard + + + + + Alt+P + Alt+П + + + + Enter the message you want to sign here + + + + + Copy the current signature to the system clipboard + + + + + Sign the message to prove you own this Arepacoin address + + + + + Reset all sign message fields + + + + + + Clear &All + + + + + + &Verify Message + + + + + Enter the signing address, message (ensure you copy line breaks, spaces, tabs, etc. exactly) and signature below to verify the message. Be careful not to read more into the signature than what is in the signed message itself, to avoid being tricked by a man-in-the-middle attack. + + + + + The address the message was signed with (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Verify the message to ensure it was signed with the specified Arepacoin address + + + + + Reset all verify message fields + + + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Click "Sign Message" to generate signature + + + + + Enter Arepacoin signature + + + + + + The entered address is invalid. + + + + + + + + Please check the address and try again. + + + + + + The entered address does not refer to a key. + + + + + Wallet unlock was cancelled. + + + + + Private key for the entered address is not available. + + + + + Message signing failed. + + + + + Message signed. + + + + + The signature could not be decoded. + + + + + + Please check the signature and try again. + + + + + The signature did not match the message digest. + + + + + Message verification failed. + + + + + Message verified. + + + + + TransactionDesc + + + Open until %1 + Otvorite do %1 + + + + Open for %n block(s) + + + + + conflicted + + + + + %1/offline + + + + + %1/unconfirmed + %1/nepotvrdjeno + + + + %1 confirmations + %1 potvrde + + + + Status + + + + + , broadcast through %n node(s) + + + + + Date + datum + + + + Source + + + + + Generated + + + + + + From + + + + + + + To + + + + + + own address + + + + + label + етикета + + + + + + + + Credit + + + + + matures in %n more block(s) + + + + + not accepted + + + + + + + + Debit + + + + + Transaction fee + + + + + Net amount + + + + + Message + + + + + Comment + + + + + Transaction ID + + + + + Generated coins must mature 6 blocks before they can be spent. When you generated this block, it was broadcast to the network to be added to the block chain. If it fails to get into the chain, its state will change to "not accepted" and it won't be spendable. This may occasionally happen if another node generates a block within a few seconds of yours. + + + + + Debug information + + + + + Transaction + + + + + Inputs + + + + + Amount + iznos + + + + true + + + + + false + + + + + , has not been successfully broadcast yet + , nije još uvek uspešno emitovan + + + + unknown + nepoznato + + + + TransactionDescDialog + + + Transaction details + detalji transakcije + + + + This pane shows a detailed description of the transaction + Ovaj odeljak pokazuje detaljan opis transakcije + + + + TransactionTableModel + + + Date + datum + + + + Type + tip + + + + Address + Адреса + + + + Amount + iznos + + + + Open until %1 + Otvoreno do %1 + + + + Confirmed (%1 confirmations) + Potvrdjena (%1 potvrdjenih) + + + + Open for %n more block(s) + + + + + Offline + + + + + Unconfirmed + + + + + Confirming (%1 of %2 recommended confirmations) + + + + + Conflicted + + + + + Immature (%1 confirmations, will be available after %2) + + + + + This block was not received by any other nodes and will probably not be accepted! + Ovaj blok nije primljen od ostalih čvorova (nodova) i verovatno neće biti prihvaćen! + + + + Generated but not accepted + Generisan ali nije prihvaćen + + + + Received with + Primljen sa + + + + Received from + Primljeno od + + + + Sent to + Poslat ka + + + + Payment to yourself + Isplata samom sebi + + + + Mined + Minirano + + + + (n/a) + (n/a) + + + + Transaction status. Hover over this field to show number of confirmations. + Status vaše transakcije. Predjite mišem preko ovog polja da bi ste videli broj konfirmacija + + + + Date and time that the transaction was received. + Datum i vreme primljene transakcije. + + + + Type of transaction. + Tip transakcije + + + + Destination address of transaction. + Destinacija i adresa transakcije + + + + Amount removed from or added to balance. + Iznos odbijen ili dodat balansu. + + + + TransactionView + + + + All + Sve + + + + Today + Danas + + + + This week + ove nedelje + + + + This month + Ovog meseca + + + + Last month + Prošlog meseca + + + + This year + Ove godine + + + + Range... + Opseg... + + + + Received with + Primljen sa + + + + Sent to + Poslat ka + + + + To yourself + Vama - samom sebi + + + + Mined + Minirano + + + + Other + Drugi + + + + Enter address or label to search + Navedite adresu ili naziv koji bi ste potražili + + + + Min amount + Min iznos + + + + Copy address + kopiraj adresu + + + + Copy label + kopiraj naziv + + + + Copy amount + kopiraj iznos + + + + Copy transaction ID + + + + + Edit label + promeni naziv + + + + Show transaction details + + + + + Export Transaction Data + + + + + Comma separated file (*.csv) + Зарезом одвојене вредности (*.csv) + + + + Confirmed + Potvrdjen + + + + Date + datum + + + + Type + tip + + + + Label + Етикета + + + + Address + Адреса + + + + Amount + iznos + + + + ID + + + + + Error exporting + + + + + Could not write to file %1. + + + + + Range: + Opseg: + + + + to + do + + + + WalletModel + + + Sending... + + + + + bitcoin-core + + + Arepacoin version + + + + + Usage: + Korišćenje: + + + + Send command to -server or arepacoind + + + + + List commands + Listaj komande + + + + Get help for a command + Zatraži pomoć za komande + + + + Options: + Opcije + + + + Specify configuration file (default: arepacoin.conf) + + + + + Specify pid file (default: arepacoind.pid) + + + + + Specify wallet file (within data directory) + + + + + Specify data directory + Gde je konkretni data direktorijum + + + + Set database cache size in megabytes (default: 25) + + + + + Set database disk log size in megabytes (default: 100) + + + + + Listen for connections on <port> (default: 9853 or testnet: 19853) + + + + + Maintain at most <n> connections to peers (default: 125) + Održavaj najviše <n> konekcija po priključku (default: 125) + + + + + Connect to a node to retrieve peer addresses, and disconnect + + + + + Specify your own public address + + + + + Bind to given address. Use [host]:port notation for IPv6 + + + + + Stake your coins to support network and gain reward (default: 1) + + + + + Threshold for disconnecting misbehaving peers (default: 100) + + + + + Number of seconds to keep misbehaving peers from reconnecting (default: 86400) + + + + + An error occurred while setting up the RPC port %u for listening on IPv4: %s + + + + + Detach block and address databases. Increases shutdown time (default: 0) + + + + + 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. + + + + + Error: This transaction requires a transaction fee of at least %s because of its amount, complexity, or use of recently received funds + + + + + Listen for JSON-RPC connections on <port> (default: 9852 or testnet: 19852) + + + + + Accept command line and JSON-RPC commands + Prihvati komandnu liniju i JSON-RPC komande + + + + Error: Transaction creation failed + + + + + Error: Wallet locked, unable to create transaction + + + + + Importing blockchain data file. + + + + + Importing bootstrap blockchain data file. + + + + + Run in the background as a daemon and accept commands + Radi u pozadini kao daemon servis i prihvati komande + + + + Use the test network + Koristi testnu mrežu + + + + Accept connections from outside (default: 1 if no -proxy or -connect) + + + + + An error occurred while setting up the RPC port %u for listening on IPv6, falling back to IPv4: %s + + + + + Error initializing database environment %s! To recover, BACKUP THAT DIRECTORY, then remove everything from it except for wallet.dat. + + + + + Set maximum size of high-priority/low-fee transactions in bytes (default: 27000) + + + + + Warning: -paytxfee is set very high! This is the transaction fee you will pay if you send a transaction. + + + + + Warning: Please check that your computer's date and time are correct! If your clock is wrong Arepacoin will not work properly. + + + + + Warning: error reading wallet.dat! All keys read correctly, but transaction data or address book entries might be missing or incorrect. + + + + + Warning: wallet.dat corrupt, data salvaged! Original wallet.dat saved as wallet.{timestamp}.bak in %s; if your balance or transactions are incorrect you should restore from a backup. + + + + + Attempt to recover private keys from a corrupt wallet.dat + + + + + Block creation options: + + + + + Connect only to the specified node(s) + + + + + Discover own IP address (default: 1 when listening and no -externalip) + + + + + Failed to listen on any port. Use -listen=0 if you want this. + + + + + Find peers using DNS lookup (default: 1) + + + + + Sync checkpoints policy (default: strict) + + + + + Invalid -tor address: '%s' + + + + + Invalid amount for -reservebalance=<amount> + + + + + Maximum per-connection receive buffer, <n>*1000 bytes (default: 5000) + + + + + Maximum per-connection send buffer, <n>*1000 bytes (default: 1000) + + + + + Only connect to nodes in network <net> (IPv4, IPv6 or Tor) + + + + + Output extra debugging information. Implies all other -debug* options + + + + + Output extra network debugging information + + + + + Prepend debug output with timestamp + + + + + SSL options: (see the Bitcoin Wiki for SSL setup instructions) + + + + + Select the version of socks proxy to use (4-5, default: 5) + + + + + Send trace/debug info to console instead of debug.log file + + + + + Send trace/debug info to debugger + + + + + Set maximum block size in bytes (default: 250000) + + + + + Set minimum block size in bytes (default: 0) + + + + + Shrink debug.log file on client startup (default: 1 when no -debug) + + + + + Specify connection timeout in milliseconds (default: 5000) + + + + + Unable to sign checkpoint, wrong checkpointkey? + + + + + + Use UPnP to map the listening port (default: 0) + + + + + Use UPnP to map the listening port (default: 1 when listening) + + + + + Use proxy to reach tor hidden services (default: same as -proxy) + + + + + Username for JSON-RPC connections + Korisničko ime za JSON-RPC konekcije + + + + Verifying database integrity... + + + + + WARNING: syncronized checkpoint violation detected, but skipped! + + + + + Warning: Disk space is low! + + + + + Warning: This version is obsolete, upgrade required! + + + + + wallet.dat corrupt, salvage failed + + + + + Password for JSON-RPC connections + Lozinka za JSON-RPC konekcije + + + + %s, you must set a rpcpassword in the configuration file: + %s +It is recommended you use the following random password: +rpcuser=arepacoinrpc +rpcpassword=%s +(you do not need to remember this password) +The username and password MUST NOT be the same. +If the file does not exist, create it with owner-readable-only file permissions. +It is also recommended to set alertnotify so you are notified of problems; +for example: alertnotify=echo %%s | mail -s "Arepacoin Alert" admin@foo.com + + + + + + Find peers using internet relay chat (default: 0) + + + + + Sync time with other nodes. Disable if time on your system is precise e.g. syncing with NTP (default: 1) + + + + + When creating transactions, ignore inputs with value less than this (default: 0.01) + + + + + Allow JSON-RPC connections from specified IP address + Dozvoli JSON-RPC konekcije sa posebne IP adrese + + + + Send commands to node running on <ip> (default: 127.0.0.1) + Pošalji komande to nodu koji radi na <ip> (default: 127.0.0.1) + + + + Execute command when the best block changes (%s in cmd is replaced by block hash) + + + + + Execute command when a wallet transaction changes (%s in cmd is replaced by TxID) + + + + + Require a confirmations for change (default: 0) + + + + + Enforce transaction scripts to use canonical PUSH operators (default: 1) + + + + + Execute command when a relevant alert is received (%s in cmd is replaced by message) + + + + + Upgrade wallet to latest format + + + + + Set key pool size to <n> (default: 100) + Odredi veličinu zaštićenih ključeva na <n> (default: 100) + + + + Rescan the block chain for missing wallet transactions + Ponovo skeniraj lanac blokova za nedostajuće transakcije iz novčanika + + + + How many blocks to check at startup (default: 2500, 0 = all) + + + + + How thorough the block verification is (0-6, default: 1) + + + + + Imports blocks from external blk000?.dat file + + + + + Use OpenSSL (https) for JSON-RPC connections + Koristi OpenSSL (https) za JSON-RPC konekcije + + + + Server certificate file (default: server.cert) + + + + + Server private key (default: server.pem) + privatni ključ za Server (podrazumevan: server.pem) + + + + Acceptable ciphers (default: TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH) + + + + + Error: Wallet unlocked for staking only, unable to create transaction. + + + + + WARNING: Invalid checkpoint found! Displayed transactions may not be correct! You may need to upgrade, or notify developers. + + + + + This help message + Ova poruka Pomoći + + + + Wallet %s resides outside data directory %s. + + + + + Cannot obtain a lock on data directory %s. Arepacoin is probably already running. + + + + + Arepacoin + + + + + Unable to bind to %s on this computer (bind returned error %d, %s) + + + + + Connect through socks proxy + + + + + Allow DNS lookups for -addnode, -seednode and -connect + + + + + Loading addresses... + učitavam adrese.... + + + + Error loading blkindex.dat + + + + + Error loading wallet.dat: Wallet corrupted + Грешка током учитавања wallet.dat: Новчаник је покварен + + + + Error loading wallet.dat: Wallet requires newer version of Arepacoin + + + + + Wallet needed to be rewritten: restart Arepacoin to complete + + + + + Error loading wallet.dat + Грешка током учитавања wallet.dat + + + + Invalid -proxy address: '%s' + + + + + Unknown network specified in -onlynet: '%s' + + + + + Unknown -socks proxy version requested: %i + + + + + Cannot resolve -bind address: '%s' + + + + + Cannot resolve -externalip address: '%s' + + + + + Invalid amount for -paytxfee=<amount>: '%s' + + + + + Error: could not start node + + + + + Sending... + + + + + Invalid amount + + + + + Insufficient funds + + + + + Loading block index... + Učitavam blok indeksa... + + + + Add a node to connect to and attempt to keep the connection open + + + + + Unable to bind to %s on this computer. Arepacoin is probably already running. + + + + + Fee per KB to add to transactions you send + + + + + Invalid amount for -mininput=<amount>: '%s' + + + + + Loading wallet... + Новчаник се учитава... + + + + Cannot downgrade wallet + + + + + Cannot initialize keypool + + + + + Cannot write default address + + + + + Rescanning... + Ponovo skeniram... + + + + Done loading + Završeno učitavanje + + + + To use the %s option + + + + + Error + + + + + You must set rpcpassword=<password> in the configuration file: +%s +If the file does not exist, create it with owner-readable-only file permissions. + + + + \ No newline at end of file diff --git a/src/qt/locale/bitcoin_sv.ts b/src/qt/locale/bitcoin_sv.ts new file mode 100755 index 0000000..37e5e4f --- /dev/null +++ b/src/qt/locale/bitcoin_sv.ts @@ -0,0 +1,3314 @@ + + + AboutDialog + + + About Arepacoin + Vad du behöver veta om Arepacoin + + + + <b>Arepacoin</b> version + <b>Arepacoin</b> version + + + + Copyright © 2009-2014 The Bitcoin developers +Copyright © 2012-2014 The NovaCoin developers +Copyright © 2014 The Arepacoin developers + Copyright © 2009-2014 The Bitcoin developers +Copyright © 2012-2014 The NovaCoin developers +Copyright © 2014 The Arepacoin developers + + + + +This is experimental software. + +Distributed under the MIT/X11 software license, see the accompanying file COPYING or http://www.opensource.org/licenses/mit-license.php. + +This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit (http://www.openssl.org/) and cryptographic software written by Eric Young (eay@cryptsoft.com) and UPnP software written by Thomas Bernard. + +Detta är experimentell mjukvara. + + +Distribuerad under mjukvarulicensen MIT/X11, se den medföljande filen COPYING eller http://www.opensource.org/licenses/mit-license.php. + +Denna produkten innehåller mjukvara utvecklad av OpenSSL Project för användning i OpenSSL Toolkit (http://www.openssl.org/) och kryptografisk mjukvara utvecklad av Eric Young (eay@cryptsoft.com) samt UPnP-mjukvara skriven av Thomas Bernard. + + + + AddressBookPage + + + Address Book + Adressbok + + + + Double-click to edit address or label + Dubbel-klicka för att ändra adressen eller etiketten + + + + Create a new address + Skapa ny adress + + + + Copy the currently selected address to the system clipboard + Kopiera den markerade adressen till systemets Urklipp + + + + &New Address + Ny adress + + + + These are your Arepacoin addresses for receiving payments. You may want to give a different one to each sender so you can keep track of who is paying you. + Dessa är dina Arepacoin adesser för att mottaga betalningsförsändelser. Du kan även använda olika adresser för varje avsändare för att enkelt hålla koll på vem som har skickat en betalning. + + + + &Copy Address + &Kopiera adress + + + + Show &QR Code + Visa &QR kod + + + + Sign a message to prove you own a Arepacoin address + Signera ett meddelande för att bevisa att du äger Arepacoin adressen + + + + Sign &Message + Signera &Meddelande + + + + Delete the currently selected address from the list + Ta bort den valda adressen från listan + + + + Verify a message to ensure it was signed with a specified Arepacoin address + Verifiera ett meddelande för att försäkra dig över att det var signerat av en specifik Arepacoin adress + + + + &Verify Message + &Verifiera meddelande + + + + &Delete + &Radera + + + + Copy &Label + Kopiera &etikett + + + + &Edit + &Editera + + + + Export Address Book Data + Exportera adressboken + + + + Comma separated file (*.csv) + Kommaseparerad fil (*.csv) + + + + Error exporting + Exportera felmeddelanden + + + + Could not write to file %1. + Kunde inte skriva till fil %1 + + + + AddressTableModel + + + Label + Etikett + + + + Address + Adress + + + + (no label) + (Ingen etikett) + + + + AskPassphraseDialog + + + Passphrase Dialog + Lösenords Dialog + + + + Enter passphrase + Ange lösenord + + + + New passphrase + Nytt lösenord + + + + Repeat new passphrase + Upprepa nytt lösenord + + + + Serves to disable the trivial sendmoney when OS account compromised. Provides no real security. + Avaktiverar "sendmoney" om ditt operativsystem har blivit äventyrat. ger ingen verklig säkerhet. + + + + For staking only + Endast för "staking" + + + + Enter the new passphrase to the wallet.<br/>Please use a passphrase of <b>10 or more random characters</b>, or <b>eight or more words</b>. + Ange plånbokens nya lösenord. <br/> Använd ett lösenord på <b>10 eller fler slumpmässiga tecken,</b> eller <b>åtta eller fler ord.</b> + + + + Encrypt wallet + Kryptera plånbok + + + + This operation needs your wallet passphrase to unlock the wallet. + Denna operation behöver din plånboks lösenord för att låsa upp plånboken. + + + + Unlock wallet + Lås upp plånbok + + + + This operation needs your wallet passphrase to decrypt the wallet. + Denna operation behöver din plånboks lösenord för att dekryptera plånboken. + + + + Decrypt wallet + Dekryptera plånbok + + + + Change passphrase + Ändra lösenord + + + + Enter the old and new passphrase to the wallet. + Ange plånbokens gamla och nya lösenord. + + + + Confirm wallet encryption + Bekräfta kryptering av plånbok + + + + Warning: If you encrypt your wallet and lose your passphrase, you will <b>LOSE ALL OF YOUR COINS</b>! + Varning: Om du krypterar plånboken och glömmer lösenordet, kommer du att <b>FÖRLORA ALLA COINS</b>! + + + + Are you sure you wish to encrypt your wallet? + Är du säker på att du vill kryptera din plånbok? + + + + IMPORTANT: Any previous backups you have made of your wallet file should be replaced with the newly generated, encrypted wallet file. For security reasons, previous backups of the unencrypted wallet file will become useless as soon as you start using the new, encrypted wallet. + VIKTIGT: Alla tidigare säkerhetskopior du har gjort av plånbokens fil ska ersättas med den nya genererade, krypterade plånboks filen. Av säkerhetsskäl kommer tidigare säkerhetskopior av den okrypterade plånboks filen blir oanvändbara när du börjar använda en ny, krypterad plånbok. + + + + + Warning: The Caps Lock key is on! + Varning: Caps Lock är påslaget! + + + + + Wallet encrypted + Plånboken är krypterad + + + + Arepacoin will close now to finish the encryption process. Remember that encrypting your wallet cannot fully protect your coins from being stolen by malware infecting your computer. + Arepacoin plånboken kommer nu att stängas för att slutföra krypteringen: Kom ihåg att även en krypterad plånboks säkerhet kan äventyras genom keyloggers eller dylika malwares. + + + + + + + Wallet encryption failed + Kryptering av plånbok misslyckades + + + + Wallet encryption failed due to an internal error. Your wallet was not encrypted. + Kryptering av plånbok misslyckades på grund av ett internt fel. Din plånbok blev inte krypterad. + + + + + The supplied passphrases do not match. + De angivna lösenorden överensstämmer inte. + + + + Wallet unlock failed + Upplåsning av plånbok misslyckades + + + + + + The passphrase entered for the wallet decryption was incorrect. + Lösenordet för dekryptering av plånbok var felaktig. + + + + Wallet decryption failed + Dekryptering av plånbok misslyckades + + + + Wallet passphrase was successfully changed. + Plånbokens lösenord har ändrats. + + + + BitcoinGUI + + + Sign &message... + Signera &meddelande... + + + + Synchronizing with network... + Synkroniserar med nätverk... + + + + &Overview + &Översikt + + + + Show general overview of wallet + Visa översiktsvy av plånbok + + + + &Transactions + &Transaktioner + + + + Browse transaction history + Bläddra i transaktionshistorik + + + + &Address Book + &Adress bok + + + + Edit the list of stored addresses and labels + Editera listan över sparade adresser och deras namn + + + + &Receive coins + &Ta emot coins + + + + Show the list of addresses for receiving payments + Visa adresslista för att mottaga betalningar + + + + &Send coins + &Skicka coins + + + + E&xit + &Avsluta + + + + Quit application + Avsluta programmet + + + + Show information about Arepacoin + Visa information om Arepacoin + + + + About &Qt + Om &Qt + + + + Show information about Qt + Visa information om Qt + + + + &Options... + &Alternativ... + + + + &Encrypt Wallet... + &Kryptera plånbok... + + + + &Backup Wallet... + &Säkerhetskopiera plånbok... + + + + &Change Passphrase... + &Byt Lösenord... + + + + ~%n block(s) remaining + ~%n block remaining~%n block kvar + + + + Downloaded %1 of %2 blocks of transaction history (%3% done). + Laddat ner %1 av %2 block av transaktions-historiken (%3% klart) + + + + &Export... + &Exportera... + + + + Send coins to a Arepacoin address + Skicka coins till en Arepacoin adress + + + + Modify configuration options for Arepacoin + Modifiera konfigurations-alternativ för Arepacoin + + + + Export the data in the current tab to a file + Exportera datan i tabben till en fil + + + + Encrypt or decrypt wallet + Kryptera eller avkryptera plånbok + + + + Backup wallet to another location + Säkerhetskopiera plånboken till en annan plats + + + + Change the passphrase used for wallet encryption + Byt lösenord för kryptering av plånbok + + + + &Debug window + &Debug fönster + + + + Open debugging and diagnostic console + Öppna debug- och diagnostikkonsolen + + + + &Verify message... + &Verifiera meddelande... + + + + Arepacoin + Arepacoin + + + + Wallet + Plånbok + + + + &About Arepacoin + &Om Arepacoin + + + + &Show / Hide + &Visa / Göm + + + + Unlock wallet + Lås upp plånbok + + + + &Lock Wallet + &Lås plånbok + + + + Lock wallet + Lås plånbok + + + + &File + &Arkiv + + + + &Settings + &Inställningar + + + + &Help + &Hjälp + + + + Tabs toolbar + Verktygsfält för Tabbar + + + + Actions toolbar + Verktygsfält för handlingar + + + + + [testnet] + [testnet] + + + + + Arepacoin client + Arepacoin klient + + + + %n active connection(s) to Arepacoin network + %n aktiv anslutning till Arepacoin nätverket%n aktiva anslutning till Arepacoin nätverket + + + + Downloaded %1 blocks of transaction history. + Laddade ner %1 block av transaktionshistoriken. + + + + Staking.<br>Your weight is %1<br>Network weight is %2<br>Expected time to earn reward is %3 + Staking.<br>Din vikt är %1<br>Nätverkets vikt är %2<br>Uppskattad tid för att få belöning är %3 + + + + Not staking because wallet is locked + Ingen staking för att plånboken är låst + + + + Not staking because wallet is offline + Ingen staking för att plånboken är offline + + + + Not staking because wallet is syncing + Ingen staking för att plånboken synkroniseras + + + + Not staking because you don't have mature coins + Ingen staking för att dina coins är ännu inte föråldrade + + + + %n second(s) ago + %n sekund sen%n sekunder sen + + + + &Unlock Wallet... + Lås &Upp plånboken + + + + %n minute(s) ago + %n minut sen%n minuter sen + + + + %n hour(s) ago + %n timme sen%n timmar sen + + + + %n day(s) ago + %n dag sen%n dagar sen + + + + Up to date + Uppdaterad + + + + Catching up... + Hämtar senaste... + + + + Last received block was generated %1. + Senaste mottagna block genererades %1. + + + + This transaction is over the size limit. You can still send it for a fee of %1, which goes to the nodes that process your transaction and helps to support the network. Do you want to pay the fee? + Denna transaktion är över gränsen. Du kan ändå skicka den med en %1 avgift, som går till noderna som processerar din transaktion och hjälper till med att upprätthålla nätverket. Vill du betala denna avgift? + + + + Confirm transaction fee + Bekräfta transaktionsavgiften + + + + Sent transaction + Transaktion skickad + + + + Incoming transaction + Inkommande transaktion + + + + Date: %1 +Amount: %2 +Type: %3 +Address: %4 + + Datum: %1 +Belopp: %2 +Typ: %3 +Adress: %4 + + + + + + URI handling + URI hantering + + + + + URI can not be parsed! This can be caused by an invalid Arepacoin address or malformed URI parameters. + URI:n kan inte tolkas! Detta kan bero på en ogiltig Arepacoin adress eller felaktiga URI parametrar. + + + + Wallet is <b>encrypted</b> and currently <b>unlocked</b> + Denna plånbok är <b>krypterad</b> och för närvarande <b>olåst</b> + + + + Wallet is <b>encrypted</b> and currently <b>locked</b> + Denna plånbok är <b>krypterad</b> och för närvarande <b>låst</b> + + + + Backup Wallet + Säkerhetskopiera plånbok + + + + Wallet Data (*.dat) + Plånboksdata (*.dat) + + + + Backup Failed + Säkerhetskopieringen misslyckades + + + + There was an error trying to save the wallet data to the new location. + Ett fel uppstod vid sparandet av plånboken till den nya platsen. + + + + %n second(s) + %n sekund%n sekunder + + + + %n minute(s) + %n minut%n minuter + + + + %n hour(s) + %n timme%n timmar + + + + %n day(s) + %n dag%n dagar + + + + Not staking + Ingen staking + + + + A fatal error occurred. Arepacoin can no longer continue safely and will quit. + Ett fatalt fel uppstod. Arepacoin kan inte fortsätta och stänger programmet. + + + + ClientModel + + + Network Alert + Nätverkslarm + + + + CoinControlDialog + + + Coin Control + Coin kontroll + + + + Quantity: + Antal: + + + + Bytes: + Bytes: + + + + Amount: + Belopp: + + + + Priority: + Prioritet: + + + + Fee: + Avgift: + + + + Low Output: + Låg utskrift: + + + + no + nej + + + + After Fee: + Efter avgift: + + + + Change: + Ändra: + + + + (un)select all + välj/avvälj alla + + + + Tree mode + Träd visning + + + + List mode + List visning + + + + Amount + Mängd + + + + Label + etikett + + + + Address + Adress + + + + Date + Datum + + + + Confirmations + Bekräftelser + + + + Confirmed + Bekräftad + + + + Priority + Prioritet + + + + Copy address + Kopiera adress + + + + Copy label + Kopiera etikett + + + + + Copy amount + Kopiera belopp + + + + Copy transaction ID + Kopiera transaktions ID + + + + Copy quantity + Kopiera antal + + + + Copy fee + Kopiera avgift + + + + Copy after fee + Kopiera efter avgift + + + + Copy bytes + Kopiera bytes + + + + Copy priority + Kopiera prioritet + + + + Copy low output + Kopiera låg utskrift + + + + Copy change + Kopiera förändringarna + + + + highest + högst + + + + high + hög + + + + medium-high + medium-hög + + + + medium + medium + + + + low-medium + låg-medium + + + + low + låg + + + + lowest + lägsta + + + + DUST + STOFT + + + + yes + ja + + + + This label turns red, if the transaction size is bigger than 10000 bytes. + + This means a fee of at least %1 per kb is required. + + Can vary +/- 1 Byte per input. + Denna label blir röd, om storleken på transaktionen är över 10000 bytes. + + Detta betyder att en avgift på %1 per kb måste betalas. + + Kan variera +/- 1 Byte per ingång. + + + + Transactions with higher priority get more likely into a block. + +This label turns red, if the priority is smaller than "medium". + + This means a fee of at least %1 per kb is required. + Transaktioner med en högre prioritet har en större sannolikhet att bli adderat till ett block. + +Denna label blir röd, om prioriteten är lägre än "medium". + +Detta betyder att en avgift på minst %1 krävs. + + + + This label turns red, if any recipient receives an amount smaller than %1. + + This means a fee of at least %2 is required. + + Amounts below 0.546 times the minimum relay fee are shown as DUST. + Denna label blir röd, om en mottagare får en mängd mindre än %1 + +Detta betyder att en avgift på minst %2 krävs. + +Mängder under 0,546 gånger minimiavgiften visas som DUST. + + + + This label turns red, if the change is smaller than %1. + + This means a fee of at least %2 is required. + Denna label blir röd, om ändringen är mindre än %1. + +Detta betyder att en avgift på minst %2 krävs. + + + + + (no label) + (Ingen etikett) + + + + change from %1 (%2) + ändra från %1(%2) + + + + (change) + (ändra) + + + + EditAddressDialog + + + Edit Address + Redigera Adress + + + + &Label + &Etikett + + + + The label associated with this address book entry + Namnet som kopplats till denna Arepacoin-adress + + + + &Address + &Adress + + + + The address associated with this address book entry. This can only be modified for sending addresses. + Adressen är kopplad till detta inlägg i adressboken. Denna kan endast ändras för skickande adresser. + + + + New receiving address + Ny mottagaradress + + + + New sending address + Ny avsändaradress + + + + Edit receiving address + Redigera mottagaradress + + + + Edit sending address + Redigera avsändaradress + + + + The entered address "%1" is already in the address book. + Den angivna adressen "%1" finns redan i adressboken. + + + + The entered address "%1" is not a valid Arepacoin address. + Den inslagna adressen "%1" är inte en giltig Arepacoin adress. + + + + Could not unlock wallet. + Plånboken kunde inte låsas upp. + + + + New key generation failed. + Misslyckades med generering av ny nyckel. + + + + GUIUtil::HelpMessageBox + + + + Arepacoin-Qt + Arepacoin-Qt + + + + version + version + + + + Usage: + Användning: + + + + command-line options + Command-line alternativ + + + + UI options + UI alternativ + + + + Set language, for example "de_DE" (default: system locale) + Ställ in språk, t.ex. "de_DE" (förval: systemets språk) + + + + Start minimized + Starta som minimerad + + + + Show splash screen on startup (default: 1) + Visa startscreen vid start (förval: 1) + + + + OptionsDialog + + + Options + Alternativ + + + + &Main + &Allmänt + + + + Optional transaction fee per kB that helps make sure your transactions are processed quickly. Most transactions are 1 kB. Fee 0.01 recommended. + Valfri transaktionsavgift per kB som försäkrar att transaktionen behandlas snabbt. De flesta transaktionerna är 1 kB. En avgift på 0,01 är rekommenderad. + + + + Pay transaction &fee + Betala överförings&avgift + + + + Reserved amount does not participate in staking and is therefore spendable at any time. + Reserverad mängd deltar inte i stake-processen och kan därför spenderas när som helst. + + + + Reserve + Reservera + + + + Automatically start Arepacoin after logging in to the system. + Starta Arepacoin automatiskt vid inloggning. + + + + &Start Arepacoin on system login + &Starta Arepacoin vid inloggning + + + + Detach block and address databases at shutdown. This means they can be moved to another data directory, but it slows down shutdown. The wallet is always detached. + Koppla ifrån block och adress-databaserna vid nedstängning. Detta betyder att det kan flyttas till en annan datamapp men saktar ner avstängningen. Plånboken är alltid frånkopplad. + + + + &Detach databases at shutdown + Koppla bort &databaserna vid nedkörning + + + + &Network + &Nätverk + + + + Automatically open the Arepacoin client port on the router. This only works when your router supports UPnP and it is enabled. + Öppna automatiskt Arepacoin klientens port på routern. Detta fungerar endast om din router stödjer UPnP och det är aktiverat. + + + + Map port using &UPnP + Tilldela port med hjälp av &UPnP + + + + Connect to the Arepacoin network through a SOCKS proxy (e.g. when connecting through Tor). + Anslut till Arepacoin nätverket via en SOCKS proxy (t.ex. när du ansluter genom Tor). + + + + &Connect through SOCKS proxy: + &Anslut genom en SOCKS proxy: + + + + Proxy &IP: + Proxy-&IP: + + + + IP address of the proxy (e.g. 127.0.0.1) + Proxyns IP-adress (t.ex. 127.0.0.1) + + + + &Port: + &Port: + + + + Port of the proxy (e.g. 9050) + Proxyns port (t.ex. 9050) + + + + SOCKS &Version: + SOCKS &Version: + + + + SOCKS version of the proxy (e.g. 5) + SOCKS version av proxyn (t.ex. 5) + + + + &Window + &Fönster + + + + Show only a tray icon after minimizing the window. + Visa endast en systemfältsikon vid minimering. + + + + &Minimize to the tray instead of the taskbar + &Minimera till systemfältet istället för aktivitetsfältet + + + + Minimize instead of exit the application when the window is closed. When this option is enabled, the application will be closed only after selecting Quit in the menu. + Minimera applikationen istället för att stänga ner den när fönstret stängs. Detta innebär att programmet fotrsätter att köras tills du väljer Avsluta i menyn. + + + + M&inimize on close + M&inimera vid stängning + + + + &Display + &Visa + + + + User Interface &language: + Användargränssnittets &språk: + + + + The user interface language can be set here. This setting will take effect after restarting Arepacoin. + Användargränssnittets språk kan ställas in här. Inställningen börjar gälla efter omstart av Arepacoin. + + + + &Unit to show amounts in: + &Måttenhet att visa belopp i: + + + + Choose the default subdivision unit to show in the interface and when sending coins. + Välj en måttenhet att visa när du skickar mynt. + + + + Whether to show Arepacoin addresses in the transaction list or not. + Om Arepacoin adresser skall visas i transaktionslistan eller inte. + + + + &Display addresses in transaction list + &Visa adresser i transaktionslistan + + + + Whether to show coin control features or not. + Om coin kontrollinställningar skall visas eller inte. + + + + Display coin &control features (experts only!) + Visa coin kontrollinställningar (endast avancerade användare!) + + + + &OK + &OK + + + + &Cancel + &Avbryt + + + + &Apply + &Verkställ + + + + default + standard + + + + + Warning + Varning + + + + + This setting will take effect after restarting Arepacoin. + Inställningen börjar gälla efter omstart av Arepacoin. + + + + The supplied proxy address is invalid. + Den medföljande proxy adressen är ogiltig. + + + + OverviewPage + + + Form + Formulär + + + + + The displayed information may be out of date. Your wallet automatically synchronizes with the Arepacoin network after a connection is established, but this process has not completed yet. + Den visade informationen kan vara gammal. Din plånbok synkroniseras automatiskt med Arepacoin nätverket efter att en anslutning skapats, men denna process är inte klar än. + + + + Stake: + Stake: + + + + Unconfirmed: + Obekräftat: + + + + Wallet + Plånbok + + + + Spendable: + Spenderbart: + + + + Your current spendable balance + Ditt tillgängliga saldo + + + + Immature: + Omogen: + + + + Mined balance that has not yet matured + Den genererade balansen som ännu inte har mognat + + + + Total: + Totalt: + + + + Your current total balance + Ditt nuvarande totala saldo + + + + <b>Recent transactions</b> + <b>Nyligen genomförda transaktioner</b> + + + + Total of transactions that have yet to be confirmed, and do not yet count toward the current balance + Totala antalet transaktioner inte har blivit bekräftade än och därför inte räknas mot det totala saldot + + + + Total of coins that was staked, and do not yet count toward the current balance + Antal coins som var i stake-processen, och räknas ännu inte till nuvarande saldo + + + + + out of sync + osynkroniserad + + + + QRCodeDialog + + + QR Code Dialog + QR-Kod Dialog + + + + Request Payment + Begär Betalning + + + + Amount: + Belopp: + + + + Label: + Etikett: + + + + Message: + Meddelande: + + + + &Save As... + &Spara Som... + + + + Error encoding URI into QR Code. + Fel vid skapande av QR-kod från URI. + + + + The entered amount is invalid, please check. + Den angivna mängden är felaktig, var vänlig kontrollera. + + + + Resulting URI too long, try to reduce the text for label / message. + URI:n är för lång, försök minska texten för etikett / meddelande. + + + + Save QR Code + Spara QR-kod + + + + PNG Images (*.png) + PNG Bilder (*.png) + + + + RPCConsole + + + Client name + Klientnamn + + + + + + + + + + + + + N/A + ej tillgänglig + + + + Client version + Klient-version + + + + &Information + &Information + + + + Using OpenSSL version + Använder OpenSSL version + + + + Startup time + Uppstartstid + + + + Network + Nätverk + + + + Number of connections + Antalet anslutningar + + + + On testnet + På testnet + + + + Block chain + Blockkedja + + + + Current number of blocks + Aktuellt antal block + + + + Estimated total blocks + Beräknade totala block + + + + Last block time + Sista blocktid + + + + &Open + &Öppna + + + + Command-line options + Kommandoradsalternativ + + + + Show the Arepacoin-Qt help message to get a list with possible Arepacoin command-line options. + Visa Arepacoin-Qt hjälp meddelandet för att få en lista över möjliga Arepacoin kommandoradsalternativ. + + + + &Show + &Visa + + + + &Console + &Konsol + + + + Build date + Kompileringsdatum + + + + Arepacoin - Debug window + Arepacoin - Felsökningsfönster + + + + Arepacoin Core + Arepacoin Core + + + + Debug log file + Debugloggfil + + + + Open the Arepacoin debug log file from the current data directory. This can take a few seconds for large log files. + Öppna Arepacoin felsöknings-loggfilen från nuvarande data mapp. Detta kan kan ta ett par minuter för stora log filer. + + + + Clear console + Rensa konsollen + + + + Welcome to the Arepacoin RPC console. + Välkommen till Arepacoin RPC konsoll. + + + + Use up and down arrows to navigate history, and <b>Ctrl-L</b> to clear screen. + Använd upp- och ner-pilarna för att navigera i historiken, och <b>Ctrl-L</b> för att rensa skärmen. + + + + Type <b>help</b> for an overview of available commands. + Skriv <b>help</b> för en översikt av alla kommandon. + + + + SendCoinsDialog + + + + + + + + + + Send Coins + Skicka pengar + + + + Coin Control Features + Coin kontrollinställningar + + + + Inputs... + Ingångar... + + + + automatically selected + automatiskt vald + + + + Insufficient funds! + Otillräckligt saldo! + + + + Quantity: + Antal: + + + + + 0 + 0 + + + + Bytes: + Bytes: + + + + Amount: + Belopp: + + + + + + + 0.00 BC + 123.456 BC {0.00 ?} + + + + Priority: + Prioritet: + + + + medium + mellan + + + + Fee: + Avgift: + + + + Low Output: + Låg utmatning: + + + + no + nej + + + + After Fee: + Efter avgift: + + + + Change + Ändra + + + + custom change address + egen ändringsadress + + + + Send to multiple recipients at once + Skicka till flera mottagare samtidigt + + + + Add &Recipient + Lägg till &mottagare + + + + Remove all transaction fields + Ta bort alla transaktionsfält + + + + Clear &All + Rensa &alla + + + + Balance: + Balans: + + + + 123.456 BC + 123.456 BC + + + + Confirm the send action + Bekräfta sändordern + + + + S&end + &Skicka + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + Fyll i en Arepacoin adress (t.ex. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + Copy quantity + Kopiera antal + + + + Copy amount + Kopiera belopp + + + + Copy fee + Kopiera avgift + + + + Copy after fee + Kopiera efter avgift + + + + Copy bytes + Kopiera bytes + + + + Copy priority + Kopiera prioritet + + + + Copy low output + Kopiera låg utmatning + + + + Copy change + Kopiera ändring + + + + <b>%1</b> to %2 (%3) + <b>%1</b> till %2 (%3) + + + + Confirm send coins + Bekräfta skickade mynt + + + + Are you sure you want to send %1? + Är du säker att du vill skicka %1? + + + + and + och + + + + The recipient address is not valid, please recheck. + Mottagarens adress är inte giltig, vänligen kontrollera igen. + + + + The amount to pay must be larger than 0. + Det betalade beloppet måste vara större än 0. + + + + The amount exceeds your balance. + Värdet överstiger ditt saldo. + + + + The total exceeds your balance when the %1 transaction fee is included. + Totalvärdet överstiger ditt saldo när transaktionsavgiften %1 är pålagd. + + + + Duplicate address found, can only send to each address once per send operation. + Dubblett av adress funnen, kan bara skicka till varje adress en gång per sändning. + + + + Error: Transaction creation failed. + Fel: Transaktionen kunde inte skapas. + + + + 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. + Fel: Transaktionen nekades. Detta kan hända om vissa av mynten i din plånbok redan är använda, t.ex om du använder en kopia av wallet.dat och mynten redan var använda i kopia men inte markerade som använda här. + + + + WARNING: Invalid Arepacoin address + VARNING: Ogiltig Arepacoin adress + + + + (no label) + (Ingen etikett) + + + + WARNING: unknown change address + VARNING: okänd ändringsadress + + + + SendCoinsEntry + + + Form + Formulär + + + + A&mount: + &Belopp: + + + + Pay &To: + Betala &Till: + + + + + Enter a label for this address to add it to your address book + Ange ett namn för den här adressen och lägg till den i din adressbok + + + + &Label: + &Etikett: + + + + The address to send the payment to (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + Adressen att skicka betalningen till (t.ex. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + Choose address from address book + Välj adress från adressbok + + + + Alt+A + Alt+A + + + + Paste address from clipboard + Klistra in adress från Urklipp + + + + Alt+P + Alt+P + + + + Remove this recipient + Ta bort denna mottagare + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + Fyll i en Arepacoin adress (t.ex. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + SignVerifyMessageDialog + + + Signatures - Sign / Verify a Message + Signaturer - Signera / Verifiera ett Meddelande + + + + + &Sign Message + &Signera Meddelande + + + + You can sign messages with your addresses to prove you own them. Be careful not to sign anything vague, as phishing attacks may try to trick you into signing your identity over to them. Only sign fully-detailed statements you agree to. + Du kan signera meddelanden med dina adresser för att bevisa att du äger dem. Var försiktig med vad du signerar eftersom phising-attacker kan försöka få dig att skriva över din identitet till någon annan. Signera bara väldetaljerade påståenden du kan gå i god för. + + + + The address to sign the message with (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + Adressen att signera meddelandet med (t.ex. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Choose an address from the address book + Välj en adress från adressboken + + + + + Alt+A + Alt+A + + + + Paste address from clipboard + Klistra in adress från Urklipp + + + + Alt+P + Alt+P + + + + Enter the message you want to sign here + Skriv in meddelandet du vill signera här + + + + Copy the current signature to the system clipboard + Kopiera signaturen till systemets Urklipp + + + + Sign the message to prove you own this Arepacoin address + Signera meddelandet för att verifiera att du äger denna Arepacoin adressen + + + + Reset all sign message fields + Rensa alla fält + + + + + Clear &All + Rensa &alla + + + + + &Verify Message + &Verifiera Meddelande + + + + Enter the signing address, message (ensure you copy line breaks, spaces, tabs, etc. exactly) and signature below to verify the message. Be careful not to read more into the signature than what is in the signed message itself, to avoid being tricked by a man-in-the-middle attack. + Skriv in din adress, meddelande (se till att du kopierar radbrytningar, mellanslag, tabbar, osv. exakt) och signatur nedan för att verifiera meddelandet. Var noga med att inte läsa in mer i signaturen än vad som finns i det signerade meddelandet, för att undvika att luras av en man-in-the-middle attack. + + + + The address the message was signed with (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + Adressen meddelandet var signerad med (t.ex. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + Verify the message to ensure it was signed with the specified Arepacoin address + Verifiera meddelandet för att vara säker på att det var signerat med den angivna Arepacoin adressen + + + + Reset all verify message fields + Rensa alla fält + + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + Fyll i en Arepacoin adress (t.ex. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + Click "Sign Message" to generate signature + Klicka "Signera Meddelande" för att få en signatur + + + + Enter Arepacoin signature + Fyll i Arepacoin signatur + + + + + The entered address is invalid. + Den angivna adressen är ogiltig. + + + + + + + Please check the address and try again. + Vad god kontrollera adressen och försök igen. + + + + + The entered address does not refer to a key. + Den angivna adressen refererar inte till en nyckel. + + + + Wallet unlock was cancelled. + Upplåsningen av plånboken avbröts. + + + + Private key for the entered address is not available. + Privata nyckel för den angivna adressen är inte tillgänglig. + + + + Message signing failed. + Signeringen av meddelandet misslyckades. + + + + Message signed. + Meddelandet är signerat. + + + + The signature could not be decoded. + Signaturen kunde inte avkodas. + + + + + Please check the signature and try again. + Kontrollera signaturen och försök igen. + + + + The signature did not match the message digest. + Signaturen matchade inte meddelandesammanfattningen. + + + + Message verification failed. + Meddelandet verifikation misslyckades. + + + + Message verified. + Meddelandet är verifierad. + + + + TransactionDesc + + + Open until %1 + Öppet till %1 + + + + Open for %n block(s) + Öppen för %n blockÖppen för %n block + + + + conflicted + konflikt + + + + %1/offline + %1/nerkopplad + + + + %1/unconfirmed + %1/obekräftade + + + + %1 confirmations + %1 bekräftelser + + + + Status + Status + + + + , broadcast through %n node(s) + , sänd genom %n nod, sänd genom %n noder + + + + Date + Datum + + + + Source + Källa + + + + Generated + Genererad + + + + + From + Från + + + + + + To + Till + + + + + own address + egen adress + + + + label + etikett + + + + + + + + Credit + Kredit + + + + matures in %n more block(s) + mognar om %n blockmognar om %n fler block + + + + not accepted + inte accepterad + + + + + + + Debit + Belasta + + + + Transaction fee + Transaktionsavgift + + + + Net amount + Nettobelopp + + + + Message + Meddelande + + + + Comment + Kommentar + + + + Transaction ID + Transaktions-ID + + + + Generated coins must mature 6 blocks before they can be spent. When you generated this block, it was broadcast to the network to be added to the block chain. If it fails to get into the chain, its state will change to "not accepted" and it won't be spendable. This may occasionally happen if another node generates a block within a few seconds of yours. + Genererad mynt måste mogna i 6 block före de kan användas. När du genererade detta blocket sändes det ut till nätverket för att läggas till i blockkedjan. Om det inte kan läggas till i kedjan kommer dess status att ändras till "Ej accepterat" och det kommer inte gå att använda. Detta kan hända imellanåt om en annan klient genererar ett block inom ett par sekunder från ditt. + + + + Debug information + Debug information + + + + Transaction + Transaktion + + + + Inputs + Inputs + + + + Amount + Mängd + + + + true + sant + + + + false + falsk + + + + , has not been successfully broadcast yet + , har inte lyckats skickas ännu + + + + unknown + okänd + + + + TransactionDescDialog + + + Transaction details + Transaktionsdetaljer + + + + This pane shows a detailed description of the transaction + Den här panelen visar en detaljerad beskrivning av transaktionen + + + + TransactionTableModel + + + Date + Datum + + + + Type + Typ + + + + Address + Adress + + + + Amount + Mängd + + + + Open until %1 + Öppet till %1 + + + + Confirmed (%1 confirmations) + Bekräftad (%1 bekräftelser) + + + + Open for %n more block(s) + Öppet för %n mer blockÖppet för %n mer block + + + + Offline + Nerkopplad + + + + Unconfirmed + Obekräftad + + + + Confirming (%1 of %2 recommended confirmations) + Bekräftar (%1 av %2 rekommenderade bekräftelser) + + + + Conflicted + Konflikt + + + + Immature (%1 confirmations, will be available after %2) + Omogen (%1 bekräftningar, kommer bli tillgänglig efter %2) + + + + This block was not received by any other nodes and will probably not be accepted! + Det här blocket togs inte emot av några andra noder och kommer antagligen inte att bli godkänt. + + + + Generated but not accepted + Genererad men inte accepterad + + + + Received with + Mottagen med + + + + Received from + Mottaget från + + + + Sent to + Skickad till + + + + Payment to yourself + Betalning till dig själv + + + + Mined + Genererade + + + + (n/a) + (n/a) + + + + Transaction status. Hover over this field to show number of confirmations. + Transaktionsstatus. Håll muspekaren över för att se antal bekräftelser. + + + + Date and time that the transaction was received. + Tidpunkt då transaktionen mottogs. + + + + Type of transaction. + Transaktionstyp. + + + + Destination address of transaction. + Transaktionens destinationsadress. + + + + Amount removed from or added to balance. + Belopp draget eller tillagt till balans. + + + + TransactionView + + + + All + Alla + + + + Today + Idag + + + + This week + Denna vecka + + + + This month + Denna månad + + + + Last month + Föregående månad + + + + This year + Det här året + + + + Range... + Period... + + + + Received with + Mottagen med + + + + Sent to + Skickad till + + + + To yourself + Till dig själv + + + + Mined + Genererade + + + + Other + Övriga + + + + Enter address or label to search + Sök efter adress eller etikett + + + + Min amount + Minsta mängd + + + + Copy address + Kopiera adress + + + + Copy label + Kopiera etikett + + + + Copy amount + Kopiera belopp + + + + Copy transaction ID + Kopiera transaktions ID + + + + Edit label + Ändra etikett + + + + Show transaction details + Visa transaktionsdetaljer + + + + Export Transaction Data + Exportera transaktionsdata + + + + Comma separated file (*.csv) + Kommaseparerad fil (*. csv) + + + + Confirmed + Bekräftad + + + + Date + Datum + + + + Type + Typ + + + + Label + Etikett + + + + Address + Adress + + + + Amount + Mängd + + + + ID + ID + + + + Error exporting + Fel vid exportering + + + + Could not write to file %1. + Kan inte skriva till fil %1. + + + + Range: + Intervall: + + + + to + till + + + + WalletModel + + + Sending... + Skickar... + + + + bitcoin-core + + + Arepacoin version + Arepacoin version + + + + Usage: + Användning: + + + + Send command to -server or arepacoind + Skicka kommando till -server eller arepacoind + + + + List commands + Lista kommandon + + + + Get help for a command + Få hjälp med ett kommando + + + + Options: + Inställningar: + + + + Specify configuration file (default: arepacoin.conf) + Ange konfigurationsfilen (standard: arepacoin.conf) + + + + Specify pid file (default: arepacoind.pid) + Ange pid filen (standard arepacoind.pid) + + + + Specify wallet file (within data directory) + Ange plånboksfil (inom datakatalogen) + + + + Specify data directory + Ange katalog för data + + + + Set database cache size in megabytes (default: 25) + Sätt databas cache storleken i megabyte (förvalt: 25) + + + + Set database disk log size in megabytes (default: 100) + Sätt databas logg storleken i MB (standard: 100) + + + + Listen for connections on <port> (default: 9853 or testnet: 19853) + Lyssna efter anslutningar på <port> (standard: 9853 eller testnät: 19853) + + + + Maintain at most <n> connections to peers (default: 125) + Ha som mest <n> anslutningar till andra klienter (förvalt: 125) + + + + Connect to a node to retrieve peer addresses, and disconnect + Anslut till en nod för att hämta klientadresser, och koppla från + + + + Specify your own public address + Ange din egen publika adress + + + + Bind to given address. Use [host]:port notation for IPv6 + Bind till angiven adress. Använd [host]:port för IPv6 + + + + Stake your coins to support network and gain reward (default: 1) + Använd dina coins för stake-processen, du upprätthåller då nätverket och får belöning (förval: 1) + + + + Threshold for disconnecting misbehaving peers (default: 100) + Tröskelvärde för att koppla ifrån klienter som missköter sig (förvalt: 100) + + + + Number of seconds to keep misbehaving peers from reconnecting (default: 86400) + Antal sekunder att hindra klienter som missköter sig från att ansluta (förvalt: 86400) + + + + An error occurred while setting up the RPC port %u for listening on IPv4: %s + Ett fel uppstod vid upprättandet av RPC port %u för att lyssna på IPv4: %s + + + + Detach block and address databases. Increases shutdown time (default: 0) + Koppla ifrån block och adress databaser. Ökar nedstängningstid (standard: 0) + + + + 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. + Fel: Transaktionen nekades. Detta kan hända om vissa av mynten i din plånbok redan är använda, t.ex om du använder en kopia av wallet.dat och mynten redan var använda i kopia men inte markerade som använda här. + + + + Error: This transaction requires a transaction fee of at least %s because of its amount, complexity, or use of recently received funds + Fel: Transaktionen kräver en transaktionsavgift på min %s på grund av dess storlek, komplexitet eller användning av nyligen mottagna kapital + + + + Listen for JSON-RPC connections on <port> (default: 9852 or testnet: 19852) + Lyssna efter JSON-RPC anslutningar på <port> (standard: 9852 eller testnät: 19852) + + + + Accept command line and JSON-RPC commands + Tillåt kommandon från kommandotolken och JSON-RPC-kommandon + + + + Error: Transaction creation failed + Fel: Skapandet av transaktion misslyckades + + + + Error: Wallet locked, unable to create transaction + Fel: Plånboken låst, kan inte utföra transaktion + + + + Importing blockchain data file. + Importerar blockchain data fil. + + + + Importing bootstrap blockchain data file. + Importerar bootstrap blockchain data fil. + + + + Run in the background as a daemon and accept commands + Kör i bakgrunden som tjänst och acceptera kommandon + + + + Use the test network + Använd testnätverket + + + + Accept connections from outside (default: 1 if no -proxy or -connect) + Acceptera anslutningar utifrån (förvalt: 1 om ingen -proxy eller -connect) + + + + An error occurred while setting up the RPC port %u for listening on IPv6, falling back to IPv4: %s + Ett fel uppstod vid upprättandet av RPC port %u för att lyssna på IPv6, faller tillbaka till IPV4: %s + + + + Error initializing database environment %s! To recover, BACKUP THAT DIRECTORY, then remove everything from it except for wallet.dat. + Ett fel uppstod vid initialiseringen av databasen %s! För att återställa, SÄKERHETSKOPIERA MAPPEN, radera sedan allt från mappen förutom wallet.dat. + + + + Set maximum size of high-priority/low-fee transactions in bytes (default: 27000) + Ställ in max storlek för hög prioritet/lågavgifts transaktioner i bytes (förval: 27000) + + + + Warning: -paytxfee is set very high! This is the transaction fee you will pay if you send a transaction. + Varning: -paytxfee är satt väldigt hög! Detta är avgiften du kommer betala för varje transaktion. + + + + Warning: Please check that your computer's date and time are correct! If your clock is wrong Arepacoin will not work properly. + Varning: Kolla att din dators tid och datum är rätt. Arepacoin kan inte fungera ordentligt om tiden i datorn är fel. + + + + Warning: error reading wallet.dat! All keys read correctly, but transaction data or address book entries might be missing or incorrect. + Varning: fel vid läsning av wallet.dat! Alla nycklar lästes korrekt, men transaktionsdatan eller adressbokens poster kanske saknas eller är felaktiga. + + + + Warning: wallet.dat corrupt, data salvaged! Original wallet.dat saved as wallet.{timestamp}.bak in %s; if your balance or transactions are incorrect you should restore from a backup. + Varning: wallet.dat korrupt, datan har räddats! Den ursprungliga wallet.dat har sparas som wallet.{timestamp}.bak i %s; om ditt saldo eller transaktioner är felaktiga ska du återställa från en säkerhetskopia. + + + + Attempt to recover private keys from a corrupt wallet.dat + Försök att rädda de privata nycklarna från en korrupt wallet.dat + + + + Block creation options: + Block skapande inställningar: + + + + Connect only to the specified node(s) + Koppla enbart upp till den/de specificerade noden/noder + + + + Discover own IP address (default: 1 when listening and no -externalip) + Hitta egen IP-adress (förvalt: 1 under lyssning och utan -externalip) + + + + Failed to listen on any port. Use -listen=0 if you want this. + Misslyckades att lyssna på någon port. Använd -listen=0 om du vill detta. + + + + Find peers using DNS lookup (default: 1) + Hitta andra klienter via DNS uppsökning (standard: 1) + + + + Sync checkpoints policy (default: strict) + Synka kontrollpunkts policy (standard: strict) + + + + Invalid -tor address: '%s' + Fel -tor adress: '%s' + + + + Invalid amount for -reservebalance=<amount> + Fel mängd för -reservebalance=<amount> + + + + Maximum per-connection receive buffer, <n>*1000 bytes (default: 5000) + Maximal buffert för mottagning per anslutning, <n>*1000 byte (förvalt: 5000) + + + + Maximum per-connection send buffer, <n>*1000 bytes (default: 1000) + Maximal buffert för sändning per anslutning, <n>*1000 byte (förvalt: 5000) + + + + Only connect to nodes in network <net> (IPv4, IPv6 or Tor) + Anslut enbart till noder i nätverket <net> (IPv4, IPv6 eller Tor) + + + + Output extra debugging information. Implies all other -debug* options + Skriv ut extra debug information. Betyder alla andra -debug* alternativ + + + + Output extra network debugging information + Skriv ut extra nätverks debug information + + + + Prepend debug output with timestamp + Tidstämpla debug utskriften + + + + SSL options: (see the Bitcoin Wiki for SSL setup instructions) + SSL-inställningar: (se Bitcoin-wikin för SSL-setup instruktioner) + + + + Select the version of socks proxy to use (4-5, default: 5) + Välj version av socks proxy (4-5, förval 5) + + + + Send trace/debug info to console instead of debug.log file + Skicka trace-/debuginformation till terminalen istället för till debug.log + + + + Send trace/debug info to debugger + Skicka trace/debug till debuggern + + + + Set maximum block size in bytes (default: 250000) + Sätt största blockstorlek i bytes (förvalt: 250000) + + + + Set minimum block size in bytes (default: 0) + Sätt minsta blockstorlek i byte (förvalt: 0) + + + + Shrink debug.log file on client startup (default: 1 when no -debug) + Krymp debug.log filen vid klient start (förvalt: 1 vid ingen -debug) + + + + Specify connection timeout in milliseconds (default: 5000) + Ange timeout för uppkoppling i millisekunder (förvalt: 5000) + + + + Unable to sign checkpoint, wrong checkpointkey? + + Kan inte signera checkpoint, fel checkpointkey? + + + + + Use UPnP to map the listening port (default: 0) + Använd UPnP för att mappa den lyssnande porten (förvalt: 0) + + + + Use UPnP to map the listening port (default: 1 when listening) + Använd UPnP för att mappa den lyssnande porten (förvalt: 1 under lyssning) + + + + Use proxy to reach tor hidden services (default: same as -proxy) + Använd proxy för att nå Tor gömda servicer (standard: samma som -proxy) + + + + Username for JSON-RPC connections + Användarnamn för JSON-RPC-anslutningar + + + + Verifying database integrity... + Verifierar integriteten i databasen... + + + + WARNING: syncronized checkpoint violation detected, but skipped! + VARNING: synkroniserad kontrollpunkts brott upptäckt, men hoppades över! + + + + Warning: Disk space is low! + Varning: Lågt skivutrymme + + + + Warning: This version is obsolete, upgrade required! + Varning: denna version är föråldrad, uppgradering krävs! + + + + wallet.dat corrupt, salvage failed + wallet.dat korrupt, räddning misslyckades + + + + Password for JSON-RPC connections + Lösenord för JSON-RPC-anslutningar + + + + %s, you must set a rpcpassword in the configuration file: + %s +It is recommended you use the following random password: +rpcuser=arepacoinrpc +rpcpassword=%s +(you do not need to remember this password) +The username and password MUST NOT be the same. +If the file does not exist, create it with owner-readable-only file permissions. +It is also recommended to set alertnotify so you are notified of problems; +for example: alertnotify=echo %%s | mail -s "Arepacoin Alert" admin@foo.com + + %s, du måste sätta rpcpassword i konfigurationsfilen: + %s +Det är rekommenderat att du använder följande slumpmässiga lösenord: +rpcuser=arepacoinrpc +rpcpassword=%s +(du behöver inte komma ihåg detta lösenord) +Användarnamnet och lösenordet FÅR INTE vara samma. +Om filen inte finns, skapa den med endast ägarrättigheter. +Det är också rekommenderat att sätta alertnotify så du blir notifierad om problem; +till exempel: alertnotify=echo %%s | mail -s "Arepacoin Varning" admin@foo.com + + + + + Find peers using internet relay chat (default: 0) + Hitta andra klienter genom internet relay chat (standard: 1) {0)?} + + + + Sync time with other nodes. Disable if time on your system is precise e.g. syncing with NTP (default: 1) + Synkronisera tiden med andra noder. Avaktivera om klockan i ditt sytem är exakt som t.ex. synkroniserad med NTP (förval: 1) + + + + When creating transactions, ignore inputs with value less than this (default: 0.01) + När transaktioner skapas, ignorera värden som är lägre än detta (standard: 0.01) + + + + Allow JSON-RPC connections from specified IP address + Tillåt JSON-RPC-anslutningar från specifika IP-adresser + + + + Send commands to node running on <ip> (default: 127.0.0.1) + Skicka kommandon till klient på <ip> (förvalt: 127.0.0.1) + + + + Execute command when the best block changes (%s in cmd is replaced by block hash) + Exekvera kommando när det bästa blocket ändras (%s i cmd är utbytt av blockhash) + + + + Execute command when a wallet transaction changes (%s in cmd is replaced by TxID) + Exekvera kommando när en plånbokstransaktion ändras (%s i cmd är ersatt av TxID) + + + + Require a confirmations for change (default: 0) + Kräv bekräftelse för ändring (förval: 0) + + + + Enforce transaction scripts to use canonical PUSH operators (default: 1) + Tvinga transaktionsskript att använda kanoniska PUSH operatörer (standard: 1) + + + + Execute command when a relevant alert is received (%s in cmd is replaced by message) + Kör kommando när en relevant alert är mottagen (%s i cmd är ersatt av meddelandet) + + + + Upgrade wallet to latest format + Uppgradera plånboken till senaste formatet + + + + Set key pool size to <n> (default: 100) + Sätt storleken på nyckelpoolen till <n> (förvalt: 100) + + + + Rescan the block chain for missing wallet transactions + Sök i blockkedjan efter saknade plånboks transaktioner + + + + How many blocks to check at startup (default: 2500, 0 = all) + Antal block som kollas vid start (standard: 2500, 0=alla) + + + + How thorough the block verification is (0-6, default: 1) + Hur genomförlig blockverifikationen är (0-6, standard: 1) + + + + Imports blocks from external blk000?.dat file + Importera block från en extern blk000?.dat fil + + + + Use OpenSSL (https) for JSON-RPC connections + Använd OpenSSL (https) för JSON-RPC-anslutningar + + + + Server certificate file (default: server.cert) + Serverns certifikatfil (förvalt: server.cert) + + + + Server private key (default: server.pem) + Serverns privata nyckel (förvalt: server.pem) + + + + Acceptable ciphers (default: TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH) + Godtagbara chiffer (standard: TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH) + + + + Error: Wallet unlocked for staking only, unable to create transaction. + Fel: Plånboken öppnad endast för stake-process, kan inte skapa transaktion. + + + + WARNING: Invalid checkpoint found! Displayed transactions may not be correct! You may need to upgrade, or notify developers. + VARNING: Felaktig kontrollpunkt hittad! Visade transaktioner kan vara felaktiga! Du kan behöva uppgradera eller kontakta utvecklarna. + + + + This help message + Det här hjälp medelandet + + + + Wallet %s resides outside data directory %s. + Plånbok %s ligger utanför datamappen %s. + + + + Cannot obtain a lock on data directory %s. Arepacoin is probably already running. + Kan inte låsa datan i mappen %s. Arepacoin är kanske redan startad. + + + + Arepacoin + Arepacoin + + + + Unable to bind to %s on this computer (bind returned error %d, %s) + Det går inte att binda till %s på den här datorn (bind returnerade felmeddelande %d, %s) + + + + Connect through socks proxy + Koppla genom en socks proxy + + + + Allow DNS lookups for -addnode, -seednode and -connect + Tillåt DNS-sökningar för -addnode, -seednode och -connect + + + + Loading addresses... + Laddar adresser... + + + + Error loading blkindex.dat + Fel vid laddande av blkindex.dat + + + + Error loading wallet.dat: Wallet corrupted + Fel vid inläsningen av wallet.dat: Plånboken är skadad + + + + Error loading wallet.dat: Wallet requires newer version of Arepacoin + Kunde inte ladda wallet.dat: En nyare version av Arepacoin krävs + + + + Wallet needed to be rewritten: restart Arepacoin to complete + Plånboken måste skrivas om: Starta om Arepacoin för att slutföra + + + + Error loading wallet.dat + Fel vid inläsning av plånboksfilen wallet.dat + + + + Invalid -proxy address: '%s' + Ogiltig -proxy adress: '%s' + + + + Unknown network specified in -onlynet: '%s' + Okänt nätverk som anges i -onlynet: '%s' + + + + Unknown -socks proxy version requested: %i + Okänd -socks proxy version begärd: %i + + + + Cannot resolve -bind address: '%s' + Kan inte matcha -bind adress: '%s' + + + + Cannot resolve -externalip address: '%s' + Kan inte matcha -externalip adress: '%s' + + + + Invalid amount for -paytxfee=<amount>: '%s' + Ogiltigt belopp för -paytxfee=<belopp>:'%s' + + + + Error: could not start node + Fel: kunde inte starta noden + + + + Sending... + Skickar... + + + + Invalid amount + Ogiltig mängd + + + + Insufficient funds + Otillräckligt med bitcoins + + + + Loading block index... + Laddar blockindex... + + + + Add a node to connect to and attempt to keep the connection open + Lägg till en nod att koppla upp mot och försök att hålla anslutningen öppen + + + + Unable to bind to %s on this computer. Arepacoin is probably already running. + Kan inte binda till %s på denna dator. Arepacoin är sannolikt redan startad. + + + + Fee per KB to add to transactions you send + Avgift per KB som adderas till transaktionen du sänder + + + + Invalid amount for -mininput=<amount>: '%s' + Fel mängd för -mininput=<amount>: '%s' + + + + Loading wallet... + Laddar plånbok... + + + + Cannot downgrade wallet + Kan inte nedgradera plånboken + + + + Cannot initialize keypool + Kan inte initialisera keypool + + + + Cannot write default address + Kan inte skriva standardadress + + + + Rescanning... + Söker igen... + + + + Done loading + Klar med laddning + + + + To use the %s option + Att använda %s alternativet + + + + Error + Fel + + + + You must set rpcpassword=<password> in the configuration file: +%s +If the file does not exist, create it with owner-readable-only file permissions. + Du behöver välja ett rpclösensord i konfigurationsfilen: +%s +Om filen inte existerar, skapa den med filrättigheten endast läsbar för ägaren. + + + \ No newline at end of file diff --git a/src/qt/locale/bitcoin_th_TH.ts b/src/qt/locale/bitcoin_th_TH.ts new file mode 100755 index 0000000..1d203d9 --- /dev/null +++ b/src/qt/locale/bitcoin_th_TH.ts @@ -0,0 +1,3275 @@ + + + AboutDialog + + + About Arepacoin + + + + + <b>Arepacoin</b> version + + + + + Copyright © 2009-2014 The Bitcoin developers +Copyright © 2012-2014 The NovaCoin developers +Copyright © 2014 The Arepacoin developers + + + + + +This is experimental software. + +Distributed under the MIT/X11 software license, see the accompanying file COPYING or http://www.opensource.org/licenses/mit-license.php. + +This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit (http://www.openssl.org/) and cryptographic software written by Eric Young (eay@cryptsoft.com) and UPnP software written by Thomas Bernard. + + + + + AddressBookPage + + + Address Book + + + + + Double-click to edit address or label + ดับเบิลคลิก เพื่อแก้ไขที่อยู่ หรือชื่อ + + + + Create a new address + สร้างที่อยู่ใหม่ + + + + Copy the currently selected address to the system clipboard + คัดลอกที่อยู่ที่ถูกเลือกไปยัง คลิปบอร์ดของระบบ + + + + &New Address + + + + + These are your Arepacoin addresses for receiving payments. You may want to give a different one to each sender so you can keep track of who is paying you. + + + + + &Copy Address + + + + + Show &QR Code + + + + + Sign a message to prove you own a Arepacoin address + + + + + Sign &Message + + + + + Delete the currently selected address from the list + + + + + Verify a message to ensure it was signed with a specified Arepacoin address + + + + + &Verify Message + + + + + &Delete + ลบ + + + + Copy &Label + + + + + &Edit + + + + + Export Address Book Data + + + + + Comma separated file (*.csv) + + + + + Error exporting + + + + + Could not write to file %1. + + + + + AddressTableModel + + + Label + ชื่อ + + + + Address + ที่อยู่ + + + + (no label) + (ไม่มีชื่อ) + + + + AskPassphraseDialog + + + Passphrase Dialog + + + + + Enter passphrase + ใส่รหัสผ่าน + + + + New passphrase + รหัสผา่นใหม่ + + + + Repeat new passphrase + กรุณากรอกรหัสผ่านใหม่อีกครั้งหนึ่ง + + + + Serves to disable the trivial sendmoney when OS account compromised. Provides no real security. + + + + + For staking only + + + + + Enter the new passphrase to the wallet.<br/>Please use a passphrase of <b>10 or more random characters</b>, or <b>eight or more words</b>. + + + + + Encrypt wallet + กระเป๋าสตางค์ที่เข้ารหัส + + + + This operation needs your wallet passphrase to unlock the wallet. + + + + + Unlock wallet + เปิดกระเป๋าสตางค์ + + + + This operation needs your wallet passphrase to decrypt the wallet. + + + + + Decrypt wallet + ถอดรหัสกระเป๋าสตางค์ + + + + Change passphrase + เปลี่ยนรหัสผ่าน + + + + Enter the old and new passphrase to the wallet. + กรอกรหัสผ่านเก่าและรหัสผ่านใหม่สำหรับกระเป๋าสตางค์ + + + + Confirm wallet encryption + ยืนยันการเข้ารหัสกระเป๋าสตางค์ + + + + Warning: If you encrypt your wallet and lose your passphrase, you will <b>LOSE ALL OF YOUR COINS</b>! + + + + + Are you sure you wish to encrypt your wallet? + + + + + IMPORTANT: Any previous backups you have made of your wallet file should be replaced with the newly generated, encrypted wallet file. For security reasons, previous backups of the unencrypted wallet file will become useless as soon as you start using the new, encrypted wallet. + + + + + + Warning: The Caps Lock key is on! + + + + + + Wallet encrypted + กระเป๋าสตางค์ถูกเข้ารหัสเรียบร้อยแล้ว + + + + Arepacoin will close now to finish the encryption process. Remember that encrypting your wallet cannot fully protect your coins from being stolen by malware infecting your computer. + + + + + + + + Wallet encryption failed + การเข้ารหัสกระเป๋าสตางค์ผิดพลาด + + + + Wallet encryption failed due to an internal error. Your wallet was not encrypted. + + + + + + The supplied passphrases do not match. + รหัสผ่านที่คุณกรอกไม่ตรงกัน + + + + Wallet unlock failed + + + + + + + The passphrase entered for the wallet decryption was incorrect. + + + + + Wallet decryption failed + + + + + Wallet passphrase was successfully changed. + + + + + BitcoinGUI + + + Sign &message... + + + + + Synchronizing with network... + + + + + &Overview + + + + + Show general overview of wallet + + + + + &Transactions + + + + + Browse transaction history + + + + + &Address Book + + + + + Edit the list of stored addresses and labels + + + + + &Receive coins + + + + + Show the list of addresses for receiving payments + + + + + &Send coins + + + + + E&xit + + + + + Quit application + + + + + Show information about Arepacoin + + + + + About &Qt + + + + + Show information about Qt + + + + + &Options... + + + + + &Encrypt Wallet... + + + + + &Backup Wallet... + + + + + &Change Passphrase... + + + + + ~%n block(s) remaining + + + + + Downloaded %1 of %2 blocks of transaction history (%3% done). + + + + + &Export... + + + + + Send coins to a Arepacoin address + + + + + Modify configuration options for Arepacoin + + + + + Export the data in the current tab to a file + + + + + Encrypt or decrypt wallet + + + + + Backup wallet to another location + + + + + Change the passphrase used for wallet encryption + + + + + &Debug window + + + + + Open debugging and diagnostic console + + + + + &Verify message... + + + + + Arepacoin + + + + + Wallet + + + + + &About Arepacoin + + + + + &Show / Hide + + + + + Unlock wallet + + + + + &Lock Wallet + + + + + Lock wallet + + + + + &File + + + + + &Settings + + + + + &Help + + + + + Tabs toolbar + + + + + Actions toolbar + + + + + + [testnet] + + + + + + Arepacoin client + + + + + %n active connection(s) to Arepacoin network + + + + + Downloaded %1 blocks of transaction history. + + + + + Staking.<br>Your weight is %1<br>Network weight is %2<br>Expected time to earn reward is %3 + + + + + Not staking because wallet is locked + + + + + Not staking because wallet is offline + + + + + Not staking because wallet is syncing + + + + + Not staking because you don't have mature coins + + + + + %n second(s) ago + + + + + &Unlock Wallet... + + + + + %n minute(s) ago + + + + + %n hour(s) ago + + + + + %n day(s) ago + + + + + Up to date + + + + + Catching up... + + + + + Last received block was generated %1. + + + + + This transaction is over the size limit. You can still send it for a fee of %1, which goes to the nodes that process your transaction and helps to support the network. Do you want to pay the fee? + + + + + Confirm transaction fee + + + + + Sent transaction + + + + + Incoming transaction + + + + + Date: %1 +Amount: %2 +Type: %3 +Address: %4 + + + + + + + URI handling + + + + + + URI can not be parsed! This can be caused by an invalid Arepacoin address or malformed URI parameters. + + + + + Wallet is <b>encrypted</b> and currently <b>unlocked</b> + + + + + Wallet is <b>encrypted</b> and currently <b>locked</b> + + + + + Backup Wallet + + + + + Wallet Data (*.dat) + + + + + Backup Failed + + + + + There was an error trying to save the wallet data to the new location. + + + + + %n second(s) + + + + + %n minute(s) + + + + + %n hour(s) + + + + + %n day(s) + + + + + Not staking + + + + + A fatal error occurred. Arepacoin can no longer continue safely and will quit. + + + + + ClientModel + + + Network Alert + + + + + CoinControlDialog + + + Coin Control + + + + + Quantity: + + + + + Bytes: + + + + + Amount: + + + + + Priority: + + + + + Fee: + + + + + Low Output: + + + + + no + + + + + After Fee: + + + + + Change: + + + + + (un)select all + + + + + Tree mode + + + + + List mode + + + + + Amount + + + + + Label + + + + + Address + ที่อยู่ + + + + Date + + + + + Confirmations + + + + + Confirmed + + + + + Priority + + + + + Copy address + + + + + Copy label + + + + + + Copy amount + + + + + Copy transaction ID + + + + + Copy quantity + + + + + Copy fee + + + + + Copy after fee + + + + + Copy bytes + + + + + Copy priority + + + + + Copy low output + + + + + Copy change + + + + + highest + + + + + high + + + + + medium-high + + + + + medium + + + + + low-medium + + + + + low + + + + + lowest + + + + + DUST + + + + + yes + + + + + This label turns red, if the transaction size is bigger than 10000 bytes. + + This means a fee of at least %1 per kb is required. + + Can vary +/- 1 Byte per input. + + + + + Transactions with higher priority get more likely into a block. + +This label turns red, if the priority is smaller than "medium". + + This means a fee of at least %1 per kb is required. + + + + + This label turns red, if any recipient receives an amount smaller than %1. + + This means a fee of at least %2 is required. + + Amounts below 0.546 times the minimum relay fee are shown as DUST. + + + + + This label turns red, if the change is smaller than %1. + + This means a fee of at least %2 is required. + + + + + + (no label) + (ไม่มีชื่อ) + + + + change from %1 (%2) + + + + + (change) + + + + + EditAddressDialog + + + Edit Address + + + + + &Label + + + + + The label associated with this address book entry + + + + + &Address + + + + + The address associated with this address book entry. This can only be modified for sending addresses. + + + + + New receiving address + + + + + New sending address + + + + + Edit receiving address + + + + + Edit sending address + + + + + The entered address "%1" is already in the address book. + + + + + The entered address "%1" is not a valid Arepacoin address. + + + + + Could not unlock wallet. + + + + + New key generation failed. + + + + + GUIUtil::HelpMessageBox + + + + Arepacoin-Qt + + + + + version + + + + + Usage: + + + + + command-line options + + + + + UI options + + + + + Set language, for example "de_DE" (default: system locale) + + + + + Start minimized + + + + + Show splash screen on startup (default: 1) + + + + + OptionsDialog + + + Options + + + + + &Main + + + + + Optional transaction fee per kB that helps make sure your transactions are processed quickly. Most transactions are 1 kB. Fee 0.01 recommended. + + + + + Pay transaction &fee + + + + + Reserved amount does not participate in staking and is therefore spendable at any time. + + + + + Reserve + + + + + Automatically start Arepacoin after logging in to the system. + + + + + &Start Arepacoin on system login + + + + + Detach block and address databases at shutdown. This means they can be moved to another data directory, but it slows down shutdown. The wallet is always detached. + + + + + &Detach databases at shutdown + + + + + &Network + + + + + Automatically open the Arepacoin client port on the router. This only works when your router supports UPnP and it is enabled. + + + + + Map port using &UPnP + + + + + Connect to the Arepacoin network through a SOCKS proxy (e.g. when connecting through Tor). + + + + + &Connect through SOCKS proxy: + + + + + Proxy &IP: + + + + + IP address of the proxy (e.g. 127.0.0.1) + + + + + &Port: + + + + + Port of the proxy (e.g. 9050) + + + + + SOCKS &Version: + + + + + SOCKS version of the proxy (e.g. 5) + + + + + &Window + + + + + Show only a tray icon after minimizing the window. + + + + + &Minimize to the tray instead of the taskbar + + + + + Minimize instead of exit the application when the window is closed. When this option is enabled, the application will be closed only after selecting Quit in the menu. + + + + + M&inimize on close + + + + + &Display + + + + + User Interface &language: + + + + + The user interface language can be set here. This setting will take effect after restarting Arepacoin. + + + + + &Unit to show amounts in: + + + + + Choose the default subdivision unit to show in the interface and when sending coins. + + + + + Whether to show Arepacoin addresses in the transaction list or not. + + + + + &Display addresses in transaction list + + + + + Whether to show coin control features or not. + + + + + Display coin &control features (experts only!) + + + + + &OK + + + + + &Cancel + + + + + &Apply + + + + + default + + + + + + Warning + + + + + + This setting will take effect after restarting Arepacoin. + + + + + The supplied proxy address is invalid. + + + + + OverviewPage + + + Form + + + + + + The displayed information may be out of date. Your wallet automatically synchronizes with the Arepacoin network after a connection is established, but this process has not completed yet. + + + + + Stake: + + + + + Unconfirmed: + + + + + Wallet + + + + + Spendable: + + + + + Your current spendable balance + + + + + Immature: + + + + + Mined balance that has not yet matured + + + + + Total: + + + + + Your current total balance + + + + + <b>Recent transactions</b> + + + + + Total of transactions that have yet to be confirmed, and do not yet count toward the current balance + + + + + Total of coins that was staked, and do not yet count toward the current balance + + + + + + out of sync + + + + + QRCodeDialog + + + QR Code Dialog + + + + + Request Payment + + + + + Amount: + + + + + Label: + + + + + Message: + + + + + &Save As... + + + + + Error encoding URI into QR Code. + + + + + The entered amount is invalid, please check. + + + + + Resulting URI too long, try to reduce the text for label / message. + + + + + Save QR Code + + + + + PNG Images (*.png) + + + + + RPCConsole + + + Client name + + + + + + + + + + + + + + N/A + + + + + Client version + + + + + &Information + + + + + Using OpenSSL version + + + + + Startup time + + + + + Network + + + + + Number of connections + + + + + On testnet + + + + + Block chain + + + + + Current number of blocks + + + + + Estimated total blocks + + + + + Last block time + + + + + &Open + + + + + Command-line options + + + + + Show the Arepacoin-Qt help message to get a list with possible Arepacoin command-line options. + + + + + &Show + + + + + &Console + + + + + Build date + + + + + Arepacoin - Debug window + + + + + Arepacoin Core + + + + + Debug log file + + + + + Open the Arepacoin debug log file from the current data directory. This can take a few seconds for large log files. + + + + + Clear console + + + + + Welcome to the Arepacoin RPC console. + + + + + Use up and down arrows to navigate history, and <b>Ctrl-L</b> to clear screen. + + + + + Type <b>help</b> for an overview of available commands. + + + + + SendCoinsDialog + + + + + + + + + + Send Coins + + + + + Coin Control Features + + + + + Inputs... + + + + + automatically selected + + + + + Insufficient funds! + + + + + Quantity: + + + + + + 0 + + + + + Bytes: + + + + + Amount: + + + + + + + + 0.00 BC + + + + + Priority: + + + + + medium + + + + + Fee: + + + + + Low Output: + + + + + no + + + + + After Fee: + + + + + Change + + + + + custom change address + + + + + Send to multiple recipients at once + + + + + Add &Recipient + + + + + Remove all transaction fields + + + + + Clear &All + + + + + Balance: + + + + + 123.456 BC + + + + + Confirm the send action + + + + + S&end + + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Copy quantity + + + + + Copy amount + + + + + Copy fee + + + + + Copy after fee + + + + + Copy bytes + + + + + Copy priority + + + + + Copy low output + + + + + Copy change + + + + + <b>%1</b> to %2 (%3) + + + + + Confirm send coins + + + + + Are you sure you want to send %1? + + + + + and + + + + + The recipient address is not valid, please recheck. + + + + + The amount to pay must be larger than 0. + + + + + The amount exceeds your balance. + + + + + The total exceeds your balance when the %1 transaction fee is included. + + + + + Duplicate address found, can only send to each address once per send operation. + + + + + Error: Transaction creation failed. + + + + + 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. + + + + + WARNING: Invalid Arepacoin address + + + + + (no label) + (ไม่มีชื่อ) + + + + WARNING: unknown change address + + + + + SendCoinsEntry + + + Form + + + + + A&mount: + + + + + Pay &To: + + + + + + Enter a label for this address to add it to your address book + + + + + &Label: + + + + + The address to send the payment to (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Choose address from address book + + + + + Alt+A + + + + + Paste address from clipboard + + + + + Alt+P + + + + + Remove this recipient + + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + SignVerifyMessageDialog + + + Signatures - Sign / Verify a Message + + + + + + &Sign Message + + + + + You can sign messages with your addresses to prove you own them. Be careful not to sign anything vague, as phishing attacks may try to trick you into signing your identity over to them. Only sign fully-detailed statements you agree to. + + + + + The address to sign the message with (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + + Choose an address from the address book + + + + + + Alt+A + + + + + Paste address from clipboard + + + + + Alt+P + + + + + Enter the message you want to sign here + + + + + Copy the current signature to the system clipboard + + + + + Sign the message to prove you own this Arepacoin address + + + + + Reset all sign message fields + + + + + + Clear &All + + + + + + &Verify Message + + + + + Enter the signing address, message (ensure you copy line breaks, spaces, tabs, etc. exactly) and signature below to verify the message. Be careful not to read more into the signature than what is in the signed message itself, to avoid being tricked by a man-in-the-middle attack. + + + + + The address the message was signed with (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Verify the message to ensure it was signed with the specified Arepacoin address + + + + + Reset all verify message fields + + + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Click "Sign Message" to generate signature + + + + + Enter Arepacoin signature + + + + + + The entered address is invalid. + + + + + + + + Please check the address and try again. + + + + + + The entered address does not refer to a key. + + + + + Wallet unlock was cancelled. + + + + + Private key for the entered address is not available. + + + + + Message signing failed. + + + + + Message signed. + + + + + The signature could not be decoded. + + + + + + Please check the signature and try again. + + + + + The signature did not match the message digest. + + + + + Message verification failed. + + + + + Message verified. + + + + + TransactionDesc + + + Open until %1 + + + + + Open for %n block(s) + + + + + conflicted + + + + + %1/offline + + + + + %1/unconfirmed + + + + + %1 confirmations + + + + + Status + + + + + , broadcast through %n node(s) + + + + + Date + + + + + Source + + + + + Generated + + + + + + From + + + + + + + To + + + + + + own address + + + + + label + + + + + + + + + Credit + + + + + matures in %n more block(s) + + + + + not accepted + + + + + + + + Debit + + + + + Transaction fee + + + + + Net amount + + + + + Message + + + + + Comment + + + + + Transaction ID + + + + + Generated coins must mature 6 blocks before they can be spent. When you generated this block, it was broadcast to the network to be added to the block chain. If it fails to get into the chain, its state will change to "not accepted" and it won't be spendable. This may occasionally happen if another node generates a block within a few seconds of yours. + + + + + Debug information + + + + + Transaction + + + + + Inputs + + + + + Amount + + + + + true + + + + + false + + + + + , has not been successfully broadcast yet + + + + + unknown + + + + + TransactionDescDialog + + + Transaction details + + + + + This pane shows a detailed description of the transaction + + + + + TransactionTableModel + + + Date + + + + + Type + + + + + Address + ที่อยู่ + + + + Amount + + + + + Open until %1 + + + + + Confirmed (%1 confirmations) + + + + + Open for %n more block(s) + + + + + Offline + + + + + Unconfirmed + + + + + Confirming (%1 of %2 recommended confirmations) + + + + + Conflicted + + + + + Immature (%1 confirmations, will be available after %2) + + + + + This block was not received by any other nodes and will probably not be accepted! + + + + + Generated but not accepted + + + + + Received with + + + + + Received from + + + + + Sent to + + + + + Payment to yourself + + + + + Mined + + + + + (n/a) + + + + + Transaction status. Hover over this field to show number of confirmations. + + + + + Date and time that the transaction was received. + + + + + Type of transaction. + + + + + Destination address of transaction. + + + + + Amount removed from or added to balance. + + + + + TransactionView + + + + All + + + + + Today + วันนี้ + + + + This week + + + + + This month + + + + + Last month + + + + + This year + + + + + Range... + + + + + Received with + + + + + Sent to + + + + + To yourself + + + + + Mined + + + + + Other + + + + + Enter address or label to search + + + + + Min amount + + + + + Copy address + + + + + Copy label + + + + + Copy amount + + + + + Copy transaction ID + + + + + Edit label + + + + + Show transaction details + + + + + Export Transaction Data + + + + + Comma separated file (*.csv) + + + + + Confirmed + + + + + Date + + + + + Type + + + + + Label + ชื่อ + + + + Address + ที่อยู่ + + + + Amount + + + + + ID + + + + + Error exporting + + + + + Could not write to file %1. + + + + + Range: + + + + + to + + + + + WalletModel + + + Sending... + + + + + bitcoin-core + + + Arepacoin version + + + + + Usage: + + + + + Send command to -server or arepacoind + + + + + List commands + + + + + Get help for a command + + + + + Options: + + + + + Specify configuration file (default: arepacoin.conf) + + + + + Specify pid file (default: arepacoind.pid) + + + + + Specify wallet file (within data directory) + + + + + Specify data directory + + + + + Set database cache size in megabytes (default: 25) + + + + + Set database disk log size in megabytes (default: 100) + + + + + Listen for connections on <port> (default: 9853 or testnet: 19853) + + + + + Maintain at most <n> connections to peers (default: 125) + + + + + Connect to a node to retrieve peer addresses, and disconnect + + + + + Specify your own public address + + + + + Bind to given address. Use [host]:port notation for IPv6 + + + + + Stake your coins to support network and gain reward (default: 1) + + + + + Threshold for disconnecting misbehaving peers (default: 100) + + + + + Number of seconds to keep misbehaving peers from reconnecting (default: 86400) + + + + + An error occurred while setting up the RPC port %u for listening on IPv4: %s + + + + + Detach block and address databases. Increases shutdown time (default: 0) + + + + + 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. + + + + + Error: This transaction requires a transaction fee of at least %s because of its amount, complexity, or use of recently received funds + + + + + Listen for JSON-RPC connections on <port> (default: 9852 or testnet: 19852) + + + + + Accept command line and JSON-RPC commands + + + + + Error: Transaction creation failed + + + + + Error: Wallet locked, unable to create transaction + + + + + Importing blockchain data file. + + + + + Importing bootstrap blockchain data file. + + + + + Run in the background as a daemon and accept commands + + + + + Use the test network + + + + + Accept connections from outside (default: 1 if no -proxy or -connect) + + + + + An error occurred while setting up the RPC port %u for listening on IPv6, falling back to IPv4: %s + + + + + Error initializing database environment %s! To recover, BACKUP THAT DIRECTORY, then remove everything from it except for wallet.dat. + + + + + Set maximum size of high-priority/low-fee transactions in bytes (default: 27000) + + + + + Warning: -paytxfee is set very high! This is the transaction fee you will pay if you send a transaction. + + + + + Warning: Please check that your computer's date and time are correct! If your clock is wrong Arepacoin will not work properly. + + + + + Warning: error reading wallet.dat! All keys read correctly, but transaction data or address book entries might be missing or incorrect. + + + + + Warning: wallet.dat corrupt, data salvaged! Original wallet.dat saved as wallet.{timestamp}.bak in %s; if your balance or transactions are incorrect you should restore from a backup. + + + + + Attempt to recover private keys from a corrupt wallet.dat + + + + + Block creation options: + + + + + Connect only to the specified node(s) + + + + + Discover own IP address (default: 1 when listening and no -externalip) + + + + + Failed to listen on any port. Use -listen=0 if you want this. + + + + + Find peers using DNS lookup (default: 1) + + + + + Sync checkpoints policy (default: strict) + + + + + Invalid -tor address: '%s' + + + + + Invalid amount for -reservebalance=<amount> + + + + + Maximum per-connection receive buffer, <n>*1000 bytes (default: 5000) + + + + + Maximum per-connection send buffer, <n>*1000 bytes (default: 1000) + + + + + Only connect to nodes in network <net> (IPv4, IPv6 or Tor) + + + + + Output extra debugging information. Implies all other -debug* options + + + + + Output extra network debugging information + + + + + Prepend debug output with timestamp + + + + + SSL options: (see the Bitcoin Wiki for SSL setup instructions) + + + + + Select the version of socks proxy to use (4-5, default: 5) + + + + + Send trace/debug info to console instead of debug.log file + + + + + Send trace/debug info to debugger + + + + + Set maximum block size in bytes (default: 250000) + + + + + Set minimum block size in bytes (default: 0) + + + + + Shrink debug.log file on client startup (default: 1 when no -debug) + + + + + Specify connection timeout in milliseconds (default: 5000) + + + + + Unable to sign checkpoint, wrong checkpointkey? + + + + + + Use UPnP to map the listening port (default: 0) + + + + + Use UPnP to map the listening port (default: 1 when listening) + + + + + Use proxy to reach tor hidden services (default: same as -proxy) + + + + + Username for JSON-RPC connections + + + + + Verifying database integrity... + + + + + WARNING: syncronized checkpoint violation detected, but skipped! + + + + + Warning: Disk space is low! + + + + + Warning: This version is obsolete, upgrade required! + + + + + wallet.dat corrupt, salvage failed + + + + + Password for JSON-RPC connections + + + + + %s, you must set a rpcpassword in the configuration file: + %s +It is recommended you use the following random password: +rpcuser=arepacoinrpc +rpcpassword=%s +(you do not need to remember this password) +The username and password MUST NOT be the same. +If the file does not exist, create it with owner-readable-only file permissions. +It is also recommended to set alertnotify so you are notified of problems; +for example: alertnotify=echo %%s | mail -s "Arepacoin Alert" admin@foo.com + + + + + + Find peers using internet relay chat (default: 0) + + + + + Sync time with other nodes. Disable if time on your system is precise e.g. syncing with NTP (default: 1) + + + + + When creating transactions, ignore inputs with value less than this (default: 0.01) + + + + + Allow JSON-RPC connections from specified IP address + + + + + Send commands to node running on <ip> (default: 127.0.0.1) + + + + + Execute command when the best block changes (%s in cmd is replaced by block hash) + + + + + Execute command when a wallet transaction changes (%s in cmd is replaced by TxID) + + + + + Require a confirmations for change (default: 0) + + + + + Enforce transaction scripts to use canonical PUSH operators (default: 1) + + + + + Execute command when a relevant alert is received (%s in cmd is replaced by message) + + + + + Upgrade wallet to latest format + + + + + Set key pool size to <n> (default: 100) + + + + + Rescan the block chain for missing wallet transactions + + + + + How many blocks to check at startup (default: 2500, 0 = all) + + + + + How thorough the block verification is (0-6, default: 1) + + + + + Imports blocks from external blk000?.dat file + + + + + Use OpenSSL (https) for JSON-RPC connections + + + + + Server certificate file (default: server.cert) + + + + + Server private key (default: server.pem) + + + + + Acceptable ciphers (default: TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH) + + + + + Error: Wallet unlocked for staking only, unable to create transaction. + + + + + WARNING: Invalid checkpoint found! Displayed transactions may not be correct! You may need to upgrade, or notify developers. + + + + + This help message + + + + + Wallet %s resides outside data directory %s. + + + + + Cannot obtain a lock on data directory %s. Arepacoin is probably already running. + + + + + Arepacoin + + + + + Unable to bind to %s on this computer (bind returned error %d, %s) + + + + + Connect through socks proxy + + + + + Allow DNS lookups for -addnode, -seednode and -connect + + + + + Loading addresses... + + + + + Error loading blkindex.dat + + + + + Error loading wallet.dat: Wallet corrupted + + + + + Error loading wallet.dat: Wallet requires newer version of Arepacoin + + + + + Wallet needed to be rewritten: restart Arepacoin to complete + + + + + Error loading wallet.dat + + + + + Invalid -proxy address: '%s' + + + + + Unknown network specified in -onlynet: '%s' + + + + + Unknown -socks proxy version requested: %i + + + + + Cannot resolve -bind address: '%s' + + + + + Cannot resolve -externalip address: '%s' + + + + + Invalid amount for -paytxfee=<amount>: '%s' + + + + + Error: could not start node + + + + + Sending... + + + + + Invalid amount + + + + + Insufficient funds + + + + + Loading block index... + + + + + Add a node to connect to and attempt to keep the connection open + + + + + Unable to bind to %s on this computer. Arepacoin is probably already running. + + + + + Fee per KB to add to transactions you send + + + + + Invalid amount for -mininput=<amount>: '%s' + + + + + Loading wallet... + + + + + Cannot downgrade wallet + + + + + Cannot initialize keypool + + + + + Cannot write default address + + + + + Rescanning... + + + + + Done loading + + + + + To use the %s option + + + + + Error + + + + + You must set rpcpassword=<password> in the configuration file: +%s +If the file does not exist, create it with owner-readable-only file permissions. + + + + \ No newline at end of file diff --git a/src/qt/locale/bitcoin_tr.ts b/src/qt/locale/bitcoin_tr.ts new file mode 100755 index 0000000..c6c7694 --- /dev/null +++ b/src/qt/locale/bitcoin_tr.ts @@ -0,0 +1,3311 @@ + + + AboutDialog + + + About Arepacoin + Arepacoin Hakkında + + + + <b>Arepacoin</b> version + <b>Arepacoin</b> versiyonu + + + + Copyright © 2009-2014 The Bitcoin developers +Copyright © 2012-2014 The NovaCoin developers +Copyright © 2014 The Arepacoin developers + + + + + +This is experimental software. + +Distributed under the MIT/X11 software license, see the accompanying file COPYING or http://www.opensource.org/licenses/mit-license.php. + +This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit (http://www.openssl.org/) and cryptographic software written by Eric Young (eay@cryptsoft.com) and UPnP software written by Thomas Bernard. + + Bu, deneysel bir yazılımdır. + + MIT/X11 yazılım lisansı kapsamında yayınlanmıştır, beraberindeki COPYING dosyasına ya da http://www.opensource.org/licenses/mit-license.php sayfasına bakınız. + + Bu ürün, OpenSSL Araç Takımı'nda (http://www.openssl.org/) kullanılmak üzere OpenSSL projesi tarafından geliştirilen yazılımı, Eric Young (eay@cryptsoft.com) tarafından hazırlanmış kriptografik yazılımı ve Thomas Bernard tarafından yazılmış UPnP yazılımı içerir. + + + + AddressBookPage + + + Address Book + Adres Defteri + + + + Double-click to edit address or label + Adresi ya da etiketi düzenlemek için çift tıklayınız + + + + Create a new address + Yeni bir adres oluştur + + + + Copy the currently selected address to the system clipboard + Seçili adresi sistem panosuna kopyala + + + + &New Address + &Yeni Adres + + + + These are your Arepacoin addresses for receiving payments. You may want to give a different one to each sender so you can keep track of who is paying you. + Bunlar, ödeme almak için Arepacoin adreslerinizdir. Her bir göndericiye farklı birini verebilir, böylece size kimin ödeme yaptığını takip edebilirsiniz. + + + + &Copy Address + Adresi &Kopyala + + + + Show &QR Code + &QR Kodunu Göster + + + + Sign a message to prove you own a Arepacoin address + Bir Arepacoin adresine sahip olduğunu ispatlamak için bir mesaj imzala + + + + Sign &Message + &Mesaj İmzala + + + + Delete the currently selected address from the list + Seçili adresi listeden sil + + + + Verify a message to ensure it was signed with a specified Arepacoin address + Mesajın, belirli bir Arepacoin adresiyle imzalandığından emin olmak için onu doğrula + + + + &Verify Message + Mesajı &Doğrula + + + + &Delete + &Sil + + + + Copy &Label + &Etiketi Kopyala + + + + &Edit + &Düzenle + + + + Export Address Book Data + Adres Defteri Verisini Dışarı Aktar + + + + Comma separated file (*.csv) + Virgülle ayrılmış değerler dosyası (*.csv) + + + + Error exporting + Dışarı aktarım hatası + + + + Could not write to file %1. + %1 dosyasına yazılamadı. + + + + AddressTableModel + + + Label + Etiket + + + + Address + Adres + + + + (no label) + (boş etiket) + + + + AskPassphraseDialog + + + Passphrase Dialog + Parola Diyaloğu + + + + Enter passphrase + Parolayı giriniz + + + + New passphrase + Yeni parola + + + + Repeat new passphrase + Yeni parolayı tekrarlayınız + + + + Serves to disable the trivial sendmoney when OS account compromised. Provides no real security. + OS hesabı tehlike girdiğinde önemsiz para gönderme özelliğini devre dışı bırakmayı sağlar. Gerçek anlamda bir güvenlik sağlamaz. + + + + For staking only + Sadece pay almak için + + + + Enter the new passphrase to the wallet.<br/>Please use a passphrase of <b>10 or more random characters</b>, or <b>eight or more words</b>. + Cüzdanınız için yeni parolayı giriniz.<br/>Lütfen <b>10 ya da daha fazla rastgele karakter</b> veya <b>sekiz ya da daha fazla kelime</b> içeren bir parola seçiniz. + + + + Encrypt wallet + Cüzdanı şifrele + + + + This operation needs your wallet passphrase to unlock the wallet. + Bu işlem cüzdan kilidini açmak için cüzdan parolanızı gerektirir. + + + + Unlock wallet + Cüzdan kilidini aç + + + + This operation needs your wallet passphrase to decrypt the wallet. + Bu işlem, cüzdan şifresini açmak için cüzdan parolasını gerektirir. + + + + Decrypt wallet + Cüzdan şifresini aç + + + + Change passphrase + Parolayı değiştir + + + + Enter the old and new passphrase to the wallet. + Cüzdan için eski ve yeni parolaları giriniz. + + + + Confirm wallet encryption + Cüzdan şifrelenmesini teyit eder + + + + Warning: If you encrypt your wallet and lose your passphrase, you will <b>LOSE ALL OF YOUR COINS</b>! + Uyarı: Eğer cüzdanınızı şifreleyip parolanızı kaybederseniz, <b> TÜM COINLERİNİZİ KAYBEDECEKSİNİZ</b>! + + + + Are you sure you wish to encrypt your wallet? + Cüzdanınızı şifrelemek istediğinizden emin misiniz? + + + + IMPORTANT: Any previous backups you have made of your wallet file should be replaced with the newly generated, encrypted wallet file. For security reasons, previous backups of the unencrypted wallet file will become useless as soon as you start using the new, encrypted wallet. + ÖNEMLİ: Önceden yapmış olduğunuz cüzdan dosyası yedeklemelerinin yeni oluşturulan, şifrelenmiş cüzdan dosyası ile değiştirilmeleri gerekmektedir. Güvenlik nedenleriyle yeni, şifrelenmiş cüzdanı kullanmaya başladığınızda, şifrelenmemiş cüzdan dosyasının önceki yedekleri işe yaramaz hale gelecektir. + + + + + Warning: The Caps Lock key is on! + Uyarı: Caps Lock tuşu faal durumda! + + + + + Wallet encrypted + Cüzdan şifrelendi + + + + Arepacoin will close now to finish the encryption process. Remember that encrypting your wallet cannot fully protect your coins from being stolen by malware infecting your computer. + Arepacoin, şifreleme işlemini tamamlamak için şimdi kapatılacak. Cüzdanınızı şifrelemenin; coinlerinizin, bilgisayarınızı etkileyen zararlı yazılımlar tarafından çalınmasını bütünüyle engelleyemeyebileceğini unutmayınız. + + + + + + + Wallet encryption failed + Cüzdan şifrelemesi başarısız oldu + + + + Wallet encryption failed due to an internal error. Your wallet was not encrypted. + Dahili bir hata sebebiyle cüzdan şifrelemesi başarısız oldu. Cüzdanınız şifrelenmedi. + + + + + The supplied passphrases do not match. + Girilen parolalar birbirleriyle eşleşmiyor. + + + + Wallet unlock failed + Cüzdan kilidinin açılması başarısız oldu + + + + + + The passphrase entered for the wallet decryption was incorrect. + Cüzdan şifresinin açılması için girilen parola yanlıştı. + + + + Wallet decryption failed + Cüzdan şifresinin açılması başarısız oldu + + + + Wallet passphrase was successfully changed. + Cüzdan parolası başarılı bir şekilde değiştirildi. + + + + BitcoinGUI + + + Sign &message... + &Mesaj imzala... + + + + Synchronizing with network... + Ağ ile senkronizasyon... + + + + &Overview + &Genel bakış + + + + Show general overview of wallet + Cüzdana genel bakışı göster + + + + &Transactions + &İşlemler + + + + Browse transaction history + İşlem geçmişine göz at + + + + &Address Book + &Adres Defteri + + + + Edit the list of stored addresses and labels + Kayıtlı adresler ve etiketler listesini düzenle + + + + &Receive coins + Coin &al + + + + Show the list of addresses for receiving payments + Ödeme almak için kullanılan adres listesini göster + + + + &Send coins + Coin &gönder + + + + E&xit + &Çık + + + + Quit application + Uygulamadan çık + + + + Show information about Arepacoin + Arepacoin hakkındaki bilgiyi göster + + + + About &Qt + &Qt hakkında + + + + Show information about Qt + Qt hakkındaki bilgiyi göster + + + + &Options... + &Seçenekler... + + + + &Encrypt Wallet... + Cüzdanı &Şifrele... + + + + &Backup Wallet... + Cüzdanı &Yedekle... + + + + &Change Passphrase... + Parolayı &Değiştir... + + + + ~%n block(s) remaining + ~%n blok kaldı~%n blok kaldı + + + + Downloaded %1 of %2 blocks of transaction history (%3% done). + İşlem geçmişindeki %2 bloğun %1'i indirildi (%3% tamamlandı). + + + + &Export... + &Dışarı aktar... + + + + Send coins to a Arepacoin address + Bir Arepacoin adresine coin gönder + + + + Modify configuration options for Arepacoin + Arepacoin yapılandırma seçeneklerini değiştir + + + + Export the data in the current tab to a file + Mevcut sekmedeki veriyi bir dosyaya aktar + + + + Encrypt or decrypt wallet + Cüzdanı şifrele veya cüzdanın şifresini aç + + + + Backup wallet to another location + Cüzdanı başka bir konuma yedekle + + + + Change the passphrase used for wallet encryption + Cüzdan şifrelemesi için kullanılan parolayı değiştir + + + + &Debug window + &Hata ayıklama penceresi + + + + Open debugging and diagnostic console + Hata ayıklama ve teşhis penceresini aç + + + + &Verify message... + Mesajı &doğrula... + + + + Arepacoin + Arepacoin + + + + Wallet + Cüzdan + + + + &About Arepacoin + Arepacoin &Hakkında + + + + &Show / Hide + &Göster / Gizle + + + + Unlock wallet + Cüzdanın kilidini aç + + + + &Lock Wallet + Cüzdanı &Kilitle + + + + Lock wallet + Cüzdanı kilitle + + + + &File + &Dosya + + + + &Settings + &Ayarlar + + + + &Help + &Yardım + + + + Tabs toolbar + Sekme araç çubuğu + + + + Actions toolbar + Eylem araç çubuğu + + + + + [testnet] + [testnet] + + + + + Arepacoin client + Arepacoin istemcisi + + + + %n active connection(s) to Arepacoin network + Arepacoin ağına %n etkin bağlantıArepacoin ağına %n etkin bağlantı + + + + Downloaded %1 blocks of transaction history. + İşlem geçmişinin %1 bloğu indirildi. + + + + Staking.<br>Your weight is %1<br>Network weight is %2<br>Expected time to earn reward is %3 + Pay alınıyor.<br>Sizin ağırlığınız %1<br>Ağın ağırlığı %2<br>Ödül almak için tahmini süre %3 + + + + Not staking because wallet is locked + Pay alınmıyor çünkü cüzdan kilitlidir + + + + Not staking because wallet is offline + Pay alınmıyor çünkü cüzdan çevrimdışıdır + + + + Not staking because wallet is syncing + Pay alınmıyor çünkü cüzdan senkronize ediliyor + + + + Not staking because you don't have mature coins + Pay alınmıyor çünkü olgunlaşmış coininiz yoktur + + + + %n second(s) ago + %n saniye önce%n saniye önce + + + + &Unlock Wallet... + Cüzdanı &Kilitle... + + + + %n minute(s) ago + %n dakika önce%n dakika önce + + + + %n hour(s) ago + %n saat önce%n saat önce + + + + %n day(s) ago + %n gün önce%n gün önce + + + + Up to date + Güncel + + + + Catching up... + Aralık kapatılıyor... + + + + Last received block was generated %1. + Son alınan blok, üretildi %1. + + + + This transaction is over the size limit. You can still send it for a fee of %1, which goes to the nodes that process your transaction and helps to support the network. Do you want to pay the fee? + Bu işlem, büyüklük sınırının üzerindedir. İşleminizi gerçekleştirecek devrelere gidecek ve ağı desteklemeye yardımcı olacak %1 ücretle coin gönderebilirsiniz. Ücreti ödemek istiyor musunuz? + + + + Confirm transaction fee + İşlem ücretini onayla + + + + Sent transaction + İşlem gerçekleştirildi + + + + Incoming transaction + Gelen işlem + + + + Date: %1 +Amount: %2 +Type: %3 +Address: %4 + + Tarih: %1 +Miktar: %2 +Tür: %3 +Adres: %4 + + + + + + URI handling + URI işleme + + + + + URI can not be parsed! This can be caused by an invalid Arepacoin address or malformed URI parameters. + URI ayrıştırılamadı! Bu, geçersiz bir Arepacoin adresi veya hatalı URI parametreleri nedeniyle olabilir. + + + + Wallet is <b>encrypted</b> and currently <b>unlocked</b> + Cüzdan <b>şifrelenmiştir</b> ve şu anda <b>kilidi açıktır</b> + + + + Wallet is <b>encrypted</b> and currently <b>locked</b> + Cüzdan <b>şifrelenmiştir</b> ve şu anda <b>kilitlidir</b> + + + + Backup Wallet + Cüzdanı Yedekle + + + + Wallet Data (*.dat) + Cüzdan Verisi (*.dat) + + + + Backup Failed + Yedekleme Başarısız Oldu + + + + There was an error trying to save the wallet data to the new location. + Cüzdan verisi, yeni bir konuma kaydedilmeye çalışılırken bir hata oluştu. + + + + %n second(s) + %n saniye%n saniye + + + + %n minute(s) + %n dakika%n dakika + + + + %n hour(s) + %n saat%n saat + + + + %n day(s) + %n gün%n gün + + + + Not staking + Pay alınmıyor + + + + A fatal error occurred. Arepacoin can no longer continue safely and will quit. + Önemli bir hata oluştu. Arepacoin artık güvenli bir şekilde devam edemez ve şimdi kapatılacak. + + + + ClientModel + + + Network Alert + Ağ Uyarısı + + + + CoinControlDialog + + + Coin Control + Coin Kontrolü + + + + Quantity: + Adet: + + + + Bytes: + Bayt: + + + + Amount: + Miktar: + + + + Priority: + Öncelik: + + + + Fee: + Ücret: + + + + Low Output: + Düşük Çıktı: + + + + no + hayır + + + + After Fee: + Ücretten sonra: + + + + Change: + Para üstü: + + + + (un)select all + tümünü seç(me) + + + + Tree mode + Ağaç kipi + + + + List mode + Liste kipi + + + + Amount + Miktar + + + + Label + Etiket + + + + Address + Adres + + + + Date + Tarih + + + + Confirmations + Onaylar + + + + Confirmed + Onaylandı + + + + Priority + Öncelik + + + + Copy address + Adresi kopyala + + + + Copy label + Etiketi kopyala + + + + + Copy amount + Miktarı kopyala + + + + Copy transaction ID + İşlem Numarasını Kopyala + + + + Copy quantity + Adedi kopyala + + + + Copy fee + Ücreti kopyala + + + + Copy after fee + Ücretten sonrakini kopyala + + + + Copy bytes + Baytları kopyala + + + + Copy priority + Önceliği kopyala + + + + Copy low output + Düşük çıktıyı kopyala + + + + Copy change + Para üstünü kopyala + + + + highest + en yüksek + + + + high + yüksek + + + + medium-high + orta-yüksek + + + + medium + orta + + + + low-medium + düşük-orta + + + + low + düşük + + + + lowest + en düşük + + + + DUST + BOZUKLUK + + + + yes + evet + + + + This label turns red, if the transaction size is bigger than 10000 bytes. + + This means a fee of at least %1 per kb is required. + + Can vary +/- 1 Byte per input. + İşlem büyüklüğü 10000 bayttan büyükse, bu etiket kırmızıya dönüşür. + + Bu, kb başına en az %1 ücret gerektiği anlamına gelir. + + Girdi başına +/- 1 Byte değişkenlik gösterebilir. + + + + Transactions with higher priority get more likely into a block. + +This label turns red, if the priority is smaller than "medium". + + This means a fee of at least %1 per kb is required. + Yüksek öncelikli işlemler, daha yüksek ihtimalle bir bloğa düşer. + +Öncelik "orta" seviyeden düşükse, bu etiket kırmızıya döner. + + Bu, kb başına en az %1 ücret gerektiği anlamına gelir. + + + + This label turns red, if any recipient receives an amount smaller than %1. + + This means a fee of at least %2 is required. + + Amounts below 0.546 times the minimum relay fee are shown as DUST. + Eğer herhangi bir alıcı, %1'den daha küçük bir miktar alırsa, bu etiket kırmızıya dönüşür. + + Bu, en az %2 bir ücretin gerektiği anlamına gelir. + + Minimum aktarım ücretinin 0.546 katından düşük miktarlar, BOZUKLUK olarak gösterilir. + + + + This label turns red, if the change is smaller than %1. + + This means a fee of at least %2 is required. + Eğer para üstü %1'den küçükse, bu etiket kırmızıya dönüşür. + + Bu, en az %2 bir ücretin gerektiği anlamına gelir. + + + + + (no label) + (boş etiket) + + + + change from %1 (%2) + %1 unsurundan para üstü (%2) + + + + (change) + (para üstü) + + + + EditAddressDialog + + + Edit Address + Adresi düzenle + + + + &Label + &Etiket + + + + The label associated with this address book entry + Bu adres defteri kaydıyla ilişkili etiket + + + + &Address + &Adres + + + + The address associated with this address book entry. This can only be modified for sending addresses. + Bu adres defteri kaydıyla ilişkili etiket. Bu, sadece gönderi adresleri için değiştirilebilir. + + + + New receiving address + Yeni alım adresi + + + + New sending address + Yeni gönderi adresi + + + + Edit receiving address + Alım adresini düzenle + + + + Edit sending address + Gönderi adresini düzenle + + + + The entered address "%1" is already in the address book. + Girilen "%1" adresi hâlihazırda adres defterinde mevcuttur. + + + + The entered address "%1" is not a valid Arepacoin address. + Girilen %1 adresi, geçerli bir Arepacoin adresi değildir. + + + + Could not unlock wallet. + Cüzdan kilidi açılamadı. + + + + New key generation failed. + Yeni anahtar oluşturulması başarısız oldu. + + + + GUIUtil::HelpMessageBox + + + + Arepacoin-Qt + Arepacoin-Qt + + + + version + versiyon + + + + Usage: + Kullanım: + + + + command-line options + komut satırı seçenekleri + + + + UI options + GA seçenekleri + + + + Set language, for example "de_DE" (default: system locale) + Dili ayarla, örneğin "de_DE" (varsayılan: sistem yerel ayarları) + + + + Start minimized + Simge durumunda başlat + + + + Show splash screen on startup (default: 1) + Başlangıçta açılış ekranını göster (varsayılan: 1) + + + + OptionsDialog + + + Options + Seçenekler + + + + &Main + &Esas ayarlar + + + + Optional transaction fee per kB that helps make sure your transactions are processed quickly. Most transactions are 1 kB. Fee 0.01 recommended. + İşlemlerinizin hızlıca gerçekleştirilmesini sağlayan kB başına opsiyonel işlem ücreti. Birçok işlem 1 kB'tır. Tavsiye edilen ücret 0.01'dir. + + + + Pay transaction &fee + Muamele ücreti &öde + + + + Reserved amount does not participate in staking and is therefore spendable at any time. + Ayrılan miktar, pay almaya katılamıyor ve bu yüzden herhangi bir anda harcanabilir. + + + + Reserve + Ayrılan + + + + Automatically start Arepacoin after logging in to the system. + Sisteme giriş yaptıktan sonra Arepacoin'i otomatik olarak başlat + + + + &Start Arepacoin on system login + Sisteme girişte Arepacoin'i &başlat + + + + Detach block and address databases at shutdown. This means they can be moved to another data directory, but it slows down shutdown. The wallet is always detached. + Kapanışta blok ve adres veritabanlarını birbirinden ayır. Bu, onların başka bir veri klasörüne taşınabileceği anlamına gelir ancak bu işlem kapanışı yavaşlatır. Cüzdan ise her zaman ayrılmıştır. + + + + &Detach databases at shutdown + Kapanışta veritabanlarını &ayır + + + + &Network + &Şebeke + + + + Automatically open the Arepacoin client port on the router. This only works when your router supports UPnP and it is enabled. + Yönelticide Arepacoin istemci portunu otomatik olarak aç. Bu, sadece yönelticiniz UPnP'i desteklediğinde ve etkin olduğunda çalışır. + + + + Map port using &UPnP + Portları &UPnP kullanarak haritala + + + + Connect to the Arepacoin network through a SOCKS proxy (e.g. when connecting through Tor). + Arepacoin ağına bir SOCKS vekil sunucusu yoluyla bağlan (örn. Tor yoluyla bağlanıldığında) + + + + &Connect through SOCKS proxy: + SOCKS vekil sunucusu yoluyla &bağlan: + + + + Proxy &IP: + Vekil &İP: + + + + IP address of the proxy (e.g. 127.0.0.1) + Vekil sunucunun IP adresi (örn. 127.0.0.1) + + + + &Port: + &Port: + + + + Port of the proxy (e.g. 9050) + Vekil sunucunun portu (mesela 9050) + + + + SOCKS &Version: + SOCKS &sürümü: + + + + SOCKS version of the proxy (e.g. 5) + Vekil sunucunun SOCKS sürümü (mesela 5) + + + + &Window + &Pencere + + + + Show only a tray icon after minimizing the window. + Küçültüldükten sonra sadece çekmece ikonu göster. + + + + &Minimize to the tray instead of the taskbar + İşlem çubuğu yerine sistem çekmecesine &küçült + + + + Minimize instead of exit the application when the window is closed. When this option is enabled, the application will be closed only after selecting Quit in the menu. + Pencere kapatıldığında uygulamadan çıkmak yerine uygulamayı küçültür. Bu seçenek etkinleştirildiğinde, uygulama sadece menüden çıkış seçildiğinde kapanacaktır. + + + + M&inimize on close + Kapatma sırasında k&üçült + + + + &Display + &Görünüm + + + + User Interface &language: + Kullanıcı arayüzü &lisanı: + + + + The user interface language can be set here. This setting will take effect after restarting Arepacoin. + Kullanıcı arabirimi dili buradan ayarlanabilir. Ayar, Arepacoin yeniden başlatıldığında etkin olacaktır. + + + + &Unit to show amounts in: + Meblağları göstermek için &birim: + + + + Choose the default subdivision unit to show in the interface and when sending coins. + Bitcoin gönderildiğinde arayüzde gösterilecek varsayılan alt birimi seçiniz. + + + + Whether to show Arepacoin addresses in the transaction list or not. + Arepacoin adresinin işlem listesinde gösterilmesi veya gösterilmemesi + + + + &Display addresses in transaction list + Muamele listesinde adresleri &göster + + + + Whether to show coin control features or not. + Para kontrol özelliklerinin gösterilip gösterilmeyeceğini ayarlar. + + + + Display coin &control features (experts only!) + Coin &kontrol özelliklerini göster (sadece uzman kişiler!) + + + + &OK + &Tamam + + + + &Cancel + &İptal + + + + &Apply + &Uygula + + + + default + varsayılan + + + + + Warning + Uyarı + + + + + This setting will take effect after restarting Arepacoin. + Bu ayar, Arepacoin'i yeniden başlattıktan sonra etkin olacaktır. + + + + The supplied proxy address is invalid. + Girilen vekil sunucu adresi geçersizdir. + + + + OverviewPage + + + Form + Form + + + + + The displayed information may be out of date. Your wallet automatically synchronizes with the Arepacoin network after a connection is established, but this process has not completed yet. + Görüntülenen bilginin tarihi geçmiş olabilir. Cüzdanınız, bağlantı kurulduktan sonra otomatik olarak Arepacoin ağı ile senkronize olur ancak bu süreç, henüz tamamlanmamıştır. + + + + Stake: + Pay: + + + + Unconfirmed: + Doğrulanmamış: + + + + Wallet + Cüzdan + + + + Spendable: + Harcanabilir: + + + + Your current spendable balance + Güncel harcanabilir bakiyeniz + + + + Immature: + Olgunlaşmamış: + + + + Mined balance that has not yet matured + Oluşturulan bakiye henüz olgunlaşmamıştır + + + + Total: + Toplam: + + + + Your current total balance + Güncel toplam bakiyeniz + + + + <b>Recent transactions</b> + <b>Son muameleler</b> + + + + Total of transactions that have yet to be confirmed, and do not yet count toward the current balance + Henüz onaylanmamış ve mevcut bakiyede yer almayan işlemler toplamı + + + + Total of coins that was staked, and do not yet count toward the current balance + Pay alınmış ve mevcut bakiyede yer almayan coin toplamı + + + + + out of sync + eşleşme dışı + + + + QRCodeDialog + + + QR Code Dialog + QR Kodu İletisi + + + + Request Payment + Ödeme Talep Et + + + + Amount: + Miktar: + + + + Label: + Etiket: + + + + Message: + Mesaj: + + + + &Save As... + &Farklı Kaydet... + + + + Error encoding URI into QR Code. + URI'nin QR koduna kodlanmasında hata oluştu. + + + + The entered amount is invalid, please check. + Girilen miktar geçersizdir, lütfen kontrol ediniz. + + + + Resulting URI too long, try to reduce the text for label / message. + Sonuç URI'si çok uzundur, etiket / mesaj için olan metni kısaltmaya çalışın. + + + + Save QR Code + QR Kodu'nu Kaydet + + + + PNG Images (*.png) + PNG İmgeleri (*.png) + + + + RPCConsole + + + Client name + İstemci ismi + + + + + + + + + + + + + N/A + Mevcut değil + + + + Client version + İstemci sürümü + + + + &Information + &Malumat + + + + Using OpenSSL version + Kullanılan OpenSSL sürümü + + + + Startup time + Başlama zamanı + + + + Network + Şebeke + + + + Number of connections + Bağlantı sayısı + + + + On testnet + Testnet üzerinde + + + + Block chain + Blok zinciri + + + + Current number of blocks + Güncel blok sayısı + + + + Estimated total blocks + Tahmini toplam blok sayısı + + + + Last block time + Son blok zamanı + + + + &Open + &Aç + + + + Command-line options + Komut satırı seçenekleri + + + + Show the Arepacoin-Qt help message to get a list with possible Arepacoin command-line options. + Muhtemel Arepacoin komut satırı seçeneklerinin bir listesini getirmek için Arepacoin-Qt yardım mesajını göster + + + + &Show + &Göster + + + + &Console + &Konsol + + + + Build date + Derleme tarihi + + + + Arepacoin - Debug window + Arepacoin - Hata ayıklama penceresi + + + + Arepacoin Core + Arepacoin Core + + + + Debug log file + Hata ayıklama kütük dosyası + + + + Open the Arepacoin debug log file from the current data directory. This can take a few seconds for large log files. + Arepacoin hata ayıklama günlük kütüğü dosyasını, mevcut veri klasöründen aç. Bu işlem, büyük günlük kütüğü dosyaları için birkaç saniye sürebilir. + + + + Clear console + Konsolu temizle + + + + Welcome to the Arepacoin RPC console. + Arepacoin RPC konsoluna hoş geldiniz. + + + + Use up and down arrows to navigate history, and <b>Ctrl-L</b> to clear screen. + Tarihçede gezinmek için imleç tuşlarını kullanınız, <b>Ctrl-L</b> ile de ekranı temizleyebilirsiniz. + + + + Type <b>help</b> for an overview of available commands. + Mevcut komutların listesi için <b>help</b> yazınız. + + + + SendCoinsDialog + + + + + + + + + + Send Coins + Bitcoin yolla + + + + Coin Control Features + Para kontrolü özellikleri + + + + Inputs... + Girdiler... + + + + automatically selected + otomatik seçilmiş + + + + Insufficient funds! + Yetersiz fon! + + + + Quantity: + Miktar: + + + + + 0 + 0 + + + + Bytes: + Bayt: + + + + Amount: + Meblağ: + + + + + + + 0.00 BC + 123.456 BC {0.00 ?} + + + + Priority: + Öncelik: + + + + medium + orta + + + + Fee: + Ücret: + + + + Low Output: + Düşük çıktı: + + + + no + hayır + + + + After Fee: + Ücretten sonra: + + + + Change + Değiştir + + + + custom change address + özel adres değişikliği + + + + Send to multiple recipients at once + Birçok alıcıya aynı anda gönder + + + + Add &Recipient + &Alıcı ekle + + + + Remove all transaction fields + Tüm işlem alanlarını kaldır + + + + Clear &All + Tümünü &temizle + + + + Balance: + Bakiye: + + + + 123.456 BC + 123.456 BC + + + + Confirm the send action + Yollama etkinliğini teyit ediniz + + + + S&end + G&önder + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + Bir Arepacoin adresi gir (örn: AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + Copy quantity + Miktarı kopyala + + + + Copy amount + Meblağı kopyala + + + + Copy fee + Ücreti kopyala + + + + Copy after fee + Ücretten sonrakini kopyala + + + + Copy bytes + Baytları kopyala + + + + Copy priority + Önceliği kopyala + + + + Copy low output + Düşük çıktıyı kopyala + + + + Copy change + Para üstünü kopyala + + + + <b>%1</b> to %2 (%3) + <b>%1</b> %2'ye (%3) + + + + Confirm send coins + Gönderiyi teyit ediniz + + + + Are you sure you want to send %1? + %1 göndermek istediğinizden emin misiniz? + + + + and + ve + + + + The recipient address is not valid, please recheck. + Alıcı adresi geçerli değildir, lütfen denetleyiniz. + + + + The amount to pay must be larger than 0. + Ödeyeceğiniz tutarın sıfırdan yüksek olması gerekir. + + + + The amount exceeds your balance. + Tutar bakiyenizden yüksektir. + + + + The total exceeds your balance when the %1 transaction fee is included. + Toplam, %1 muamele ücreti ilâve edildiğinde bakiyenizi geçmektedir. + + + + Duplicate address found, can only send to each address once per send operation. + Çift adres bulundu, belli bir gönderi sırasında her adrese sadece tek bir gönderide bulunulabilir. + + + + Error: Transaction creation failed. + Hata: İşlem yaratma başarısız oldu. + + + + 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. + Hata: İşlem reddedildi. Bu, örneğin wallet.dat dosyasının bir kopyasını kullandıysanız ve coinler, kopyada harcanmış ve burada harcanmış olarak işaretlenmemişse, cüzdanınızdaki coinlerin bir bölümünün harcanması nedeniyle olabilir. + + + + WARNING: Invalid Arepacoin address + UYARI: Geçersiz Arepacoin adresi + + + + (no label) + (boş etiket) + + + + WARNING: unknown change address + UYARI: bilinmeyen adres değişikliği + + + + SendCoinsEntry + + + Form + Form + + + + A&mount: + Mebla&ğ: + + + + Pay &To: + &Şu adrese öde: + + + + + Enter a label for this address to add it to your address book + Adres defterinize eklemek için bu adrese ilişik bir etiket giriniz + + + + &Label: + &Etiket: + + + + The address to send the payment to (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + Ödemenin gönderileceği adres (örn: AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + Choose address from address book + Adres defterinden adres seç + + + + Alt+A + Alt+A + + + + Paste address from clipboard + Panodan adres yapıştır + + + + Alt+P + Alt+P + + + + Remove this recipient + Bu alıcıyı kaldır + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + Bir Arepacoin adresi girin (örn: AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + SignVerifyMessageDialog + + + Signatures - Sign / Verify a Message + İmzalar - Mesaj İmzala / Kontrol et + + + + + &Sign Message + Mesaj &imzala + + + + You can sign messages with your addresses to prove you own them. Be careful not to sign anything vague, as phishing attacks may try to trick you into signing your identity over to them. Only sign fully-detailed statements you agree to. + Bir adresin sizin olduğunu ispatlamak için adresinizle mesaj imzalayabilirsiniz. Oltalama saldırılarının kimliğinizi imzanızla elde etmeyi deneyebilecekleri için belirsiz hiçbir şey imzalamamaya dikkat ediniz. Sadece ayrıntılı açıklaması olan ve tümüne katıldığınız ifadeleri imzalayınız. + + + + The address to sign the message with (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + Mesajın imzalanacağı adres (örn: AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Choose an address from the address book + Adres defterinden adres seç + + + + + Alt+A + Alt+A + + + + Paste address from clipboard + Panodan adres yapıştır + + + + Alt+P + Alt+P + + + + Enter the message you want to sign here + İmzalamak istediğiniz mesajı burada giriniz + + + + Copy the current signature to the system clipboard + Güncel imzayı sistem panosuna kopyala + + + + Sign the message to prove you own this Arepacoin address + Bu Arepacoin adresine sahip olduğunuzu ispatlamak için mesajı imzala + + + + Reset all sign message fields + Tüm mesaj alanlarını sıfırla + + + + + Clear &All + Tümünü &temizle + + + + + &Verify Message + Mesaj &kontrol et + + + + Enter the signing address, message (ensure you copy line breaks, spaces, tabs, etc. exactly) and signature below to verify the message. Be careful not to read more into the signature than what is in the signed message itself, to avoid being tricked by a man-in-the-middle attack. + İmza için kullanılan adresi, mesajı (satır sonları, boşluklar, sekmeler vs. karakterleri tam olarak kopyaladığınızdan emin olunuz) ve imzayı aşağıda giriniz. Bir ortadaki adam saldırısı tarafından kandırılmaya mâni olmak için imzadan, imzalı mesajın içeriğini aşan bir anlam çıkarmamaya dikkat ediniz. + + + + The address the message was signed with (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + Mesajın imzalandığı adres (örn: AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + Verify the message to ensure it was signed with the specified Arepacoin address + Mesajın, belirtilen Arepacoin adresiyle imzalandığından emin olmak için onu doğrula + + + + Reset all verify message fields + Tüm mesaj kontrolü alanlarını sıfırla + + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + Bir Arepacoin adresi girin (örn: AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + Click "Sign Message" to generate signature + İmzayı oluşturmak için "Mesaj İmzala" unsurunu tıklayın + + + + Enter Arepacoin signature + Arepacoin imzası gir + + + + + The entered address is invalid. + Girilen adres geçersizdir. + + + + + + + Please check the address and try again. + Adresi kontrol edip tekrar deneyiniz. + + + + + The entered address does not refer to a key. + Girilen adres herhangi bir anahtara işaret etmemektedir. + + + + Wallet unlock was cancelled. + Cüzdan kilidinin açılması iptal edildi. + + + + Private key for the entered address is not available. + Girilen adres için özel anahtar mevcut değildir. + + + + Message signing failed. + Mesajın imzalanması başarısız oldu. + + + + Message signed. + Mesaj imzalandı. + + + + The signature could not be decoded. + İmzanın kodu çözülemedi. + + + + + Please check the signature and try again. + İmzayı kontrol edip tekrar deneyiniz. + + + + The signature did not match the message digest. + İmza mesajın hash değeri ile eşleşmedi. + + + + Message verification failed. + Mesaj doğrulaması başarısız oldu. + + + + Message verified. + Mesaj doğrulandı. + + + + TransactionDesc + + + Open until %1 + %1 değerine dek açık + + + + Open for %n block(s) + %n blok için aç%n blok için aç + + + + conflicted + çakışma + + + + %1/offline + %1/çevrim dışı + + + + %1/unconfirmed + %1/doğrulanmadı + + + + %1 confirmations + %1 teyit + + + + Status + Durum + + + + , broadcast through %n node(s) + , %n devre üzerinde yayınlama, %n devre üzerinde yayınlama + + + + Date + Tarih + + + + Source + Kaynak + + + + Generated + Oluşturuldu + + + + + From + Gönderen + + + + + + To + Alıcı + + + + + own address + kendi adresiniz + + + + label + etiket + + + + + + + + Credit + Gider + + + + matures in %n more block(s) + %n blok içerisinde olgunlaşıyor%n blok içerisinde olgunlaşıyor + + + + not accepted + kabul edilmedi + + + + + + + Debit + Gelir + + + + Transaction fee + Muamele ücreti + + + + Net amount + Net meblağ + + + + Message + Mesaj + + + + Comment + Yorum + + + + Transaction ID + Muamele tanımlayıcı + + + + Generated coins must mature 6 blocks before they can be spent. When you generated this block, it was broadcast to the network to be added to the block chain. If it fails to get into the chain, its state will change to "not accepted" and it won't be spendable. This may occasionally happen if another node generates a block within a few seconds of yours. + Üretilen coinler, harcanmaya başlamadan önce 6 blokta olgunlaşmalıdır. Bu bloğu ürettiğinizde, blok zincirine eklenmek üzere ağda yayınlanır. Eğer blok, zincire girmede başarısız olursa, bloğun durumu "kabul edilmedi"ye dönüşür ve harcanamaz. Bu, başka bir devre sizden birkaç saniye önce bir blok ürettiyse gerçekleşebilir. + + + + Debug information + Hata ayıklama verileri + + + + Transaction + Muamele + + + + Inputs + Girdiler + + + + Amount + Meblağ + + + + true + doğru + + + + false + yanlış + + + + , has not been successfully broadcast yet + , henüz başarılı bir şekilde yayınlanmadı + + + + unknown + bilinmiyor + + + + TransactionDescDialog + + + Transaction details + Muamele detayları + + + + This pane shows a detailed description of the transaction + Bu pano muamelenin ayrıntılı açıklamasını gösterir + + + + TransactionTableModel + + + Date + Tarih + + + + Type + Tür + + + + Address + Adres + + + + Amount + Meblağ + + + + Open until %1 + %1 değerine dek açık + + + + Confirmed (%1 confirmations) + Doğrulandı (%1 teyit) + + + + Open for %n more block(s) + %n blok için aç%n blok için aç + + + + Offline + Çevrim dışı + + + + Unconfirmed + Teyit edilmemiş + + + + Confirming (%1 of %2 recommended confirmations) + Teyit ediliyor (tavsiye edilen %2 teyit üzerinden %1 doğrulama) + + + + Conflicted + Çakışma + + + + Immature (%1 confirmations, will be available after %2) + Olgunlaşmamış (%1 teyit, %2 teyit ardından kullanılabilir olacaktır) + + + + This block was not received by any other nodes and will probably not be accepted! + Bu blok başka hiçbir düğüm tarafından alınmamıştır ve muhtemelen kabul edilmeyecektir! + + + + Generated but not accepted + Oluşturuldu ama kabul edilmedi + + + + Received with + Şununla alındı + + + + Received from + Alındığı kişi + + + + Sent to + Gönderildiği adres + + + + Payment to yourself + Kendinize ödeme + + + + Mined + Madenden çıkarılan + + + + (n/a) + (mevcut değil) + + + + Transaction status. Hover over this field to show number of confirmations. + Muamele durumu. Doğrulama sayısını görüntülemek için imleci bu alanda tutunuz. + + + + Date and time that the transaction was received. + Muamelenin alındığı tarih ve zaman. + + + + Type of transaction. + Muamele türü. + + + + Destination address of transaction. + Muamelenin alıcı adresi. + + + + Amount removed from or added to balance. + Bakiyeden alınan ya da bakiyeye eklenen meblağ. + + + + TransactionView + + + + All + Hepsi + + + + Today + Bugün + + + + This week + Bu hafta + + + + This month + Bu ay + + + + Last month + Geçen ay + + + + This year + Bu sene + + + + Range... + Aralık... + + + + Received with + Şununla alınan + + + + Sent to + Gönderildiği adres + + + + To yourself + Kendinize + + + + Mined + Oluşturulan + + + + Other + Diğer + + + + Enter address or label to search + Aranacak adres ya da etiket giriniz + + + + Min amount + Asgari meblağ + + + + Copy address + Adresi kopyala + + + + Copy label + Etiketi kopyala + + + + Copy amount + Meblağı kopyala + + + + Copy transaction ID + Muamele kimliğini kopyala + + + + Edit label + Etiketi düzenle + + + + Show transaction details + Muamele detaylarını göster + + + + Export Transaction Data + İşlem Verisini Dışarı Aktar + + + + Comma separated file (*.csv) + Virgülle ayrılmış değerler dosyası (*.csv) + + + + Confirmed + Doğrulandı + + + + Date + Tarih + + + + Type + Tür + + + + Label + Etiket + + + + Address + Adres + + + + Amount + Meblağ + + + + ID + Tanımlayıcı + + + + Error exporting + Dışarı aktarmada hata + + + + Could not write to file %1. + %1 dosyasına yazılamadı. + + + + Range: + Aralık: + + + + to + ilâ + + + + WalletModel + + + Sending... + Gönderiyor... + + + + bitcoin-core + + + Arepacoin version + Arepacoin versiyonu + + + + Usage: + Kullanım: + + + + Send command to -server or arepacoind + -sunucu veya arepacoind'ye komut gönder + + + + List commands + Komutları listele + + + + Get help for a command + Bir komut için yardım al + + + + Options: + Seçenekler: + + + + Specify configuration file (default: arepacoin.conf) + Konfigürasyon dosyasını belirt (varsayılan: arepacoin.conf) + + + + Specify pid file (default: arepacoind.pid) + pid dosyasını belirt (varsayılan: arepacoin.pid) + + + + Specify wallet file (within data directory) + Cüzdan dosyası belirtiniz (veri klasörünün içinde) + + + + Specify data directory + Veri dizinini belirt + + + + Set database cache size in megabytes (default: 25) + Veritabanı önbellek boyutunu megabayt olarak belirt (varsayılan: 25) + + + + Set database disk log size in megabytes (default: 100) + Veritabanı disk log boyutunu megabayt olarak ayarla (varsayılan: 100) + + + + Listen for connections on <port> (default: 9853 or testnet: 19853) + <port> üzerinde bağlantıları dinle (varsayılan: 9853 veya testnet: 19853) + + + + Maintain at most <n> connections to peers (default: 125) + Eşler ile en çok <n> adet bağlantı kur (varsayılan: 125) + + + + Connect to a node to retrieve peer addresses, and disconnect + Eş adresleri elde etmek için bir düğüme bağlan ve ardından bağlantıyı kes + + + + Specify your own public address + Kendi genel adresinizi tanımlayın + + + + Bind to given address. Use [host]:port notation for IPv6 + Belirtilen adrese bağlı. IPv6 için [host]:port notasyonunu kullan + + + + Stake your coins to support network and gain reward (default: 1) + Ağı desteklemek için coinlerinizden pay alın ve ödül kazanın (varsayılan: 1) + + + + Threshold for disconnecting misbehaving peers (default: 100) + Aksaklık gösteren eşlerle bağlantıyı kesme sınırı (varsayılan: 100) + + + + Number of seconds to keep misbehaving peers from reconnecting (default: 86400) + Aksaklık gösteren eşlerle yeni bağlantıları engelleme süresi, saniye olarak (varsayılan: 86400) + + + + An error occurred while setting up the RPC port %u for listening on IPv4: %s + IPv4 üzerinde dinlemek için %u numaralı RPC portunun kurulumu sırasında hata meydana geldi: %s + + + + Detach block and address databases. Increases shutdown time (default: 0) + Blok ve adres veritabanlarını birbirinden ayır. Kapanma süresini arttırır (varsayılan: 0) + + + + 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. + Hata: İşlem reddedildi. Bu; cüzdanınızdaki bazı coinler, önceden harcanmışsa, örneğin wallet.dat dosyasının bir kopyasını kullandıysanız ve bu kopyadaki coinler harcanmış ve burada harcanmış olarak işaretlenmediyse gerçekleşebilir. + + + + Error: This transaction requires a transaction fee of at least %s because of its amount, complexity, or use of recently received funds + Hata: Bu işlem; miktarı, karmaşıklığı veya son alınan miktarın kullanımı nedeniyle en az %s işlem ücreti gerektirir + + + + Listen for JSON-RPC connections on <port> (default: 9852 or testnet: 19852) + <port> üzerinde JSON-RPC bağlantılarını dinle (varsayılan: 9852 veya testnet: 19852) + + + + Accept command line and JSON-RPC commands + Konut satırı ve JSON-RPC komutlarını kabul et + + + + Error: Transaction creation failed + Hata: İşlem yaratma başarısız oldu + + + + Error: Wallet locked, unable to create transaction + Hata: Cüzdan kilitli, işlem yaratılamıyor + + + + Importing blockchain data file. + Blok zinciri veri dosyası içeri aktarılıyor. + + + + Importing bootstrap blockchain data file. + Önyükleme blok zinciri veri dosyası içeri aktarılıyor. + + + + Run in the background as a daemon and accept commands + Arka planda daemon (servis) olarak çalış ve komutları kabul et + + + + Use the test network + Deneme şebekesini kullan + + + + Accept connections from outside (default: 1 if no -proxy or -connect) + Dışarıdan gelen bağlantıları kabul et (varsayılan: -proxy veya -connect yoksa 1) + + + + An error occurred while setting up the RPC port %u for listening on IPv6, falling back to IPv4: %s + IPv6 üzerinde dinlemek için %u numaralı RPC portu kurulurken bir hata meydana geldi, IPv4'e dönülüyor: %s + + + + Error initializing database environment %s! To recover, BACKUP THAT DIRECTORY, then remove everything from it except for wallet.dat. + Veritabanı ortamı %s başlatılırken hata oluştu! Kurtarmak için, İLGİLİ KLASÖRÜ YEDEKLEYİN, ardından wallet.dat dışındaki her şeyi silin. + + + + Set maximum size of high-priority/low-fee transactions in bytes (default: 27000) + Bayt olarak yüksek öncelikli/düşük ücretli işlemlerin maksimum boyutunu belirle (varsayılan: 27000) + + + + Warning: -paytxfee is set very high! This is the transaction fee you will pay if you send a transaction. + Uyarı: -paytxfee çok yüksek bir değere ayarlanmış! Bu, muamele gönderirseniz ödeyeceğiniz muamele ücretidir. + + + + Warning: Please check that your computer's date and time are correct! If your clock is wrong Arepacoin will not work properly. + Uyarı: Lütfen bilgisayarınızın tarih ve saatinin doğru olduğunu kontrol ediniz! Saatiniz yanlış ise, Arepacoin düzgün çalışmayacaktır. + + + + Warning: error reading wallet.dat! All keys read correctly, but transaction data or address book entries might be missing or incorrect. + Uyarı: wallet.dat dosyasının okunması sırasında bir hata meydana geldi! Tüm anahtarlar doğru bir şekilde okundu, ancak muamele verileri ya da adres defteri unsurları hatalı veya eksik olabilir. + + + + Warning: wallet.dat corrupt, data salvaged! Original wallet.dat saved as wallet.{timestamp}.bak in %s; if your balance or transactions are incorrect you should restore from a backup. + Uyarı: wallet.dat bozuk, veriler geri kazanıldı! Özgün wallet.dat, wallet.{zamandamgası}.bak olarak %s klasörüne kaydedildi; bakiyeniz ya da muameleleriniz yanlışsa bir yedeklemeden tekrar yüklemeniz gerekir. + + + + Attempt to recover private keys from a corrupt wallet.dat + Bozuk bir wallet.dat dosyasından özel anahtarları geri kazanmayı dene + + + + Block creation options: + Blok oluşturma seçenekleri: + + + + Connect only to the specified node(s) + Sadece belirtilen düğüme veya düğümlere bağlan + + + + Discover own IP address (default: 1 when listening and no -externalip) + Kendi IP adresini keşfet (varsayılan: dinlenildiğinde ve -externalip yoksa 1) + + + + Failed to listen on any port. Use -listen=0 if you want this. + Herhangi bir portun dinlenmesi başarısız oldu. Bunu istiyorsanız -listen=0 seçeneğini kullanınız. + + + + Find peers using DNS lookup (default: 1) + DNS arama kullanarak eşleri bul (varsayılan: 1) + + + + Sync checkpoints policy (default: strict) + Kontrol noktası politikasını senkronize et (varsayılan: sıkı) + + + + Invalid -tor address: '%s' + Geçersiz -tor adresi: '%s' + + + + Invalid amount for -reservebalance=<amount> + -reservebalance=<amount> için geçersiz miktar + + + + Maximum per-connection receive buffer, <n>*1000 bytes (default: 5000) + Bağlantı başına azami alım tamponu, <n>*1000 bayt (varsayılan: 5000) + + + + Maximum per-connection send buffer, <n>*1000 bytes (default: 1000) + Bağlantı başına azami yollama tamponu, <n>*1000 bayt (varsayılan: 1000) + + + + Only connect to nodes in network <net> (IPv4, IPv6 or Tor) + Sadece <net> şebekesindeki düğümlere bağlan (IPv4, IPv6 ya da Tor) + + + + Output extra debugging information. Implies all other -debug* options + Ekstra hata ayıklama bilgisini çıktı al. Diğer tüm -debug* seçeneklerini kapsar + + + + Output extra network debugging information + Ekstra ağ hata ayıklama bilgisini çıktı al + + + + Prepend debug output with timestamp + Tarih bilgisini, hata ayıklama çıktısının başına ekle + + + + SSL options: (see the Bitcoin Wiki for SSL setup instructions) + SSL seçenekleri: (SSL kurulum bilgisi için Bitcoin vikisine bakınız) + + + + Select the version of socks proxy to use (4-5, default: 5) + Kullanılacak socks vekil sunucusunun versiyonunu seç (4-5, varsayılan: 5) + + + + Send trace/debug info to console instead of debug.log file + Trace/hata ayıklama verilerini debug.log dosyası yerine konsola gönder + + + + Send trace/debug info to debugger + Hata ayıklayıcıya iz sürme/hata ayıklama bilgisi gönder + + + + Set maximum block size in bytes (default: 250000) + Bayt olarak maksimum blok boyutunu belirle (varsayılan: 250000) + + + + Set minimum block size in bytes (default: 0) + Bayt olarak asgari blok boyutunu tanımla (varsayılan: 0) + + + + Shrink debug.log file on client startup (default: 1 when no -debug) + İstemci başlatıldığında debug.log dosyasını küçült (varsayılan: -debug bulunmadığında 1) + + + + Specify connection timeout in milliseconds (default: 5000) + Bağlantı zaman aşım süresini milisaniye olarak belirt (varsayılan: 5000) + + + + Unable to sign checkpoint, wrong checkpointkey? + + Kontrol noktası imzalanamadı, bu bir hatalı kontrol noktası anahtarı mı? + + + + + Use UPnP to map the listening port (default: 0) + Dinlenecek portu haritalamak için UPnP kullan (varsayılan: 0) + + + + Use UPnP to map the listening port (default: 1 when listening) + Dinlenecek portu haritalamak için UPnP kullan (varsayılan: dinlenildiğinde 1) + + + + Use proxy to reach tor hidden services (default: same as -proxy) + Tor gizli servisine erişim için vekil sunucu kullan (varsayılan: -proxy ile aynı) + + + + Username for JSON-RPC connections + JSON-RPC bağlantıları için kullanıcı ismi + + + + Verifying database integrity... + Veritabanı bütünlüğü doğrulanıyor... + + + + WARNING: syncronized checkpoint violation detected, but skipped! + UYARI: senkronize edilen kontrol noktası ihlali tespit edildi ancak atlandı! + + + + Warning: Disk space is low! + Uyarı: Disk alanı düşüktür! + + + + Warning: This version is obsolete, upgrade required! + Uyarı: Bu sürüm çok eskidir, güncellemeniz gerekir! + + + + wallet.dat corrupt, salvage failed + wallet.dat bozuk, geri kazanım başarısız oldu + + + + Password for JSON-RPC connections + JSON-RPC bağlantıları için parola + + + + %s, you must set a rpcpassword in the configuration file: + %s +It is recommended you use the following random password: +rpcuser=arepacoinrpc +rpcpassword=%s +(you do not need to remember this password) +The username and password MUST NOT be the same. +If the file does not exist, create it with owner-readable-only file permissions. +It is also recommended to set alertnotify so you are notified of problems; +for example: alertnotify=echo %%s | mail -s "Arepacoin Alert" admin@foo.com + + %s, konfigürasyon dosyasında bir rpcpassword belirlemelisiniz: + %s +Aşağıdaki rastgele parolayı kullanmanız tavsiye edilir: +rpcuser=arepacoinrpc +rpcpassword=%s +(bu parolayı hatırlamanız gerekmemektedir) +Kullanıcı adı ve parola aynı OLMAMALIDIR. +Dosya mevcut değilse, dosyayı sadece-kullanıcı-okuyabilir dosya izniyle yaratınız. +alertnotify ayarlamanız da ayrıca tavsiye edilir böylece sorunlar, size bildirilir; +örneğin: alertnotify=echo %%s | mail -s "Arepacoin Uyarısı" admin@foo.com + + + + + Find peers using internet relay chat (default: 0) + Internet aktarımlı söyleşi kullanarak eşleri bul (varsayılan: 1) {0)?} + + + + Sync time with other nodes. Disable if time on your system is precise e.g. syncing with NTP (default: 1) + Diğer devrelerle saati senkronize et. Sisteminizdeki saat doğru ise devre dışı bırakın, örn: NTC ile senkronize etme (varsayılan: 1) + + + + When creating transactions, ignore inputs with value less than this (default: 0.01) + + + + + Allow JSON-RPC connections from specified IP address + Belirtilen İP adresinden JSON-RPC bağlantılarını kabul et + + + + Send commands to node running on <ip> (default: 127.0.0.1) + Şu <ip> adresinde (varsayılan: 127.0.0.1) çalışan düğüme komut yolla + + + + Execute command when the best block changes (%s in cmd is replaced by block hash) + En iyi blok değiştiğinde komutu çalıştır (komut için %s parametresi blok hash değeri ile değiştirilecektir) + + + + Execute command when a wallet transaction changes (%s in cmd is replaced by TxID) + Bir cüzdan muamelesi değiştiğinde komutu çalıştır (komuttaki %s TxID ile değiştirilecektir) + + + + Require a confirmations for change (default: 0) + + + + + Enforce transaction scripts to use canonical PUSH operators (default: 1) + + + + + Execute command when a relevant alert is received (%s in cmd is replaced by message) + + + + + Upgrade wallet to latest format + Cüzdanı en yeni biçime güncelle + + + + Set key pool size to <n> (default: 100) + Anahtar alan boyutunu <n> değerine ayarla (varsayılan: 100) + + + + Rescan the block chain for missing wallet transactions + Blok zincirini eksik cüzdan muameleleri için tekrar tara + + + + How many blocks to check at startup (default: 2500, 0 = all) + + + + + How thorough the block verification is (0-6, default: 1) + + + + + Imports blocks from external blk000?.dat file + + + + + Use OpenSSL (https) for JSON-RPC connections + JSON-RPC bağlantıları için OpenSSL (https) kullan + + + + Server certificate file (default: server.cert) + Sunucu sertifika dosyası (varsayılan: server.cert) + + + + Server private key (default: server.pem) + Sunucu özel anahtarı (varsayılan: server.pem) + + + + Acceptable ciphers (default: TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH) + + + + + Error: Wallet unlocked for staking only, unable to create transaction. + + + + + WARNING: Invalid checkpoint found! Displayed transactions may not be correct! You may need to upgrade, or notify developers. + + + + + This help message + Bu yardım mesajı + + + + Wallet %s resides outside data directory %s. + + + + + Cannot obtain a lock on data directory %s. Arepacoin is probably already running. + + + + + Arepacoin + + + + + Unable to bind to %s on this computer (bind returned error %d, %s) + Bu bilgisayarda %s unsuruna bağlanılamadı. (bind şu hatayı iletti: %d, %s) + + + + Connect through socks proxy + + + + + Allow DNS lookups for -addnode, -seednode and -connect + -addnode, -seednode ve -connect için DNS aramalarına izin ver + + + + Loading addresses... + Adresler yükleniyor... + + + + Error loading blkindex.dat + + + + + Error loading wallet.dat: Wallet corrupted + wallet.dat dosyasının yüklenmesinde hata oluştu: bozuk cüzdan + + + + Error loading wallet.dat: Wallet requires newer version of Arepacoin + + + + + Wallet needed to be rewritten: restart Arepacoin to complete + + + + + Error loading wallet.dat + wallet.dat dosyasının yüklenmesinde hata oluştu + + + + Invalid -proxy address: '%s' + Geçersiz -proxy adresi: '%s' + + + + Unknown network specified in -onlynet: '%s' + -onlynet için bilinmeyen bir şebeke belirtildi: '%s' + + + + Unknown -socks proxy version requested: %i + Bilinmeyen bir -socks vekil sürümü talep edildi: %i + + + + Cannot resolve -bind address: '%s' + -bind adresi çözümlenemedi: '%s' + + + + Cannot resolve -externalip address: '%s' + -externalip adresi çözümlenemedi: '%s' + + + + Invalid amount for -paytxfee=<amount>: '%s' + -paytxfee=<meblağ> için geçersiz meblağ: '%s' + + + + Error: could not start node + + + + + Sending... + + + + + Invalid amount + Geçersiz meblağ + + + + Insufficient funds + Yetersiz bakiye + + + + Loading block index... + Blok indeksi yükleniyor... + + + + Add a node to connect to and attempt to keep the connection open + Bağlanılacak düğüm ekle ve bağlantıyı zinde tutmaya çalış + + + + Unable to bind to %s on this computer. Arepacoin is probably already running. + + + + + Fee per KB to add to transactions you send + + + + + Invalid amount for -mininput=<amount>: '%s' + + + + + Loading wallet... + Cüzdan yükleniyor... + + + + Cannot downgrade wallet + Cüzdan eski biçime geri alınamaz + + + + Cannot initialize keypool + + + + + Cannot write default address + Varsayılan adres yazılamadı + + + + Rescanning... + Yeniden tarama... + + + + Done loading + Yükleme tamamlandı + + + + To use the %s option + %s seçeneğini kullanmak için + + + + Error + Hata + + + + You must set rpcpassword=<password> in the configuration file: +%s +If the file does not exist, create it with owner-readable-only file permissions. + rpcpassword=<parola> şu yapılandırma dosyasında belirtilmelidir: +%s +Dosya mevcut değilse, sadece sahibi için okumayla sınırlı izin ile oluşturunuz. + + + \ No newline at end of file diff --git a/src/qt/locale/bitcoin_uk.ts b/src/qt/locale/bitcoin_uk.ts new file mode 100755 index 0000000..47c24ed --- /dev/null +++ b/src/qt/locale/bitcoin_uk.ts @@ -0,0 +1,3286 @@ + + + AboutDialog + + + About Arepacoin + + + + + <b>Arepacoin</b> version + + + + + Copyright © 2009-2014 The Bitcoin developers +Copyright © 2012-2014 The NovaCoin developers +Copyright © 2014 The Arepacoin developers + + + + + +This is experimental software. + +Distributed under the MIT/X11 software license, see the accompanying file COPYING or http://www.opensource.org/licenses/mit-license.php. + +This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit (http://www.openssl.org/) and cryptographic software written by Eric Young (eay@cryptsoft.com) and UPnP software written by Thomas Bernard. + +Це програмне забезпечення є експериментальним. + +Поширюється за ліцензією MIT/X11, додаткова інформація міститься у файлі COPYING, а також за адресою http://www.opensource.org/licenses/mit-license.php. + +Цей продукт включає в себе програмне забезпечення, розроблене в рамках проекту OpenSSL (http://www.openssl.org/), криптографічне програмне забезпечення, написане Еріком Янгом (eay@cryptsoft.com), та функції для роботи з UPnP, написані Томасом Бернардом. + + + + AddressBookPage + + + Address Book + + + + + Double-click to edit address or label + Двічі клікніть на адресу чи назву для їх зміни + + + + Create a new address + Створити нову адресу + + + + Copy the currently selected address to the system clipboard + Копіювати виділену адресу в буфер обміну + + + + &New Address + + + + + These are your Arepacoin addresses for receiving payments. You may want to give a different one to each sender so you can keep track of who is paying you. + + + + + &Copy Address + &Скопіювати адресу + + + + Show &QR Code + + + + + Sign a message to prove you own a Arepacoin address + + + + + Sign &Message + + + + + Delete the currently selected address from the list + Вилучити вибрані адреси з переліку + + + + Verify a message to ensure it was signed with a specified Arepacoin address + + + + + &Verify Message + + + + + &Delete + &Видалити + + + + Copy &Label + Скопіювати &мітку + + + + &Edit + &Редагувати + + + + Export Address Book Data + + + + + Comma separated file (*.csv) + Файли відділені комами (*.csv) + + + + Error exporting + + + + + Could not write to file %1. + + + + + AddressTableModel + + + Label + Назва + + + + Address + Адреса + + + + (no label) + (немає назви) + + + + AskPassphraseDialog + + + Passphrase Dialog + Діалог введення паролю + + + + Enter passphrase + Введіть пароль + + + + New passphrase + Новий пароль + + + + Repeat new passphrase + Повторіть пароль + + + + Serves to disable the trivial sendmoney when OS account compromised. Provides no real security. + + + + + For staking only + + + + + Enter the new passphrase to the wallet.<br/>Please use a passphrase of <b>10 or more random characters</b>, or <b>eight or more words</b>. + Введіть новий пароль для гаманця.<br/>Будь ласка, використовуйте паролі що містять <b>як мінімум 10 випадкових символів</b>, або <b>як мінімум 8 слів</b>. + + + + Encrypt wallet + Зашифрувати гаманець + + + + This operation needs your wallet passphrase to unlock the wallet. + Ця операція потребує пароль для розблокування гаманця. + + + + Unlock wallet + Розблокувати гаманець + + + + This operation needs your wallet passphrase to decrypt the wallet. + Ця операція потребує пароль для дешифрування гаманця. + + + + Decrypt wallet + Дешифрувати гаманець + + + + Change passphrase + Змінити пароль + + + + Enter the old and new passphrase to the wallet. + Ввести старий та новий паролі для гаманця. + + + + Confirm wallet encryption + Підтвердити шифрування гаманця + + + + Warning: If you encrypt your wallet and lose your passphrase, you will <b>LOSE ALL OF YOUR COINS</b>! + + + + + Are you sure you wish to encrypt your wallet? + Ви дійсно хочете зашифрувати свій гаманець? + + + + IMPORTANT: Any previous backups you have made of your wallet file should be replaced with the newly generated, encrypted wallet file. For security reasons, previous backups of the unencrypted wallet file will become useless as soon as you start using the new, encrypted wallet. + ВАЖЛИВО: Всі попередні резервні копії, які ви зробили з вашого гаманця файл повинен бути замінений новоствореному, зашифрованому файлі гаманця. З міркувань безпеки, попередні резервні копії в незашифрованому файлі гаманець стане марним, як тільки ви починаєте використовувати нову, зашифрований гаманець. + + + + + Warning: The Caps Lock key is on! + Увага: Ввімкнено Caps Lock! + + + + + Wallet encrypted + Гаманець зашифровано + + + + Arepacoin will close now to finish the encryption process. Remember that encrypting your wallet cannot fully protect your coins from being stolen by malware infecting your computer. + + + + + + + + Wallet encryption failed + Не вдалося зашифрувати гаманець + + + + Wallet encryption failed due to an internal error. Your wallet was not encrypted. + Виникла помилка під час шифрування гаманця. Ваш гаманець не було зашифровано. + + + + + The supplied passphrases do not match. + Введені паролі не співпадають. + + + + Wallet unlock failed + Не вдалося розблокувати гаманець + + + + + + The passphrase entered for the wallet decryption was incorrect. + Введений пароль є невірним. + + + + Wallet decryption failed + Не вдалося розшифрувати гаманець + + + + Wallet passphrase was successfully changed. + Пароль було успішно змінено. + + + + BitcoinGUI + + + Sign &message... + &Підписати повідомлення... + + + + Synchronizing with network... + Синхронізація з мережею... + + + + &Overview + &Огляд + + + + Show general overview of wallet + Показати загальний огляд гаманця + + + + &Transactions + Транзакції + + + + Browse transaction history + Переглянути історію транзакцій + + + + &Address Book + + + + + Edit the list of stored addresses and labels + + + + + &Receive coins + + + + + Show the list of addresses for receiving payments + + + + + &Send coins + + + + + E&xit + &Вихід + + + + Quit application + Вийти + + + + Show information about Arepacoin + + + + + About &Qt + &Про Qt + + + + Show information about Qt + Показати інформацію про Qt + + + + &Options... + &Параметри... + + + + &Encrypt Wallet... + &Шифрування гаманця... + + + + &Backup Wallet... + &Резервне копіювання гаманця... + + + + &Change Passphrase... + Змінити парол&ь... + + + + ~%n block(s) remaining + + + + + Downloaded %1 of %2 blocks of transaction history (%3% done). + + + + + &Export... + + + + + Send coins to a Arepacoin address + + + + + Modify configuration options for Arepacoin + + + + + Export the data in the current tab to a file + + + + + Encrypt or decrypt wallet + + + + + Backup wallet to another location + Резервне копіювання гаманця в інше місце + + + + Change the passphrase used for wallet encryption + Змінити пароль, який використовується для шифрування гаманця + + + + &Debug window + Вікно зневадження + + + + Open debugging and diagnostic console + Відкрити консоль зневадження і діагностики + + + + &Verify message... + Перевірити повідомлення... + + + + Arepacoin + + + + + Wallet + Гаманець + + + + &About Arepacoin + + + + + &Show / Hide + Показати / Приховати + + + + Unlock wallet + + + + + &Lock Wallet + + + + + Lock wallet + + + + + &File + &Файл + + + + &Settings + &Налаштування + + + + &Help + &Довідка + + + + Tabs toolbar + Панель вкладок + + + + Actions toolbar + + + + + + [testnet] + [тестова мережа] + + + + + Arepacoin client + + + + + %n active connection(s) to Arepacoin network + + + + + Downloaded %1 blocks of transaction history. + + + + + Staking.<br>Your weight is %1<br>Network weight is %2<br>Expected time to earn reward is %3 + + + + + Not staking because wallet is locked + + + + + Not staking because wallet is offline + + + + + Not staking because wallet is syncing + + + + + Not staking because you don't have mature coins + + + + + %n second(s) ago + + + + + &Unlock Wallet... + + + + + %n minute(s) ago + + + + + %n hour(s) ago + + + + + %n day(s) ago + + + + + Up to date + Синхронізовано + + + + Catching up... + Синхронізується... + + + + Last received block was generated %1. + + + + + This transaction is over the size limit. You can still send it for a fee of %1, which goes to the nodes that process your transaction and helps to support the network. Do you want to pay the fee? + + + + + Confirm transaction fee + + + + + Sent transaction + Надіслані транзакції + + + + Incoming transaction + Отримані перекази + + + + Date: %1 +Amount: %2 +Type: %3 +Address: %4 + + Дата: %1 +Кількість: %2 +Тип: %3 +Адреса: %4 + + + + + + URI handling + + + + + + URI can not be parsed! This can be caused by an invalid Arepacoin address or malformed URI parameters. + + + + + Wallet is <b>encrypted</b> and currently <b>unlocked</b> + <b>Зашифрований</b> гаманець <b>розблоковано</b> + + + + Wallet is <b>encrypted</b> and currently <b>locked</b> + <b>Зашифрований</b> гаманець <b>заблоковано</b> + + + + Backup Wallet + + + + + Wallet Data (*.dat) + + + + + Backup Failed + + + + + There was an error trying to save the wallet data to the new location. + + + + + %n second(s) + + + + + %n minute(s) + + + + + %n hour(s) + + + + + %n day(s) + + + + + Not staking + + + + + A fatal error occurred. Arepacoin can no longer continue safely and will quit. + + + + + ClientModel + + + Network Alert + Сповіщення мережі + + + + CoinControlDialog + + + Coin Control + + + + + Quantity: + + + + + Bytes: + + + + + Amount: + Кількість: + + + + Priority: + + + + + Fee: + + + + + Low Output: + + + + + no + + + + + After Fee: + + + + + Change: + + + + + (un)select all + + + + + Tree mode + + + + + List mode + + + + + Amount + Кількість + + + + Label + + + + + Address + Адреса + + + + Date + Дата + + + + Confirmations + + + + + Confirmed + Підтверджені + + + + Priority + + + + + Copy address + Скопіювати адресу + + + + Copy label + Скопіювати мітку + + + + + Copy amount + Копіювати кількість + + + + Copy transaction ID + Копіювати ID транзакції + + + + Copy quantity + + + + + Copy fee + + + + + Copy after fee + + + + + Copy bytes + + + + + Copy priority + + + + + Copy low output + + + + + Copy change + + + + + highest + + + + + high + + + + + medium-high + + + + + medium + + + + + low-medium + + + + + low + + + + + lowest + + + + + DUST + + + + + yes + + + + + This label turns red, if the transaction size is bigger than 10000 bytes. + + This means a fee of at least %1 per kb is required. + + Can vary +/- 1 Byte per input. + + + + + Transactions with higher priority get more likely into a block. + +This label turns red, if the priority is smaller than "medium". + + This means a fee of at least %1 per kb is required. + + + + + This label turns red, if any recipient receives an amount smaller than %1. + + This means a fee of at least %2 is required. + + Amounts below 0.546 times the minimum relay fee are shown as DUST. + + + + + This label turns red, if the change is smaller than %1. + + This means a fee of at least %2 is required. + + + + + + (no label) + (немає назви) + + + + change from %1 (%2) + + + + + (change) + + + + + EditAddressDialog + + + Edit Address + Редагувати адресу + + + + &Label + &Мітка + + + + The label associated with this address book entry + + + + + &Address + &Адреса + + + + The address associated with this address book entry. This can only be modified for sending addresses. + + + + + New receiving address + Нова адреса для отримання + + + + New sending address + Нова адреса для відправлення + + + + Edit receiving address + Редагувати адресу для отримання + + + + Edit sending address + Редагувати адресу для відправлення + + + + The entered address "%1" is already in the address book. + Введена адреса «%1» вже присутня в адресній книзі. + + + + The entered address "%1" is not a valid Arepacoin address. + + + + + Could not unlock wallet. + Неможливо розблокувати гаманець. + + + + New key generation failed. + Не вдалося згенерувати нові ключі. + + + + GUIUtil::HelpMessageBox + + + + Arepacoin-Qt + + + + + version + + + + + Usage: + + + + + command-line options + + + + + UI options + + + + + Set language, for example "de_DE" (default: system locale) + + + + + Start minimized + + + + + Show splash screen on startup (default: 1) + + + + + OptionsDialog + + + Options + Параметри + + + + &Main + &Головні + + + + Optional transaction fee per kB that helps make sure your transactions are processed quickly. Most transactions are 1 kB. Fee 0.01 recommended. + + + + + Pay transaction &fee + Заплатити комісі&ю + + + + Reserved amount does not participate in staking and is therefore spendable at any time. + + + + + Reserve + + + + + Automatically start Arepacoin after logging in to the system. + + + + + &Start Arepacoin on system login + + + + + Detach block and address databases at shutdown. This means they can be moved to another data directory, but it slows down shutdown. The wallet is always detached. + + + + + &Detach databases at shutdown + + + + + &Network + &Мережа + + + + Automatically open the Arepacoin client port on the router. This only works when your router supports UPnP and it is enabled. + + + + + Map port using &UPnP + Відображення порту через &UPnP + + + + Connect to the Arepacoin network through a SOCKS proxy (e.g. when connecting through Tor). + + + + + &Connect through SOCKS proxy: + + + + + Proxy &IP: + &IP проксі: + + + + IP address of the proxy (e.g. 127.0.0.1) + + + + + &Port: + &Порт: + + + + Port of the proxy (e.g. 9050) + Порт проксі-сервера (наприклад 9050) + + + + SOCKS &Version: + SOCKS версії: + + + + SOCKS version of the proxy (e.g. 5) + Версія SOCKS-проксі (наприклад 5) + + + + &Window + &Вікно + + + + Show only a tray icon after minimizing the window. + Показувати лише іконку в треї після згортання вікна. + + + + &Minimize to the tray instead of the taskbar + Мінімізувати &у трей + + + + Minimize instead of exit the application when the window is closed. When this option is enabled, the application will be closed only after selecting Quit in the menu. + Згортати замість закриття. Якщо ця опція включена, програма закриється лише після вибору відповідного пункту в меню. + + + + M&inimize on close + Згортати замість закритт&я + + + + &Display + &Відображення + + + + User Interface &language: + Мова інтерфейсу користувача: + + + + The user interface language can be set here. This setting will take effect after restarting Arepacoin. + + + + + &Unit to show amounts in: + В&имірювати монети в: + + + + Choose the default subdivision unit to show in the interface and when sending coins. + Виберіть одиницю вимірювання монет, яка буде відображатись в гаманці та при відправленні. + + + + Whether to show Arepacoin addresses in the transaction list or not. + + + + + &Display addresses in transaction list + &Відображати адресу в списку транзакцій + + + + Whether to show coin control features or not. + + + + + Display coin &control features (experts only!) + + + + + &OK + &Гаразд + + + + &Cancel + &Скасувати + + + + &Apply + + + + + default + типово + + + + + Warning + + + + + + This setting will take effect after restarting Arepacoin. + + + + + The supplied proxy address is invalid. + Невірно вказано адресу проксі. + + + + OverviewPage + + + Form + Форма + + + + + The displayed information may be out of date. Your wallet automatically synchronizes with the Arepacoin network after a connection is established, but this process has not completed yet. + + + + + Stake: + + + + + Unconfirmed: + + + + + Wallet + Гаманець + + + + Spendable: + + + + + Your current spendable balance + Ваш поточний баланс расходуемого + + + + Immature: + незрілі: + + + + Mined balance that has not yet matured + Замінований баланс, який ще не дозрів + + + + Total: + всього: + + + + Your current total balance + Ваше поточне Сукупний баланс + + + + <b>Recent transactions</b> + <b>Недавні транзакції</b> + + + + Total of transactions that have yet to be confirmed, and do not yet count toward the current balance + + + + + Total of coins that was staked, and do not yet count toward the current balance + + + + + + out of sync + не синхронізовано + + + + QRCodeDialog + + + QR Code Dialog + + + + + Request Payment + + + + + Amount: + + + + + Label: + + + + + Message: + + + + + &Save As... + + + + + Error encoding URI into QR Code. + + + + + The entered amount is invalid, please check. + + + + + Resulting URI too long, try to reduce the text for label / message. + + + + + Save QR Code + + + + + PNG Images (*.png) + + + + + RPCConsole + + + Client name + Назва клієнту + + + + + + + + + + + + + N/A + Н/Д + + + + Client version + Версія клієнту + + + + &Information + &Інформація + + + + Using OpenSSL version + Використовується OpenSSL версії + + + + Startup time + Час запуску + + + + Network + Мережа + + + + Number of connections + Кількість підключень + + + + On testnet + + + + + Block chain + Ланцюг блоків + + + + Current number of blocks + Поточне число блоків + + + + Estimated total blocks + Розрахункове число блоків + + + + Last block time + Час останнього блоку + + + + &Open + Відкрити + + + + Command-line options + + + + + Show the Arepacoin-Qt help message to get a list with possible Arepacoin command-line options. + + + + + &Show + + + + + &Console + Консоль + + + + Build date + Дата збирання + + + + Arepacoin - Debug window + + + + + Arepacoin Core + + + + + Debug log file + Файл звіту зневадження + + + + Open the Arepacoin debug log file from the current data directory. This can take a few seconds for large log files. + + + + + Clear console + Очистити консоль + + + + Welcome to the Arepacoin RPC console. + + + + + Use up and down arrows to navigate history, and <b>Ctrl-L</b> to clear screen. + Використовуйте стрілки вгору вниз для навігації по історії, і <b>Ctrl-L</b> для очищення екрана. + + + + Type <b>help</b> for an overview of available commands. + Наберіть <b>help</b> для перегляду доступних команд. + + + + SendCoinsDialog + + + + + + + + + + Send Coins + Відправити + + + + Coin Control Features + + + + + Inputs... + + + + + automatically selected + + + + + Insufficient funds! + + + + + Quantity: + + + + + + 0 + + + + + Bytes: + + + + + Amount: + Кількість: + + + + + + + 0.00 BC + + + + + Priority: + + + + + medium + + + + + Fee: + + + + + Low Output: + + + + + no + + + + + After Fee: + + + + + Change + + + + + custom change address + + + + + Send to multiple recipients at once + Відправити на декілька адрес + + + + Add &Recipient + Дод&ати одержувача + + + + Remove all transaction fields + + + + + Clear &All + Очистити &все + + + + Balance: + Баланс: + + + + 123.456 BC + + + + + Confirm the send action + Підтвердити відправлення + + + + S&end + &Відправити + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Copy quantity + + + + + Copy amount + Копіювати кількість + + + + Copy fee + + + + + Copy after fee + + + + + Copy bytes + + + + + Copy priority + + + + + Copy low output + + + + + Copy change + + + + + <b>%1</b> to %2 (%3) + + + + + Confirm send coins + Підтвердіть відправлення + + + + Are you sure you want to send %1? + + + + + and + + + + + The recipient address is not valid, please recheck. + Адреса отримувача невірна, будь ласка перепровірте. + + + + The amount to pay must be larger than 0. + Кількість монет для відправлення повинна бути більшою 0. + + + + The amount exceeds your balance. + Кількість монет для відправлення перевищує ваш баланс. + + + + The total exceeds your balance when the %1 transaction fee is included. + Сума перевищить ваш баланс, якщо комісія %1 буде додана до вашої транзакції. + + + + Duplicate address found, can only send to each address once per send operation. + Знайдено адресу що дублюється. Відправлення на кожну адресу дозволяється лише один раз на кожну операцію переказу. + + + + Error: Transaction creation failed. + + + + + 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. + + + + + WARNING: Invalid Arepacoin address + + + + + (no label) + (немає назви) + + + + WARNING: unknown change address + + + + + SendCoinsEntry + + + Form + + + + + A&mount: + &Кількість: + + + + Pay &To: + &Отримувач: + + + + + Enter a label for this address to add it to your address book + Введіть мітку для цієї адреси для додавання її в адресну книгу + + + + &Label: + &Мітка: + + + + The address to send the payment to (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Choose address from address book + + + + + Alt+A + Alt+A + + + + Paste address from clipboard + Вставити адресу + + + + Alt+P + Alt+P + + + + Remove this recipient + + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + SignVerifyMessageDialog + + + Signatures - Sign / Verify a Message + Підписи - Підпис / Перевірка повідомлення + + + + + &Sign Message + &Підписати повідомлення + + + + You can sign messages with your addresses to prove you own them. Be careful not to sign anything vague, as phishing attacks may try to trick you into signing your identity over to them. Only sign fully-detailed statements you agree to. + Ви можете зареєструватися повідомленнями зі своїми адресами, щоб довести, що ви є їх власником. Будьте обережні, щоб не підписувати що-небудь неясне, як фішинг-атак може спробувати обдурити вас в підписанні вашу особистість до них. Тільки підписати повністю докладні свідчення, користувач зобов'язується. + + + + The address to sign the message with (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + + Choose an address from the address book + + + + + + Alt+A + Alt+A + + + + Paste address from clipboard + Вставити адресу + + + + Alt+P + Alt+P + + + + Enter the message you want to sign here + Введіть повідомлення, яке ви хочете підписати тут + + + + Copy the current signature to the system clipboard + Копіювати поточну сигнатуру до системного буферу обміну + + + + Sign the message to prove you own this Arepacoin address + + + + + Reset all sign message fields + Скинути всі поля підпису повідомлення + + + + + Clear &All + Очистити &все + + + + + &Verify Message + Перевірити повідомлення + + + + Enter the signing address, message (ensure you copy line breaks, spaces, tabs, etc. exactly) and signature below to verify the message. Be careful not to read more into the signature than what is in the signed message itself, to avoid being tricked by a man-in-the-middle attack. + Введіть адресу підписання, повідомлення (забезпечення копіюванні розриви рядків, прогалини, вкладки і т.д. точно) і підпис нижче, щоб перевірити повідомлення. Будьте обережні, щоб не читати далі в підпис, ніж те, що в підписаному самого повідомлення, щоб уникнути обдурять нападу чоловік-в-середній. + + + + The address the message was signed with (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Verify the message to ensure it was signed with the specified Arepacoin address + + + + + Reset all verify message fields + Скинути всі поля перевірки повідомлення + + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Click "Sign Message" to generate signature + Натисніть кнопку «Підписати повідомлення», для отримання підпису + + + + Enter Arepacoin signature + + + + + + The entered address is invalid. + Введена нечинна адреса. + + + + + + + Please check the address and try again. + Будь ласка, перевірте адресу та спробуйте ще. + + + + + The entered address does not refer to a key. + Введений адреса не відноситься до ключа. + + + + Wallet unlock was cancelled. + Розблокування Гаманець був скасований. + + + + Private key for the entered address is not available. + Приватний ключ для введеної адреси недоступний. + + + + Message signing failed. + Не вдалося підписати повідомлення. + + + + Message signed. + Повідомлення підписано. + + + + The signature could not be decoded. + Підпис не можливо декодувати. + + + + + Please check the signature and try again. + Будь ласка, перевірте підпис та спробуйте ще. + + + + The signature did not match the message digest. + Підпис не відповідає дайджест повідомлення. + + + + Message verification failed. + Не вдалося перевірити повідомлення. + + + + Message verified. + Повідомлення перевірено. + + + + TransactionDesc + + + Open until %1 + Відкрити до %1 + + + + Open for %n block(s) + + + + + conflicted + + + + + %1/offline + %1/поза інтернетом + + + + %1/unconfirmed + %1/не підтверджено + + + + %1 confirmations + %1 підтверджень + + + + Status + Статус + + + + , broadcast through %n node(s) + + + + + Date + Дата + + + + Source + Джерело + + + + Generated + Згенеровано + + + + + From + Відправник + + + + + + To + Отримувач + + + + + own address + Власна адреса + + + + label + Мітка + + + + + + + + Credit + Кредит + + + + matures in %n more block(s) + + + + + not accepted + не прийнято + + + + + + + Debit + Дебет + + + + Transaction fee + Комісія за транзакцію + + + + Net amount + Загальна сума + + + + Message + Повідомлення + + + + Comment + Коментар + + + + Transaction ID + ID транзакції + + + + Generated coins must mature 6 blocks before they can be spent. When you generated this block, it was broadcast to the network to be added to the block chain. If it fails to get into the chain, its state will change to "not accepted" and it won't be spendable. This may occasionally happen if another node generates a block within a few seconds of yours. + + + + + Debug information + Отладочна інформація + + + + Transaction + Транзакція + + + + Inputs + витрати + + + + Amount + Кількість + + + + true + true + + + + false + false + + + + , has not been successfully broadcast yet + , ще не було успішно розіслано + + + + unknown + невідомий + + + + TransactionDescDialog + + + Transaction details + Деталі транзакції + + + + This pane shows a detailed description of the transaction + Даний діалог показує детальну статистику по вибраній транзакції + + + + TransactionTableModel + + + Date + Дата + + + + Type + Тип + + + + Address + Адреса + + + + Amount + Кількість + + + + Open until %1 + Відкрити до %1 + + + + Confirmed (%1 confirmations) + Підтверджено (%1 підтверджень) + + + + Open for %n more block(s) + + + + + Offline + + + + + Unconfirmed + + + + + Confirming (%1 of %2 recommended confirmations) + + + + + Conflicted + + + + + Immature (%1 confirmations, will be available after %2) + + + + + This block was not received by any other nodes and will probably not be accepted! + Цей блок не був отриманий жодними іншими вузлами і, ймовірно, не буде прийнятий! + + + + Generated but not accepted + Згенеровано, але не підтверджено + + + + Received with + Отримано + + + + Received from + Отримано від + + + + Sent to + Відправлено + + + + Payment to yourself + Відправлено собі + + + + Mined + Добуто + + + + (n/a) + (недоступно) + + + + Transaction status. Hover over this field to show number of confirmations. + Статус транзакції. Наведіть вказівник на це поле, щоб показати кількість підтверджень. + + + + Date and time that the transaction was received. + Дата і час, коли транзакцію було отримано. + + + + Type of transaction. + Тип транзакції. + + + + Destination address of transaction. + Адреса отримувача транзакції. + + + + Amount removed from or added to balance. + Сума, додана чи знята з балансу. + + + + TransactionView + + + + All + Всі + + + + Today + Сьогодні + + + + This week + На цьому тижні + + + + This month + На цьому місяці + + + + Last month + Минулого місяця + + + + This year + Цього року + + + + Range... + Проміжок... + + + + Received with + Отримані на + + + + Sent to + Відправлені на + + + + To yourself + Відправлені собі + + + + Mined + Добуті + + + + Other + Інше + + + + Enter address or label to search + Введіть адресу чи мітку для пошуку + + + + Min amount + Мінімальна сума + + + + Copy address + Скопіювати адресу + + + + Copy label + Скопіювати мітку + + + + Copy amount + Копіювати кількість + + + + Copy transaction ID + Копіювати ID транзакції + + + + Edit label + Редагувати мітку + + + + Show transaction details + Показати деталі транзакції + + + + Export Transaction Data + + + + + Comma separated file (*.csv) + Файли, розділені комою (*.csv) + + + + Confirmed + Підтверджені + + + + Date + Дата + + + + Type + Тип + + + + Label + Мітка + + + + Address + Адреса + + + + Amount + Кількість + + + + ID + Ідентифікатор + + + + Error exporting + + + + + Could not write to file %1. + + + + + Range: + Діапазон від: + + + + to + до + + + + WalletModel + + + Sending... + + + + + bitcoin-core + + + Arepacoin version + + + + + Usage: + Використання: + + + + Send command to -server or arepacoind + + + + + List commands + Список команд + + + + Get help for a command + Отримати довідку по команді + + + + Options: + Параметри: + + + + Specify configuration file (default: arepacoin.conf) + + + + + Specify pid file (default: arepacoind.pid) + + + + + Specify wallet file (within data directory) + + + + + Specify data directory + Вкажіть робочий каталог + + + + Set database cache size in megabytes (default: 25) + Встановити розмір кешу бази даних в мегабайтах (типово: 25) + + + + Set database disk log size in megabytes (default: 100) + + + + + Listen for connections on <port> (default: 9853 or testnet: 19853) + + + + + Maintain at most <n> connections to peers (default: 125) + Підтримувати не більше <n> зв'язків з колегами (типово: 125) + + + + Connect to a node to retrieve peer addresses, and disconnect + Підключитись до вузла, щоб отримати список адрес інших учасників та від'єднатись + + + + Specify your own public address + Вкажіть вашу власну публічну адресу + + + + Bind to given address. Use [host]:port notation for IPv6 + + + + + Stake your coins to support network and gain reward (default: 1) + + + + + Threshold for disconnecting misbehaving peers (default: 100) + Поріг відключення неправильно під'єднаних пірів (типово: 100) + + + + Number of seconds to keep misbehaving peers from reconnecting (default: 86400) + Максимальній розмір вхідного буферу на одне з'єднання (типово: 86400) + + + + An error occurred while setting up the RPC port %u for listening on IPv4: %s + + + + + Detach block and address databases. Increases shutdown time (default: 0) + + + + + 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. + + + + + Error: This transaction requires a transaction fee of at least %s because of its amount, complexity, or use of recently received funds + + + + + Listen for JSON-RPC connections on <port> (default: 9852 or testnet: 19852) + + + + + Accept command line and JSON-RPC commands + Приймати команди із командного рядка та команди JSON-RPC + + + + Error: Transaction creation failed + + + + + Error: Wallet locked, unable to create transaction + + + + + Importing blockchain data file. + + + + + Importing bootstrap blockchain data file. + + + + + Run in the background as a daemon and accept commands + Запустити в фоновому режимі (як демон) та приймати команди + + + + Use the test network + Використовувати тестову мережу + + + + Accept connections from outside (default: 1 if no -proxy or -connect) + Приймати з'єднання ззовні (за замовчуванням: 1, якщо ні-проксі або-з'єднання) + + + + An error occurred while setting up the RPC port %u for listening on IPv6, falling back to IPv4: %s + + + + + Error initializing database environment %s! To recover, BACKUP THAT DIRECTORY, then remove everything from it except for wallet.dat. + + + + + Set maximum size of high-priority/low-fee transactions in bytes (default: 27000) + + + + + Warning: -paytxfee is set very high! This is the transaction fee you will pay if you send a transaction. + Увага: встановлено занадто велику комісію (-paytxfee). Комісія зніматиметься кожен раз коли ви проводитимете транзакції. + + + + Warning: Please check that your computer's date and time are correct! If your clock is wrong Arepacoin will not work properly. + + + + + Warning: error reading wallet.dat! All keys read correctly, but transaction data or address book entries might be missing or incorrect. + Увага: помилка читання wallet.dat! Всі ключі прочитано коректно, але дані транзакцій чи записи адресної книги можуть бути пропущені, або пошкоджені. + + + + Warning: wallet.dat corrupt, data salvaged! Original wallet.dat saved as wallet.{timestamp}.bak in %s; if your balance or transactions are incorrect you should restore from a backup. + Увага: файл wallet.dat пошкоджено, дані врятовано! Оригінальний wallet.dat збережено як wallet.{timestamp}.bak до %s; якщо Ваш баланс чи транзакції неправильні, Ви можете відновити їх з резервної копії. + + + + Attempt to recover private keys from a corrupt wallet.dat + Спроба відновити закриті ключі з пошкодженого wallet.dat + + + + Block creation options: + Опції створення блоку: + + + + Connect only to the specified node(s) + Підключитись лише до вказаного вузла + + + + Discover own IP address (default: 1 when listening and no -externalip) + Відкрийте власну IP-адресу (за замовчуванням: 1, коли не чує і-externalip) + + + + Failed to listen on any port. Use -listen=0 if you want this. + Не вдалося слухати на будь-якому порту. Використовуйте-слухати = 0, якщо ви хочете цього. + + + + Find peers using DNS lookup (default: 1) + + + + + Sync checkpoints policy (default: strict) + + + + + Invalid -tor address: '%s' + + + + + Invalid amount for -reservebalance=<amount> + + + + + Maximum per-connection receive buffer, <n>*1000 bytes (default: 5000) + Максимальний буфер, <n>*1000 байт (типово: 5000) + + + + Maximum per-connection send buffer, <n>*1000 bytes (default: 1000) + Максимальній розмір вихідного буферу на одне з'єднання, <n>*1000 байт (типово: 1000) + + + + Only connect to nodes in network <net> (IPv4, IPv6 or Tor) + Підключити тільки до вузлів в мережі <net> (IPv4, IPv6 або Tor) + + + + Output extra debugging information. Implies all other -debug* options + + + + + Output extra network debugging information + + + + + Prepend debug output with timestamp + + + + + SSL options: (see the Bitcoin Wiki for SSL setup instructions) + Параметри SSL: (див. Bitcoin Wiki для налаштування SSL) + + + + Select the version of socks proxy to use (4-5, default: 5) + + + + + Send trace/debug info to console instead of debug.log file + Відсилати налагоджувальну інформацію на консоль, а не у файл debug.log + + + + Send trace/debug info to debugger + + + + + Set maximum block size in bytes (default: 250000) + + + + + Set minimum block size in bytes (default: 0) + Встановити мінімальний розмір блоку у байтах (типово: 0) + + + + Shrink debug.log file on client startup (default: 1 when no -debug) + Стискати файл debug.log під час старту клієнта (типово: 1 коли відсутутній параметр -debug) + + + + Specify connection timeout in milliseconds (default: 5000) + Вказати тайм-аут підключення у мілісекундах (типово: 5000) + + + + Unable to sign checkpoint, wrong checkpointkey? + + + + + + Use UPnP to map the listening port (default: 0) + Намагатись використовувати UPnP для відображення порту, що прослуховується на роутері (default: 0) + + + + Use UPnP to map the listening port (default: 1 when listening) + Намагатись використовувати UPnP для відображення порту, що прослуховується на роутері (default: 1 when listening) + + + + Use proxy to reach tor hidden services (default: same as -proxy) + + + + + Username for JSON-RPC connections + Ім'я користувача для JSON-RPC-з'єднань + + + + Verifying database integrity... + + + + + WARNING: syncronized checkpoint violation detected, but skipped! + + + + + Warning: Disk space is low! + + + + + Warning: This version is obsolete, upgrade required! + Увага: Поточна версія застаріла, необхідне оновлення! + + + + wallet.dat corrupt, salvage failed + wallet.dat пошкоджено, відновлення не вдалося + + + + Password for JSON-RPC connections + Пароль для JSON-RPC-з'єднань + + + + %s, you must set a rpcpassword in the configuration file: + %s +It is recommended you use the following random password: +rpcuser=arepacoinrpc +rpcpassword=%s +(you do not need to remember this password) +The username and password MUST NOT be the same. +If the file does not exist, create it with owner-readable-only file permissions. +It is also recommended to set alertnotify so you are notified of problems; +for example: alertnotify=echo %%s | mail -s "Arepacoin Alert" admin@foo.com + + + + + + Find peers using internet relay chat (default: 0) + + + + + Sync time with other nodes. Disable if time on your system is precise e.g. syncing with NTP (default: 1) + + + + + When creating transactions, ignore inputs with value less than this (default: 0.01) + + + + + Allow JSON-RPC connections from specified IP address + Дозволити JSON-RPC-з'єднання з вказаної IP-адреси + + + + Send commands to node running on <ip> (default: 127.0.0.1) + Відправляти команди на вузол, запущений на <ip> (типово: 127.0.0.1) + + + + Execute command when the best block changes (%s in cmd is replaced by block hash) + Виконати команду, коли з'явиться новий блок (%s в команді змінюється на хеш блоку) + + + + Execute command when a wallet transaction changes (%s in cmd is replaced by TxID) + + + + + Require a confirmations for change (default: 0) + + + + + Enforce transaction scripts to use canonical PUSH operators (default: 1) + + + + + Execute command when a relevant alert is received (%s in cmd is replaced by message) + + + + + Upgrade wallet to latest format + Модернізувати гаманець до останнього формату + + + + Set key pool size to <n> (default: 100) + Встановити розмір пулу ключів <n> (типово: 100) + + + + Rescan the block chain for missing wallet transactions + Пересканувати ланцюжок блоків, в пошуку втрачених транзакцій + + + + How many blocks to check at startup (default: 2500, 0 = all) + + + + + How thorough the block verification is (0-6, default: 1) + + + + + Imports blocks from external blk000?.dat file + + + + + Use OpenSSL (https) for JSON-RPC connections + Використовувати OpenSSL (https) для JSON-RPC-з'єднань + + + + Server certificate file (default: server.cert) + Файл сертифіката сервера (типово: server.cert) + + + + Server private key (default: server.pem) + Закритий ключ сервера (типово: server.pem) + + + + Acceptable ciphers (default: TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH) + + + + + Error: Wallet unlocked for staking only, unable to create transaction. + + + + + WARNING: Invalid checkpoint found! Displayed transactions may not be correct! You may need to upgrade, or notify developers. + + + + + This help message + Дана довідка + + + + Wallet %s resides outside data directory %s. + + + + + Cannot obtain a lock on data directory %s. Arepacoin is probably already running. + + + + + Arepacoin + + + + + Unable to bind to %s on this computer (bind returned error %d, %s) + Неможливо прив'язати до порту %s на цьому комп'ютері (bind returned error %d, %s) + + + + Connect through socks proxy + + + + + Allow DNS lookups for -addnode, -seednode and -connect + Дозволити пошук в DNS для команд -addnode, -seednode та -connect + + + + Loading addresses... + Завантаження адрес... + + + + Error loading blkindex.dat + + + + + Error loading wallet.dat: Wallet corrupted + Помилка при завантаженні wallet.dat: Гаманець пошкоджено + + + + Error loading wallet.dat: Wallet requires newer version of Arepacoin + + + + + Wallet needed to be rewritten: restart Arepacoin to complete + + + + + Error loading wallet.dat + Помилка при завантаженні wallet.dat + + + + Invalid -proxy address: '%s' + Помилка в адресі проксі-сервера: «%s» + + + + Unknown network specified in -onlynet: '%s' + Невідома мережа вказана в -onlynet: «%s» + + + + Unknown -socks proxy version requested: %i + В параметрі -socks запитується невідома версія: %i + + + + Cannot resolve -bind address: '%s' + + + + + Cannot resolve -externalip address: '%s' + + + + + Invalid amount for -paytxfee=<amount>: '%s' + Помилка у величині комісії -paytxfee=<amount>: «%s» + + + + Error: could not start node + + + + + Sending... + + + + + Invalid amount + Некоректна кількість + + + + Insufficient funds + Недостатньо коштів + + + + Loading block index... + Завантаження індексу блоків... + + + + Add a node to connect to and attempt to keep the connection open + Додати вузол до підключення і лишити його відкритим + + + + Unable to bind to %s on this computer. Arepacoin is probably already running. + + + + + Fee per KB to add to transactions you send + + + + + Invalid amount for -mininput=<amount>: '%s' + + + + + Loading wallet... + Завантаження гаманця... + + + + Cannot downgrade wallet + Не вдається понизити версію гаманця + + + + Cannot initialize keypool + + + + + Cannot write default address + Неможливо записати типову адресу + + + + Rescanning... + Сканування... + + + + Done loading + Завантаження завершене + + + + To use the %s option + Щоб використати опцію %s + + + + Error + Помилка + + + + You must set rpcpassword=<password> in the configuration file: +%s +If the file does not exist, create it with owner-readable-only file permissions. + Ви мусите встановити rpcpassword=<password> в файлі конфігурації: +%s +Якщо файл не існує, створіть його із правами тільки для читання власником (owner-readable-only). + + + \ No newline at end of file diff --git a/src/qt/locale/bitcoin_ur_PK.ts b/src/qt/locale/bitcoin_ur_PK.ts new file mode 100755 index 0000000..283ae14 --- /dev/null +++ b/src/qt/locale/bitcoin_ur_PK.ts @@ -0,0 +1,3275 @@ + + + AboutDialog + + + About Arepacoin + + + + + <b>Arepacoin</b> version + + + + + Copyright © 2009-2014 The Bitcoin developers +Copyright © 2012-2014 The NovaCoin developers +Copyright © 2014 The Arepacoin developers + + + + + +This is experimental software. + +Distributed under the MIT/X11 software license, see the accompanying file COPYING or http://www.opensource.org/licenses/mit-license.php. + +This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit (http://www.openssl.org/) and cryptographic software written by Eric Young (eay@cryptsoft.com) and UPnP software written by Thomas Bernard. + + + + + AddressBookPage + + + Address Book + + + + + Double-click to edit address or label + ایڈریس یا لیبل میں ترمیم کرنے پر ڈبل کلک کریں + + + + Create a new address + نیا ایڈریس بنائیں + + + + Copy the currently selected address to the system clipboard + + + + + &New Address + + + + + These are your Arepacoin addresses for receiving payments. You may want to give a different one to each sender so you can keep track of who is paying you. + + + + + &Copy Address + + + + + Show &QR Code + + + + + Sign a message to prove you own a Arepacoin address + + + + + Sign &Message + + + + + Delete the currently selected address from the list + + + + + Verify a message to ensure it was signed with a specified Arepacoin address + + + + + &Verify Message + + + + + &Delete + + + + + Copy &Label + + + + + &Edit + + + + + Export Address Book Data + + + + + Comma separated file (*.csv) + + + + + Error exporting + + + + + Could not write to file %1. + + + + + AddressTableModel + + + Label + چٹ + + + + Address + پتہ + + + + (no label) + چٹ کے بغیر + + + + AskPassphraseDialog + + + Passphrase Dialog + + + + + Enter passphrase + پاس فریز داخل کریں + + + + New passphrase + نیا پاس فریز + + + + Repeat new passphrase + نیا پاس فریز دہرائیں + + + + Serves to disable the trivial sendmoney when OS account compromised. Provides no real security. + + + + + For staking only + + + + + Enter the new passphrase to the wallet.<br/>Please use a passphrase of <b>10 or more random characters</b>, or <b>eight or more words</b>. + + + + + Encrypt wallet + + + + + This operation needs your wallet passphrase to unlock the wallet. + + + + + Unlock wallet + بٹوا ان لاک + + + + This operation needs your wallet passphrase to decrypt the wallet. + + + + + Decrypt wallet + خفیہ کشائی کر یںبٹوے کے + + + + Change passphrase + پاس فریز تبدیل کریں + + + + Enter the old and new passphrase to the wallet. + + + + + Confirm wallet encryption + + + + + Warning: If you encrypt your wallet and lose your passphrase, you will <b>LOSE ALL OF YOUR COINS</b>! + + + + + Are you sure you wish to encrypt your wallet? + + + + + IMPORTANT: Any previous backups you have made of your wallet file should be replaced with the newly generated, encrypted wallet file. For security reasons, previous backups of the unencrypted wallet file will become useless as soon as you start using the new, encrypted wallet. + + + + + + Warning: The Caps Lock key is on! + + + + + + Wallet encrypted + + + + + Arepacoin will close now to finish the encryption process. Remember that encrypting your wallet cannot fully protect your coins from being stolen by malware infecting your computer. + + + + + + + + Wallet encryption failed + + + + + Wallet encryption failed due to an internal error. Your wallet was not encrypted. + + + + + + The supplied passphrases do not match. + + + + + Wallet unlock failed + + + + + + + The passphrase entered for the wallet decryption was incorrect. + + + + + Wallet decryption failed + + + + + Wallet passphrase was successfully changed. + + + + + BitcoinGUI + + + Sign &message... + + + + + Synchronizing with network... + + + + + &Overview + + + + + Show general overview of wallet + + + + + &Transactions + + + + + Browse transaction history + + + + + &Address Book + + + + + Edit the list of stored addresses and labels + + + + + &Receive coins + + + + + Show the list of addresses for receiving payments + + + + + &Send coins + + + + + E&xit + + + + + Quit application + + + + + Show information about Arepacoin + + + + + About &Qt + + + + + Show information about Qt + + + + + &Options... + + + + + &Encrypt Wallet... + + + + + &Backup Wallet... + + + + + &Change Passphrase... + + + + + ~%n block(s) remaining + + + + + Downloaded %1 of %2 blocks of transaction history (%3% done). + + + + + &Export... + + + + + Send coins to a Arepacoin address + + + + + Modify configuration options for Arepacoin + + + + + Export the data in the current tab to a file + + + + + Encrypt or decrypt wallet + + + + + Backup wallet to another location + + + + + Change the passphrase used for wallet encryption + + + + + &Debug window + + + + + Open debugging and diagnostic console + + + + + &Verify message... + + + + + Arepacoin + + + + + Wallet + + + + + &About Arepacoin + + + + + &Show / Hide + + + + + Unlock wallet + + + + + &Lock Wallet + + + + + Lock wallet + + + + + &File + + + + + &Settings + + + + + &Help + + + + + Tabs toolbar + + + + + Actions toolbar + + + + + + [testnet] + + + + + + Arepacoin client + + + + + %n active connection(s) to Arepacoin network + + + + + Downloaded %1 blocks of transaction history. + + + + + Staking.<br>Your weight is %1<br>Network weight is %2<br>Expected time to earn reward is %3 + + + + + Not staking because wallet is locked + + + + + Not staking because wallet is offline + + + + + Not staking because wallet is syncing + + + + + Not staking because you don't have mature coins + + + + + %n second(s) ago + + + + + &Unlock Wallet... + + + + + %n minute(s) ago + + + + + %n hour(s) ago + + + + + %n day(s) ago + + + + + Up to date + + + + + Catching up... + + + + + Last received block was generated %1. + + + + + This transaction is over the size limit. You can still send it for a fee of %1, which goes to the nodes that process your transaction and helps to support the network. Do you want to pay the fee? + + + + + Confirm transaction fee + + + + + Sent transaction + + + + + Incoming transaction + + + + + Date: %1 +Amount: %2 +Type: %3 +Address: %4 + + + + + + + URI handling + + + + + + URI can not be parsed! This can be caused by an invalid Arepacoin address or malformed URI parameters. + + + + + Wallet is <b>encrypted</b> and currently <b>unlocked</b> + + + + + Wallet is <b>encrypted</b> and currently <b>locked</b> + + + + + Backup Wallet + + + + + Wallet Data (*.dat) + + + + + Backup Failed + + + + + There was an error trying to save the wallet data to the new location. + + + + + %n second(s) + + + + + %n minute(s) + + + + + %n hour(s) + + + + + %n day(s) + + + + + Not staking + + + + + A fatal error occurred. Arepacoin can no longer continue safely and will quit. + + + + + ClientModel + + + Network Alert + + + + + CoinControlDialog + + + Coin Control + + + + + Quantity: + + + + + Bytes: + + + + + Amount: + + + + + Priority: + + + + + Fee: + + + + + Low Output: + + + + + no + + + + + After Fee: + + + + + Change: + + + + + (un)select all + + + + + Tree mode + + + + + List mode + + + + + Amount + رقم + + + + Label + + + + + Address + پتہ + + + + Date + تاریخ + + + + Confirmations + + + + + Confirmed + + + + + Priority + + + + + Copy address + + + + + Copy label + + + + + + Copy amount + + + + + Copy transaction ID + + + + + Copy quantity + + + + + Copy fee + + + + + Copy after fee + + + + + Copy bytes + + + + + Copy priority + + + + + Copy low output + + + + + Copy change + + + + + highest + + + + + high + + + + + medium-high + + + + + medium + + + + + low-medium + + + + + low + + + + + lowest + + + + + DUST + + + + + yes + + + + + This label turns red, if the transaction size is bigger than 10000 bytes. + + This means a fee of at least %1 per kb is required. + + Can vary +/- 1 Byte per input. + + + + + Transactions with higher priority get more likely into a block. + +This label turns red, if the priority is smaller than "medium". + + This means a fee of at least %1 per kb is required. + + + + + This label turns red, if any recipient receives an amount smaller than %1. + + This means a fee of at least %2 is required. + + Amounts below 0.546 times the minimum relay fee are shown as DUST. + + + + + This label turns red, if the change is smaller than %1. + + This means a fee of at least %2 is required. + + + + + + (no label) + چٹ کے بغیر + + + + change from %1 (%2) + + + + + (change) + + + + + EditAddressDialog + + + Edit Address + + + + + &Label + + + + + The label associated with this address book entry + + + + + &Address + + + + + The address associated with this address book entry. This can only be modified for sending addresses. + + + + + New receiving address + + + + + New sending address + + + + + Edit receiving address + + + + + Edit sending address + + + + + The entered address "%1" is already in the address book. + + + + + The entered address "%1" is not a valid Arepacoin address. + + + + + Could not unlock wallet. + + + + + New key generation failed. + + + + + GUIUtil::HelpMessageBox + + + + Arepacoin-Qt + + + + + version + + + + + Usage: + + + + + command-line options + + + + + UI options + + + + + Set language, for example "de_DE" (default: system locale) + + + + + Start minimized + + + + + Show splash screen on startup (default: 1) + + + + + OptionsDialog + + + Options + + + + + &Main + + + + + Optional transaction fee per kB that helps make sure your transactions are processed quickly. Most transactions are 1 kB. Fee 0.01 recommended. + + + + + Pay transaction &fee + + + + + Reserved amount does not participate in staking and is therefore spendable at any time. + + + + + Reserve + + + + + Automatically start Arepacoin after logging in to the system. + + + + + &Start Arepacoin on system login + + + + + Detach block and address databases at shutdown. This means they can be moved to another data directory, but it slows down shutdown. The wallet is always detached. + + + + + &Detach databases at shutdown + + + + + &Network + + + + + Automatically open the Arepacoin client port on the router. This only works when your router supports UPnP and it is enabled. + + + + + Map port using &UPnP + + + + + Connect to the Arepacoin network through a SOCKS proxy (e.g. when connecting through Tor). + + + + + &Connect through SOCKS proxy: + + + + + Proxy &IP: + + + + + IP address of the proxy (e.g. 127.0.0.1) + + + + + &Port: + + + + + Port of the proxy (e.g. 9050) + + + + + SOCKS &Version: + + + + + SOCKS version of the proxy (e.g. 5) + + + + + &Window + + + + + Show only a tray icon after minimizing the window. + + + + + &Minimize to the tray instead of the taskbar + + + + + Minimize instead of exit the application when the window is closed. When this option is enabled, the application will be closed only after selecting Quit in the menu. + + + + + M&inimize on close + + + + + &Display + + + + + User Interface &language: + + + + + The user interface language can be set here. This setting will take effect after restarting Arepacoin. + + + + + &Unit to show amounts in: + + + + + Choose the default subdivision unit to show in the interface and when sending coins. + + + + + Whether to show Arepacoin addresses in the transaction list or not. + + + + + &Display addresses in transaction list + + + + + Whether to show coin control features or not. + + + + + Display coin &control features (experts only!) + + + + + &OK + + + + + &Cancel + + + + + &Apply + + + + + default + + + + + + Warning + + + + + + This setting will take effect after restarting Arepacoin. + + + + + The supplied proxy address is invalid. + + + + + OverviewPage + + + Form + + + + + + The displayed information may be out of date. Your wallet automatically synchronizes with the Arepacoin network after a connection is established, but this process has not completed yet. + + + + + Stake: + + + + + Unconfirmed: + + + + + Wallet + + + + + Spendable: + + + + + Your current spendable balance + + + + + Immature: + + + + + Mined balance that has not yet matured + + + + + Total: + + + + + Your current total balance + + + + + <b>Recent transactions</b> + + + + + Total of transactions that have yet to be confirmed, and do not yet count toward the current balance + + + + + Total of coins that was staked, and do not yet count toward the current balance + + + + + + out of sync + + + + + QRCodeDialog + + + QR Code Dialog + + + + + Request Payment + + + + + Amount: + + + + + Label: + + + + + Message: + + + + + &Save As... + + + + + Error encoding URI into QR Code. + + + + + The entered amount is invalid, please check. + + + + + Resulting URI too long, try to reduce the text for label / message. + + + + + Save QR Code + + + + + PNG Images (*.png) + + + + + RPCConsole + + + Client name + + + + + + + + + + + + + + N/A + + + + + Client version + + + + + &Information + + + + + Using OpenSSL version + + + + + Startup time + + + + + Network + + + + + Number of connections + + + + + On testnet + + + + + Block chain + + + + + Current number of blocks + + + + + Estimated total blocks + + + + + Last block time + + + + + &Open + + + + + Command-line options + + + + + Show the Arepacoin-Qt help message to get a list with possible Arepacoin command-line options. + + + + + &Show + + + + + &Console + + + + + Build date + + + + + Arepacoin - Debug window + + + + + Arepacoin Core + + + + + Debug log file + + + + + Open the Arepacoin debug log file from the current data directory. This can take a few seconds for large log files. + + + + + Clear console + + + + + Welcome to the Arepacoin RPC console. + + + + + Use up and down arrows to navigate history, and <b>Ctrl-L</b> to clear screen. + + + + + Type <b>help</b> for an overview of available commands. + + + + + SendCoinsDialog + + + + + + + + + + Send Coins + + + + + Coin Control Features + + + + + Inputs... + + + + + automatically selected + + + + + Insufficient funds! + + + + + Quantity: + + + + + + 0 + + + + + Bytes: + + + + + Amount: + + + + + + + + 0.00 BC + + + + + Priority: + + + + + medium + + + + + Fee: + + + + + Low Output: + + + + + no + + + + + After Fee: + + + + + Change + + + + + custom change address + + + + + Send to multiple recipients at once + + + + + Add &Recipient + + + + + Remove all transaction fields + + + + + Clear &All + + + + + Balance: + بیلنس: + + + + 123.456 BC + + + + + Confirm the send action + + + + + S&end + + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Copy quantity + + + + + Copy amount + + + + + Copy fee + + + + + Copy after fee + + + + + Copy bytes + + + + + Copy priority + + + + + Copy low output + + + + + Copy change + + + + + <b>%1</b> to %2 (%3) + + + + + Confirm send coins + + + + + Are you sure you want to send %1? + + + + + and + + + + + The recipient address is not valid, please recheck. + + + + + The amount to pay must be larger than 0. + + + + + The amount exceeds your balance. + + + + + The total exceeds your balance when the %1 transaction fee is included. + + + + + Duplicate address found, can only send to each address once per send operation. + + + + + Error: Transaction creation failed. + + + + + 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. + + + + + WARNING: Invalid Arepacoin address + + + + + (no label) + چٹ کے بغیر + + + + WARNING: unknown change address + + + + + SendCoinsEntry + + + Form + + + + + A&mount: + + + + + Pay &To: + + + + + + Enter a label for this address to add it to your address book + + + + + &Label: + + + + + The address to send the payment to (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Choose address from address book + + + + + Alt+A + + + + + Paste address from clipboard + + + + + Alt+P + + + + + Remove this recipient + + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + SignVerifyMessageDialog + + + Signatures - Sign / Verify a Message + + + + + + &Sign Message + + + + + You can sign messages with your addresses to prove you own them. Be careful not to sign anything vague, as phishing attacks may try to trick you into signing your identity over to them. Only sign fully-detailed statements you agree to. + + + + + The address to sign the message with (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + + Choose an address from the address book + + + + + + Alt+A + + + + + Paste address from clipboard + + + + + Alt+P + + + + + Enter the message you want to sign here + + + + + Copy the current signature to the system clipboard + + + + + Sign the message to prove you own this Arepacoin address + + + + + Reset all sign message fields + + + + + + Clear &All + + + + + + &Verify Message + + + + + Enter the signing address, message (ensure you copy line breaks, spaces, tabs, etc. exactly) and signature below to verify the message. Be careful not to read more into the signature than what is in the signed message itself, to avoid being tricked by a man-in-the-middle attack. + + + + + The address the message was signed with (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Verify the message to ensure it was signed with the specified Arepacoin address + + + + + Reset all verify message fields + + + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Click "Sign Message" to generate signature + + + + + Enter Arepacoin signature + + + + + + The entered address is invalid. + + + + + + + + Please check the address and try again. + + + + + + The entered address does not refer to a key. + + + + + Wallet unlock was cancelled. + + + + + Private key for the entered address is not available. + + + + + Message signing failed. + + + + + Message signed. + + + + + The signature could not be decoded. + + + + + + Please check the signature and try again. + + + + + The signature did not match the message digest. + + + + + Message verification failed. + + + + + Message verified. + + + + + TransactionDesc + + + Open until %1 + + + + + Open for %n block(s) + + + + + conflicted + + + + + %1/offline + + + + + %1/unconfirmed + + + + + %1 confirmations + + + + + Status + + + + + , broadcast through %n node(s) + + + + + Date + تاریخ + + + + Source + + + + + Generated + + + + + + From + + + + + + + To + + + + + + own address + + + + + label + + + + + + + + + Credit + + + + + matures in %n more block(s) + + + + + not accepted + + + + + + + + Debit + + + + + Transaction fee + + + + + Net amount + + + + + Message + + + + + Comment + + + + + Transaction ID + + + + + Generated coins must mature 6 blocks before they can be spent. When you generated this block, it was broadcast to the network to be added to the block chain. If it fails to get into the chain, its state will change to "not accepted" and it won't be spendable. This may occasionally happen if another node generates a block within a few seconds of yours. + + + + + Debug information + + + + + Transaction + + + + + Inputs + + + + + Amount + رقم + + + + true + + + + + false + + + + + , has not been successfully broadcast yet + + + + + unknown + + + + + TransactionDescDialog + + + Transaction details + + + + + This pane shows a detailed description of the transaction + + + + + TransactionTableModel + + + Date + تاریخ + + + + Type + ٹائپ + + + + Address + پتہ + + + + Amount + رقم + + + + Open until %1 + + + + + Confirmed (%1 confirmations) + + + + + Open for %n more block(s) + + + + + Offline + + + + + Unconfirmed + + + + + Confirming (%1 of %2 recommended confirmations) + + + + + Conflicted + + + + + Immature (%1 confirmations, will be available after %2) + + + + + This block was not received by any other nodes and will probably not be accepted! + + + + + Generated but not accepted + + + + + Received with + + + + + Received from + + + + + Sent to + کو بھیجا + + + + Payment to yourself + + + + + Mined + + + + + (n/a) + (N / A) + + + + Transaction status. Hover over this field to show number of confirmations. + + + + + Date and time that the transaction was received. + + + + + Type of transaction. + + + + + Destination address of transaction. + + + + + Amount removed from or added to balance. + + + + + TransactionView + + + + All + تمام + + + + Today + آج + + + + This week + اس ہفتے + + + + This month + اس مہینے + + + + Last month + پچھلے مہینے + + + + This year + اس سال + + + + Range... + دیگر + + + + Received with + + + + + Sent to + کو بھیجا + + + + To yourself + + + + + Mined + + + + + Other + + + + + Enter address or label to search + + + + + Min amount + + + + + Copy address + + + + + Copy label + + + + + Copy amount + + + + + Copy transaction ID + + + + + Edit label + + + + + Show transaction details + + + + + Export Transaction Data + + + + + Comma separated file (*.csv) + + + + + Confirmed + + + + + Date + تاریخ + + + + Type + ٹائپ + + + + Label + چٹ + + + + Address + پتہ + + + + Amount + رقم + + + + ID + + + + + Error exporting + + + + + Could not write to file %1. + + + + + Range: + + + + + to + + + + + WalletModel + + + Sending... + + + + + bitcoin-core + + + Arepacoin version + + + + + Usage: + + + + + Send command to -server or arepacoind + + + + + List commands + + + + + Get help for a command + + + + + Options: + + + + + Specify configuration file (default: arepacoin.conf) + + + + + Specify pid file (default: arepacoind.pid) + + + + + Specify wallet file (within data directory) + + + + + Specify data directory + + + + + Set database cache size in megabytes (default: 25) + + + + + Set database disk log size in megabytes (default: 100) + + + + + Listen for connections on <port> (default: 9853 or testnet: 19853) + + + + + Maintain at most <n> connections to peers (default: 125) + + + + + Connect to a node to retrieve peer addresses, and disconnect + + + + + Specify your own public address + + + + + Bind to given address. Use [host]:port notation for IPv6 + + + + + Stake your coins to support network and gain reward (default: 1) + + + + + Threshold for disconnecting misbehaving peers (default: 100) + + + + + Number of seconds to keep misbehaving peers from reconnecting (default: 86400) + + + + + An error occurred while setting up the RPC port %u for listening on IPv4: %s + + + + + Detach block and address databases. Increases shutdown time (default: 0) + + + + + 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. + + + + + Error: This transaction requires a transaction fee of at least %s because of its amount, complexity, or use of recently received funds + + + + + Listen for JSON-RPC connections on <port> (default: 9852 or testnet: 19852) + + + + + Accept command line and JSON-RPC commands + + + + + Error: Transaction creation failed + + + + + Error: Wallet locked, unable to create transaction + + + + + Importing blockchain data file. + + + + + Importing bootstrap blockchain data file. + + + + + Run in the background as a daemon and accept commands + + + + + Use the test network + + + + + Accept connections from outside (default: 1 if no -proxy or -connect) + + + + + An error occurred while setting up the RPC port %u for listening on IPv6, falling back to IPv4: %s + + + + + Error initializing database environment %s! To recover, BACKUP THAT DIRECTORY, then remove everything from it except for wallet.dat. + + + + + Set maximum size of high-priority/low-fee transactions in bytes (default: 27000) + + + + + Warning: -paytxfee is set very high! This is the transaction fee you will pay if you send a transaction. + + + + + Warning: Please check that your computer's date and time are correct! If your clock is wrong Arepacoin will not work properly. + + + + + Warning: error reading wallet.dat! All keys read correctly, but transaction data or address book entries might be missing or incorrect. + + + + + Warning: wallet.dat corrupt, data salvaged! Original wallet.dat saved as wallet.{timestamp}.bak in %s; if your balance or transactions are incorrect you should restore from a backup. + + + + + Attempt to recover private keys from a corrupt wallet.dat + + + + + Block creation options: + + + + + Connect only to the specified node(s) + + + + + Discover own IP address (default: 1 when listening and no -externalip) + + + + + Failed to listen on any port. Use -listen=0 if you want this. + + + + + Find peers using DNS lookup (default: 1) + + + + + Sync checkpoints policy (default: strict) + + + + + Invalid -tor address: '%s' + + + + + Invalid amount for -reservebalance=<amount> + + + + + Maximum per-connection receive buffer, <n>*1000 bytes (default: 5000) + + + + + Maximum per-connection send buffer, <n>*1000 bytes (default: 1000) + + + + + Only connect to nodes in network <net> (IPv4, IPv6 or Tor) + + + + + Output extra debugging information. Implies all other -debug* options + + + + + Output extra network debugging information + + + + + Prepend debug output with timestamp + + + + + SSL options: (see the Bitcoin Wiki for SSL setup instructions) + + + + + Select the version of socks proxy to use (4-5, default: 5) + + + + + Send trace/debug info to console instead of debug.log file + + + + + Send trace/debug info to debugger + + + + + Set maximum block size in bytes (default: 250000) + + + + + Set minimum block size in bytes (default: 0) + + + + + Shrink debug.log file on client startup (default: 1 when no -debug) + + + + + Specify connection timeout in milliseconds (default: 5000) + + + + + Unable to sign checkpoint, wrong checkpointkey? + + + + + + Use UPnP to map the listening port (default: 0) + + + + + Use UPnP to map the listening port (default: 1 when listening) + + + + + Use proxy to reach tor hidden services (default: same as -proxy) + + + + + Username for JSON-RPC connections + + + + + Verifying database integrity... + + + + + WARNING: syncronized checkpoint violation detected, but skipped! + + + + + Warning: Disk space is low! + + + + + Warning: This version is obsolete, upgrade required! + + + + + wallet.dat corrupt, salvage failed + + + + + Password for JSON-RPC connections + + + + + %s, you must set a rpcpassword in the configuration file: + %s +It is recommended you use the following random password: +rpcuser=arepacoinrpc +rpcpassword=%s +(you do not need to remember this password) +The username and password MUST NOT be the same. +If the file does not exist, create it with owner-readable-only file permissions. +It is also recommended to set alertnotify so you are notified of problems; +for example: alertnotify=echo %%s | mail -s "Arepacoin Alert" admin@foo.com + + + + + + Find peers using internet relay chat (default: 0) + + + + + Sync time with other nodes. Disable if time on your system is precise e.g. syncing with NTP (default: 1) + + + + + When creating transactions, ignore inputs with value less than this (default: 0.01) + + + + + Allow JSON-RPC connections from specified IP address + + + + + Send commands to node running on <ip> (default: 127.0.0.1) + + + + + Execute command when the best block changes (%s in cmd is replaced by block hash) + + + + + Execute command when a wallet transaction changes (%s in cmd is replaced by TxID) + + + + + Require a confirmations for change (default: 0) + + + + + Enforce transaction scripts to use canonical PUSH operators (default: 1) + + + + + Execute command when a relevant alert is received (%s in cmd is replaced by message) + + + + + Upgrade wallet to latest format + + + + + Set key pool size to <n> (default: 100) + + + + + Rescan the block chain for missing wallet transactions + + + + + How many blocks to check at startup (default: 2500, 0 = all) + + + + + How thorough the block verification is (0-6, default: 1) + + + + + Imports blocks from external blk000?.dat file + + + + + Use OpenSSL (https) for JSON-RPC connections + + + + + Server certificate file (default: server.cert) + + + + + Server private key (default: server.pem) + + + + + Acceptable ciphers (default: TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH) + + + + + Error: Wallet unlocked for staking only, unable to create transaction. + + + + + WARNING: Invalid checkpoint found! Displayed transactions may not be correct! You may need to upgrade, or notify developers. + + + + + This help message + یہ مدد کا پیغام + + + + Wallet %s resides outside data directory %s. + + + + + Cannot obtain a lock on data directory %s. Arepacoin is probably already running. + + + + + Arepacoin + + + + + Unable to bind to %s on this computer (bind returned error %d, %s) + + + + + Connect through socks proxy + + + + + Allow DNS lookups for -addnode, -seednode and -connect + + + + + Loading addresses... + + + + + Error loading blkindex.dat + + + + + Error loading wallet.dat: Wallet corrupted + + + + + Error loading wallet.dat: Wallet requires newer version of Arepacoin + + + + + Wallet needed to be rewritten: restart Arepacoin to complete + + + + + Error loading wallet.dat + + + + + Invalid -proxy address: '%s' + + + + + Unknown network specified in -onlynet: '%s' + + + + + Unknown -socks proxy version requested: %i + + + + + Cannot resolve -bind address: '%s' + + + + + Cannot resolve -externalip address: '%s' + + + + + Invalid amount for -paytxfee=<amount>: '%s' + + + + + Error: could not start node + + + + + Sending... + + + + + Invalid amount + غلط رقم + + + + Insufficient funds + ناکافی فنڈز + + + + Loading block index... + + + + + Add a node to connect to and attempt to keep the connection open + + + + + Unable to bind to %s on this computer. Arepacoin is probably already running. + + + + + Fee per KB to add to transactions you send + + + + + Invalid amount for -mininput=<amount>: '%s' + + + + + Loading wallet... + + + + + Cannot downgrade wallet + + + + + Cannot initialize keypool + + + + + Cannot write default address + + + + + Rescanning... + + + + + Done loading + + + + + To use the %s option + + + + + Error + نقص + + + + You must set rpcpassword=<password> in the configuration file: +%s +If the file does not exist, create it with owner-readable-only file permissions. + + + + \ No newline at end of file diff --git a/src/qt/locale/bitcoin_vi.ts b/src/qt/locale/bitcoin_vi.ts new file mode 100755 index 0000000..69f8fdc --- /dev/null +++ b/src/qt/locale/bitcoin_vi.ts @@ -0,0 +1,3275 @@ + + + AboutDialog + + + About Arepacoin + + + + + <b>Arepacoin</b> version + + + + + Copyright © 2009-2014 The Bitcoin developers +Copyright © 2012-2014 The NovaCoin developers +Copyright © 2014 The Arepacoin developers + + + + + +This is experimental software. + +Distributed under the MIT/X11 software license, see the accompanying file COPYING or http://www.opensource.org/licenses/mit-license.php. + +This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit (http://www.openssl.org/) and cryptographic software written by Eric Young (eay@cryptsoft.com) and UPnP software written by Thomas Bernard. + + + + + AddressBookPage + + + Address Book + + + + + Double-click to edit address or label + Click đúp chuột để chỉnh sửa địa chỉ hoặc nhãn dữ liệu + + + + Create a new address + Tạo một địa chỉ mới + + + + Copy the currently selected address to the system clipboard + Sao chép các địa chỉ đã được chọn vào bộ nhớ tạm thời của hệ thống + + + + &New Address + + + + + These are your Arepacoin addresses for receiving payments. You may want to give a different one to each sender so you can keep track of who is paying you. + + + + + &Copy Address + + + + + Show &QR Code + + + + + Sign a message to prove you own a Arepacoin address + + + + + Sign &Message + + + + + Delete the currently selected address from the list + + + + + Verify a message to ensure it was signed with a specified Arepacoin address + + + + + &Verify Message + + + + + &Delete + &Xóa + + + + Copy &Label + + + + + &Edit + + + + + Export Address Book Data + + + + + Comma separated file (*.csv) + Tập tin tách biệt bởi dấu phẩy (*.csv) + + + + Error exporting + + + + + Could not write to file %1. + + + + + AddressTableModel + + + Label + Nhãn dữ liệu + + + + Address + Địa chỉ + + + + (no label) + (chưa có nhãn) + + + + AskPassphraseDialog + + + Passphrase Dialog + + + + + Enter passphrase + + + + + New passphrase + + + + + Repeat new passphrase + + + + + Serves to disable the trivial sendmoney when OS account compromised. Provides no real security. + + + + + For staking only + + + + + Enter the new passphrase to the wallet.<br/>Please use a passphrase of <b>10 or more random characters</b>, or <b>eight or more words</b>. + + + + + Encrypt wallet + + + + + This operation needs your wallet passphrase to unlock the wallet. + + + + + Unlock wallet + + + + + This operation needs your wallet passphrase to decrypt the wallet. + + + + + Decrypt wallet + + + + + Change passphrase + + + + + Enter the old and new passphrase to the wallet. + + + + + Confirm wallet encryption + + + + + Warning: If you encrypt your wallet and lose your passphrase, you will <b>LOSE ALL OF YOUR COINS</b>! + + + + + Are you sure you wish to encrypt your wallet? + + + + + IMPORTANT: Any previous backups you have made of your wallet file should be replaced with the newly generated, encrypted wallet file. For security reasons, previous backups of the unencrypted wallet file will become useless as soon as you start using the new, encrypted wallet. + + + + + + Warning: The Caps Lock key is on! + + + + + + Wallet encrypted + + + + + Arepacoin will close now to finish the encryption process. Remember that encrypting your wallet cannot fully protect your coins from being stolen by malware infecting your computer. + + + + + + + + Wallet encryption failed + + + + + Wallet encryption failed due to an internal error. Your wallet was not encrypted. + + + + + + The supplied passphrases do not match. + + + + + Wallet unlock failed + + + + + + + The passphrase entered for the wallet decryption was incorrect. + + + + + Wallet decryption failed + + + + + Wallet passphrase was successfully changed. + + + + + BitcoinGUI + + + Sign &message... + + + + + Synchronizing with network... + + + + + &Overview + + + + + Show general overview of wallet + + + + + &Transactions + + + + + Browse transaction history + + + + + &Address Book + + + + + Edit the list of stored addresses and labels + + + + + &Receive coins + + + + + Show the list of addresses for receiving payments + + + + + &Send coins + + + + + E&xit + + + + + Quit application + + + + + Show information about Arepacoin + + + + + About &Qt + + + + + Show information about Qt + + + + + &Options... + + + + + &Encrypt Wallet... + + + + + &Backup Wallet... + + + + + &Change Passphrase... + + + + + ~%n block(s) remaining + + + + + Downloaded %1 of %2 blocks of transaction history (%3% done). + + + + + &Export... + + + + + Send coins to a Arepacoin address + + + + + Modify configuration options for Arepacoin + + + + + Export the data in the current tab to a file + + + + + Encrypt or decrypt wallet + + + + + Backup wallet to another location + + + + + Change the passphrase used for wallet encryption + + + + + &Debug window + + + + + Open debugging and diagnostic console + + + + + &Verify message... + + + + + Arepacoin + + + + + Wallet + + + + + &About Arepacoin + + + + + &Show / Hide + + + + + Unlock wallet + + + + + &Lock Wallet + + + + + Lock wallet + + + + + &File + + + + + &Settings + + + + + &Help + + + + + Tabs toolbar + + + + + Actions toolbar + + + + + + [testnet] + + + + + + Arepacoin client + + + + + %n active connection(s) to Arepacoin network + + + + + Downloaded %1 blocks of transaction history. + + + + + Staking.<br>Your weight is %1<br>Network weight is %2<br>Expected time to earn reward is %3 + + + + + Not staking because wallet is locked + + + + + Not staking because wallet is offline + + + + + Not staking because wallet is syncing + + + + + Not staking because you don't have mature coins + + + + + %n second(s) ago + + + + + &Unlock Wallet... + + + + + %n minute(s) ago + + + + + %n hour(s) ago + + + + + %n day(s) ago + + + + + Up to date + + + + + Catching up... + + + + + Last received block was generated %1. + + + + + This transaction is over the size limit. You can still send it for a fee of %1, which goes to the nodes that process your transaction and helps to support the network. Do you want to pay the fee? + + + + + Confirm transaction fee + + + + + Sent transaction + + + + + Incoming transaction + + + + + Date: %1 +Amount: %2 +Type: %3 +Address: %4 + + + + + + + URI handling + + + + + + URI can not be parsed! This can be caused by an invalid Arepacoin address or malformed URI parameters. + + + + + Wallet is <b>encrypted</b> and currently <b>unlocked</b> + + + + + Wallet is <b>encrypted</b> and currently <b>locked</b> + + + + + Backup Wallet + + + + + Wallet Data (*.dat) + + + + + Backup Failed + + + + + There was an error trying to save the wallet data to the new location. + + + + + %n second(s) + + + + + %n minute(s) + + + + + %n hour(s) + + + + + %n day(s) + + + + + Not staking + + + + + A fatal error occurred. Arepacoin can no longer continue safely and will quit. + + + + + ClientModel + + + Network Alert + + + + + CoinControlDialog + + + Coin Control + + + + + Quantity: + + + + + Bytes: + + + + + Amount: + + + + + Priority: + + + + + Fee: + + + + + Low Output: + + + + + no + + + + + After Fee: + + + + + Change: + + + + + (un)select all + + + + + Tree mode + + + + + List mode + + + + + Amount + Số lượng + + + + Label + + + + + Address + Địa chỉ + + + + Date + + + + + Confirmations + + + + + Confirmed + + + + + Priority + + + + + Copy address + + + + + Copy label + + + + + + Copy amount + + + + + Copy transaction ID + + + + + Copy quantity + + + + + Copy fee + + + + + Copy after fee + + + + + Copy bytes + + + + + Copy priority + + + + + Copy low output + + + + + Copy change + + + + + highest + + + + + high + + + + + medium-high + + + + + medium + + + + + low-medium + + + + + low + + + + + lowest + + + + + DUST + + + + + yes + + + + + This label turns red, if the transaction size is bigger than 10000 bytes. + + This means a fee of at least %1 per kb is required. + + Can vary +/- 1 Byte per input. + + + + + Transactions with higher priority get more likely into a block. + +This label turns red, if the priority is smaller than "medium". + + This means a fee of at least %1 per kb is required. + + + + + This label turns red, if any recipient receives an amount smaller than %1. + + This means a fee of at least %2 is required. + + Amounts below 0.546 times the minimum relay fee are shown as DUST. + + + + + This label turns red, if the change is smaller than %1. + + This means a fee of at least %2 is required. + + + + + + (no label) + (chưa có nhãn) + + + + change from %1 (%2) + + + + + (change) + + + + + EditAddressDialog + + + Edit Address + + + + + &Label + + + + + The label associated with this address book entry + + + + + &Address + + + + + The address associated with this address book entry. This can only be modified for sending addresses. + + + + + New receiving address + + + + + New sending address + + + + + Edit receiving address + + + + + Edit sending address + + + + + The entered address "%1" is already in the address book. + + + + + The entered address "%1" is not a valid Arepacoin address. + + + + + Could not unlock wallet. + + + + + New key generation failed. + + + + + GUIUtil::HelpMessageBox + + + + Arepacoin-Qt + + + + + version + + + + + Usage: + + + + + command-line options + + + + + UI options + + + + + Set language, for example "de_DE" (default: system locale) + + + + + Start minimized + + + + + Show splash screen on startup (default: 1) + + + + + OptionsDialog + + + Options + + + + + &Main + + + + + Optional transaction fee per kB that helps make sure your transactions are processed quickly. Most transactions are 1 kB. Fee 0.01 recommended. + + + + + Pay transaction &fee + + + + + Reserved amount does not participate in staking and is therefore spendable at any time. + + + + + Reserve + + + + + Automatically start Arepacoin after logging in to the system. + + + + + &Start Arepacoin on system login + + + + + Detach block and address databases at shutdown. This means they can be moved to another data directory, but it slows down shutdown. The wallet is always detached. + + + + + &Detach databases at shutdown + + + + + &Network + + + + + Automatically open the Arepacoin client port on the router. This only works when your router supports UPnP and it is enabled. + + + + + Map port using &UPnP + + + + + Connect to the Arepacoin network through a SOCKS proxy (e.g. when connecting through Tor). + + + + + &Connect through SOCKS proxy: + + + + + Proxy &IP: + + + + + IP address of the proxy (e.g. 127.0.0.1) + + + + + &Port: + + + + + Port of the proxy (e.g. 9050) + + + + + SOCKS &Version: + + + + + SOCKS version of the proxy (e.g. 5) + + + + + &Window + + + + + Show only a tray icon after minimizing the window. + + + + + &Minimize to the tray instead of the taskbar + + + + + Minimize instead of exit the application when the window is closed. When this option is enabled, the application will be closed only after selecting Quit in the menu. + + + + + M&inimize on close + + + + + &Display + + + + + User Interface &language: + + + + + The user interface language can be set here. This setting will take effect after restarting Arepacoin. + + + + + &Unit to show amounts in: + + + + + Choose the default subdivision unit to show in the interface and when sending coins. + + + + + Whether to show Arepacoin addresses in the transaction list or not. + + + + + &Display addresses in transaction list + + + + + Whether to show coin control features or not. + + + + + Display coin &control features (experts only!) + + + + + &OK + + + + + &Cancel + + + + + &Apply + + + + + default + + + + + + Warning + + + + + + This setting will take effect after restarting Arepacoin. + + + + + The supplied proxy address is invalid. + + + + + OverviewPage + + + Form + + + + + + The displayed information may be out of date. Your wallet automatically synchronizes with the Arepacoin network after a connection is established, but this process has not completed yet. + + + + + Stake: + + + + + Unconfirmed: + + + + + Wallet + + + + + Spendable: + + + + + Your current spendable balance + + + + + Immature: + + + + + Mined balance that has not yet matured + + + + + Total: + + + + + Your current total balance + + + + + <b>Recent transactions</b> + + + + + Total of transactions that have yet to be confirmed, and do not yet count toward the current balance + + + + + Total of coins that was staked, and do not yet count toward the current balance + + + + + + out of sync + + + + + QRCodeDialog + + + QR Code Dialog + + + + + Request Payment + + + + + Amount: + + + + + Label: + + + + + Message: + + + + + &Save As... + + + + + Error encoding URI into QR Code. + + + + + The entered amount is invalid, please check. + + + + + Resulting URI too long, try to reduce the text for label / message. + + + + + Save QR Code + + + + + PNG Images (*.png) + + + + + RPCConsole + + + Client name + + + + + + + + + + + + + + N/A + + + + + Client version + + + + + &Information + + + + + Using OpenSSL version + + + + + Startup time + + + + + Network + + + + + Number of connections + + + + + On testnet + + + + + Block chain + + + + + Current number of blocks + + + + + Estimated total blocks + + + + + Last block time + + + + + &Open + + + + + Command-line options + + + + + Show the Arepacoin-Qt help message to get a list with possible Arepacoin command-line options. + + + + + &Show + + + + + &Console + + + + + Build date + + + + + Arepacoin - Debug window + + + + + Arepacoin Core + + + + + Debug log file + + + + + Open the Arepacoin debug log file from the current data directory. This can take a few seconds for large log files. + + + + + Clear console + + + + + Welcome to the Arepacoin RPC console. + + + + + Use up and down arrows to navigate history, and <b>Ctrl-L</b> to clear screen. + + + + + Type <b>help</b> for an overview of available commands. + + + + + SendCoinsDialog + + + + + + + + + + Send Coins + + + + + Coin Control Features + + + + + Inputs... + + + + + automatically selected + + + + + Insufficient funds! + + + + + Quantity: + + + + + + 0 + + + + + Bytes: + + + + + Amount: + + + + + + + + 0.00 BC + + + + + Priority: + + + + + medium + + + + + Fee: + + + + + Low Output: + + + + + no + + + + + After Fee: + + + + + Change + + + + + custom change address + + + + + Send to multiple recipients at once + + + + + Add &Recipient + + + + + Remove all transaction fields + + + + + Clear &All + + + + + Balance: + + + + + 123.456 BC + + + + + Confirm the send action + + + + + S&end + + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Copy quantity + + + + + Copy amount + + + + + Copy fee + + + + + Copy after fee + + + + + Copy bytes + + + + + Copy priority + + + + + Copy low output + + + + + Copy change + + + + + <b>%1</b> to %2 (%3) + + + + + Confirm send coins + + + + + Are you sure you want to send %1? + + + + + and + + + + + The recipient address is not valid, please recheck. + + + + + The amount to pay must be larger than 0. + + + + + The amount exceeds your balance. + + + + + The total exceeds your balance when the %1 transaction fee is included. + + + + + Duplicate address found, can only send to each address once per send operation. + + + + + Error: Transaction creation failed. + + + + + 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. + + + + + WARNING: Invalid Arepacoin address + + + + + (no label) + (chưa có nhãn) + + + + WARNING: unknown change address + + + + + SendCoinsEntry + + + Form + + + + + A&mount: + + + + + Pay &To: + + + + + + Enter a label for this address to add it to your address book + + + + + &Label: + + + + + The address to send the payment to (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Choose address from address book + + + + + Alt+A + + + + + Paste address from clipboard + + + + + Alt+P + + + + + Remove this recipient + + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + SignVerifyMessageDialog + + + Signatures - Sign / Verify a Message + + + + + + &Sign Message + + + + + You can sign messages with your addresses to prove you own them. Be careful not to sign anything vague, as phishing attacks may try to trick you into signing your identity over to them. Only sign fully-detailed statements you agree to. + + + + + The address to sign the message with (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + + Choose an address from the address book + + + + + + Alt+A + + + + + Paste address from clipboard + + + + + Alt+P + + + + + Enter the message you want to sign here + + + + + Copy the current signature to the system clipboard + + + + + Sign the message to prove you own this Arepacoin address + + + + + Reset all sign message fields + + + + + + Clear &All + + + + + + &Verify Message + + + + + Enter the signing address, message (ensure you copy line breaks, spaces, tabs, etc. exactly) and signature below to verify the message. Be careful not to read more into the signature than what is in the signed message itself, to avoid being tricked by a man-in-the-middle attack. + + + + + The address the message was signed with (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Verify the message to ensure it was signed with the specified Arepacoin address + + + + + Reset all verify message fields + + + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Click "Sign Message" to generate signature + + + + + Enter Arepacoin signature + + + + + + The entered address is invalid. + + + + + + + + Please check the address and try again. + + + + + + The entered address does not refer to a key. + + + + + Wallet unlock was cancelled. + + + + + Private key for the entered address is not available. + + + + + Message signing failed. + + + + + Message signed. + + + + + The signature could not be decoded. + + + + + + Please check the signature and try again. + + + + + The signature did not match the message digest. + + + + + Message verification failed. + + + + + Message verified. + + + + + TransactionDesc + + + Open until %1 + + + + + Open for %n block(s) + + + + + conflicted + + + + + %1/offline + + + + + %1/unconfirmed + + + + + %1 confirmations + + + + + Status + + + + + , broadcast through %n node(s) + + + + + Date + + + + + Source + + + + + Generated + + + + + + From + + + + + + + To + + + + + + own address + + + + + label + + + + + + + + + Credit + + + + + matures in %n more block(s) + + + + + not accepted + + + + + + + + Debit + + + + + Transaction fee + + + + + Net amount + + + + + Message + + + + + Comment + + + + + Transaction ID + + + + + Generated coins must mature 6 blocks before they can be spent. When you generated this block, it was broadcast to the network to be added to the block chain. If it fails to get into the chain, its state will change to "not accepted" and it won't be spendable. This may occasionally happen if another node generates a block within a few seconds of yours. + + + + + Debug information + + + + + Transaction + + + + + Inputs + + + + + Amount + Số lượng + + + + true + + + + + false + + + + + , has not been successfully broadcast yet + + + + + unknown + + + + + TransactionDescDialog + + + Transaction details + + + + + This pane shows a detailed description of the transaction + + + + + TransactionTableModel + + + Date + + + + + Type + + + + + Address + Địa chỉ + + + + Amount + Số lượng + + + + Open until %1 + + + + + Confirmed (%1 confirmations) + + + + + Open for %n more block(s) + + + + + Offline + + + + + Unconfirmed + + + + + Confirming (%1 of %2 recommended confirmations) + + + + + Conflicted + + + + + Immature (%1 confirmations, will be available after %2) + + + + + This block was not received by any other nodes and will probably not be accepted! + + + + + Generated but not accepted + + + + + Received with + + + + + Received from + + + + + Sent to + + + + + Payment to yourself + + + + + Mined + + + + + (n/a) + + + + + Transaction status. Hover over this field to show number of confirmations. + + + + + Date and time that the transaction was received. + + + + + Type of transaction. + + + + + Destination address of transaction. + + + + + Amount removed from or added to balance. + + + + + TransactionView + + + + All + + + + + Today + + + + + This week + + + + + This month + + + + + Last month + + + + + This year + + + + + Range... + + + + + Received with + + + + + Sent to + + + + + To yourself + + + + + Mined + + + + + Other + + + + + Enter address or label to search + + + + + Min amount + + + + + Copy address + + + + + Copy label + + + + + Copy amount + + + + + Copy transaction ID + + + + + Edit label + + + + + Show transaction details + + + + + Export Transaction Data + + + + + Comma separated file (*.csv) + Tập tin tách biệt bởi dấu phẩy (*.csv) + + + + Confirmed + + + + + Date + + + + + Type + + + + + Label + Nhãn dữ liệu + + + + Address + Địa chỉ + + + + Amount + Số lượng + + + + ID + + + + + Error exporting + + + + + Could not write to file %1. + + + + + Range: + + + + + to + + + + + WalletModel + + + Sending... + + + + + bitcoin-core + + + Arepacoin version + + + + + Usage: + + + + + Send command to -server or arepacoind + + + + + List commands + + + + + Get help for a command + + + + + Options: + + + + + Specify configuration file (default: arepacoin.conf) + + + + + Specify pid file (default: arepacoind.pid) + + + + + Specify wallet file (within data directory) + + + + + Specify data directory + + + + + Set database cache size in megabytes (default: 25) + + + + + Set database disk log size in megabytes (default: 100) + + + + + Listen for connections on <port> (default: 9853 or testnet: 19853) + + + + + Maintain at most <n> connections to peers (default: 125) + + + + + Connect to a node to retrieve peer addresses, and disconnect + + + + + Specify your own public address + + + + + Bind to given address. Use [host]:port notation for IPv6 + + + + + Stake your coins to support network and gain reward (default: 1) + + + + + Threshold for disconnecting misbehaving peers (default: 100) + + + + + Number of seconds to keep misbehaving peers from reconnecting (default: 86400) + + + + + An error occurred while setting up the RPC port %u for listening on IPv4: %s + + + + + Detach block and address databases. Increases shutdown time (default: 0) + + + + + 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. + + + + + Error: This transaction requires a transaction fee of at least %s because of its amount, complexity, or use of recently received funds + + + + + Listen for JSON-RPC connections on <port> (default: 9852 or testnet: 19852) + + + + + Accept command line and JSON-RPC commands + + + + + Error: Transaction creation failed + + + + + Error: Wallet locked, unable to create transaction + + + + + Importing blockchain data file. + + + + + Importing bootstrap blockchain data file. + + + + + Run in the background as a daemon and accept commands + + + + + Use the test network + + + + + Accept connections from outside (default: 1 if no -proxy or -connect) + + + + + An error occurred while setting up the RPC port %u for listening on IPv6, falling back to IPv4: %s + + + + + Error initializing database environment %s! To recover, BACKUP THAT DIRECTORY, then remove everything from it except for wallet.dat. + + + + + Set maximum size of high-priority/low-fee transactions in bytes (default: 27000) + + + + + Warning: -paytxfee is set very high! This is the transaction fee you will pay if you send a transaction. + + + + + Warning: Please check that your computer's date and time are correct! If your clock is wrong Arepacoin will not work properly. + + + + + Warning: error reading wallet.dat! All keys read correctly, but transaction data or address book entries might be missing or incorrect. + + + + + Warning: wallet.dat corrupt, data salvaged! Original wallet.dat saved as wallet.{timestamp}.bak in %s; if your balance or transactions are incorrect you should restore from a backup. + + + + + Attempt to recover private keys from a corrupt wallet.dat + + + + + Block creation options: + + + + + Connect only to the specified node(s) + + + + + Discover own IP address (default: 1 when listening and no -externalip) + + + + + Failed to listen on any port. Use -listen=0 if you want this. + + + + + Find peers using DNS lookup (default: 1) + + + + + Sync checkpoints policy (default: strict) + + + + + Invalid -tor address: '%s' + + + + + Invalid amount for -reservebalance=<amount> + + + + + Maximum per-connection receive buffer, <n>*1000 bytes (default: 5000) + + + + + Maximum per-connection send buffer, <n>*1000 bytes (default: 1000) + + + + + Only connect to nodes in network <net> (IPv4, IPv6 or Tor) + + + + + Output extra debugging information. Implies all other -debug* options + + + + + Output extra network debugging information + + + + + Prepend debug output with timestamp + + + + + SSL options: (see the Bitcoin Wiki for SSL setup instructions) + + + + + Select the version of socks proxy to use (4-5, default: 5) + + + + + Send trace/debug info to console instead of debug.log file + + + + + Send trace/debug info to debugger + + + + + Set maximum block size in bytes (default: 250000) + + + + + Set minimum block size in bytes (default: 0) + + + + + Shrink debug.log file on client startup (default: 1 when no -debug) + + + + + Specify connection timeout in milliseconds (default: 5000) + + + + + Unable to sign checkpoint, wrong checkpointkey? + + + + + + Use UPnP to map the listening port (default: 0) + + + + + Use UPnP to map the listening port (default: 1 when listening) + + + + + Use proxy to reach tor hidden services (default: same as -proxy) + + + + + Username for JSON-RPC connections + + + + + Verifying database integrity... + + + + + WARNING: syncronized checkpoint violation detected, but skipped! + + + + + Warning: Disk space is low! + + + + + Warning: This version is obsolete, upgrade required! + + + + + wallet.dat corrupt, salvage failed + + + + + Password for JSON-RPC connections + + + + + %s, you must set a rpcpassword in the configuration file: + %s +It is recommended you use the following random password: +rpcuser=arepacoinrpc +rpcpassword=%s +(you do not need to remember this password) +The username and password MUST NOT be the same. +If the file does not exist, create it with owner-readable-only file permissions. +It is also recommended to set alertnotify so you are notified of problems; +for example: alertnotify=echo %%s | mail -s "Arepacoin Alert" admin@foo.com + + + + + + Find peers using internet relay chat (default: 0) + + + + + Sync time with other nodes. Disable if time on your system is precise e.g. syncing with NTP (default: 1) + + + + + When creating transactions, ignore inputs with value less than this (default: 0.01) + + + + + Allow JSON-RPC connections from specified IP address + + + + + Send commands to node running on <ip> (default: 127.0.0.1) + + + + + Execute command when the best block changes (%s in cmd is replaced by block hash) + + + + + Execute command when a wallet transaction changes (%s in cmd is replaced by TxID) + + + + + Require a confirmations for change (default: 0) + + + + + Enforce transaction scripts to use canonical PUSH operators (default: 1) + + + + + Execute command when a relevant alert is received (%s in cmd is replaced by message) + + + + + Upgrade wallet to latest format + + + + + Set key pool size to <n> (default: 100) + + + + + Rescan the block chain for missing wallet transactions + + + + + How many blocks to check at startup (default: 2500, 0 = all) + + + + + How thorough the block verification is (0-6, default: 1) + + + + + Imports blocks from external blk000?.dat file + + + + + Use OpenSSL (https) for JSON-RPC connections + + + + + Server certificate file (default: server.cert) + + + + + Server private key (default: server.pem) + + + + + Acceptable ciphers (default: TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH) + + + + + Error: Wallet unlocked for staking only, unable to create transaction. + + + + + WARNING: Invalid checkpoint found! Displayed transactions may not be correct! You may need to upgrade, or notify developers. + + + + + This help message + + + + + Wallet %s resides outside data directory %s. + + + + + Cannot obtain a lock on data directory %s. Arepacoin is probably already running. + + + + + Arepacoin + + + + + Unable to bind to %s on this computer (bind returned error %d, %s) + + + + + Connect through socks proxy + + + + + Allow DNS lookups for -addnode, -seednode and -connect + + + + + Loading addresses... + + + + + Error loading blkindex.dat + + + + + Error loading wallet.dat: Wallet corrupted + + + + + Error loading wallet.dat: Wallet requires newer version of Arepacoin + + + + + Wallet needed to be rewritten: restart Arepacoin to complete + + + + + Error loading wallet.dat + + + + + Invalid -proxy address: '%s' + + + + + Unknown network specified in -onlynet: '%s' + + + + + Unknown -socks proxy version requested: %i + + + + + Cannot resolve -bind address: '%s' + + + + + Cannot resolve -externalip address: '%s' + + + + + Invalid amount for -paytxfee=<amount>: '%s' + + + + + Error: could not start node + + + + + Sending... + + + + + Invalid amount + + + + + Insufficient funds + + + + + Loading block index... + + + + + Add a node to connect to and attempt to keep the connection open + + + + + Unable to bind to %s on this computer. Arepacoin is probably already running. + + + + + Fee per KB to add to transactions you send + + + + + Invalid amount for -mininput=<amount>: '%s' + + + + + Loading wallet... + + + + + Cannot downgrade wallet + + + + + Cannot initialize keypool + + + + + Cannot write default address + + + + + Rescanning... + + + + + Done loading + + + + + To use the %s option + + + + + Error + + + + + You must set rpcpassword=<password> in the configuration file: +%s +If the file does not exist, create it with owner-readable-only file permissions. + + + + \ No newline at end of file diff --git a/src/qt/locale/bitcoin_vi_VN.ts b/src/qt/locale/bitcoin_vi_VN.ts new file mode 100755 index 0000000..9081b62 --- /dev/null +++ b/src/qt/locale/bitcoin_vi_VN.ts @@ -0,0 +1,3275 @@ + + + AboutDialog + + + About Arepacoin + + + + + <b>Arepacoin</b> version + + + + + Copyright © 2009-2014 The Bitcoin developers +Copyright © 2012-2014 The NovaCoin developers +Copyright © 2014 The Arepacoin developers + + + + + +This is experimental software. + +Distributed under the MIT/X11 software license, see the accompanying file COPYING or http://www.opensource.org/licenses/mit-license.php. + +This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit (http://www.openssl.org/) and cryptographic software written by Eric Young (eay@cryptsoft.com) and UPnP software written by Thomas Bernard. + + + + + AddressBookPage + + + Address Book + + + + + Double-click to edit address or label + + + + + Create a new address + Tạo một địa chỉ mới + + + + Copy the currently selected address to the system clipboard + + + + + &New Address + + + + + These are your Arepacoin addresses for receiving payments. You may want to give a different one to each sender so you can keep track of who is paying you. + + + + + &Copy Address + + + + + Show &QR Code + + + + + Sign a message to prove you own a Arepacoin address + + + + + Sign &Message + + + + + Delete the currently selected address from the list + + + + + Verify a message to ensure it was signed with a specified Arepacoin address + + + + + &Verify Message + + + + + &Delete + + + + + Copy &Label + + + + + &Edit + + + + + Export Address Book Data + + + + + Comma separated file (*.csv) + + + + + Error exporting + + + + + Could not write to file %1. + + + + + AddressTableModel + + + Label + + + + + Address + + + + + (no label) + + + + + AskPassphraseDialog + + + Passphrase Dialog + + + + + Enter passphrase + + + + + New passphrase + + + + + Repeat new passphrase + + + + + Serves to disable the trivial sendmoney when OS account compromised. Provides no real security. + + + + + For staking only + + + + + Enter the new passphrase to the wallet.<br/>Please use a passphrase of <b>10 or more random characters</b>, or <b>eight or more words</b>. + + + + + Encrypt wallet + + + + + This operation needs your wallet passphrase to unlock the wallet. + + + + + Unlock wallet + + + + + This operation needs your wallet passphrase to decrypt the wallet. + + + + + Decrypt wallet + + + + + Change passphrase + + + + + Enter the old and new passphrase to the wallet. + + + + + Confirm wallet encryption + + + + + Warning: If you encrypt your wallet and lose your passphrase, you will <b>LOSE ALL OF YOUR COINS</b>! + + + + + Are you sure you wish to encrypt your wallet? + + + + + IMPORTANT: Any previous backups you have made of your wallet file should be replaced with the newly generated, encrypted wallet file. For security reasons, previous backups of the unencrypted wallet file will become useless as soon as you start using the new, encrypted wallet. + + + + + + Warning: The Caps Lock key is on! + + + + + + Wallet encrypted + + + + + Arepacoin will close now to finish the encryption process. Remember that encrypting your wallet cannot fully protect your coins from being stolen by malware infecting your computer. + + + + + + + + Wallet encryption failed + + + + + Wallet encryption failed due to an internal error. Your wallet was not encrypted. + + + + + + The supplied passphrases do not match. + + + + + Wallet unlock failed + + + + + + + The passphrase entered for the wallet decryption was incorrect. + + + + + Wallet decryption failed + + + + + Wallet passphrase was successfully changed. + + + + + BitcoinGUI + + + Sign &message... + + + + + Synchronizing with network... + + + + + &Overview + + + + + Show general overview of wallet + + + + + &Transactions + + + + + Browse transaction history + + + + + &Address Book + + + + + Edit the list of stored addresses and labels + + + + + &Receive coins + + + + + Show the list of addresses for receiving payments + + + + + &Send coins + + + + + E&xit + + + + + Quit application + + + + + Show information about Arepacoin + + + + + About &Qt + + + + + Show information about Qt + + + + + &Options... + + + + + &Encrypt Wallet... + + + + + &Backup Wallet... + + + + + &Change Passphrase... + + + + + ~%n block(s) remaining + + + + + Downloaded %1 of %2 blocks of transaction history (%3% done). + + + + + &Export... + + + + + Send coins to a Arepacoin address + + + + + Modify configuration options for Arepacoin + + + + + Export the data in the current tab to a file + + + + + Encrypt or decrypt wallet + + + + + Backup wallet to another location + + + + + Change the passphrase used for wallet encryption + + + + + &Debug window + + + + + Open debugging and diagnostic console + + + + + &Verify message... + + + + + Arepacoin + + + + + Wallet + + + + + &About Arepacoin + + + + + &Show / Hide + + + + + Unlock wallet + + + + + &Lock Wallet + + + + + Lock wallet + + + + + &File + + + + + &Settings + + + + + &Help + + + + + Tabs toolbar + + + + + Actions toolbar + + + + + + [testnet] + + + + + + Arepacoin client + + + + + %n active connection(s) to Arepacoin network + + + + + Downloaded %1 blocks of transaction history. + + + + + Staking.<br>Your weight is %1<br>Network weight is %2<br>Expected time to earn reward is %3 + + + + + Not staking because wallet is locked + + + + + Not staking because wallet is offline + + + + + Not staking because wallet is syncing + + + + + Not staking because you don't have mature coins + + + + + %n second(s) ago + + + + + &Unlock Wallet... + + + + + %n minute(s) ago + + + + + %n hour(s) ago + + + + + %n day(s) ago + + + + + Up to date + + + + + Catching up... + + + + + Last received block was generated %1. + + + + + This transaction is over the size limit. You can still send it for a fee of %1, which goes to the nodes that process your transaction and helps to support the network. Do you want to pay the fee? + + + + + Confirm transaction fee + + + + + Sent transaction + + + + + Incoming transaction + + + + + Date: %1 +Amount: %2 +Type: %3 +Address: %4 + + + + + + + URI handling + + + + + + URI can not be parsed! This can be caused by an invalid Arepacoin address or malformed URI parameters. + + + + + Wallet is <b>encrypted</b> and currently <b>unlocked</b> + + + + + Wallet is <b>encrypted</b> and currently <b>locked</b> + + + + + Backup Wallet + + + + + Wallet Data (*.dat) + + + + + Backup Failed + + + + + There was an error trying to save the wallet data to the new location. + + + + + %n second(s) + + + + + %n minute(s) + + + + + %n hour(s) + + + + + %n day(s) + + + + + Not staking + + + + + A fatal error occurred. Arepacoin can no longer continue safely and will quit. + + + + + ClientModel + + + Network Alert + + + + + CoinControlDialog + + + Coin Control + + + + + Quantity: + + + + + Bytes: + + + + + Amount: + + + + + Priority: + + + + + Fee: + + + + + Low Output: + + + + + no + + + + + After Fee: + + + + + Change: + + + + + (un)select all + + + + + Tree mode + + + + + List mode + + + + + Amount + + + + + Label + + + + + Address + + + + + Date + + + + + Confirmations + + + + + Confirmed + + + + + Priority + + + + + Copy address + + + + + Copy label + + + + + + Copy amount + + + + + Copy transaction ID + + + + + Copy quantity + + + + + Copy fee + + + + + Copy after fee + + + + + Copy bytes + + + + + Copy priority + + + + + Copy low output + + + + + Copy change + + + + + highest + + + + + high + + + + + medium-high + + + + + medium + + + + + low-medium + + + + + low + + + + + lowest + + + + + DUST + + + + + yes + + + + + This label turns red, if the transaction size is bigger than 10000 bytes. + + This means a fee of at least %1 per kb is required. + + Can vary +/- 1 Byte per input. + + + + + Transactions with higher priority get more likely into a block. + +This label turns red, if the priority is smaller than "medium". + + This means a fee of at least %1 per kb is required. + + + + + This label turns red, if any recipient receives an amount smaller than %1. + + This means a fee of at least %2 is required. + + Amounts below 0.546 times the minimum relay fee are shown as DUST. + + + + + This label turns red, if the change is smaller than %1. + + This means a fee of at least %2 is required. + + + + + + (no label) + + + + + change from %1 (%2) + + + + + (change) + + + + + EditAddressDialog + + + Edit Address + + + + + &Label + + + + + The label associated with this address book entry + + + + + &Address + + + + + The address associated with this address book entry. This can only be modified for sending addresses. + + + + + New receiving address + + + + + New sending address + + + + + Edit receiving address + + + + + Edit sending address + + + + + The entered address "%1" is already in the address book. + + + + + The entered address "%1" is not a valid Arepacoin address. + + + + + Could not unlock wallet. + + + + + New key generation failed. + + + + + GUIUtil::HelpMessageBox + + + + Arepacoin-Qt + + + + + version + + + + + Usage: + + + + + command-line options + + + + + UI options + + + + + Set language, for example "de_DE" (default: system locale) + + + + + Start minimized + + + + + Show splash screen on startup (default: 1) + + + + + OptionsDialog + + + Options + + + + + &Main + + + + + Optional transaction fee per kB that helps make sure your transactions are processed quickly. Most transactions are 1 kB. Fee 0.01 recommended. + + + + + Pay transaction &fee + + + + + Reserved amount does not participate in staking and is therefore spendable at any time. + + + + + Reserve + + + + + Automatically start Arepacoin after logging in to the system. + + + + + &Start Arepacoin on system login + + + + + Detach block and address databases at shutdown. This means they can be moved to another data directory, but it slows down shutdown. The wallet is always detached. + + + + + &Detach databases at shutdown + + + + + &Network + + + + + Automatically open the Arepacoin client port on the router. This only works when your router supports UPnP and it is enabled. + + + + + Map port using &UPnP + + + + + Connect to the Arepacoin network through a SOCKS proxy (e.g. when connecting through Tor). + + + + + &Connect through SOCKS proxy: + + + + + Proxy &IP: + + + + + IP address of the proxy (e.g. 127.0.0.1) + + + + + &Port: + + + + + Port of the proxy (e.g. 9050) + + + + + SOCKS &Version: + + + + + SOCKS version of the proxy (e.g. 5) + + + + + &Window + + + + + Show only a tray icon after minimizing the window. + + + + + &Minimize to the tray instead of the taskbar + + + + + Minimize instead of exit the application when the window is closed. When this option is enabled, the application will be closed only after selecting Quit in the menu. + + + + + M&inimize on close + + + + + &Display + + + + + User Interface &language: + + + + + The user interface language can be set here. This setting will take effect after restarting Arepacoin. + + + + + &Unit to show amounts in: + + + + + Choose the default subdivision unit to show in the interface and when sending coins. + + + + + Whether to show Arepacoin addresses in the transaction list or not. + + + + + &Display addresses in transaction list + + + + + Whether to show coin control features or not. + + + + + Display coin &control features (experts only!) + + + + + &OK + + + + + &Cancel + + + + + &Apply + + + + + default + + + + + + Warning + + + + + + This setting will take effect after restarting Arepacoin. + + + + + The supplied proxy address is invalid. + + + + + OverviewPage + + + Form + + + + + + The displayed information may be out of date. Your wallet automatically synchronizes with the Arepacoin network after a connection is established, but this process has not completed yet. + + + + + Stake: + + + + + Unconfirmed: + + + + + Wallet + + + + + Spendable: + + + + + Your current spendable balance + + + + + Immature: + + + + + Mined balance that has not yet matured + + + + + Total: + + + + + Your current total balance + + + + + <b>Recent transactions</b> + + + + + Total of transactions that have yet to be confirmed, and do not yet count toward the current balance + + + + + Total of coins that was staked, and do not yet count toward the current balance + + + + + + out of sync + + + + + QRCodeDialog + + + QR Code Dialog + + + + + Request Payment + + + + + Amount: + + + + + Label: + + + + + Message: + + + + + &Save As... + + + + + Error encoding URI into QR Code. + + + + + The entered amount is invalid, please check. + + + + + Resulting URI too long, try to reduce the text for label / message. + + + + + Save QR Code + + + + + PNG Images (*.png) + + + + + RPCConsole + + + Client name + + + + + + + + + + + + + + N/A + + + + + Client version + + + + + &Information + + + + + Using OpenSSL version + + + + + Startup time + + + + + Network + + + + + Number of connections + + + + + On testnet + + + + + Block chain + + + + + Current number of blocks + + + + + Estimated total blocks + + + + + Last block time + + + + + &Open + + + + + Command-line options + + + + + Show the Arepacoin-Qt help message to get a list with possible Arepacoin command-line options. + + + + + &Show + + + + + &Console + + + + + Build date + + + + + Arepacoin - Debug window + + + + + Arepacoin Core + + + + + Debug log file + + + + + Open the Arepacoin debug log file from the current data directory. This can take a few seconds for large log files. + + + + + Clear console + + + + + Welcome to the Arepacoin RPC console. + + + + + Use up and down arrows to navigate history, and <b>Ctrl-L</b> to clear screen. + + + + + Type <b>help</b> for an overview of available commands. + + + + + SendCoinsDialog + + + + + + + + + + Send Coins + + + + + Coin Control Features + + + + + Inputs... + + + + + automatically selected + + + + + Insufficient funds! + + + + + Quantity: + + + + + + 0 + + + + + Bytes: + + + + + Amount: + + + + + + + + 0.00 BC + + + + + Priority: + + + + + medium + + + + + Fee: + + + + + Low Output: + + + + + no + + + + + After Fee: + + + + + Change + + + + + custom change address + + + + + Send to multiple recipients at once + + + + + Add &Recipient + + + + + Remove all transaction fields + + + + + Clear &All + + + + + Balance: + + + + + 123.456 BC + + + + + Confirm the send action + + + + + S&end + + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Copy quantity + + + + + Copy amount + + + + + Copy fee + + + + + Copy after fee + + + + + Copy bytes + + + + + Copy priority + + + + + Copy low output + + + + + Copy change + + + + + <b>%1</b> to %2 (%3) + + + + + Confirm send coins + + + + + Are you sure you want to send %1? + + + + + and + + + + + The recipient address is not valid, please recheck. + + + + + The amount to pay must be larger than 0. + + + + + The amount exceeds your balance. + + + + + The total exceeds your balance when the %1 transaction fee is included. + + + + + Duplicate address found, can only send to each address once per send operation. + + + + + Error: Transaction creation failed. + + + + + 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. + + + + + WARNING: Invalid Arepacoin address + + + + + (no label) + + + + + WARNING: unknown change address + + + + + SendCoinsEntry + + + Form + + + + + A&mount: + + + + + Pay &To: + + + + + + Enter a label for this address to add it to your address book + + + + + &Label: + + + + + The address to send the payment to (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Choose address from address book + + + + + Alt+A + + + + + Paste address from clipboard + + + + + Alt+P + + + + + Remove this recipient + + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + SignVerifyMessageDialog + + + Signatures - Sign / Verify a Message + + + + + + &Sign Message + + + + + You can sign messages with your addresses to prove you own them. Be careful not to sign anything vague, as phishing attacks may try to trick you into signing your identity over to them. Only sign fully-detailed statements you agree to. + + + + + The address to sign the message with (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + + Choose an address from the address book + + + + + + Alt+A + + + + + Paste address from clipboard + + + + + Alt+P + + + + + Enter the message you want to sign here + + + + + Copy the current signature to the system clipboard + + + + + Sign the message to prove you own this Arepacoin address + + + + + Reset all sign message fields + + + + + + Clear &All + + + + + + &Verify Message + + + + + Enter the signing address, message (ensure you copy line breaks, spaces, tabs, etc. exactly) and signature below to verify the message. Be careful not to read more into the signature than what is in the signed message itself, to avoid being tricked by a man-in-the-middle attack. + + + + + The address the message was signed with (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Verify the message to ensure it was signed with the specified Arepacoin address + + + + + Reset all verify message fields + + + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Click "Sign Message" to generate signature + + + + + Enter Arepacoin signature + + + + + + The entered address is invalid. + + + + + + + + Please check the address and try again. + + + + + + The entered address does not refer to a key. + + + + + Wallet unlock was cancelled. + + + + + Private key for the entered address is not available. + + + + + Message signing failed. + + + + + Message signed. + + + + + The signature could not be decoded. + + + + + + Please check the signature and try again. + + + + + The signature did not match the message digest. + + + + + Message verification failed. + + + + + Message verified. + + + + + TransactionDesc + + + Open until %1 + + + + + Open for %n block(s) + + + + + conflicted + + + + + %1/offline + + + + + %1/unconfirmed + + + + + %1 confirmations + + + + + Status + + + + + , broadcast through %n node(s) + + + + + Date + + + + + Source + + + + + Generated + + + + + + From + + + + + + + To + + + + + + own address + + + + + label + + + + + + + + + Credit + + + + + matures in %n more block(s) + + + + + not accepted + + + + + + + + Debit + + + + + Transaction fee + + + + + Net amount + + + + + Message + + + + + Comment + + + + + Transaction ID + + + + + Generated coins must mature 6 blocks before they can be spent. When you generated this block, it was broadcast to the network to be added to the block chain. If it fails to get into the chain, its state will change to "not accepted" and it won't be spendable. This may occasionally happen if another node generates a block within a few seconds of yours. + + + + + Debug information + + + + + Transaction + + + + + Inputs + + + + + Amount + + + + + true + + + + + false + + + + + , has not been successfully broadcast yet + + + + + unknown + + + + + TransactionDescDialog + + + Transaction details + + + + + This pane shows a detailed description of the transaction + + + + + TransactionTableModel + + + Date + + + + + Type + + + + + Address + + + + + Amount + + + + + Open until %1 + + + + + Confirmed (%1 confirmations) + + + + + Open for %n more block(s) + + + + + Offline + + + + + Unconfirmed + + + + + Confirming (%1 of %2 recommended confirmations) + + + + + Conflicted + + + + + Immature (%1 confirmations, will be available after %2) + + + + + This block was not received by any other nodes and will probably not be accepted! + + + + + Generated but not accepted + + + + + Received with + + + + + Received from + + + + + Sent to + + + + + Payment to yourself + + + + + Mined + + + + + (n/a) + + + + + Transaction status. Hover over this field to show number of confirmations. + + + + + Date and time that the transaction was received. + + + + + Type of transaction. + + + + + Destination address of transaction. + + + + + Amount removed from or added to balance. + + + + + TransactionView + + + + All + + + + + Today + + + + + This week + + + + + This month + + + + + Last month + + + + + This year + + + + + Range... + + + + + Received with + + + + + Sent to + + + + + To yourself + + + + + Mined + + + + + Other + + + + + Enter address or label to search + + + + + Min amount + + + + + Copy address + + + + + Copy label + + + + + Copy amount + + + + + Copy transaction ID + + + + + Edit label + + + + + Show transaction details + + + + + Export Transaction Data + + + + + Comma separated file (*.csv) + + + + + Confirmed + + + + + Date + + + + + Type + + + + + Label + + + + + Address + + + + + Amount + + + + + ID + + + + + Error exporting + + + + + Could not write to file %1. + + + + + Range: + + + + + to + + + + + WalletModel + + + Sending... + + + + + bitcoin-core + + + Arepacoin version + + + + + Usage: + + + + + Send command to -server or arepacoind + + + + + List commands + + + + + Get help for a command + + + + + Options: + + + + + Specify configuration file (default: arepacoin.conf) + + + + + Specify pid file (default: arepacoind.pid) + + + + + Specify wallet file (within data directory) + + + + + Specify data directory + + + + + Set database cache size in megabytes (default: 25) + + + + + Set database disk log size in megabytes (default: 100) + + + + + Listen for connections on <port> (default: 9853 or testnet: 19853) + + + + + Maintain at most <n> connections to peers (default: 125) + + + + + Connect to a node to retrieve peer addresses, and disconnect + + + + + Specify your own public address + + + + + Bind to given address. Use [host]:port notation for IPv6 + + + + + Stake your coins to support network and gain reward (default: 1) + + + + + Threshold for disconnecting misbehaving peers (default: 100) + + + + + Number of seconds to keep misbehaving peers from reconnecting (default: 86400) + + + + + An error occurred while setting up the RPC port %u for listening on IPv4: %s + + + + + Detach block and address databases. Increases shutdown time (default: 0) + + + + + 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. + + + + + Error: This transaction requires a transaction fee of at least %s because of its amount, complexity, or use of recently received funds + + + + + Listen for JSON-RPC connections on <port> (default: 9852 or testnet: 19852) + + + + + Accept command line and JSON-RPC commands + + + + + Error: Transaction creation failed + + + + + Error: Wallet locked, unable to create transaction + + + + + Importing blockchain data file. + + + + + Importing bootstrap blockchain data file. + + + + + Run in the background as a daemon and accept commands + + + + + Use the test network + + + + + Accept connections from outside (default: 1 if no -proxy or -connect) + + + + + An error occurred while setting up the RPC port %u for listening on IPv6, falling back to IPv4: %s + + + + + Error initializing database environment %s! To recover, BACKUP THAT DIRECTORY, then remove everything from it except for wallet.dat. + + + + + Set maximum size of high-priority/low-fee transactions in bytes (default: 27000) + + + + + Warning: -paytxfee is set very high! This is the transaction fee you will pay if you send a transaction. + + + + + Warning: Please check that your computer's date and time are correct! If your clock is wrong Arepacoin will not work properly. + + + + + Warning: error reading wallet.dat! All keys read correctly, but transaction data or address book entries might be missing or incorrect. + + + + + Warning: wallet.dat corrupt, data salvaged! Original wallet.dat saved as wallet.{timestamp}.bak in %s; if your balance or transactions are incorrect you should restore from a backup. + + + + + Attempt to recover private keys from a corrupt wallet.dat + + + + + Block creation options: + + + + + Connect only to the specified node(s) + + + + + Discover own IP address (default: 1 when listening and no -externalip) + + + + + Failed to listen on any port. Use -listen=0 if you want this. + + + + + Find peers using DNS lookup (default: 1) + + + + + Sync checkpoints policy (default: strict) + + + + + Invalid -tor address: '%s' + + + + + Invalid amount for -reservebalance=<amount> + + + + + Maximum per-connection receive buffer, <n>*1000 bytes (default: 5000) + + + + + Maximum per-connection send buffer, <n>*1000 bytes (default: 1000) + + + + + Only connect to nodes in network <net> (IPv4, IPv6 or Tor) + + + + + Output extra debugging information. Implies all other -debug* options + + + + + Output extra network debugging information + + + + + Prepend debug output with timestamp + + + + + SSL options: (see the Bitcoin Wiki for SSL setup instructions) + + + + + Select the version of socks proxy to use (4-5, default: 5) + + + + + Send trace/debug info to console instead of debug.log file + + + + + Send trace/debug info to debugger + + + + + Set maximum block size in bytes (default: 250000) + + + + + Set minimum block size in bytes (default: 0) + + + + + Shrink debug.log file on client startup (default: 1 when no -debug) + + + + + Specify connection timeout in milliseconds (default: 5000) + + + + + Unable to sign checkpoint, wrong checkpointkey? + + + + + + Use UPnP to map the listening port (default: 0) + + + + + Use UPnP to map the listening port (default: 1 when listening) + + + + + Use proxy to reach tor hidden services (default: same as -proxy) + + + + + Username for JSON-RPC connections + + + + + Verifying database integrity... + + + + + WARNING: syncronized checkpoint violation detected, but skipped! + + + + + Warning: Disk space is low! + + + + + Warning: This version is obsolete, upgrade required! + + + + + wallet.dat corrupt, salvage failed + + + + + Password for JSON-RPC connections + + + + + %s, you must set a rpcpassword in the configuration file: + %s +It is recommended you use the following random password: +rpcuser=arepacoinrpc +rpcpassword=%s +(you do not need to remember this password) +The username and password MUST NOT be the same. +If the file does not exist, create it with owner-readable-only file permissions. +It is also recommended to set alertnotify so you are notified of problems; +for example: alertnotify=echo %%s | mail -s "Arepacoin Alert" admin@foo.com + + + + + + Find peers using internet relay chat (default: 0) + + + + + Sync time with other nodes. Disable if time on your system is precise e.g. syncing with NTP (default: 1) + + + + + When creating transactions, ignore inputs with value less than this (default: 0.01) + + + + + Allow JSON-RPC connections from specified IP address + + + + + Send commands to node running on <ip> (default: 127.0.0.1) + + + + + Execute command when the best block changes (%s in cmd is replaced by block hash) + + + + + Execute command when a wallet transaction changes (%s in cmd is replaced by TxID) + + + + + Require a confirmations for change (default: 0) + + + + + Enforce transaction scripts to use canonical PUSH operators (default: 1) + + + + + Execute command when a relevant alert is received (%s in cmd is replaced by message) + + + + + Upgrade wallet to latest format + + + + + Set key pool size to <n> (default: 100) + + + + + Rescan the block chain for missing wallet transactions + + + + + How many blocks to check at startup (default: 2500, 0 = all) + + + + + How thorough the block verification is (0-6, default: 1) + + + + + Imports blocks from external blk000?.dat file + + + + + Use OpenSSL (https) for JSON-RPC connections + + + + + Server certificate file (default: server.cert) + + + + + Server private key (default: server.pem) + + + + + Acceptable ciphers (default: TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH) + + + + + Error: Wallet unlocked for staking only, unable to create transaction. + + + + + WARNING: Invalid checkpoint found! Displayed transactions may not be correct! You may need to upgrade, or notify developers. + + + + + This help message + + + + + Wallet %s resides outside data directory %s. + + + + + Cannot obtain a lock on data directory %s. Arepacoin is probably already running. + + + + + Arepacoin + + + + + Unable to bind to %s on this computer (bind returned error %d, %s) + + + + + Connect through socks proxy + + + + + Allow DNS lookups for -addnode, -seednode and -connect + + + + + Loading addresses... + + + + + Error loading blkindex.dat + + + + + Error loading wallet.dat: Wallet corrupted + + + + + Error loading wallet.dat: Wallet requires newer version of Arepacoin + + + + + Wallet needed to be rewritten: restart Arepacoin to complete + + + + + Error loading wallet.dat + + + + + Invalid -proxy address: '%s' + + + + + Unknown network specified in -onlynet: '%s' + + + + + Unknown -socks proxy version requested: %i + + + + + Cannot resolve -bind address: '%s' + + + + + Cannot resolve -externalip address: '%s' + + + + + Invalid amount for -paytxfee=<amount>: '%s' + + + + + Error: could not start node + + + + + Sending... + + + + + Invalid amount + + + + + Insufficient funds + + + + + Loading block index... + + + + + Add a node to connect to and attempt to keep the connection open + + + + + Unable to bind to %s on this computer. Arepacoin is probably already running. + + + + + Fee per KB to add to transactions you send + + + + + Invalid amount for -mininput=<amount>: '%s' + + + + + Loading wallet... + + + + + Cannot downgrade wallet + + + + + Cannot initialize keypool + + + + + Cannot write default address + + + + + Rescanning... + + + + + Done loading + + + + + To use the %s option + + + + + Error + + + + + You must set rpcpassword=<password> in the configuration file: +%s +If the file does not exist, create it with owner-readable-only file permissions. + + + + \ No newline at end of file diff --git a/src/qt/locale/bitcoin_zh_CN.ts b/src/qt/locale/bitcoin_zh_CN.ts new file mode 100755 index 0000000..7bf855f --- /dev/null +++ b/src/qt/locale/bitcoin_zh_CN.ts @@ -0,0 +1,3318 @@ + + + AboutDialog + + + About Arepacoin + 关于黑币 + + + + <b>Arepacoin</b> version + <b>黑币客户端</b> 版本 + + + + Copyright © 2009-2014 The Bitcoin developers +Copyright © 2012-2014 The NovaCoin developers +Copyright © 2014 The Arepacoin developers + 版权所有 © 2009-2014 比特币Bitcoin开发组 +版权所有 © 2012-2014 新星币Novacoin开发组 +版权所有 © 2014 黑币Arepacoin开发组 + + + + +This is experimental software. + +Distributed under the MIT/X11 software license, see the accompanying file COPYING or http://www.opensource.org/licenses/mit-license.php. + +This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit (http://www.openssl.org/) and cryptographic software written by Eric Young (eay@cryptsoft.com) and UPnP software written by Thomas Bernard. + +测试版软件 + +经MIT/X11软件授权发布, 具体参见http://www.opensource.org/licenses/mit-license.php. + +本产品包括由OpenSSL Project (http://www.openssl.org/)开发的OpenSSL工具包 ,由 Eric Young (eay@cryptsoft.com) 撰写的密码学软件以及由 Thomas Bernard 撰写的UPnP软件. + + + + AddressBookPage + + + Address Book + 地址簿 + + + + Double-click to edit address or label + 双击编辑地址或标签 + + + + Create a new address + 创建新地址 + + + + Copy the currently selected address to the system clipboard + 复制当前选中的地址到系统剪贴板 + + + + &New Address + 新建地址(&N) + + + + These are your Arepacoin addresses for receiving payments. You may want to give a different one to each sender so you can keep track of who is paying you. + 这是您用来接收支付的黑币地址列表。为不同的支付方建立不同的地址以便于了解支付来源。 + + + + &Copy Address + 复制地址(&C) + + + + Show &QR Code + 显示二维码(&Q) + + + + Sign a message to prove you own a Arepacoin address + 对信息进行签名以证明您对该黑币地址的所有权 + + + + Sign &Message + 签名(&M) + + + + Delete the currently selected address from the list + 从列表中删除选中的地址 + + + + Verify a message to ensure it was signed with a specified Arepacoin address + 验证信息以保证其经过指定黑币地址的签名 + + + + &Verify Message + 验证消息(&V) + + + + &Delete + 删除(&D) + + + + Copy &Label + 复制标签(&L) + + + + &Edit + 编辑(&E) + + + + Export Address Book Data + 导出地址簿数据 + + + + Comma separated file (*.csv) + 逗号分隔文件 (*.csv) + + + + Error exporting + 导出时发生错误 + + + + Could not write to file %1. + 无法写入文件 %1 。 + + + + AddressTableModel + + + Label + 标签 + + + + Address + 地址 + + + + (no label) + (没有标签) + + + + AskPassphraseDialog + + + Passphrase Dialog + 密码对话框 + + + + Enter passphrase + 输入密码 + + + + New passphrase + 新密码 + + + + Repeat new passphrase + 重复新密码 + + + + Serves to disable the trivial sendmoney when OS account compromised. Provides no real security. + 在系统允许的情况下用于防止sendmoney欺诈,并未提供真正的安全防护措施。 + + + + For staking only + 仅用于权益增值 + + + + Enter the new passphrase to the wallet.<br/>Please use a passphrase of <b>10 or more random characters</b>, or <b>eight or more words</b>. + 输入钱包的新密码。<br/>使用的密码请至少包含<b>10个以上随机字符</>,或者是<b>8个以上的单词</b>。 + + + + Encrypt wallet + 加密钱包 + + + + This operation needs your wallet passphrase to unlock the wallet. + 此操作需要您首先使用密码解锁该钱包。 + + + + Unlock wallet + 解锁钱包 + + + + This operation needs your wallet passphrase to decrypt the wallet. + 该操作需要您首先使用密码解密钱包。 + + + + Decrypt wallet + 解密钱包 + + + + Change passphrase + 更改密码 + + + + Enter the old and new passphrase to the wallet. + 请输入该钱包的旧密码与新密码。 + + + + Confirm wallet encryption + 确认加密钱包 + + + + Warning: If you encrypt your wallet and lose your passphrase, you will <b>LOSE ALL OF YOUR COINS</b>! + 警告:如果您丢失了加密该钱包的密码,其中所有的黑币将会丢失! + + + + Are you sure you wish to encrypt your wallet? + 您确定需要为钱包加密吗? + + + + IMPORTANT: Any previous backups you have made of your wallet file should be replaced with the newly generated, encrypted wallet file. For security reasons, previous backups of the unencrypted wallet file will become useless as soon as you start using the new, encrypted wallet. + 重要提示:您以前备份的钱包文件应该替换成最新生成的加密钱包文件(重新备份)。从安全性上考虑,您以前备份的未加密的钱包文件,在您使用新的加密钱包后将无效,请重新备份。 + + + + + Warning: The Caps Lock key is on! + 警告:大写锁定键处于打开状态! + + + + + Wallet encrypted + 钱包已加密 + + + + Arepacoin will close now to finish the encryption process. Remember that encrypting your wallet cannot fully protect your coins from being stolen by malware infecting your computer. + 黑币客户端即将关闭以完成加密过程。请记住,加密钱包并不能完全防止您的电子货币被入侵您计算机的木马软件盗窃。 + + + + + + + Wallet encryption failed + 钱包加密失败 + + + + Wallet encryption failed due to an internal error. Your wallet was not encrypted. + 由于一个本地错误,加密钱包的操作已经失败。您的钱包没能被加密。 + + + + + The supplied passphrases do not match. + 密码不匹配。 + + + + Wallet unlock failed + 钱包解锁失败 + + + + + + The passphrase entered for the wallet decryption was incorrect. + 用于解密钱包的密码不正确。 + + + + Wallet decryption failed + 钱包解密失败。 + + + + Wallet passphrase was successfully changed. + 修改钱包密码成功。 + + + + BitcoinGUI + + + Sign &message... + 消息签名(&M)... + + + + Synchronizing with network... + 正在与网络同步... + + + + &Overview + 概况(&O) + + + + Show general overview of wallet + 显示钱包概况 + + + + &Transactions + 交易记录(&T) + + + + Browse transaction history + 查看交易历史 + + + + &Address Book + 地址簿(&A) + + + + Edit the list of stored addresses and labels + 管理已储存的地址和标签 + + + + &Receive coins + 接收黑币(&R) + + + + Show the list of addresses for receiving payments + 显示用于接收支付的地址列表 + + + + &Send coins + 发送黑币(&S) + + + + E&xit + 退出(&X) + + + + Quit application + 退出程序 + + + + Show information about Arepacoin + 显示关于黑币的信息 + + + + About &Qt + 关于 &Qt + + + + Show information about Qt + 显示 Qt 相关信息 + + + + &Options... + 选项(&O)... + + + + &Encrypt Wallet... + 加密钱包(&E)... + + + + &Backup Wallet... + 备份钱包(&B)... + + + + &Change Passphrase... + 更改密码(&C)... + + + + ~%n block(s) remaining + ~%n 个区块未完成 + + + + Downloaded %1 of %2 blocks of transaction history (%3% done). + 交易记录已下载%3% (%1 / %2 个区块) + + + + &Export... + 导出(&E) + + + + Send coins to a Arepacoin address + 向指定的地址发送黑币 + + + + Modify configuration options for Arepacoin + 更改设置选项 + + + + Export the data in the current tab to a file + 导出当前标签页的数据 + + + + Encrypt or decrypt wallet + 加密/解密钱包 + + + + Backup wallet to another location + 备份钱包到其他文件夹 + + + + Change the passphrase used for wallet encryption + 更改钱包加密口令 + + + + &Debug window + 调试窗口(&D) + + + + Open debugging and diagnostic console + 打开调试和诊断控制台 + + + + &Verify message... + 验证消息(&V)... + + + + Arepacoin + 黑币 + + + + Wallet + 钱包 + + + + &About Arepacoin + 关于黑币(&A) + + + + &Show / Hide + 显示 / 隐藏(&S) + + + + Unlock wallet + 解锁钱包 + + + + &Lock Wallet + 锁定钱包(&L) + + + + Lock wallet + 锁定钱包 + + + + &File + 文件(&F) + + + + &Settings + 设置(&S) + + + + &Help + 帮助(&H) + + + + Tabs toolbar + 分页工具栏 + + + + Actions toolbar + 工具栏 + + + + + [testnet] + [测试网络] + + + + + Arepacoin client + 黑币客户端 + + + + %n active connection(s) to Arepacoin network + 与黑币网络建立了 %n 个连接 + + + + Downloaded %1 blocks of transaction history. + 已下载 %1 个区块的交易记录 + + + + Staking.<br>Your weight is %1<br>Network weight is %2<br>Expected time to earn reward is %3 + 权益增值中 <br>您的权重为 %1 <br>网络总权重为 %2<br>预计将在 %3 之后获得收益 + + + + Not staking because wallet is locked + 未进行权益增值,因为钱包已锁定 + + + + Not staking because wallet is offline + 未进行权益增值,因为钱包处于离线状态 + + + + Not staking because wallet is syncing + 未进行权益增值,因为钱包正在同步 + + + + Not staking because you don't have mature coins + 未进行权益增值,因为钱包中没有成熟的黑币 + + + + %n second(s) ago + %n 秒前 + + + + &Unlock Wallet... + 解锁钱包(&U) + + + + %n minute(s) ago + %n 分钟前 + + + + %n hour(s) ago + %n 小时前 + + + + %n day(s) ago + %n 天前 + + + + Up to date + 已是最新 + + + + Catching up... + 更新中... + + + + Last received block was generated %1. + 最近生成的区块接收于%1 + + + + This transaction is over the size limit. You can still send it for a fee of %1, which goes to the nodes that process your transaction and helps to support the network. Do you want to pay the fee? + 该笔交易数据量太大,需支付%1手续费给执行该笔交易的网络结点。您愿意支付吗? + + + + Confirm transaction fee + 手续费确认 + + + + Sent transaction + 发送交易 + + + + Incoming transaction + 流入交易 + + + + Date: %1 +Amount: %2 +Type: %3 +Address: %4 + + 日期: %1 +金额: %2 +类别: %3 +地址: %4 + + + + + + URI handling + URI处理 + + + + + URI can not be parsed! This can be caused by an invalid Arepacoin address or malformed URI parameters. + 无法解析URI:无效的黑币地址或错误的URI参数。 + + + + Wallet is <b>encrypted</b> and currently <b>unlocked</b> + 钱包已被<b>加密</b>,当前为<b>解锁</b>状态 + + + + Wallet is <b>encrypted</b> and currently <b>locked</b> + 钱包已被<b>加密</b>,当前为<b>锁定</b>状态 + + + + Backup Wallet + 备份钱包 + + + + Wallet Data (*.dat) + 钱包数据文件(*.dat) + + + + Backup Failed + 备份失败 + + + + There was an error trying to save the wallet data to the new location. + 试图将钱包地址保存到新位置时出现错误 + + + + %n second(s) + %n秒 + + + + %n minute(s) + %n 分钟 + + + + %n hour(s) + %n 小时 + + + + %n day(s) + %n 天 + + + + Not staking + 未进行权益增值 + + + + A fatal error occurred. Arepacoin can no longer continue safely and will quit. + 发生严重错误,黑币客户端即将关闭。 + + + + ClientModel + + + Network Alert + 网络警报 + + + + CoinControlDialog + + + Coin Control + 黑币控制 + + + + Quantity: + 总量: + + + + Bytes: + 字节: + + + + Amount: + 金额: + + + + Priority: + 优先级: + + + + Fee: + 费用: + + + + Low Output: + 低输出 + + + + no + + + + + After Fee: + 加上交易费用后: + + + + Change: + 变更 : + + + + (un)select all + (不)全选 + + + + Tree mode + 树状模式 + + + + List mode + 列表模式 + + + + Amount + 金额 + + + + Label + 标签 + + + + Address + 地址 + + + + Date + 日期 + + + + Confirmations + 确认 + + + + Confirmed + 已确认 + + + + Priority + 优先级 + + + + Copy address + 复制地址 + + + + Copy label + 复制标签 + + + + + Copy amount + 复制金额 + + + + Copy transaction ID + 复制交易编号 + + + + Copy quantity + 复制金额 + + + + Copy fee + 复制交易费 + + + + Copy after fee + 复制含交易费的金额 + + + + Copy bytes + 复制字节 + + + + Copy priority + 复制优先级 + + + + Copy low output + 复制低输出 + + + + Copy change + 复制零钱 + + + + highest + 最高 + + + + high + + + + + medium-high + 中高 + + + + medium + 中等 + + + + low-medium + 中低 + + + + low + + + + + lowest + 最低 + + + + DUST + DUST + + + + yes + + + + + This label turns red, if the transaction size is bigger than 10000 bytes. + + This means a fee of at least %1 per kb is required. + + Can vary +/- 1 Byte per input. + 交易数据量超过10000字节时,该标签变为红色。 +此时每kb数据量将会收取 %1 的手续费。 +可能有+/-1字节的误差。 + + + + Transactions with higher priority get more likely into a block. + +This label turns red, if the priority is smaller than "medium". + + This means a fee of at least %1 per kb is required. + 优先度较高的交易有更高可能进入到区块中。 +当优先度为中级以下时,该标签变为红色。 +此时需要收取每kb %1 的手续费。 + + + + This label turns red, if any recipient receives an amount smaller than %1. + + This means a fee of at least %2 is required. + + Amounts below 0.546 times the minimum relay fee are shown as DUST. + 如果收款人所收款项少于 %1,该标签变为红色。 +此时需收取 %2 的手续费。 +低于该手续费的0.546倍的款项将被显示为DUST。 + + + + This label turns red, if the change is smaller than %1. + + This means a fee of at least %2 is required. + 如果零钱少于 %1,该标签变为红色。 +此时需收取 %2 的手续费。 + + + + + (no label) + (没有标签) + + + + change from %1 (%2) + 来自%1的零钱 (%2) + + + + (change) + (零钱) + + + + EditAddressDialog + + + Edit Address + 编辑地址 + + + + &Label + 标签(&L) + + + + The label associated with this address book entry + 地址簿内该项目对应的标签 + + + + &Address + 地址(&A) + + + + The address associated with this address book entry. This can only be modified for sending addresses. + 地址簿内该项目对应的地址。只有“收款人地址”分类下的地址可以修改。 + + + + New receiving address + 新建接收地址 + + + + New sending address + 新建发送地址 + + + + Edit receiving address + 编辑接收地址 + + + + Edit sending address + 编辑发送地址 + + + + The entered address "%1" is already in the address book. + 输入的地址“%1”已经存在于地址簿中。 + + + + The entered address "%1" is not a valid Arepacoin address. + “%1” 不是有效的黑币地址。 + + + + Could not unlock wallet. + 无法解锁钱包 + + + + New key generation failed. + 新的密钥生成失败。 + + + + GUIUtil::HelpMessageBox + + + + Arepacoin-Qt + 黑币客户端Arepacoin-Qt + + + + version + 版本 + + + + Usage: + 使用 + + + + command-line options + 命令行选项 + + + + UI options + 用户界面选项 + + + + Set language, for example "de_DE" (default: system locale) + 设定语言,例如 “de_DE" (默认语言为本地操作系统语言) + + + + Start minimized + 启动时最小化 + + + + Show splash screen on startup (default: 1) + 登录时显示Logo界面 (默认开启) + + + + OptionsDialog + + + Options + 选项 + + + + &Main + 主要(&M) + + + + Optional transaction fee per kB that helps make sure your transactions are processed quickly. Most transactions are 1 kB. Fee 0.01 recommended. + 支付可选的交易手续费以加速交易(每kB)。大多数交易的数据量为1kB。推荐额0.01。 + + + + Pay transaction &fee + 支付交易费用(&F) + + + + Reserved amount does not participate in staking and is therefore spendable at any time. + 保留金额不参与权益累积,可以随时使用。 + + + + Reserve + 保留 + + + + Automatically start Arepacoin after logging in to the system. + 开机自动启动黑币客户端 + + + + &Start Arepacoin on system login + 开机时自动启动黑币客户端(&S) + + + + Detach block and address databases at shutdown. This means they can be moved to another data directory, but it slows down shutdown. The wallet is always detached. + 关机时断开区块和地址数据连接使得它们可以被移动到其他目录。这样做会使关机速度变慢。钱包数据总是断开存储的。 + + + + &Detach databases at shutdown + 关机时断开区块和地址数据库连接(&D) + + + + &Network + 网络(&N) + + + + Automatically open the Arepacoin client port on the router. This only works when your router supports UPnP and it is enabled. + 路由器自动打开黑币客户端端口。该功能仅在路由器开启UPnP支持时有效。 + + + + Map port using &UPnP + 使用 &UPnP 映射端口 + + + + Connect to the Arepacoin network through a SOCKS proxy (e.g. when connecting through Tor). + 经SOCKS代理连接到黑币网络(例如使用Tor) + + + + &Connect through SOCKS proxy: + 经SOCKS代理连接(&C) + + + + Proxy &IP: + 代理服务器 &IP: + + + + IP address of the proxy (e.g. 127.0.0.1) + 代理地址(如:127.0.0.1) + + + + &Port: + 端口(&P): + + + + Port of the proxy (e.g. 9050) + 代理端口(例如 9050) + + + + SOCKS &Version: + Socks 版本(&V): + + + + SOCKS version of the proxy (e.g. 5) + Socks 代理版本(例如 5) + + + + &Window + 窗口(&W) + + + + Show only a tray icon after minimizing the window. + 最小化窗口后仅显示托盘图标 + + + + &Minimize to the tray instead of the taskbar + 最小化到托盘(&M) + + + + Minimize instead of exit the application when the window is closed. When this option is enabled, the application will be closed only after selecting Quit in the menu. + 当窗口关闭时程序最小化而不是退出。当使用该选项时,程序只能通过在菜单中选择退出来关闭 + + + + M&inimize on close + 单击关闭按钮最小化(&I) + + + + &Display + 显示(&D) + + + + User Interface &language: + 用户界面语言(&L): + + + + The user interface language can be set here. This setting will take effect after restarting Arepacoin. + 在此设置用户界面语言。重启黑币客户端后设置生效。 + + + + &Unit to show amounts in: + 黑币金额单位(&U): + + + + Choose the default subdivision unit to show in the interface and when sending coins. + 选择黑币单位。 + + + + Whether to show Arepacoin addresses in the transaction list or not. + 是否在交易列表中显示黑币地址 + + + + &Display addresses in transaction list + 在交易清单中显示黑币地址(&D) + + + + Whether to show coin control features or not. + 是否需要交易源地址控制功能。 + + + + Display coin &control features (experts only!) + 显示黑币控制选项(仅用于专家用户) + + + + &OK + 确定(&O) + + + + &Cancel + 取消(&C) + + + + &Apply + 应用(&A) + + + + default + 默认 + + + + + Warning + 警告 + + + + + This setting will take effect after restarting Arepacoin. + 重启客户端后设置生效 + + + + The supplied proxy address is invalid. + 提供的代理服务器地址无效。 + + + + OverviewPage + + + Form + 表单 + + + + + The displayed information may be out of date. Your wallet automatically synchronizes with the Arepacoin network after a connection is established, but this process has not completed yet. + 所显示的信息尚未更新,建立连接后钱包客户端会自动和网络进行同步,但目前该过程尚未完成。 + + + + Stake: + 用于权益累积: + + + + Unconfirmed: + 未确认: + + + + Wallet + 钱包 + + + + Spendable: + 可用金额: + + + + Your current spendable balance + 您当前可使用的余额 + + + + Immature: + 未成熟的: + + + + Mined balance that has not yet matured + 尚未成熟的挖矿收入余额 + + + + Total: + 总额: + + + + Your current total balance + 您当前的总余额 + + + + <b>Recent transactions</b> + <b>最近交易记录</b> + + + + Total of transactions that have yet to be confirmed, and do not yet count toward the current balance + 尚未确认的交易总额(不计入目前钱包余额) + + + + Total of coins that was staked, and do not yet count toward the current balance + 正在进行权益累积的货币总额(不计入目前钱包余额) + + + + + out of sync + 数据未同步 + + + + QRCodeDialog + + + QR Code Dialog + QR二维码对话框 + + + + Request Payment + 请求支付 + + + + Amount: + 金额: + + + + Label: + 标签: + + + + Message: + 信息: + + + + &Save As... + 另存为(&S)... + + + + Error encoding URI into QR Code. + URI编为QR二维码时出错。 + + + + The entered amount is invalid, please check. + 输入的金额无效,请检查。 + + + + Resulting URI too long, try to reduce the text for label / message. + 生成的URI过长,请减短标签或消息的长度。 + + + + Save QR Code + 保存QR二维码 + + + + PNG Images (*.png) + PNG图片(*.png) + + + + RPCConsole + + + Client name + 客户端名称 + + + + + + + + + + + + + N/A + 不可用 + + + + Client version + 客户端版本 + + + + &Information + 信息(&I) + + + + Using OpenSSL version + 使用 OpenSSL 版本 + + + + Startup time + 启动时间 + + + + Network + 网络 + + + + Number of connections + 连接数 + + + + On testnet + 测试网 + + + + Block chain + 数据链 + + + + Current number of blocks + 当前数据块数量 + + + + Estimated total blocks + 预计数据块数量 + + + + Last block time + 上一数据块时间 + + + + &Open + 打开(&O) + + + + Command-line options + 命令行选项 + + + + Show the Arepacoin-Qt help message to get a list with possible Arepacoin command-line options. + 显示关于命令行选项的帮助信息。 + + + + &Show + 显示(&S) + + + + &Console + 控制台(&C) + + + + Build date + 创建时间 + + + + Arepacoin - Debug window + 黑币客户端-调试窗口 + + + + Arepacoin Core + 黑币核心进程 + + + + Debug log file + 调试日志文件 + + + + Open the Arepacoin debug log file from the current data directory. This can take a few seconds for large log files. + 打开调试日志文件,对于较大的文件,这可能持续几秒钟。 + + + + Clear console + 清空控制台 + + + + Welcome to the Arepacoin RPC console. + 欢迎使用黑币RPC控制台。 + + + + Use up and down arrows to navigate history, and <b>Ctrl-L</b> to clear screen. + 使用上下方向键浏览历史, <b>Ctrl-L</b>清除屏幕。 + + + + Type <b>help</b> for an overview of available commands. + 使用 <b>help</b> 命令显示帮助信息。 + + + + SendCoinsDialog + + + + + + + + + + Send Coins + 发送货币 + + + + Coin Control Features + 交易源地址控制功能 + + + + Inputs... + 输入... + + + + automatically selected + 自动选择 + + + + Insufficient funds! + 存款不足! + + + + Quantity: + 总量: + + + + + 0 + 0 + + + + Bytes: + 字节: + + + + Amount: + 金额: + + + + + + + 0.00 BC + 123.456 BC {0.00 ?} + + + + Priority: + 优先级: + + + + medium + 中等 + + + + Fee: + 费用: + + + + Low Output: + 低输出 + + + + no + no + + + + After Fee: + 加上交易费用后: + + + + Change + 零钱 + + + + custom change address + 自定义零钱地址 + + + + Send to multiple recipients at once + 一次发送给多个接收者 + + + + Add &Recipient + 添加收款人(&R) + + + + Remove all transaction fields + 删除所有交易区域 + + + + Clear &All + 清除所有(&A) + + + + Balance: + 余额: + + + + 123.456 BC + 123.456 BC + + + + Confirm the send action + 确认并发送货币 + + + + S&end + 发送(&E) + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + 输入黑币地址(例如:AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + Copy quantity + 复制金额 + + + + Copy amount + 复制金额 + + + + Copy fee + 复制交易费 + + + + Copy after fee + 复制含交易费的金额 + + + + Copy bytes + 复制字节 + + + + Copy priority + 复制优先级 + + + + Copy low output + 复制低输出 + + + + Copy change + 复制零钱 + + + + <b>%1</b> to %2 (%3) + <b>%1</b> 至 %2 (%3) + + + + Confirm send coins + 确认发送货币 + + + + Are you sure you want to send %1? + 确认要发送 %1 ? + + + + and + + + + + The recipient address is not valid, please recheck. + 收款人地址不合法,请检查。 + + + + The amount to pay must be larger than 0. + 支付金额必须大于0。 + + + + The amount exceeds your balance. + 金额超出您的账上余额。 + + + + The total exceeds your balance when the %1 transaction fee is included. + 计入 %1 交易费后的金额超出您的账上余额。 + + + + Duplicate address found, can only send to each address once per send operation. + 发现重复的地址, 每次只能对同一地址发送一次。 + + + + Error: Transaction creation failed. + 错误:交易创建失败。 + + + + 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. + 错误:交易被拒绝。可能由于钱包中部分金额已被使用,例如您使用了钱包数据的副本,在副本中某些金额已被使用,但在此处尚未被标记为已使用。 + + + + WARNING: Invalid Arepacoin address + 警告:无效的黑币地址 + + + + (no label) + (没有标签) + + + + WARNING: unknown change address + 警告:未知的零钱地址 + + + + SendCoinsEntry + + + Form + 表单 + + + + A&mount: + 金额(&M) + + + + Pay &To: + 付给(&T): + + + + + Enter a label for this address to add it to your address book + 为这个地址输入一个标签,以便将它添加到您的地址簿 + + + + &Label: + 标签(&L): + + + + The address to send the payment to (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + 收款人地址(例:AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + Choose address from address book + 从地址簿选择地址 + + + + Alt+A + Alt+A + + + + Paste address from clipboard + 从剪贴板粘贴地址 + + + + Alt+P + Alt+P + + + + Remove this recipient + 删除收款人 + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + 输入一个黑币地址 (例:AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + SignVerifyMessageDialog + + + Signatures - Sign / Verify a Message + 签名 - 为消息签名/验证签名消息 + + + + + &Sign Message + 签名消息(&S) + + + + You can sign messages with your addresses to prove you own them. Be careful not to sign anything vague, as phishing attacks may try to trick you into signing your identity over to them. Only sign fully-detailed statements you agree to. + 您可以用你的地址对消息进行签名,以证明您是该地址的所有人。注意不要对模棱两可的消息签名,以免遭受钓鱼式攻击。请确保消息内容准确的表达了您的真实意愿。 + + + + The address to sign the message with (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + 用来签名该消息的地址(例: AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Choose an address from the address book + 从地址簿里选择一个地址 + + + + + Alt+A + Alt+A + + + + Paste address from clipboard + 从剪贴板粘贴地址 + + + + Alt+P + Alt+P + + + + Enter the message you want to sign here + 请输入您要发送的签名消息 + + + + Copy the current signature to the system clipboard + 复制当前签名至剪切板 + + + + Sign the message to prove you own this Arepacoin address + 对该消息进行签名以证明您对该黑币地址的所有权 + + + + Reset all sign message fields + 清空所有签名消息栏 + + + + + Clear &All + 清除所有(&A) + + + + + &Verify Message + 验证消息(&V) + + + + Enter the signing address, message (ensure you copy line breaks, spaces, tabs, etc. exactly) and signature below to verify the message. Be careful not to read more into the signature than what is in the signed message itself, to avoid being tricked by a man-in-the-middle attack. + 在下面输入签名地址,消息(请确保换行符、空格符、制表符等等一个不漏)和签名以验证消息。请确保签名信息准确,提防中间人攻击。 + + + + The address the message was signed with (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + 用来签名该消息的黑币地址(例: AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + Verify the message to ensure it was signed with the specified Arepacoin address + 确认该消息以保证它经由指定的黑币地址签名 + + + + Reset all verify message fields + 清空所有验证消息栏 + + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + 输入黑币地址(例: AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + Click "Sign Message" to generate signature + 单击“签名消息“产生签名。 + + + + Enter Arepacoin signature + 输入黑币签名 + + + + + The entered address is invalid. + 输入的地址非法。 + + + + + + + Please check the address and try again. + 请检查地址后重试。 + + + + + The entered address does not refer to a key. + 输入的地址没有关联的公私钥对。 + + + + Wallet unlock was cancelled. + 钱包解锁动作取消。 + + + + Private key for the entered address is not available. + 找不到输入地址关联的私钥。 + + + + Message signing failed. + 消息签名失败。 + + + + Message signed. + 消息已签名。 + + + + The signature could not be decoded. + 签名无法解码。 + + + + + Please check the signature and try again. + 请检查签名后重试。 + + + + The signature did not match the message digest. + 签名与消息摘要不匹配。 + + + + Message verification failed. + 消息验证失败。 + + + + Message verified. + 消息验证成功。 + + + + TransactionDesc + + + Open until %1 + 至 %1 个数据块时开启 + + + + Open for %n block(s) + 为 %n 个数据块开启 + + + + conflicted + 发现冲突 + + + + %1/offline + %1 / 离线 + + + + %1/unconfirmed + %1/未确认 + + + + %1 confirmations + %1 已确认 + + + + Status + 状态 + + + + , broadcast through %n node(s) + 通过 %n 个节点广播 + + + + Date + 日期 + + + + Source + + + + + Generated + 生成 + + + + + From + 来自 + + + + + + To + + + + + + own address + 自己的地址 + + + + label + 标签 + + + + + + + + Credit + 收入 + + + + matures in %n more block(s) + 将在 %n 个数据块后成熟 + + + + not accepted + 未被接受 + + + + + + + Debit + 支出 + + + + Transaction fee + 交易费 + + + + Net amount + 净额 + + + + Message + 消息 + + + + Comment + 备注 + + + + Transaction ID + 交易ID + + + + Generated coins must mature 6 blocks before they can be spent. When you generated this block, it was broadcast to the network to be added to the block chain. If it fails to get into the chain, its state will change to "not accepted" and it won't be spendable. This may occasionally happen if another node generates a block within a few seconds of yours. + 通过权益累积获得的金额需要在6个块确认后方可使用。此数据块生成时,将被广播到网络并加入区块链。如果未能成功加入区块链,其状态会显示为“未接受”,该部分金额也不可被使用。如果其他节点在您生成区块后的几秒钟内也生成了区块,这种情况会偶尔发生。 + + + + Debug information + 调试信息 + + + + Transaction + 交易 + + + + Inputs + 输入 + + + + Amount + 金额 + + + + true + 正确 + + + + false + 错误 + + + + , has not been successfully broadcast yet + ,未被成功广播 + + + + unknown + 未知 + + + + TransactionDescDialog + + + Transaction details + 交易细节 + + + + This pane shows a detailed description of the transaction + 当前面板显示了交易的详细信息 + + + + TransactionTableModel + + + Date + 日期 + + + + Type + 类型 + + + + Address + 地址 + + + + Amount + 数量 + + + + Open until %1 + 至 %1 个数据块时开启 + + + + Confirmed (%1 confirmations) + 已确认 (%1 条确认信息) + + + + Open for %n more block(s) + 为 %n 个更多的区块开启 + + + + Offline + 掉线 + + + + Unconfirmed + 未确认的 + + + + Confirming (%1 of %2 recommended confirmations) + 确认中 (推荐 %2个确认,已经有 %1个确认) + + + + Conflicted + 冲突的 + + + + Immature (%1 confirmations, will be available after %2) + 未成熟 (%1 个确认,将在 %2 个后可用) + + + + This block was not received by any other nodes and will probably not be accepted! + 此数据块未被任何其他节点接收,可能不被接受! + + + + Generated but not accepted + 已生成但未被接受 + + + + Received with + 接收于 + + + + Received from + 收款来自 + + + + Sent to + 发送给 + + + + Payment to yourself + 付款给自己 + + + + Mined + 挖矿所得 + + + + (n/a) + (不可用) + + + + Transaction status. Hover over this field to show number of confirmations. + 交易状态。 鼠标移到此区域可显示确认项数量。 + + + + Date and time that the transaction was received. + 接收到交易的时间 + + + + Type of transaction. + 交易类别。 + + + + Destination address of transaction. + 交易目的地址。 + + + + Amount removed from or added to balance. + 从余额添加或移除的金额。 + + + + TransactionView + + + + All + 全部 + + + + Today + 今天 + + + + This week + 本周 + + + + This month + 本月 + + + + Last month + 上月 + + + + This year + 今年 + + + + Range... + 范围... + + + + Received with + 接收于 + + + + Sent to + 发送给 + + + + To yourself + 到自己 + + + + Mined + 挖矿所得 + + + + Other + 其他 + + + + Enter address or label to search + 输入地址或标签进行搜索 + + + + Min amount + 最小金额 + + + + Copy address + 复制地址 + + + + Copy label + 复制标签 + + + + Copy amount + 复制金额 + + + + Copy transaction ID + 复制交易编号 + + + + Edit label + 编辑标签 + + + + Show transaction details + 显示交易详情 + + + + Export Transaction Data + 输出交易数据 + + + + Comma separated file (*.csv) + 逗号分隔文件 (*.csv) + + + + Confirmed + 已确认 + + + + Date + 日期 + + + + Type + 类别 + + + + Label + 标签 + + + + Address + 地址 + + + + Amount + 金额 + + + + ID + ID + + + + Error exporting + 导出出现错误 + + + + Could not write to file %1. + 无法写入文件 %1 。 + + + + Range: + 范围: + + + + to + + + + + WalletModel + + + Sending... + 正在发送 + + + + bitcoin-core + + + Arepacoin version + 黑币客户端 版本 + + + + Usage: + 使用: + + + + Send command to -server or arepacoind + 向-server服务器或arepacoind发送命令 + + + + List commands + 列出命令 + + + + + Get help for a command + 获得某条命令的帮助 + + + + + Options: + 选项: + + + + + Specify configuration file (default: arepacoin.conf) + 指定配置文件(默认: arepacoin.conf) + + + + Specify pid file (default: arepacoind.pid) + 指定pid文件(默认: arepacoind.pid) + + + + Specify wallet file (within data directory) + 指定钱包文件(数据目录内) + + + + Specify data directory + 指定数据目录 + + + + + Set database cache size in megabytes (default: 25) + 设置数据库缓冲区大小 (缺省: 25MB) + + + + Set database disk log size in megabytes (default: 100) + 设置数据库日志文件大小(单位MB,默认值100) + + + + Listen for connections on <port> (default: 9853 or testnet: 19853) + 监听<port>端口的连接 (默认: 9853 测试网: 19853) + + + + Maintain at most <n> connections to peers (default: 125) + 最大连接数 <n> (缺省: 125) + + + + Connect to a node to retrieve peer addresses, and disconnect + 连接一个节点并获取对端地址,然后断开连接 + + + + Specify your own public address + 指定您的公共地址 + + + + Bind to given address. Use [host]:port notation for IPv6 + 以IPv6 [host]:端口绑定给定地址 + + + + Stake your coins to support network and gain reward (default: 1) + 进行权益累积以支持黑币网络并获得报酬(默认: 1) + + + + Threshold for disconnecting misbehaving peers (default: 100) + 断开出现问题节点阀值(缺省: 100) + + + + Number of seconds to keep misbehaving peers from reconnecting (default: 86400) + Number of seconds to keep misbehaving peers from reconnecting (缺省: 86400) + + + + An error occurred while setting up the RPC port %u for listening on IPv4: %s + 设置RPC监听端口%u时发生错误, IPv4:%s + + + + Detach block and address databases. Increases shutdown time (default: 0) + 离线保存区块和地址数据库. 增加关机时间。 (默认: 0) + + + + 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. + 错误:交易被拒绝。可能由于钱包中部分金额已被使用,例如您使用了钱包数据的副本,在副本中某些金额已被使用,但在此处尚未被标记为已使用。 + + + + Error: This transaction requires a transaction fee of at least %s because of its amount, complexity, or use of recently received funds + 错误:该笔交易需至少支付 %s 的手续费。 + + + + Listen for JSON-RPC connections on <port> (default: 9852 or testnet: 19852) + 监听 <port> 端口的JSON-RPC连接 (默认: 9852 测试网: 19852) + + + + Accept command line and JSON-RPC commands + 接受命令行和 JSON-RPC 命令 + + + + + Error: Transaction creation failed + 错误:交易创建失败。 + + + + Error: Wallet locked, unable to create transaction + 错误:钱包已锁定,无法创建交易。 + + + + Importing blockchain data file. + 正在导入区块链数据文件 + + + + Importing bootstrap blockchain data file. + 正在导入高速区块链数据文件 + + + + Run in the background as a daemon and accept commands + 在后台运行并接受命令 + + + + + + Use the test network + 使用测试网络 + + + + + Accept connections from outside (default: 1 if no -proxy or -connect) + 接受来自外部的连接 (缺省: 如果不带 -proxy or -connect 参数设置为1) + + + + An error occurred while setting up the RPC port %u for listening on IPv6, falling back to IPv4: %s + 在IPv6模式下设置RPC监听端口 %u 失败,返回到IPv4模式: %s + + + + Error initializing database environment %s! To recover, BACKUP THAT DIRECTORY, then remove everything from it except for wallet.dat. + 数据库环境 %s 初始化错误。要修复,备份该目录并将其下除wallet.dat以外的文件全部删除。 + + + + Set maximum size of high-priority/low-fee transactions in bytes (default: 27000) + 设置高优先度/低手续费交易的最大字节数 (默认: 27000) + + + + Warning: -paytxfee is set very high! This is the transaction fee you will pay if you send a transaction. + 警告:-paytxfee 交易费设置得太高了!每笔交易都将支付交易费。 + + + + Warning: Please check that your computer's date and time are correct! If your clock is wrong Arepacoin will not work properly. + 警告:请确认您计算机的本地时间。如果时钟错误,黑币客户端将不能正常工作。 + + + + Warning: error reading wallet.dat! All keys read correctly, but transaction data or address book entries might be missing or incorrect. + 警告:钱包文件wallet.dat读取失败!最重要的公钥、私钥数据都没有问题,但是交易记录或地址簿数据不正确,或者存在数据丢失。 + + + + Warning: wallet.dat corrupt, data salvaged! Original wallet.dat saved as wallet.{timestamp}.bak in %s; if your balance or transactions are incorrect you should restore from a backup. + 警告:钱包文件wallet.dat损坏! 原始的钱包文件已经备份到%s目录下并重命名为{timestamp}.bak 。如果您的账户余额或者交易记录不正确,请使用您的钱包备份文件恢复。 + + + + Attempt to recover private keys from a corrupt wallet.dat + 尝试从损坏的钱包文件wallet.dat中恢复私钥 + + + + Block creation options: + 数据块创建选项: + + + + Connect only to the specified node(s) + 仅连接到指定节点 + + + + Discover own IP address (default: 1 when listening and no -externalip) + 发现自己的IP地址(缺省:不带 -externalip 参数监听时设置为1) + + + + Failed to listen on any port. Use -listen=0 if you want this. + 监听端口失败。请使用 -listen=0 参数。 + + + + Find peers using DNS lookup (default: 1) + 以DNS查找方式寻找节点 (默认:1) + + + + Sync checkpoints policy (default: strict) + 同步检测点政策 (默认:严格) + + + + Invalid -tor address: '%s' + 无效的 -tor 地址: '%s' + + + + Invalid amount for -reservebalance=<amount> + -reservebalance=<amount> 金额无效 + + + + Maximum per-connection receive buffer, <n>*1000 bytes (default: 5000) + 每个连接的最大接收缓存,<n>*1000 字节(缺省:5000) + + + + Maximum per-connection send buffer, <n>*1000 bytes (default: 1000) + 每个连接的最大发送缓存,<n>*1000 字节(缺省:1000) + + + + Only connect to nodes in network <net> (IPv4, IPv6 or Tor) + 仅连接至指定网络的节点<net>(IPv4, IPv6 或者 Tor) + + + + Output extra debugging information. Implies all other -debug* options + 输出额外的调试信息。相当于开启了其它所有-debug选项 + + + + Output extra network debugging information + 输出额外的网络调试信息 + + + + Prepend debug output with timestamp + 将时间信息加入调试输出中 + + + + SSL options: (see the Bitcoin Wiki for SSL setup instructions) + SSL选项:(参见Bitcoin Wiki关于SSL设置栏目) + + + + Select the version of socks proxy to use (4-5, default: 5) + 选择要使用的SOCKS代理版本 (4-5, 默认 5) + + + + Send trace/debug info to console instead of debug.log file + 跟踪/调试信息输出到控制台,不输出到 debug.log 文件 + + + + Send trace/debug info to debugger + 发送跟踪/调试信息给调试者 + + + + Set maximum block size in bytes (default: 250000) + 设置最大区块大小 (默认:250000) + + + + Set minimum block size in bytes (default: 0) + 设置最小数据块大小(缺省:0) + + + + Shrink debug.log file on client startup (default: 1 when no -debug) + 客户端启动时压缩debug.log文件(缺省:no-debug模式时为1) + + + + Specify connection timeout in milliseconds (default: 5000) + 设置连接超时时间(缺省:5000毫秒) + + + + Unable to sign checkpoint, wrong checkpointkey? + + 无法为记录点签名,错误的记录点密钥。 + + + + Use UPnP to map the listening port (default: 0) + 使用UPnP映射监听端口 (缺省: 0) + + + + Use UPnP to map the listening port (default: 1 when listening) + 使用UPnp映射监听端口(缺省: 监听状态设为1) + + + + Use proxy to reach tor hidden services (default: same as -proxy) + 开启代理以使用隐藏服务 (默认: 和-proxy设置相同) + + + + Username for JSON-RPC connections + JSON-RPC 连接用户名 + + + + Verifying database integrity... + 正在检查数据库完整性... + + + + WARNING: syncronized checkpoint violation detected, but skipped! + 警告:检测到同步记录点错误,已跳过。 + + + + Warning: Disk space is low! + 警告:磁盘空间低。 + + + + Warning: This version is obsolete, upgrade required! + 警告:该软件版本已过时,请升级! + + + + wallet.dat corrupt, salvage failed + 钱包文件wallet.dat损坏,抢救备份失败 + + + + Password for JSON-RPC connections + JSON-RPC 连接密码 + + + + + %s, you must set a rpcpassword in the configuration file: + %s +It is recommended you use the following random password: +rpcuser=arepacoinrpc +rpcpassword=%s +(you do not need to remember this password) +The username and password MUST NOT be the same. +If the file does not exist, create it with owner-readable-only file permissions. +It is also recommended to set alertnotify so you are notified of problems; +for example: alertnotify=echo %%s | mail -s "Arepacoin Alert" admin@foo.com + + %s, 必须在配置文件里设置rpc密码: + %s +建议使用如下的随机密码: +rpcuser=arepacoinrpc +rpcpassword=%s +(不需要记住该密码) +用户名和密码不能重复。 +如果该文件不存在,请自行创建并设为用户本身只读权限。 +建议创建提示以监测可能的问题,如: +alertnotify=echo %%s | mail -s "Arepacoin Alert" admin@foo.com + + + + + Find peers using internet relay chat (default: 0) + 寻找使用互联网接力聊天的节点 (默认: 1) {0)?} + + + + Sync time with other nodes. Disable if time on your system is precise e.g. syncing with NTP (default: 1) + 自动和其它节点同步时间。如果本地计算机世界是准确的,建议关闭。(默认: 1) + + + + When creating transactions, ignore inputs with value less than this (default: 0.01) + 创建交易时自动忽略该值以下的数额 (默认:0.01) + + + + Allow JSON-RPC connections from specified IP address + 允许从指定IP接受到的 JSON-RPC 连接 + + + + Send commands to node running on <ip> (default: 127.0.0.1) + 向IP地址为 <ip> 的节点发送指令 (缺省: 127.0.0.1) + + + + Execute command when the best block changes (%s in cmd is replaced by block hash) + 当最佳数据块变化时执行命令 (命令行中的 %s 会被替换成数据块哈希值) + + + + Execute command when a wallet transaction changes (%s in cmd is replaced by TxID) + 当最佳区块变化时执行命令 (命令行中的 %s 会被替换成区块哈希值) + + + + Require a confirmations for change (default: 0) + 要求对零钱进行确认 (默认:0) + + + + Enforce transaction scripts to use canonical PUSH operators (default: 1) + 强制要求交易脚本使用标准PUSH算子 (默认:1) + + + + Execute command when a relevant alert is received (%s in cmd is replaced by message) + 收到相关提示时执行命令 (命令中的%s将被信息替换) + + + + Upgrade wallet to latest format + 将钱包升级到最新的格式 + + + + Set key pool size to <n> (default: 100) + 设置密钥池大小为 <n> (缺省: 100) + + + + + Rescan the block chain for missing wallet transactions + 重新扫描区块链以查找遗漏的钱包交易 + + + + How many blocks to check at startup (default: 2500, 0 = all) + 启动时检测的区块数量 (默认: 2500, 0表示检测全部) + + + + How thorough the block verification is (0-6, default: 1) + 区块确认的彻底程度 (0-6, 默认: 1) + + + + Imports blocks from external blk000?.dat file + 从外部 blk000?.dat 文件导入区块 + + + + Use OpenSSL (https) for JSON-RPC connections + 为 JSON-RPC 连接使用 OpenSSL (https) 连接 + + + + Server certificate file (default: server.cert) + 服务器证书 (默认为 server.cert) + + + + + Server private key (default: server.pem) + 服务器私钥 (默认为 server.pem) + + + + + Acceptable ciphers (default: TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH) + 可用加密算法 (默认: TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH) + + + + Error: Wallet unlocked for staking only, unable to create transaction. + 错误:无法创建交易,已解锁的钱包仅用于权益累积。 + + + + WARNING: Invalid checkpoint found! Displayed transactions may not be correct! You may need to upgrade, or notify developers. + 警告:发现无效的记录点。所显示的交易信息未必正确!请升级客户端或联系开发者。 + + + + This help message + 本帮助信息 + + + + + Wallet %s resides outside data directory %s. + 钱包 %s 位于数据目录 %s 之外. + + + + Cannot obtain a lock on data directory %s. Arepacoin is probably already running. + 无法从数据目录 %s 获得锁定. 黑币客户端可能已在运行中. + + + + Arepacoin + 黑币 + + + + Unable to bind to %s on this computer (bind returned error %d, %s) + 无法绑定本机端口 %s (返回错误消息 %d, %s) + + + + Connect through socks proxy + 通过socks代理连接 + + + + Allow DNS lookups for -addnode, -seednode and -connect + 使用 -addnode, -seednode 和 -connect 选项时允许查询DNS + + + + Loading addresses... + 正在加载地址簿... + + + + Error loading blkindex.dat + blkindex.dat 文件加载出错 + + + + Error loading wallet.dat: Wallet corrupted + wallet.dat 钱包文件加载出错:钱包损坏 + + + + Error loading wallet.dat: Wallet requires newer version of Arepacoin + wallet.dat 钱包文件加载出错:需要新版本的客户端 + + + + Wallet needed to be rewritten: restart Arepacoin to complete + 需要重写钱包,重启客户端以完成该操作。 + + + + Error loading wallet.dat + wallet.dat 钱包文件加载出错 + + + + Invalid -proxy address: '%s' + 无效的代理地址:%s + + + + Unknown network specified in -onlynet: '%s' + -onlynet 指定的是未知网络:%s + + + + Unknown -socks proxy version requested: %i + 被指定的是未知socks代理版本: %i + + + + Cannot resolve -bind address: '%s' + 无法解析 -bind 端口地址: '%s' + + + + Cannot resolve -externalip address: '%s' + 无法解析 -externalip 地址: '%s' + + + + Invalid amount for -paytxfee=<amount>: '%s' + 非法金额 -paytxfee=<amount>: '%s' + + + + Error: could not start node + 错误:无法启动节点 + + + + Sending... + 正在发送 + + + + Invalid amount + 无效金额 + + + + Insufficient funds + 金额不足 + + + + Loading block index... + 正在加载数据块索引... + + + + Add a node to connect to and attempt to keep the connection open + 添加节点并与其保持连接 + + + + Unable to bind to %s on this computer. Arepacoin is probably already running. + 无法绑定到该计算机上的 %s. 黑币客户端可能已在运行中。 + + + + Fee per KB to add to transactions you send + 每kB交易所支付的手续费 + + + + Invalid amount for -mininput=<amount>: '%s' + 无效的数量。 -mininput=<amount>: '%s' + + + + Loading wallet... + 正在加载钱包... + + + + Cannot downgrade wallet + 无法降级钱包 + + + + Cannot initialize keypool + 无法初始化密钥池。 + + + + Cannot write default address + 无法写入默认地址 + + + + Rescanning... + 正在重新扫描... + + + + Done loading + 加载完成 + + + + To use the %s option + 使用 %s 选项 + + + + Error + 错误 + + + + You must set rpcpassword=<password> in the configuration file: +%s +If the file does not exist, create it with owner-readable-only file permissions. + 您必须在配置文件中加入选项 rpcpassword : + %s +如果配置文件不存在,请新建,并将文件权限设置为仅允许文件所有者读取. + + + \ No newline at end of file diff --git a/src/qt/locale/bitcoin_zh_TW.ts b/src/qt/locale/bitcoin_zh_TW.ts new file mode 100755 index 0000000..025606f --- /dev/null +++ b/src/qt/locale/bitcoin_zh_TW.ts @@ -0,0 +1,3289 @@ + + + AboutDialog + + + About Arepacoin + 關于黑幣 + + + + <b>Arepacoin</b> version + <b>黑幣客戶端</b> 版本 + + + + Copyright © 2009-2014 The Bitcoin developers +Copyright © 2012-2014 The NovaCoin developers +Copyright © 2014 The Arepacoin developers + + + + + +This is experimental software. + +Distributed under the MIT/X11 software license, see the accompanying file COPYING or http://www.opensource.org/licenses/mit-license.php. + +This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit (http://www.openssl.org/) and cryptographic software written by Eric Young (eay@cryptsoft.com) and UPnP software written by Thomas Bernard. + +位元幣,原名是 Bitcoin, 又叫做比特幣。 + +這是一套實驗性的軟體。 + +這套軟體是依據 MIT/X11 軟體授權條款散布,詳情請見附帶的 COPYING 檔案,或是以下網站: http://www.opensource.org/licenses/mit-license.php. + +此產品也包含了由 OpenSSL Project 所開發的 OpenSSL Toolkit (http://www.openssl.org/) 軟體,和由 Eric Young (eay@cryptsoft.com) 撰寫的加解密軟體,以及由 Thomas Bernard 所撰寫的 UPnP 軟體。 + + + + AddressBookPage + + + Address Book + 地址簿 + + + + Double-click to edit address or label + 按兩下來編輯位址或標記 + + + + Create a new address + 製造新的位址 + + + + Copy the currently selected address to the system clipboard + 複製目前選擇的位址到系統剪貼簿 + + + + &New Address + 新建地址(&N) + + + + These are your Arepacoin addresses for receiving payments. You may want to give a different one to each sender so you can keep track of who is paying you. + 這是您用來接收支付的黑幣地址列表。爲不同的支付方建立不同的地址以便于了解支付來源。 + + + + &Copy Address + 複製地址(&C) + + + + Show &QR Code + 顯示二維碼(&Q) + + + + Sign a message to prove you own a Arepacoin address + 對信息進行簽名以證明您對該黑幣地址的所有權 + + + + Sign &Message + 簽署訊息(&M) + + + + Delete the currently selected address from the list + 把目前選擇的位址從列表中刪掉 + + + + Verify a message to ensure it was signed with a specified Arepacoin address + 驗證信息以保證其經過指定黑幣地址的簽名 + + + + &Verify Message + 驗證訊息(&V) + + + + &Delete + 刪掉(&D) + + + + Copy &Label + 複製標記 + + + + &Edit + 編輯 + + + + Export Address Book Data + 導出地址簿數據 + + + + Comma separated file (*.csv) + 逗號分隔資料檔(*.csv) + + + + Error exporting + 導出時發生錯誤 + + + + Could not write to file %1. + 無法寫入文件 %1 。 + + + + AddressTableModel + + + Label + 標記 + + + + Address + 位址 + + + + (no label) + (無標記) + + + + AskPassphraseDialog + + + Passphrase Dialog + 密碼對話視窗 + + + + Enter passphrase + 請輸入密碼 + + + + New passphrase + 新密碼 + + + + Repeat new passphrase + 重複新密碼 + + + + Serves to disable the trivial sendmoney when OS account compromised. Provides no real security. + 在系統允許的情況下用于防止sendmoney欺詐,並未提供真正的安全防護措施。 + + + + For staking only + 仅用于权益增值 + + + + Enter the new passphrase to the wallet.<br/>Please use a passphrase of <b>10 or more random characters</b>, or <b>eight or more words</b>. + 請輸入錢包的新密碼。<br/>建議用<b>10 個以上的任意字元</b>,或是<b>8 個以上的單字</b>。 + + + + Encrypt wallet + 加密錢包 + + + + This operation needs your wallet passphrase to unlock the wallet. + 這個動作需要你的錢包密碼來解鎖錢包。 + + + + Unlock wallet + 解鎖錢包 + + + + This operation needs your wallet passphrase to decrypt the wallet. + 這個動作需要你的錢包密碼來把錢包解密。 + + + + Decrypt wallet + 解密錢包 + + + + Change passphrase + 改變密碼 + + + + Enter the old and new passphrase to the wallet. + 請輸入錢包的舊密碼及新密碼。 + + + + Confirm wallet encryption + 確認錢包加密 + + + + Warning: If you encrypt your wallet and lose your passphrase, you will <b>LOSE ALL OF YOUR COINS</b>! + 警告:如果您丟失了加密該錢包的密碼,其中所有的黑幣將會丟失! + + + + Are you sure you wish to encrypt your wallet? + 你確定要把錢包加密嗎? + + + + IMPORTANT: Any previous backups you have made of your wallet file should be replaced with the newly generated, encrypted wallet file. For security reasons, previous backups of the unencrypted wallet file will become useless as soon as you start using the new, encrypted wallet. + 重要: 請改用新產生有加密的錢包檔,來取代舊錢包檔的備份。為了安全性的理由,當你開始使用新的有加密的錢包後,舊錢包檔的備份就不能再使用了。 + + + + + Warning: The Caps Lock key is on! + 警告: 大寫字母鎖定作用中! + + + + + Wallet encrypted + 錢包已加密 + + + + Arepacoin will close now to finish the encryption process. Remember that encrypting your wallet cannot fully protect your coins from being stolen by malware infecting your computer. + 黑幣客戶端即將關閉以完成加密過程。請記住,加密錢包並不能完全防止您的電子貨幣被入侵您計算機的木馬軟件盜竊。 + + + + + + + Wallet encryption failed + 錢包加密失敗 + + + + Wallet encryption failed due to an internal error. Your wallet was not encrypted. + 因為內部錯誤導致錢包加密失敗。你的錢包還是沒加密。 + + + + + The supplied passphrases do not match. + 提供的密碼不一樣。 + + + + Wallet unlock failed + 錢包解鎖失敗 + + + + + + The passphrase entered for the wallet decryption was incorrect. + 輸入要用來解密錢包的密碼不對。 + + + + Wallet decryption failed + 錢包解密失敗 + + + + Wallet passphrase was successfully changed. + 錢包密碼改成功了。 + + + + BitcoinGUI + + + Sign &message... + 簽署訊息... + + + + Synchronizing with network... + 正在跟網路進行同步... + + + + &Overview + 總覽 + + + + Show general overview of wallet + 顯示錢包一般總覽 + + + + &Transactions + 交易 + + + + Browse transaction history + 瀏覽交易紀錄 + + + + &Address Book + 地址簿(&A) + + + + Edit the list of stored addresses and labels + 管理已儲存的地址和標簽 + + + + &Receive coins + 接收黑幣(&R) + + + + Show the list of addresses for receiving payments + 顯示用于接收支付的地址列表 + + + + &Send coins + 發送黑幣(&S) + + + + E&xit + 結束 + + + + Quit application + 結束應用程式 + + + + Show information about Arepacoin + 關于黑幣 + + + + About &Qt + 關於 &Qt + + + + Show information about Qt + 顯示 Qt 相關資訊 + + + + &Options... + 選項... + + + + &Encrypt Wallet... + 加密錢包... + + + + &Backup Wallet... + 備份錢包... + + + + &Change Passphrase... + 改變密碼... + + + + ~%n block(s) remaining + ~%n 個區塊未完成 + + + + Downloaded %1 of %2 blocks of transaction history (%3% done). + 交易記錄已下載%3% (%1 / %2 個區塊) + + + + &Export... + 導出(&E) + + + + Send coins to a Arepacoin address + 向指定的地址發送黑幣 + + + + Modify configuration options for Arepacoin + + + + + Export the data in the current tab to a file + + + + + Encrypt or decrypt wallet + + + + + Backup wallet to another location + 把錢包備份到其它地方 + + + + Change the passphrase used for wallet encryption + 改變錢包加密用的密碼 + + + + &Debug window + 除錯視窗 + + + + Open debugging and diagnostic console + 開啓除錯和診斷主控台 + + + + &Verify message... + 驗證訊息... + + + + Arepacoin + + + + + Wallet + 錢包 + + + + &About Arepacoin + + + + + &Show / Hide + 顯示或隱藏 + + + + Unlock wallet + + + + + &Lock Wallet + + + + + Lock wallet + + + + + &File + 檔案 + + + + &Settings + 設定 + + + + &Help + 說明 + + + + Tabs toolbar + 分頁工具列 + + + + Actions toolbar + 分頁工具欄 + + + + + [testnet] + [測試網絡] + + + + + Arepacoin client + 黑幣客戶端 + + + + %n active connection(s) to Arepacoin network + 與黑幣網絡建立了 %n 個連接 + + + + Downloaded %1 blocks of transaction history. + 已下載 %1 個區塊的交易記錄 + + + + Staking.<br>Your weight is %1<br>Network weight is %2<br>Expected time to earn reward is %3 + 權益增值中 <br>您的權重爲 %1 <br>網絡總權重爲 %2<br>預計將在 %3 之後獲得收益 + + + + Not staking because wallet is locked + + + + + Not staking because wallet is offline + + + + + Not staking because wallet is syncing + + + + + Not staking because you don't have mature coins + + + + + %n second(s) ago + + + + + &Unlock Wallet... + + + + + %n minute(s) ago + + + + + %n hour(s) ago + + + + + %n day(s) ago + + + + + Up to date + 最新狀態 + + + + Catching up... + 正在趕進度... + + + + Last received block was generated %1. + + + + + This transaction is over the size limit. You can still send it for a fee of %1, which goes to the nodes that process your transaction and helps to support the network. Do you want to pay the fee? + + + + + Confirm transaction fee + + + + + Sent transaction + 付款交易 + + + + Incoming transaction + 收款交易 + + + + Date: %1 +Amount: %2 +Type: %3 +Address: %4 + + 日期: %1 +金額: %2 +種類: %3 +位址: %4 + + + + + + URI handling + + + + + + URI can not be parsed! This can be caused by an invalid Arepacoin address or malformed URI parameters. + + + + + Wallet is <b>encrypted</b> and currently <b>unlocked</b> + 錢包<b>已加密</b>並且<b>解鎖中</b> + + + + Wallet is <b>encrypted</b> and currently <b>locked</b> + 錢包<b>已加密</b>並且<b>上鎖中</b> + + + + Backup Wallet + + + + + Wallet Data (*.dat) + + + + + Backup Failed + + + + + There was an error trying to save the wallet data to the new location. + + + + + %n second(s) + + + + + %n minute(s) + + + + + %n hour(s) + %n 個小時 + + + + %n day(s) + %n 天 + + + + Not staking + + + + + A fatal error occurred. Arepacoin can no longer continue safely and will quit. + + + + + ClientModel + + + Network Alert + 網路警報 + + + + CoinControlDialog + + + Coin Control + + + + + Quantity: + 數目: + + + + Bytes: + 位元組數: + + + + Amount: + 金額: + + + + Priority: + 優先度: + + + + Fee: + 手續費: + + + + Low Output: + 低輸出: + + + + no + + + + + After Fee: + 計費後金額: + + + + Change: + 找零金額: + + + + (un)select all + 全選或全不選 + + + + Tree mode + 樹狀模式 + + + + List mode + 列表模式 + + + + Amount + 金額 + + + + Label + + + + + Address + 位址 + + + + Date + 日期 + + + + Confirmations + 確認次數 + + + + Confirmed + 已確定 + + + + Priority + 優先度 + + + + Copy address + 複製位址 + + + + Copy label + 複製標記 + + + + + Copy amount + 複製金額 + + + + Copy transaction ID + 複製交易識別碼 + + + + Copy quantity + 複製數目 + + + + Copy fee + 複製手續費 + + + + Copy after fee + 複製計費後金額 + + + + Copy bytes + 複製位元組數 + + + + Copy priority + 複製優先度 + + + + Copy low output + 複製低輸出 + + + + Copy change + 複製找零金額 + + + + highest + 最高 + + + + high + + + + + medium-high + 中高 + + + + medium + 中等 + + + + low-medium + 中低 + + + + low + + + + + lowest + 最低 + + + + DUST + + + + + yes + + + + + This label turns red, if the transaction size is bigger than 10000 bytes. + + This means a fee of at least %1 per kb is required. + + Can vary +/- 1 Byte per input. + + + + + Transactions with higher priority get more likely into a block. + +This label turns red, if the priority is smaller than "medium". + + This means a fee of at least %1 per kb is required. + + + + + This label turns red, if any recipient receives an amount smaller than %1. + + This means a fee of at least %2 is required. + + Amounts below 0.546 times the minimum relay fee are shown as DUST. + + + + + This label turns red, if the change is smaller than %1. + + This means a fee of at least %2 is required. + + + + + + (no label) + (無標記) + + + + change from %1 (%2) + 找零前是 %1 (%2) + + + + (change) + (找零) + + + + EditAddressDialog + + + Edit Address + 編輯位址 + + + + &Label + 標記 + + + + The label associated with this address book entry + + + + + &Address + 位址 + + + + The address associated with this address book entry. This can only be modified for sending addresses. + + + + + New receiving address + 造新的收款位址 + + + + New sending address + 造新的付款位址 + + + + Edit receiving address + 編輯收款位址 + + + + Edit sending address + 編輯付款位址 + + + + The entered address "%1" is already in the address book. + 輸入的位址 %1 在位址簿中已經有了。 + + + + The entered address "%1" is not a valid Arepacoin address. + + + + + Could not unlock wallet. + 沒辦法把錢包解鎖。 + + + + New key generation failed. + 產生新的密鑰失敗了。 + + + + GUIUtil::HelpMessageBox + + + + Arepacoin-Qt + + + + + version + + + + + Usage: + + + + + command-line options + + + + + UI options + + + + + Set language, for example "de_DE" (default: system locale) + + + + + Start minimized + + + + + Show splash screen on startup (default: 1) + + + + + OptionsDialog + + + Options + 選項 + + + + &Main + 主要 + + + + Optional transaction fee per kB that helps make sure your transactions are processed quickly. Most transactions are 1 kB. Fee 0.01 recommended. + + + + + Pay transaction &fee + 付交易手續費 + + + + Reserved amount does not participate in staking and is therefore spendable at any time. + + + + + Reserve + + + + + Automatically start Arepacoin after logging in to the system. + + + + + &Start Arepacoin on system login + + + + + Detach block and address databases at shutdown. This means they can be moved to another data directory, but it slows down shutdown. The wallet is always detached. + + + + + &Detach databases at shutdown + + + + + &Network + 網路 + + + + Automatically open the Arepacoin client port on the router. This only works when your router supports UPnP and it is enabled. + + + + + Map port using &UPnP + 用 &UPnP 設定通訊埠對應 + + + + Connect to the Arepacoin network through a SOCKS proxy (e.g. when connecting through Tor). + + + + + &Connect through SOCKS proxy: + + + + + Proxy &IP: + 代理位址: + + + + IP address of the proxy (e.g. 127.0.0.1) + + + + + &Port: + 埠號: + + + + Port of the proxy (e.g. 9050) + 代理伺服器的通訊埠(像是 9050) + + + + SOCKS &Version: + SOCKS 版本: + + + + SOCKS version of the proxy (e.g. 5) + 代理伺服器的 SOCKS 協定版本(像是 5) + + + + &Window + 視窗 + + + + Show only a tray icon after minimizing the window. + 視窗縮到最小後只在通知區域顯示圖示。 + + + + &Minimize to the tray instead of the taskbar + 縮到最小到通知區域而不是工作列 + + + + Minimize instead of exit the application when the window is closed. When this option is enabled, the application will be closed only after selecting Quit in the menu. + 當視窗關閉時,把應用程式縮到最小,而不是結束。當勾選這個選項時,只能夠用選單中的結束來關掉應用程式。 + + + + M&inimize on close + 關閉時縮到最小 + + + + &Display + 顯示 + + + + User Interface &language: + 使用界面語言: + + + + The user interface language can be set here. This setting will take effect after restarting Arepacoin. + + + + + &Unit to show amounts in: + 金額顯示單位: + + + + Choose the default subdivision unit to show in the interface and when sending coins. + 選擇操作界面和付款時,預設顯示金額的細分單位。 + + + + Whether to show Arepacoin addresses in the transaction list or not. + + + + + &Display addresses in transaction list + 在交易列表顯示位址 + + + + Whether to show coin control features or not. + 是否要顯示錢幣控制功能。 + + + + Display coin &control features (experts only!) + + + + + &OK + + + + + &Cancel + 取消 + + + + &Apply + + + + + default + 預設值 + + + + + Warning + + + + + + This setting will take effect after restarting Arepacoin. + + + + + The supplied proxy address is invalid. + 提供的代理伺服器位址無效。 + + + + OverviewPage + + + Form + 表單 + + + + + The displayed information may be out of date. Your wallet automatically synchronizes with the Arepacoin network after a connection is established, but this process has not completed yet. + + + + + Stake: + + + + + Unconfirmed: + 未確定金額: + + + + Wallet + 錢包 + + + + Spendable: + + + + + Your current spendable balance + 目前可用餘額 + + + + Immature: + 未成熟金額: + + + + Mined balance that has not yet matured + 還沒成熟的開採金額 + + + + Total: + 總金額: + + + + Your current total balance + 目前全部餘額 + + + + <b>Recent transactions</b> + <b>最近交易</b> + + + + Total of transactions that have yet to be confirmed, and do not yet count toward the current balance + + + + + Total of coins that was staked, and do not yet count toward the current balance + + + + + + out of sync + 還沒同步 + + + + QRCodeDialog + + + QR Code Dialog + + + + + Request Payment + + + + + Amount: + + + + + Label: + + + + + Message: + + + + + &Save As... + + + + + Error encoding URI into QR Code. + + + + + The entered amount is invalid, please check. + + + + + Resulting URI too long, try to reduce the text for label / message. + + + + + Save QR Code + + + + + PNG Images (*.png) + + + + + RPCConsole + + + Client name + 客戶端軟體名稱 + + + + + + + + + + + + + N/A + 未知 + + + + Client version + 客戶端軟體版本 + + + + &Information + 資訊 + + + + Using OpenSSL version + 使用的 OpenSSL 版本 + + + + Startup time + 啓動時間 + + + + Network + 網路 + + + + Number of connections + 連線數 + + + + On testnet + + + + + Block chain + 區塊鏈 + + + + Current number of blocks + 目前區塊數 + + + + Estimated total blocks + 估計總區塊數 + + + + Last block time + 最近區塊時間 + + + + &Open + 開啓 + + + + Command-line options + + + + + Show the Arepacoin-Qt help message to get a list with possible Arepacoin command-line options. + + + + + &Show + + + + + &Console + 主控台 + + + + Build date + 建置日期 + + + + Arepacoin - Debug window + + + + + Arepacoin Core + + + + + Debug log file + 除錯紀錄檔 + + + + Open the Arepacoin debug log file from the current data directory. This can take a few seconds for large log files. + + + + + Clear console + 清主控台 + + + + Welcome to the Arepacoin RPC console. + + + + + Use up and down arrows to navigate history, and <b>Ctrl-L</b> to clear screen. + 請用上下游標鍵來瀏覽先前指令的紀錄,並用 <b>Ctrl-L</b> 來清理畫面。 + + + + Type <b>help</b> for an overview of available commands. + 請打 <b>help</b> 來看可用指令的簡介。 + + + + SendCoinsDialog + + + + + + + + + + Send Coins + 付款 + + + + Coin Control Features + 錢幣控制功能 + + + + Inputs... + 輸入... + + + + automatically selected + 自動選擇 + + + + Insufficient funds! + 累計金額不足! + + + + Quantity: + 數目: + + + + + 0 + + + + + Bytes: + 位元組數: + + + + Amount: + 金額: + + + + + + + 0.00 BC + + + + + Priority: + 優先度: + + + + medium + + + + + Fee: + 手續費: + + + + Low Output: + 低輸出: + + + + no + + + + + After Fee: + 計費後金額: + + + + Change + + + + + custom change address + + + + + Send to multiple recipients at once + 一次付給多個收款人 + + + + Add &Recipient + 增加收款人 + + + + Remove all transaction fields + + + + + Clear &All + 全部清掉 + + + + Balance: + 餘額: + + + + 123.456 BC + + + + + Confirm the send action + 確認付款動作 + + + + S&end + 付款 + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Copy quantity + 複製數目 + + + + Copy amount + 複製金額 + + + + Copy fee + 複製手續費 + + + + Copy after fee + 複製計費後金額 + + + + Copy bytes + 複製位元組數 + + + + Copy priority + 複製優先度 + + + + Copy low output + 複製低輸出 + + + + Copy change + 複製找零金額 + + + + <b>%1</b> to %2 (%3) + + + + + Confirm send coins + 確認付款金額 + + + + Are you sure you want to send %1? + + + + + and + + + + + The recipient address is not valid, please recheck. + 收款位址無效,請再檢查看看。 + + + + The amount to pay must be larger than 0. + 付款金額必須大於零。 + + + + The amount exceeds your balance. + 金額超過餘額了。 + + + + The total exceeds your balance when the %1 transaction fee is included. + 包含 %1 的交易手續費後,總金額超過你的餘額了。 + + + + Duplicate address found, can only send to each address once per send operation. + 發現有重複的位址。每個付款動作中,只能付給個別的位址一次。 + + + + Error: Transaction creation failed. + + + + + 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. + + + + + WARNING: Invalid Arepacoin address + + + + + (no label) + (無標記) + + + + WARNING: unknown change address + + + + + SendCoinsEntry + + + Form + + + + + A&mount: + 金額: + + + + Pay &To: + 付給: + + + + + Enter a label for this address to add it to your address book + 請輸入這個位址的標記來把它加進位址簿中 + + + + &Label: + 標記: + + + + The address to send the payment to (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Choose address from address book + + + + + Alt+A + Alt+A + + + + Paste address from clipboard + 貼上剪貼簿裡的位址 + + + + Alt+P + Alt+P + + + + Remove this recipient + + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + SignVerifyMessageDialog + + + Signatures - Sign / Verify a Message + 簽章 - 簽署或驗證訊息 + + + + + &Sign Message + 簽署訊息 + + + + You can sign messages with your addresses to prove you own them. Be careful not to sign anything vague, as phishing attacks may try to trick you into signing your identity over to them. Only sign fully-detailed statements you agree to. + 你可以用自己的位址簽署訊息,來證明你對位址的所有權。但是請小心,不要簽署語意含糊不清的內容,因為釣魚式詐騙可能會用騙你簽署的手法來冒充是你。只有在語句中的細節你都同意時才簽署。 + + + + The address to sign the message with (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + + Choose an address from the address book + + + + + + Alt+A + Alt+A + + + + Paste address from clipboard + 貼上剪貼簿裡的位址 + + + + Alt+P + Alt+P + + + + Enter the message you want to sign here + 請在這裡輸入你想簽署的訊息 + + + + Copy the current signature to the system clipboard + 複製目前的簽章到系統剪貼簿 + + + + Sign the message to prove you own this Arepacoin address + + + + + Reset all sign message fields + 重置所有訊息簽署欄位 + + + + + Clear &All + 全部清掉 + + + + + &Verify Message + 驗證訊息 + + + + Enter the signing address, message (ensure you copy line breaks, spaces, tabs, etc. exactly) and signature below to verify the message. Be careful not to read more into the signature than what is in the signed message itself, to avoid being tricked by a man-in-the-middle attack. + 請在下面輸入簽署的位址,訊息(請確定完整複製了所包含的換行,空格,跳位符號等等),以及簽章,來驗證這個訊息。請小心,除了訊息內容以外,不要對簽章本身過度解讀,以避免被用「中間人攻擊法」詐騙。 + + + + The address the message was signed with (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Verify the message to ensure it was signed with the specified Arepacoin address + + + + + Reset all verify message fields + 重置所有訊息驗證欄位 + + + + + Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD) + + + + + Click "Sign Message" to generate signature + 請按一下「簽署訊息」來產生簽章 + + + + Enter Arepacoin signature + + + + + + The entered address is invalid. + 輸入的位址無效。 + + + + + + + Please check the address and try again. + 請檢查位址是否正確後再試一次。 + + + + + The entered address does not refer to a key. + 輸入的位址沒有對應到你的任何密鑰。 + + + + Wallet unlock was cancelled. + 錢包解鎖已取消。 + + + + Private key for the entered address is not available. + 沒有對應輸入位址的密鑰。 + + + + Message signing failed. + 訊息簽署失敗。 + + + + Message signed. + 訊息簽署好了。 + + + + The signature could not be decoded. + 沒辦法把這個簽章解碼。 + + + + + Please check the signature and try again. + 請檢查簽章是否正確後再試一次。 + + + + The signature did not match the message digest. + 這個簽章跟訊息的數位摘要不符。 + + + + Message verification failed. + 訊息驗證失敗。 + + + + Message verified. + 訊息驗證沒錯。 + + + + TransactionDesc + + + Open until %1 + 要到 %1 才確定 + + + + Open for %n block(s) + + + + + conflicted + + + + + %1/offline + %1/離線中 + + + + %1/unconfirmed + %1/未確定 + + + + %1 confirmations + %1 次確認 + + + + Status + 狀態 + + + + , broadcast through %n node(s) + ,已公告給 %n 個節點 + + + + Date + 日期 + + + + Source + 來源 + + + + Generated + 生產出來 + + + + + From + 來源 + + + + + + To + 目的 + + + + + own address + 自己的位址 + + + + label + 標記 + + + + + + + + Credit + 入帳 + + + + matures in %n more block(s) + 再等 %n 個區塊生出來後成熟 + + + + not accepted + 不被接受 + + + + + + + Debit + 出帳 + + + + Transaction fee + 交易手續費 + + + + Net amount + 淨額 + + + + Message + 訊息 + + + + Comment + 附註 + + + + Transaction ID + 交易識別碼 + + + + Generated coins must mature 6 blocks before they can be spent. When you generated this block, it was broadcast to the network to be added to the block chain. If it fails to get into the chain, its state will change to "not accepted" and it won't be spendable. This may occasionally happen if another node generates a block within a few seconds of yours. + + + + + Debug information + 除錯資訊 + + + + Transaction + 交易 + + + + Inputs + 輸入 + + + + Amount + 金額 + + + + true + + + + + false + + + + + , has not been successfully broadcast yet + ,還沒成功公告出去 + + + + unknown + 未知 + + + + TransactionDescDialog + + + Transaction details + 交易明細 + + + + This pane shows a detailed description of the transaction + 這個版面顯示這次交易的詳細說明 + + + + TransactionTableModel + + + Date + 日期 + + + + Type + 種類 + + + + Address + 位址 + + + + Amount + 金額 + + + + Open until %1 + 要到 %1 才確定 + + + + Confirmed (%1 confirmations) + 已確定(%1 次確認) + + + + Open for %n more block(s) + 再等 %n 個區塊生出來後才確定 + + + + Offline + + + + + Unconfirmed + + + + + Confirming (%1 of %2 recommended confirmations) + + + + + Conflicted + + + + + Immature (%1 confirmations, will be available after %2) + 未成熟(%1 次確認,會在 %2 次確認後可用) + + + + This block was not received by any other nodes and will probably not be accepted! + 沒有其他節點收到這個區塊,也許它不會被接受! + + + + Generated but not accepted + 生產出來但是不被接受 + + + + Received with + 收款在 + + + + Received from + 收款自 + + + + Sent to + 付款給 + + + + Payment to yourself + 付給自己 + + + + Mined + 開採所得 + + + + (n/a) + (不適用) + + + + Transaction status. Hover over this field to show number of confirmations. + 交易狀態。把游標停在欄位上會顯示確認次數。 + + + + Date and time that the transaction was received. + 收到交易的日期和時間。 + + + + Type of transaction. + 交易的種類。 + + + + Destination address of transaction. + 交易的目的地位址。 + + + + Amount removed from or added to balance. + 要減掉或加進餘額的金額。 + + + + TransactionView + + + + All + 全部 + + + + Today + 今天 + + + + This week + 這星期 + + + + This month + 這個月 + + + + Last month + 上個月 + + + + This year + 今年 + + + + Range... + 指定範圍... + + + + Received with + 收款 + + + + Sent to + 付款 + + + + To yourself + 給自己 + + + + Mined + 開採所得 + + + + Other + 其它 + + + + Enter address or label to search + 請輸入要搜尋的位址或標記 + + + + Min amount + 最小金額 + + + + Copy address + 複製位址 + + + + Copy label + 複製標記 + + + + Copy amount + 複製金額 + + + + Copy transaction ID + 複製交易識別碼 + + + + Edit label + 編輯標記 + + + + Show transaction details + 顯示交易明細 + + + + Export Transaction Data + + + + + Comma separated file (*.csv) + 逗點分隔資料檔(*.csv) + + + + Confirmed + 已確定 + + + + Date + 日期 + + + + Type + 種類 + + + + Label + 標記 + + + + Address + 位址 + + + + Amount + 金額 + + + + ID + 識別碼 + + + + Error exporting + + + + + Could not write to file %1. + + + + + Range: + 範圍: + + + + to + + + + + WalletModel + + + Sending... + + + + + bitcoin-core + + + Arepacoin version + + + + + Usage: + 用法: + + + + Send command to -server or arepacoind + + + + + List commands + 列出指令 + + + + Get help for a command + 取得指令說明 + + + + Options: + 選項: + + + + Specify configuration file (default: arepacoin.conf) + + + + + Specify pid file (default: arepacoind.pid) + + + + + Specify wallet file (within data directory) + 指定錢包檔(會在資料目錄中) + + + + Specify data directory + 指定資料目錄 + + + + Set database cache size in megabytes (default: 25) + 設定資料庫快取大小成多少百萬位元組(MB;預設值: 25) + + + + Set database disk log size in megabytes (default: 100) + + + + + Listen for connections on <port> (default: 9853 or testnet: 19853) + + + + + Maintain at most <n> connections to peers (default: 125) + 維持連線節點數的上限為 <n> 個(預設值: 125) + + + + Connect to a node to retrieve peer addresses, and disconnect + 連線到某個節點來取得其它節點的位址,然後斷線 + + + + Specify your own public address + 指定自己的公開位址 + + + + Bind to given address. Use [host]:port notation for IPv6 + + + + + Stake your coins to support network and gain reward (default: 1) + + + + + Threshold for disconnecting misbehaving peers (default: 100) + 把異常節點斷線的臨界值(預設值: 100) + + + + Number of seconds to keep misbehaving peers from reconnecting (default: 86400) + 拒絕跟異常節點連線的秒數(預設值: 86400) + + + + An error occurred while setting up the RPC port %u for listening on IPv4: %s + 設定在 IPv4 網路上以通訊埠 %u 聽取 RPC 連線時發生錯誤: %s + + + + Detach block and address databases. Increases shutdown time (default: 0) + + + + + 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. + + + + + Error: This transaction requires a transaction fee of at least %s because of its amount, complexity, or use of recently received funds + + + + + Listen for JSON-RPC connections on <port> (default: 9852 or testnet: 19852) + + + + + Accept command line and JSON-RPC commands + 接受指令列和 JSON-RPC 指令 + + + + + Error: Transaction creation failed + + + + + Error: Wallet locked, unable to create transaction + + + + + Importing blockchain data file. + + + + + Importing bootstrap blockchain data file. + + + + + Run in the background as a daemon and accept commands + 用護靈模式在背後執行並接受指令 + + + + Use the test network + 使用測試網路 + + + + Accept connections from outside (default: 1 if no -proxy or -connect) + 是否接受外來連線(預設值: 當沒有 -proxy 或 -connect 時為 1) + + + + An error occurred while setting up the RPC port %u for listening on IPv6, falling back to IPv4: %s + 設定在 IPv6 網路上以通訊埠 %u 聽候 RPC 連線失敗,退而改用 IPv4 網路: %s + + + + Error initializing database environment %s! To recover, BACKUP THAT DIRECTORY, then remove everything from it except for wallet.dat. + + + + + Set maximum size of high-priority/low-fee transactions in bytes (default: 27000) + + + + + Warning: -paytxfee is set very high! This is the transaction fee you will pay if you send a transaction. + 警告: -paytxfee 設定了很高的金額!這可是你交易付款所要付的手續費。 + + + + Warning: Please check that your computer's date and time are correct! If your clock is wrong Arepacoin will not work properly. + + + + + Warning: error reading wallet.dat! All keys read correctly, but transaction data or address book entries might be missing or incorrect. + 警告: 讀取錢包檔 wallet.dat 時發生錯誤!所有的密鑰都正確讀取了,但是交易資料或位址簿資料可能會缺少或不正確。 + + + + Warning: wallet.dat corrupt, data salvaged! Original wallet.dat saved as wallet.{timestamp}.bak in %s; if your balance or transactions are incorrect you should restore from a backup. + 警告: 錢包檔 wallet.dat 壞掉,但資料被拯救回來了!原來的 wallet.dat 會改儲存在 %s, 檔名是 wallet.{timestamp}.bak. 如果餘額或交易資料有誤,你應該要用備份資料復原回來。 + + + + Attempt to recover private keys from a corrupt wallet.dat + 嘗試從壞掉的錢包檔 wallet.dat 復原密鑰 + + + + Block creation options: + 區塊製造選項: + + + + Connect only to the specified node(s) + 只連線到指定節點(可多個) + + + + Discover own IP address (default: 1 when listening and no -externalip) + 找出自己的網際網路位址(預設值: 當有聽候連線且沒有 -externalip 時為 1) + + + + Failed to listen on any port. Use -listen=0 if you want this. + 在任意的通訊埠聽候失敗。如果你希望這樣的話,可以設定 -listen=0. + + + + Find peers using DNS lookup (default: 1) + + + + + Sync checkpoints policy (default: strict) + + + + + Invalid -tor address: '%s' + + + + + Invalid amount for -reservebalance=<amount> + + + + + Maximum per-connection receive buffer, <n>*1000 bytes (default: 5000) + 每個連線的接收緩衝區大小上限為 <n>*1000 個位元組(預設值: 5000) + + + + Maximum per-connection send buffer, <n>*1000 bytes (default: 1000) + 每個連線的傳送緩衝區大小上限為 <n>*1000 位元組(預設值: 1000) + + + + Only connect to nodes in network <net> (IPv4, IPv6 or Tor) + 只和 <net> 網路上的節點連線(IPv4, IPv6, 或 Tor) + + + + Output extra debugging information. Implies all other -debug* options + + + + + Output extra network debugging information + + + + + Prepend debug output with timestamp + + + + + SSL options: (see the Bitcoin Wiki for SSL setup instructions) + SSL 選項: (SSL 設定程序請見 Bitcoin Wiki) + + + + Select the version of socks proxy to use (4-5, default: 5) + + + + + Send trace/debug info to console instead of debug.log file + 在終端機顯示追蹤或除錯資訊,而不是寫到檔案 debug.log 中 + + + + Send trace/debug info to debugger + + + + + Set maximum block size in bytes (default: 250000) + + + + + Set minimum block size in bytes (default: 0) + 設定區塊大小下限成多少位元組(預設值: 0) + + + + Shrink debug.log file on client startup (default: 1 when no -debug) + 客戶端軟體啓動時把 debug.log 檔縮小(預設值: 當沒有 -debug 時為 1) + + + + Specify connection timeout in milliseconds (default: 5000) + 指定連線在幾毫秒後逾時(預設值: 5000) + + + + Unable to sign checkpoint, wrong checkpointkey? + + + + + + Use UPnP to map the listening port (default: 0) + 是否要使用通用即插即用(UPnP)協定,來設定聽候連線的通訊埠的對應(預設值: 0) + + + + Use UPnP to map the listening port (default: 1 when listening) + 是否要使用通用即插即用(UPnP)協定,來設定聽候連線的通訊埠的對應(預設值: 當有聽候連線時為 1) + + + + Use proxy to reach tor hidden services (default: same as -proxy) + + + + + Username for JSON-RPC connections + JSON-RPC 連線使用者名稱 + + + + Verifying database integrity... + + + + + WARNING: syncronized checkpoint violation detected, but skipped! + + + + + Warning: Disk space is low! + + + + + Warning: This version is obsolete, upgrade required! + 警告: 這個版本已經被淘汰了,必須要升級! + + + + wallet.dat corrupt, salvage failed + 錢包檔 weallet.dat 壞掉了,拯救失敗 + + + + Password for JSON-RPC connections + JSON-RPC 連線密碼 + + + + %s, you must set a rpcpassword in the configuration file: + %s +It is recommended you use the following random password: +rpcuser=arepacoinrpc +rpcpassword=%s +(you do not need to remember this password) +The username and password MUST NOT be the same. +If the file does not exist, create it with owner-readable-only file permissions. +It is also recommended to set alertnotify so you are notified of problems; +for example: alertnotify=echo %%s | mail -s "Arepacoin Alert" admin@foo.com + + + + + + Find peers using internet relay chat (default: 0) + + + + + Sync time with other nodes. Disable if time on your system is precise e.g. syncing with NTP (default: 1) + + + + + When creating transactions, ignore inputs with value less than this (default: 0.01) + + + + + Allow JSON-RPC connections from specified IP address + 允許指定的來源 IP 位址進行 JSON-RPC 連線 + + + + Send commands to node running on <ip> (default: 127.0.0.1) + 傳送指令給在 <ip> 的節點(預設值: 127.0.0.1) + + + + Execute command when the best block changes (%s in cmd is replaced by block hash) + 當最新區塊改變時要執行的指令(指令中的 %s 會被取代成區塊雜湊值) + + + + Execute command when a wallet transaction changes (%s in cmd is replaced by TxID) + 當錢包有交易改變時要執行的指令(指令中的 %s 會被取代成交易識別碼) + + + + Require a confirmations for change (default: 0) + + + + + Enforce transaction scripts to use canonical PUSH operators (default: 1) + + + + + Execute command when a relevant alert is received (%s in cmd is replaced by message) + + + + + Upgrade wallet to latest format + 把錢包檔案升級成最新的格式 + + + + Set key pool size to <n> (default: 100) + 設定密鑰池大小成 <n> (預設值: 100) + + + + Rescan the block chain for missing wallet transactions + 重新掃描區塊鏈,來尋找錢包可能漏掉的交易。 + + + + How many blocks to check at startup (default: 2500, 0 = all) + + + + + How thorough the block verification is (0-6, default: 1) + + + + + Imports blocks from external blk000?.dat file + + + + + Use OpenSSL (https) for JSON-RPC connections + 在 JSON-RPC 連線使用 OpenSSL (https) + + + + Server certificate file (default: server.cert) + 伺服器憑證檔(預設值: server.cert) + + + + Server private key (default: server.pem) + 伺服器私鑰檔(預設值: server.pem) + + + + Acceptable ciphers (default: TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH) + + + + + Error: Wallet unlocked for staking only, unable to create transaction. + + + + + WARNING: Invalid checkpoint found! Displayed transactions may not be correct! You may need to upgrade, or notify developers. + + + + + This help message + 這些說明訊息 + + + + Wallet %s resides outside data directory %s. + + + + + Cannot obtain a lock on data directory %s. Arepacoin is probably already running. + + + + + Arepacoin + + + + + Unable to bind to %s on this computer (bind returned error %d, %s) + 沒辦法和這台電腦上的 %s 繫結(回傳錯誤 %d, %s) + + + + Connect through socks proxy + + + + + Allow DNS lookups for -addnode, -seednode and -connect + 允許對 -addnode, -seednode, -connect 的參數使用域名查詢 + + + + Loading addresses... + 正在載入位址資料... + + + + Error loading blkindex.dat + + + + + Error loading wallet.dat: Wallet corrupted + 載入檔案 wallet.dat 時發生錯誤: 錢包損毀了 + + + + Error loading wallet.dat: Wallet requires newer version of Arepacoin + + + + + Wallet needed to be rewritten: restart Arepacoin to complete + + + + + Error loading wallet.dat + 載入錢包檔 wallet.dat 時發生錯誤 + + + + Invalid -proxy address: '%s' + 無效的 -proxy 位址: '%s' + + + + Unknown network specified in -onlynet: '%s' + 在 -onlynet 指定了不明的網路別: '%s' + + + + Unknown -socks proxy version requested: %i + 在 -socks 指定了不明的代理協定版本: %i + + + + Cannot resolve -bind address: '%s' + 沒辦法解析 -bind 位址: '%s' + + + + Cannot resolve -externalip address: '%s' + 沒辦法解析 -externalip 位址: '%s' + + + + Invalid amount for -paytxfee=<amount>: '%s' + 設定 -paytxfee=<金額> 的金額無效: '%s' + + + + Error: could not start node + + + + + Sending... + + + + + Invalid amount + 無效的金額 + + + + Insufficient funds + 累積金額不足 + + + + Loading block index... + 正在載入區塊索引... + + + + Add a node to connect to and attempt to keep the connection open + 增加一個要連線的節線,並試著保持對它的連線暢通 + + + + Unable to bind to %s on this computer. Arepacoin is probably already running. + + + + + Fee per KB to add to transactions you send + + + + + Invalid amount for -mininput=<amount>: '%s' + + + + + Loading wallet... + 正在載入錢包資料... + + + + Cannot downgrade wallet + 沒辦法把錢包格式降級 + + + + Cannot initialize keypool + + + + + Cannot write default address + 沒辦法把預設位址寫進去 + + + + Rescanning... + 正在重新掃描... + + + + Done loading + 載入完成 + + + + To use the %s option + 為了要使用 %s 選項 + + + + Error + 錯誤 + + + + You must set rpcpassword=<password> in the configuration file: +%s +If the file does not exist, create it with owner-readable-only file permissions. + 你必須在以下設定檔中設定 RPC 密碼(rpcpassword=<password>): +%s +如果還沒有這個檔案,請在造出來的時候,設定檔案權限成只有主人才能讀取。 + + + \ No newline at end of file diff --git a/src/qt/macdockiconhandler.h b/src/qt/macdockiconhandler.h new file mode 100755 index 0000000..89baa72 --- /dev/null +++ b/src/qt/macdockiconhandler.h @@ -0,0 +1,47 @@ +#ifndef MACDOCKICONHANDLER_H +#define MACDOCKICONHANDLER_H + +#include +#include + +QT_BEGIN_NAMESPACE +class QIcon; +class QMenu; +class QWidget; +QT_END_NAMESPACE + +#ifdef __OBJC__ +@class DockIconClickEventHandler; +#else +class DockIconClickEventHandler; +#endif + +/** Macintosh-specific dock icon handler. + */ +class MacDockIconHandler : public QObject +{ + Q_OBJECT + +public: + ~MacDockIconHandler(); + + QMenu *dockMenu(); + void setIcon(const QIcon &icon); + void setMainWindow(QMainWindow *window); + static MacDockIconHandler *instance(); + + void handleDockIconClickEvent(); + +signals: + void dockIconClicked(); + +private: + MacDockIconHandler(); + + DockIconClickEventHandler *m_dockIconClickEventHandler; + QWidget *m_dummyWidget; + QMenu *m_dockMenu; + QMainWindow *mainWindow; +}; + +#endif // MACDOCKICONCLICKHANDLER_H diff --git a/src/qt/macdockiconhandler.mm b/src/qt/macdockiconhandler.mm new file mode 100755 index 0000000..fedbb01 --- /dev/null +++ b/src/qt/macdockiconhandler.mm @@ -0,0 +1,131 @@ +#include "macdockiconhandler.h" + +#include +#include +#include +#include + +#undef slots +#include + +#if QT_VERSION < 0x050000 +extern void qt_mac_set_dock_menu(QMenu *); +#endif + +@interface DockIconClickEventHandler : NSObject +{ + MacDockIconHandler* dockIconHandler; +} + +@end + +@implementation DockIconClickEventHandler + +- (id)initWithDockIconHandler:(MacDockIconHandler *)aDockIconHandler +{ + self = [super init]; + if (self) { + dockIconHandler = aDockIconHandler; + + [[NSAppleEventManager sharedAppleEventManager] + setEventHandler:self + andSelector:@selector(handleDockClickEvent:withReplyEvent:) + forEventClass:kCoreEventClass + andEventID:kAEReopenApplication]; + } + return self; +} + +- (void)handleDockClickEvent:(NSAppleEventDescriptor*)event withReplyEvent:(NSAppleEventDescriptor*)replyEvent +{ + Q_UNUSED(event) + Q_UNUSED(replyEvent) + + if (dockIconHandler) { + dockIconHandler->handleDockIconClickEvent(); + } +} + +@end + +MacDockIconHandler::MacDockIconHandler() : QObject() +{ + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + + this->m_dockIconClickEventHandler = [[DockIconClickEventHandler alloc] initWithDockIconHandler:this]; + this->m_dummyWidget = new QWidget(); + this->m_dockMenu = new QMenu(this->m_dummyWidget); + this->setMainWindow(NULL); +#if QT_VERSION < 0x050000 + qt_mac_set_dock_menu(this->m_dockMenu); +#endif + [pool release]; +} + +void MacDockIconHandler::setMainWindow(QMainWindow *window) { + this->mainWindow = window; +} + +MacDockIconHandler::~MacDockIconHandler() +{ + [this->m_dockIconClickEventHandler release]; + delete this->m_dummyWidget; + this->setMainWindow(NULL); +} + +QMenu *MacDockIconHandler::dockMenu() +{ + return this->m_dockMenu; +} + +void MacDockIconHandler::setIcon(const QIcon &icon) +{ + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + NSImage *image = nil; + if (icon.isNull()) + image = [[NSImage imageNamed:@"NSApplicationIcon"] retain]; + else { + // generate NSImage from QIcon and use this as dock icon. + QSize size = icon.actualSize(QSize(128, 128)); + QPixmap pixmap = icon.pixmap(size); + + // write temp file hack (could also be done through QIODevice [memory]) + QTemporaryFile notificationIconFile; + if (!pixmap.isNull() && notificationIconFile.open()) { + QImageWriter writer(¬ificationIconFile, "PNG"); + if (writer.write(pixmap.toImage())) { + const char *cString = notificationIconFile.fileName().toUtf8().data(); + NSString *macString = [NSString stringWithCString:cString encoding:NSUTF8StringEncoding]; + image = [[NSImage alloc] initWithContentsOfFile:macString]; + } + } + + if(!image) { + // if testnet image could not be created, load std. app icon + image = [[NSImage imageNamed:@"NSApplicationIcon"] retain]; + } + } + + [NSApp setApplicationIconImage:image]; + [image release]; + [pool release]; +} + +MacDockIconHandler *MacDockIconHandler::instance() +{ + static MacDockIconHandler *s_instance = NULL; + if (!s_instance) + s_instance = new MacDockIconHandler(); + return s_instance; +} + +void MacDockIconHandler::handleDockIconClickEvent() +{ + if (this->mainWindow) + { + this->mainWindow->activateWindow(); + this->mainWindow->show(); + } + + emit this->dockIconClicked(); +} diff --git a/src/qt/monitoreddatamapper.cpp b/src/qt/monitoreddatamapper.cpp new file mode 100755 index 0000000..88948d0 --- /dev/null +++ b/src/qt/monitoreddatamapper.cpp @@ -0,0 +1,36 @@ +#include "monitoreddatamapper.h" + +#include +#include +#include + +MonitoredDataMapper::MonitoredDataMapper(QObject *parent) : + QDataWidgetMapper(parent) +{ +} + + +void MonitoredDataMapper::addMapping(QWidget *widget, int section) +{ + QDataWidgetMapper::addMapping(widget, section); + addChangeMonitor(widget); +} + +void MonitoredDataMapper::addMapping(QWidget *widget, int section, const QByteArray &propertyName) +{ + QDataWidgetMapper::addMapping(widget, section, propertyName); + addChangeMonitor(widget); +} + +void MonitoredDataMapper::addChangeMonitor(QWidget *widget) +{ + // Watch user property of widget for changes, and connect + // the signal to our viewModified signal. + QMetaProperty prop = widget->metaObject()->userProperty(); + int signal = prop.notifySignalIndex(); + int method = this->metaObject()->indexOfMethod("viewModified()"); + if(signal != -1 && method != -1) + { + QMetaObject::connect(widget, signal, this, method); + } +} diff --git a/src/qt/monitoreddatamapper.h b/src/qt/monitoreddatamapper.h new file mode 100755 index 0000000..33a874e --- /dev/null +++ b/src/qt/monitoreddatamapper.h @@ -0,0 +1,31 @@ +#ifndef MONITOREDDATAMAPPER_H +#define MONITOREDDATAMAPPER_H + +#include + +QT_BEGIN_NAMESPACE +class QWidget; +QT_END_NAMESPACE + +/** Data to Widget mapper that watches for edits and notifies listeners when a field is edited. + This can be used, for example, to enable a commit/apply button in a configuration dialog. + */ +class MonitoredDataMapper : public QDataWidgetMapper +{ + Q_OBJECT +public: + explicit MonitoredDataMapper(QObject *parent=0); + + void addMapping(QWidget *widget, int section); + void addMapping(QWidget *widget, int section, const QByteArray &propertyName); +private: + void addChangeMonitor(QWidget *widget); + +signals: + void viewModified(); + +}; + + + +#endif // MONITOREDDATAMAPPER_H diff --git a/src/qt/notificator.cpp b/src/qt/notificator.cpp new file mode 100755 index 0000000..87919b8 --- /dev/null +++ b/src/qt/notificator.cpp @@ -0,0 +1,304 @@ +#include "notificator.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef USE_DBUS +#include +#include +#endif + +#ifdef Q_OS_MAC +#include +extern bool qt_mac_execute_apple_script(const QString &script, AEDesc *ret); +#endif + +#ifdef USE_DBUS +// https://wiki.ubuntu.com/NotificationDevelopmentGuidelines recommends at least 128 +const int FREEDESKTOP_NOTIFICATION_ICON_SIZE = 128; +#endif + +Notificator::Notificator(const QString &programName, QSystemTrayIcon *trayicon, QWidget *parent): + QObject(parent), + parent(parent), + programName(programName), + mode(None), + trayIcon(trayicon) +#ifdef USE_DBUS + ,interface(0) +#endif +{ + if(trayicon && trayicon->supportsMessages()) + { + mode = QSystemTray; + } +#ifdef USE_DBUS + interface = new QDBusInterface("org.freedesktop.Notifications", + "/org/freedesktop/Notifications", "org.freedesktop.Notifications"); + if(interface->isValid()) + { + mode = Freedesktop; + } +#endif +#ifdef Q_OS_MAC + // Check if Growl is installed (based on Qt's tray icon implementation) + CFURLRef cfurl; + OSStatus status = LSGetApplicationForInfo(kLSUnknownType, kLSUnknownCreator, CFSTR("growlTicket"), kLSRolesAll, 0, &cfurl); + if (status != kLSApplicationNotFoundErr) { + CFBundleRef bundle = CFBundleCreate(0, cfurl); + if (CFStringCompare(CFBundleGetIdentifier(bundle), CFSTR("com.Growl.GrowlHelperApp"), kCFCompareCaseInsensitive | kCFCompareBackwards) == kCFCompareEqualTo) { + if (CFStringHasSuffix(CFURLGetString(cfurl), CFSTR("/Growl.app/"))) + mode = Growl13; + else + mode = Growl12; + } + CFRelease(cfurl); + CFRelease(bundle); + } +#endif +} + +Notificator::~Notificator() +{ +#ifdef USE_DBUS + delete interface; +#endif +} + +#ifdef USE_DBUS + +// Loosely based on http://www.qtcentre.org/archive/index.php/t-25879.html +class FreedesktopImage +{ +public: + FreedesktopImage() {} + FreedesktopImage(const QImage &img); + + static int metaType(); + + // Image to variant that can be marshalled over DBus + static QVariant toVariant(const QImage &img); + +private: + int width, height, stride; + bool hasAlpha; + int channels; + int bitsPerSample; + QByteArray image; + + friend QDBusArgument &operator<<(QDBusArgument &a, const FreedesktopImage &i); + friend const QDBusArgument &operator>>(const QDBusArgument &a, FreedesktopImage &i); +}; + +Q_DECLARE_METATYPE(FreedesktopImage); + +// Image configuration settings +const int CHANNELS = 4; +const int BYTES_PER_PIXEL = 4; +const int BITS_PER_SAMPLE = 8; + +FreedesktopImage::FreedesktopImage(const QImage &img): + width(img.width()), + height(img.height()), + stride(img.width() * BYTES_PER_PIXEL), + hasAlpha(true), + channels(CHANNELS), + bitsPerSample(BITS_PER_SAMPLE) +{ + // Convert 00xAARRGGBB to RGBA bytewise (endian-independent) format + QImage tmp = img.convertToFormat(QImage::Format_ARGB32); + const uint32_t *data = reinterpret_cast(tmp.bits()); + + unsigned int num_pixels = width * height; + image.resize(num_pixels * BYTES_PER_PIXEL); + + for(unsigned int ptr = 0; ptr < num_pixels; ++ptr) + { + image[ptr*BYTES_PER_PIXEL+0] = data[ptr] >> 16; // R + image[ptr*BYTES_PER_PIXEL+1] = data[ptr] >> 8; // G + image[ptr*BYTES_PER_PIXEL+2] = data[ptr]; // B + image[ptr*BYTES_PER_PIXEL+3] = data[ptr] >> 24; // A + } +} + +QDBusArgument &operator<<(QDBusArgument &a, const FreedesktopImage &i) +{ + a.beginStructure(); + a << i.width << i.height << i.stride << i.hasAlpha << i.bitsPerSample << i.channels << i.image; + a.endStructure(); + return a; +} + +const QDBusArgument &operator>>(const QDBusArgument &a, FreedesktopImage &i) +{ + a.beginStructure(); + a >> i.width >> i.height >> i.stride >> i.hasAlpha >> i.bitsPerSample >> i.channels >> i.image; + a.endStructure(); + return a; +} + +int FreedesktopImage::metaType() +{ + return qDBusRegisterMetaType(); +} + +QVariant FreedesktopImage::toVariant(const QImage &img) +{ + FreedesktopImage fimg(img); + return QVariant(FreedesktopImage::metaType(), &fimg); +} + +void Notificator::notifyDBus(Class cls, const QString &title, const QString &text, const QIcon &icon, int millisTimeout) +{ + Q_UNUSED(cls); + // Arguments for DBus call: + QList args; + + // Program Name: + args.append(programName); + + // Unique ID of this notification type: + args.append(0U); + + // Application Icon, empty string + args.append(QString()); + + // Summary + args.append(title); + + // Body + args.append(text); + + // Actions (none, actions are deprecated) + QStringList actions; + args.append(actions); + + // Hints + QVariantMap hints; + + // If no icon specified, set icon based on class + QIcon tmpicon; + if(icon.isNull()) + { + QStyle::StandardPixmap sicon = QStyle::SP_MessageBoxQuestion; + switch(cls) + { + case Information: sicon = QStyle::SP_MessageBoxInformation; break; + case Warning: sicon = QStyle::SP_MessageBoxWarning; break; + case Critical: sicon = QStyle::SP_MessageBoxCritical; break; + default: break; + } + tmpicon = QApplication::style()->standardIcon(sicon); + } + else + { + tmpicon = icon; + } + hints["icon_data"] = FreedesktopImage::toVariant(tmpicon.pixmap(FREEDESKTOP_NOTIFICATION_ICON_SIZE).toImage()); + args.append(hints); + + // Timeout (in msec) + args.append(millisTimeout); + + // "Fire and forget" + interface->callWithArgumentList(QDBus::NoBlock, "Notify", args); +} +#endif + +void Notificator::notifySystray(Class cls, const QString &title, const QString &text, const QIcon &icon, int millisTimeout) +{ + Q_UNUSED(icon); + QSystemTrayIcon::MessageIcon sicon = QSystemTrayIcon::NoIcon; + switch(cls) // Set icon based on class + { + case Information: sicon = QSystemTrayIcon::Information; break; + case Warning: sicon = QSystemTrayIcon::Warning; break; + case Critical: sicon = QSystemTrayIcon::Critical; break; + } + trayIcon->showMessage(title, text, sicon, millisTimeout); +} + +// Based on Qt's tray icon implementation +#ifdef Q_OS_MAC +void Notificator::notifyGrowl(Class cls, const QString &title, const QString &text, const QIcon &icon) +{ + const QString script( + "tell application \"%5\"\n" + " set the allNotificationsList to {\"Notification\"}\n" // -- Make a list of all the notification types (all) + " set the enabledNotificationsList to {\"Notification\"}\n" // -- Make a list of the notifications (enabled) + " register as application \"%1\" all notifications allNotificationsList default notifications enabledNotificationsList\n" // -- Register our script with Growl + " notify with name \"Notification\" title \"%2\" description \"%3\" application name \"%1\"%4\n" // -- Send a Notification + "end tell" + ); + + QString notificationApp(QApplication::applicationName()); + if (notificationApp.isEmpty()) + notificationApp = "Application"; + + QPixmap notificationIconPixmap; + if (icon.isNull()) { // If no icon specified, set icon based on class + QStyle::StandardPixmap sicon = QStyle::SP_MessageBoxQuestion; + switch (cls) + { + case Information: sicon = QStyle::SP_MessageBoxInformation; break; + case Warning: sicon = QStyle::SP_MessageBoxWarning; break; + case Critical: sicon = QStyle::SP_MessageBoxCritical; break; + } + notificationIconPixmap = QApplication::style()->standardPixmap(sicon); + } + else { + QSize size = icon.actualSize(QSize(48, 48)); + notificationIconPixmap = icon.pixmap(size); + } + + QString notificationIcon; + QTemporaryFile notificationIconFile; + if (!notificationIconPixmap.isNull() && notificationIconFile.open()) { + QImageWriter writer(¬ificationIconFile, "PNG"); + if (writer.write(notificationIconPixmap.toImage())) + notificationIcon = QString(" image from location \"file://%1\"").arg(notificationIconFile.fileName()); + } + + QString quotedTitle(title), quotedText(text); + quotedTitle.replace("\\", "\\\\").replace("\"", "\\"); + quotedText.replace("\\", "\\\\").replace("\"", "\\"); + QString growlApp(this->mode == Notificator::Growl13 ? "Growl" : "GrowlHelperApp"); + qt_mac_execute_apple_script(script.arg(notificationApp, quotedTitle, quotedText, notificationIcon, growlApp), 0); +} +#endif + +void Notificator::notify(Class cls, const QString &title, const QString &text, const QIcon &icon, int millisTimeout) +{ + switch(mode) + { +#ifdef USE_DBUS + case Freedesktop: + notifyDBus(cls, title, text, icon, millisTimeout); + break; +#endif + case QSystemTray: + notifySystray(cls, title, text, icon, millisTimeout); + break; +#ifdef Q_OS_MAC + case Growl12: + case Growl13: + notifyGrowl(cls, title, text, icon); + break; +#endif + default: + if(cls == Critical) + { + // Fall back to old fashioned pop-up dialog if critical and no other notification available + QMessageBox::critical(parent, title, text, QMessageBox::Ok, QMessageBox::Ok); + } + break; + } +} diff --git a/src/qt/notificator.h b/src/qt/notificator.h new file mode 100755 index 0000000..abb4710 --- /dev/null +++ b/src/qt/notificator.h @@ -0,0 +1,69 @@ +#ifndef NOTIFICATOR_H +#define NOTIFICATOR_H + +#include +#include + +QT_BEGIN_NAMESPACE +class QSystemTrayIcon; +#ifdef USE_DBUS +class QDBusInterface; +#endif +QT_END_NAMESPACE + +/** Cross-platform desktop notification client. */ +class Notificator: public QObject +{ + Q_OBJECT +public: + /** Create a new notificator. + @note Ownership of trayIcon is not transferred to this object. + */ + Notificator(const QString &programName=QString(), QSystemTrayIcon *trayIcon=0, QWidget *parent=0); + ~Notificator(); + + // Message class + enum Class + { + Information, /**< Informational message */ + Warning, /**< Notify user of potential problem */ + Critical /**< An error occurred */ + }; + +public slots: + + /** Show notification message. + @param[in] cls general message class + @param[in] title title shown with message + @param[in] text message content + @param[in] icon optional icon to show with message + @param[in] millisTimeout notification timeout in milliseconds (defaults to 10 seconds) + @note Platform implementations are free to ignore any of the provided fields except for \a text. + */ + void notify(Class cls, const QString &title, const QString &text, + const QIcon &icon = QIcon(), int millisTimeout = 10000); + +private: + QWidget *parent; + enum Mode { + None, /**< Ignore informational notifications, and show a modal pop-up dialog for Critical notifications. */ + Freedesktop, /**< Use DBus org.freedesktop.Notifications */ + QSystemTray, /**< Use QSystemTray::showMessage */ + Growl12, /**< Use the Growl 1.2 notification system (Mac only) */ + Growl13 /**< Use the Growl 1.3 notification system (Mac only) */ + }; + QString programName; + Mode mode; + QSystemTrayIcon *trayIcon; +#ifdef USE_DBUS + QDBusInterface *interface; + + void notifyDBus(Class cls, const QString &title, const QString &text, const QIcon &icon, int millisTimeout); +#endif + void notifySystray(Class cls, const QString &title, const QString &text, const QIcon &icon, int millisTimeout); +#ifdef Q_OS_MAC + void notifyGrowl(Class cls, const QString &title, const QString &text, const QIcon &icon); +#endif +}; + +#endif // NOTIFICATOR_H diff --git a/src/qt/optionsdialog.cpp b/src/qt/optionsdialog.cpp new file mode 100755 index 0000000..83a6613 --- /dev/null +++ b/src/qt/optionsdialog.cpp @@ -0,0 +1,258 @@ +#include "optionsdialog.h" +#include "ui_optionsdialog.h" + +#include "bitcoinunits.h" +#include "monitoreddatamapper.h" +#include "netbase.h" +#include "optionsmodel.h" + +#include +#include +#include +#include +#include +#include + +OptionsDialog::OptionsDialog(QWidget *parent) : + QDialog(parent), + ui(new Ui::OptionsDialog), + model(0), + mapper(0), + fRestartWarningDisplayed_Proxy(false), + fRestartWarningDisplayed_Lang(false), + fProxyIpValid(true) +{ + ui->setupUi(this); + + /* Network elements init */ +#ifndef USE_UPNP + ui->mapPortUpnp->setEnabled(false); +#endif + + ui->proxyIp->setEnabled(false); + ui->proxyPort->setEnabled(false); + ui->proxyPort->setValidator(new QIntValidator(1, 65535, this)); + + ui->socksVersion->setEnabled(false); + ui->socksVersion->addItem("5", 5); + ui->socksVersion->addItem("4", 4); + ui->socksVersion->setCurrentIndex(0); + + connect(ui->connectSocks, SIGNAL(toggled(bool)), ui->proxyIp, SLOT(setEnabled(bool))); + connect(ui->connectSocks, SIGNAL(toggled(bool)), ui->proxyPort, SLOT(setEnabled(bool))); + connect(ui->connectSocks, SIGNAL(toggled(bool)), ui->socksVersion, SLOT(setEnabled(bool))); + connect(ui->connectSocks, SIGNAL(clicked(bool)), this, SLOT(showRestartWarning_Proxy())); + + ui->proxyIp->installEventFilter(this); + + /* Window elements init */ +#ifdef Q_OS_MAC + ui->tabWindow->setVisible(false); +#endif + + /* Display elements init */ + QDir translations(":translations"); + ui->lang->addItem(QString("(") + tr("default") + QString(")"), QVariant("")); + foreach(const QString &langStr, translations.entryList()) + { + QLocale locale(langStr); + + /** check if the locale name consists of 2 parts (language_country) */ + if(langStr.contains("_")) + { +#if QT_VERSION >= 0x040800 + /** display language strings as "native language - native country (locale name)", e.g. "Deutsch - Deutschland (de)" */ + ui->lang->addItem(locale.nativeLanguageName() + QString(" - ") + locale.nativeCountryName() + QString(" (") + langStr + QString(")"), QVariant(langStr)); +#else + /** display language strings as "language - country (locale name)", e.g. "German - Germany (de)" */ + ui->lang->addItem(QLocale::languageToString(locale.language()) + QString(" - ") + QLocale::countryToString(locale.country()) + QString(" (") + langStr + QString(")"), QVariant(langStr)); +#endif + } + else + { +#if QT_VERSION >= 0x040800 + /** display language strings as "native language (locale name)", e.g. "Deutsch (de)" */ + ui->lang->addItem(locale.nativeLanguageName() + QString(" (") + langStr + QString(")"), QVariant(langStr)); +#else + /** display language strings as "language (locale name)", e.g. "German (de)" */ + ui->lang->addItem(QLocale::languageToString(locale.language()) + QString(" (") + langStr + QString(")"), QVariant(langStr)); +#endif + } + } + + ui->unit->setModel(new BitcoinUnits(this)); + + /* Widget-to-option mapper */ + mapper = new MonitoredDataMapper(this); + mapper->setSubmitPolicy(QDataWidgetMapper::ManualSubmit); + mapper->setOrientation(Qt::Vertical); + + /* enable apply button when data modified */ + connect(mapper, SIGNAL(viewModified()), this, SLOT(enableApplyButton())); + /* disable apply button when new data loaded */ + connect(mapper, SIGNAL(currentIndexChanged(int)), this, SLOT(disableApplyButton())); + /* setup/change UI elements when proxy IP is invalid/valid */ + connect(this, SIGNAL(proxyIpValid(QValidatedLineEdit *, bool)), this, SLOT(handleProxyIpValid(QValidatedLineEdit *, bool))); +} + +OptionsDialog::~OptionsDialog() +{ + delete ui; +} + +void OptionsDialog::setModel(OptionsModel *model) +{ + this->model = model; + + if(model) + { + connect(model, SIGNAL(displayUnitChanged(int)), this, SLOT(updateDisplayUnit())); + + mapper->setModel(model); + setMapper(); + mapper->toFirst(); + } + + /* update the display unit, to not use the default ("BTC") */ + updateDisplayUnit(); + + /* warn only when language selection changes by user action (placed here so init via mapper doesn't trigger this) */ + connect(ui->lang, SIGNAL(valueChanged()), this, SLOT(showRestartWarning_Lang())); + + /* disable apply button after settings are loaded as there is nothing to save */ + disableApplyButton(); +} + +void OptionsDialog::setMapper() +{ + /* Main */ + mapper->addMapping(ui->transactionFee, OptionsModel::Fee); + mapper->addMapping(ui->reserveBalance, OptionsModel::ReserveBalance); + mapper->addMapping(ui->bitcoinAtStartup, OptionsModel::StartAtStartup); + + /* Network */ + mapper->addMapping(ui->mapPortUpnp, OptionsModel::MapPortUPnP); + + mapper->addMapping(ui->connectSocks, OptionsModel::ProxyUse); + mapper->addMapping(ui->proxyIp, OptionsModel::ProxyIP); + mapper->addMapping(ui->proxyPort, OptionsModel::ProxyPort); + mapper->addMapping(ui->socksVersion, OptionsModel::ProxySocksVersion); + + /* Window */ +#ifndef Q_OS_MAC + mapper->addMapping(ui->minimizeToTray, OptionsModel::MinimizeToTray); + mapper->addMapping(ui->minimizeOnClose, OptionsModel::MinimizeOnClose); +#endif + + /* Display */ + mapper->addMapping(ui->lang, OptionsModel::Language); + mapper->addMapping(ui->unit, OptionsModel::DisplayUnit); + mapper->addMapping(ui->displayAddresses, OptionsModel::DisplayAddresses); + mapper->addMapping(ui->coinControlFeatures, OptionsModel::CoinControlFeatures); + mapper->addMapping(ui->useBlackTheme, OptionsModel::UseBlackTheme); +} + +void OptionsDialog::enableApplyButton() +{ + ui->applyButton->setEnabled(true); +} + +void OptionsDialog::disableApplyButton() +{ + ui->applyButton->setEnabled(false); +} + +void OptionsDialog::enableSaveButtons() +{ + /* prevent enabling of the save buttons when data modified, if there is an invalid proxy address present */ + if(fProxyIpValid) + setSaveButtonState(true); +} + +void OptionsDialog::disableSaveButtons() +{ + setSaveButtonState(false); +} + +void OptionsDialog::setSaveButtonState(bool fState) +{ + ui->applyButton->setEnabled(fState); + ui->okButton->setEnabled(fState); +} + +void OptionsDialog::on_okButton_clicked() +{ + mapper->submit(); + accept(); +} + +void OptionsDialog::on_cancelButton_clicked() +{ + reject(); +} + +void OptionsDialog::on_applyButton_clicked() +{ + mapper->submit(); + disableApplyButton(); +} + +void OptionsDialog::showRestartWarning_Proxy() +{ + if(!fRestartWarningDisplayed_Proxy) + { + QMessageBox::warning(this, tr("Warning"), tr("This setting will take effect after restarting Arepacoin."), QMessageBox::Ok); + fRestartWarningDisplayed_Proxy = true; + } +} + +void OptionsDialog::showRestartWarning_Lang() +{ + if(!fRestartWarningDisplayed_Lang) + { + QMessageBox::warning(this, tr("Warning"), tr("This setting will take effect after restarting Arepacoin."), QMessageBox::Ok); + fRestartWarningDisplayed_Lang = true; + } +} + +void OptionsDialog::updateDisplayUnit() +{ + if(model) + { + /* Update transactionFee with the current unit */ + ui->transactionFee->setDisplayUnit(model->getDisplayUnit()); + } +} + +void OptionsDialog::handleProxyIpValid(QValidatedLineEdit *object, bool fState) +{ + // this is used in a check before re-enabling the save buttons + fProxyIpValid = fState; + + if(fProxyIpValid) + { + enableSaveButtons(); + ui->statusLabel->clear(); + } + else + { + disableSaveButtons(); + object->setValid(fProxyIpValid); + ui->statusLabel->setStyleSheet("QLabel { color: red; }"); + ui->statusLabel->setText(tr("The supplied proxy address is invalid.")); + } +} + +bool OptionsDialog::eventFilter(QObject *object, QEvent *event) +{ + if(event->type() == QEvent::FocusOut) + { + if(object == ui->proxyIp) + { + CService addr; + /* Check proxyIp for a valid IPv4/IPv6 address and emit the proxyIpValid signal */ + emit proxyIpValid(ui->proxyIp, LookupNumeric(ui->proxyIp->text().toStdString().c_str(), addr)); + } + } + return QDialog::eventFilter(object, event); +} diff --git a/src/qt/optionsdialog.h b/src/qt/optionsdialog.h new file mode 100755 index 0000000..18469f5 --- /dev/null +++ b/src/qt/optionsdialog.h @@ -0,0 +1,60 @@ +#ifndef OPTIONSDIALOG_H +#define OPTIONSDIALOG_H + +#include + +namespace Ui { +class OptionsDialog; +} +class OptionsModel; +class MonitoredDataMapper; +class QValidatedLineEdit; + +/** Preferences dialog. */ +class OptionsDialog : public QDialog +{ + Q_OBJECT + +public: + explicit OptionsDialog(QWidget *parent = 0); + ~OptionsDialog(); + + void setModel(OptionsModel *model); + void setMapper(); + +protected: + bool eventFilter(QObject *object, QEvent *event); + +private slots: + /* enable only apply button */ + void enableApplyButton(); + /* disable only apply button */ + void disableApplyButton(); + /* enable apply button and OK button */ + void enableSaveButtons(); + /* disable apply button and OK button */ + void disableSaveButtons(); + /* set apply button and OK button state (enabled / disabled) */ + void setSaveButtonState(bool fState); + void on_okButton_clicked(); + void on_cancelButton_clicked(); + void on_applyButton_clicked(); + + void showRestartWarning_Proxy(); + void showRestartWarning_Lang(); + void updateDisplayUnit(); + void handleProxyIpValid(QValidatedLineEdit *object, bool fState); + +signals: + void proxyIpValid(QValidatedLineEdit *object, bool fValid); + +private: + Ui::OptionsDialog *ui; + OptionsModel *model; + MonitoredDataMapper *mapper; + bool fRestartWarningDisplayed_Proxy; + bool fRestartWarningDisplayed_Lang; + bool fProxyIpValid; +}; + +#endif // OPTIONSDIALOG_H diff --git a/src/qt/optionsmodel.cpp b/src/qt/optionsmodel.cpp new file mode 100755 index 0000000..37936f5 --- /dev/null +++ b/src/qt/optionsmodel.cpp @@ -0,0 +1,258 @@ +#include "optionsmodel.h" +#include "bitcoinunits.h" +#include + +#include "init.h" +#include "walletdb.h" +#include "guiutil.h" + +bool fUseBlackTheme; + +OptionsModel::OptionsModel(QObject *parent) : + QAbstractListModel(parent) +{ + Init(); +} + +bool static ApplyProxySettings() +{ + QSettings settings; + CService addrProxy(settings.value("addrProxy", "127.0.0.1:9050").toString().toStdString()); + int nSocksVersion(settings.value("nSocksVersion", 5).toInt()); + if (!settings.value("fUseProxy", false).toBool()) { + addrProxy = CService(); + nSocksVersion = 0; + return false; + } + if (nSocksVersion && !addrProxy.IsValid()) + return false; + if (!IsLimited(NET_IPV4)) + SetProxy(NET_IPV4, addrProxy, nSocksVersion); + if (nSocksVersion > 4) { + if (!IsLimited(NET_IPV6)) + SetProxy(NET_IPV6, addrProxy, nSocksVersion); + SetNameProxy(addrProxy, nSocksVersion); + } + return true; +} + +void OptionsModel::Init() +{ + QSettings settings; + + // These are Qt-only settings: + nDisplayUnit = settings.value("nDisplayUnit", BitcoinUnits::BTC).toInt(); + bDisplayAddresses = settings.value("bDisplayAddresses", false).toBool(); + fMinimizeToTray = settings.value("fMinimizeToTray", false).toBool(); + fMinimizeOnClose = settings.value("fMinimizeOnClose", false).toBool(); + fCoinControlFeatures = settings.value("fCoinControlFeatures", false).toBool(); + nTransactionFee = settings.value("nTransactionFee").toLongLong(); + nReserveBalance = settings.value("nReserveBalance").toLongLong(); + language = settings.value("language", "").toString(); + fUseBlackTheme = settings.value("fUseBlackTheme", true).toBool(); + + // These are shared with core Bitcoin; we want + // command-line options to override the GUI settings: + if (settings.contains("fUseUPnP")) + SoftSetBoolArg("-upnp", settings.value("fUseUPnP").toBool()); + if (settings.contains("addrProxy") && settings.value("fUseProxy").toBool()) + SoftSetArg("-proxy", settings.value("addrProxy").toString().toStdString()); + if (settings.contains("nSocksVersion") && settings.value("fUseProxy").toBool()) + SoftSetArg("-socks", settings.value("nSocksVersion").toString().toStdString()); + if (!language.isEmpty()) + SoftSetArg("-lang", language.toStdString()); +} + +int OptionsModel::rowCount(const QModelIndex & parent) const +{ + return OptionIDRowCount; +} + +QVariant OptionsModel::data(const QModelIndex & index, int role) const +{ + if(role == Qt::EditRole) + { + QSettings settings; + switch(index.row()) + { + case StartAtStartup: + return QVariant(GUIUtil::GetStartOnSystemStartup()); + case MinimizeToTray: + return QVariant(fMinimizeToTray); + case MapPortUPnP: + return settings.value("fUseUPnP", GetBoolArg("-upnp", true)); + case MinimizeOnClose: + return QVariant(fMinimizeOnClose); + case ProxyUse: + return settings.value("fUseProxy", false); + case ProxyIP: { + proxyType proxy; + if (GetProxy(NET_IPV4, proxy)) + return QVariant(QString::fromStdString(proxy.first.ToStringIP())); + else + return QVariant(QString::fromStdString("127.0.0.1")); + } + case ProxyPort: { + proxyType proxy; + if (GetProxy(NET_IPV4, proxy)) + return QVariant(proxy.first.GetPort()); + else + return QVariant(9050); + } + case ProxySocksVersion: + return settings.value("nSocksVersion", 5); + case Fee: + return QVariant((qint64) nTransactionFee); + case ReserveBalance: + return QVariant((qint64) nReserveBalance); + case DisplayUnit: + return QVariant(nDisplayUnit); + case DisplayAddresses: + return QVariant(bDisplayAddresses); + case Language: + return settings.value("language", ""); + case CoinControlFeatures: + return QVariant(fCoinControlFeatures); + case UseBlackTheme: + return QVariant(fUseBlackTheme); + default: + return QVariant(); + } + } + return QVariant(); +} + +bool OptionsModel::setData(const QModelIndex & index, const QVariant & value, int role) +{ + bool successful = true; /* set to false on parse error */ + if(role == Qt::EditRole) + { + QSettings settings; + switch(index.row()) + { + case StartAtStartup: + successful = GUIUtil::SetStartOnSystemStartup(value.toBool()); + break; + case MinimizeToTray: + fMinimizeToTray = value.toBool(); + settings.setValue("fMinimizeToTray", fMinimizeToTray); + break; + case MapPortUPnP: + fUseUPnP = value.toBool(); + settings.setValue("fUseUPnP", fUseUPnP); + MapPort(); + break; + case MinimizeOnClose: + fMinimizeOnClose = value.toBool(); + settings.setValue("fMinimizeOnClose", fMinimizeOnClose); + break; + case ProxyUse: + settings.setValue("fUseProxy", value.toBool()); + ApplyProxySettings(); + break; + case ProxyIP: { + proxyType proxy; + proxy.first = CService("127.0.0.1", 9050); + GetProxy(NET_IPV4, proxy); + + CNetAddr addr(value.toString().toStdString()); + proxy.first.SetIP(addr); + settings.setValue("addrProxy", proxy.first.ToStringIPPort().c_str()); + successful = ApplyProxySettings(); + } + break; + case ProxyPort: { + proxyType proxy; + proxy.first = CService("127.0.0.1", 9050); + GetProxy(NET_IPV4, proxy); + + proxy.first.SetPort(value.toInt()); + settings.setValue("addrProxy", proxy.first.ToStringIPPort().c_str()); + successful = ApplyProxySettings(); + } + break; + case ProxySocksVersion: { + proxyType proxy; + proxy.second = 5; + GetProxy(NET_IPV4, proxy); + + proxy.second = value.toInt(); + settings.setValue("nSocksVersion", proxy.second); + successful = ApplyProxySettings(); + } + break; + case Fee: + nTransactionFee = value.toLongLong(); + settings.setValue("nTransactionFee", (qint64) nTransactionFee); + emit transactionFeeChanged(nTransactionFee); + break; + case ReserveBalance: + nReserveBalance = value.toLongLong(); + settings.setValue("nReserveBalance", (qint64) nReserveBalance); + emit reserveBalanceChanged(nReserveBalance); + break; + case DisplayUnit: + nDisplayUnit = value.toInt(); + settings.setValue("nDisplayUnit", nDisplayUnit); + emit displayUnitChanged(nDisplayUnit); + break; + case DisplayAddresses: + bDisplayAddresses = value.toBool(); + settings.setValue("bDisplayAddresses", bDisplayAddresses); + break; + case Language: + settings.setValue("language", value); + break; + case CoinControlFeatures: { + fCoinControlFeatures = value.toBool(); + settings.setValue("fCoinControlFeatures", fCoinControlFeatures); + emit coinControlFeaturesChanged(fCoinControlFeatures); + } + break; + case UseBlackTheme: + fUseBlackTheme = value.toBool(); + settings.setValue("fUseBlackTheme", fUseBlackTheme); + break; + default: + break; + } + } + emit dataChanged(index, index); + + return successful; +} + +qint64 OptionsModel::getTransactionFee() +{ + return nTransactionFee; +} + +qint64 OptionsModel::getReserveBalance() +{ + return nReserveBalance; +} + +bool OptionsModel::getCoinControlFeatures() +{ + return fCoinControlFeatures; +} + +bool OptionsModel::getMinimizeToTray() +{ + return fMinimizeToTray; +} + +bool OptionsModel::getMinimizeOnClose() +{ + return fMinimizeOnClose; +} + +int OptionsModel::getDisplayUnit() +{ + return nDisplayUnit; +} + +bool OptionsModel::getDisplayAddresses() +{ + return bDisplayAddresses; +} diff --git a/src/qt/optionsmodel.h b/src/qt/optionsmodel.h new file mode 100755 index 0000000..68c0292 --- /dev/null +++ b/src/qt/optionsmodel.h @@ -0,0 +1,71 @@ +#ifndef OPTIONSMODEL_H +#define OPTIONSMODEL_H + +#include + +extern bool fUseBlackTheme; + +/** Interface from Qt to configuration data structure for Bitcoin client. + To Qt, the options are presented as a list with the different options + laid out vertically. + This can be changed to a tree once the settings become sufficiently + complex. + */ +class OptionsModel : public QAbstractListModel +{ + Q_OBJECT + +public: + explicit OptionsModel(QObject *parent = 0); + + enum OptionID { + StartAtStartup, // bool + MinimizeToTray, // bool + MapPortUPnP, // bool + MinimizeOnClose, // bool + ProxyUse, // bool + ProxyIP, // QString + ProxyPort, // int + ProxySocksVersion, // int + Fee, // qint64 + ReserveBalance, // qint64 + DisplayUnit, // BitcoinUnits::Unit + DisplayAddresses, // bool + Language, // QString + CoinControlFeatures, // bool + UseBlackTheme, // bool + OptionIDRowCount, + }; + + void Init(); + + int rowCount(const QModelIndex & parent = QModelIndex()) const; + QVariant data(const QModelIndex & index, int role = Qt::DisplayRole) const; + bool setData(const QModelIndex & index, const QVariant & value, int role = Qt::EditRole); + + /* Explicit getters */ + qint64 getTransactionFee(); + qint64 getReserveBalance(); + bool getMinimizeToTray(); + bool getMinimizeOnClose(); + int getDisplayUnit(); + bool getDisplayAddresses(); + bool getCoinControlFeatures(); + QString getLanguage() { return language; } + +private: + int nDisplayUnit; + bool bDisplayAddresses; + bool fMinimizeToTray; + bool fMinimizeOnClose; + bool fCoinControlFeatures; + QString language; + +signals: + void displayUnitChanged(int unit); + void transactionFeeChanged(qint64); + void reserveBalanceChanged(qint64); + void coinControlFeaturesChanged(bool); +}; + +#endif // OPTIONSMODEL_H diff --git a/src/qt/overviewpage.cpp b/src/qt/overviewpage.cpp new file mode 100755 index 0000000..26d081e --- /dev/null +++ b/src/qt/overviewpage.cpp @@ -0,0 +1,215 @@ +#include "overviewpage.h" +#include "ui_overviewpage.h" + +#include "walletmodel.h" +#include "bitcoinunits.h" +#include "optionsmodel.h" +#include "transactiontablemodel.h" +#include "transactionfilterproxy.h" +#include "guiutil.h" +#include "guiconstants.h" + +#include +#include + +#define DECORATION_SIZE 64 +#define NUM_ITEMS 3 + +class TxViewDelegate : public QAbstractItemDelegate +{ + Q_OBJECT +public: + TxViewDelegate(): QAbstractItemDelegate(), unit(BitcoinUnits::BTC) + { + + } + + inline void paint(QPainter *painter, const QStyleOptionViewItem &option, + const QModelIndex &index ) const + { + painter->save(); + + QIcon icon = qvariant_cast(index.data(Qt::DecorationRole)); + QRect mainRect = option.rect; + QRect decorationRect(mainRect.topLeft(), QSize(DECORATION_SIZE, DECORATION_SIZE)); + int xspace = DECORATION_SIZE + 8; + int ypad = 6; + int halfheight = (mainRect.height() - 2*ypad)/2; + QRect amountRect(mainRect.left() + xspace, mainRect.top()+ypad, mainRect.width() - xspace, halfheight); + QRect addressRect(mainRect.left() + xspace, mainRect.top()+ypad+halfheight, mainRect.width() - xspace, halfheight); + icon.paint(painter, decorationRect); + + QDateTime date = index.data(TransactionTableModel::DateRole).toDateTime(); + QString address = index.data(Qt::DisplayRole).toString(); + qint64 amount = index.data(TransactionTableModel::AmountRole).toLongLong(); + bool confirmed = index.data(TransactionTableModel::ConfirmedRole).toBool(); + QVariant value = index.data(Qt::ForegroundRole); + QColor foreground = option.palette.color(QPalette::Text); +#if QT_VERSION < 0x050000 + if(qVariantCanConvert(value)) + { + foreground = qvariant_cast(value); + } +#else + if(value.canConvert()) + { + QBrush brush = qvariant_cast(value); + foreground = brush.color(); + } +#endif + + painter->setPen(fUseBlackTheme ? QColor(28,28,28) : foreground); + painter->drawText(addressRect, Qt::AlignLeft|Qt::AlignVCenter, address); + + if(amount < 0) + { + foreground = COLOR_NEGATIVE; + } + else if(!confirmed) + { + foreground = COLOR_UNCONFIRMED; + } + else + { + foreground = option.palette.color(QPalette::Text); + } + painter->setPen(fUseBlackTheme ? QColor(28,28,28) : foreground); + QString amountText = BitcoinUnits::formatWithUnit(unit, amount, true); + if(!confirmed) + { + amountText = QString("[") + amountText + QString("]"); + } + painter->drawText(amountRect, Qt::AlignRight|Qt::AlignVCenter, amountText); + + painter->setPen(fUseBlackTheme ? QColor(96, 101, 110) : option.palette.color(QPalette::Text)); + painter->drawText(amountRect, Qt::AlignLeft|Qt::AlignVCenter, GUIUtil::dateTimeStr(date)); + + painter->restore(); + } + + inline QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const + { + return QSize(DECORATION_SIZE, DECORATION_SIZE); + } + + int unit; + +}; +#include "overviewpage.moc" + +OverviewPage::OverviewPage(QWidget *parent) : + QWidget(parent), + ui(new Ui::OverviewPage), + currentBalance(-1), + currentStake(0), + currentUnconfirmedBalance(-1), + currentImmatureBalance(-1), + txdelegate(new TxViewDelegate()), + filter(0) +{ + ui->setupUi(this); + + // Recent transactions + ui->listTransactions->setItemDelegate(txdelegate); + ui->listTransactions->setIconSize(QSize(DECORATION_SIZE, DECORATION_SIZE)); + ui->listTransactions->setMinimumHeight(NUM_ITEMS * (DECORATION_SIZE + 2)); + ui->listTransactions->setAttribute(Qt::WA_MacShowFocusRect, false); + + connect(ui->listTransactions, SIGNAL(clicked(QModelIndex)), this, SLOT(handleTransactionClicked(QModelIndex))); + + // init "out of sync" warning labels + ui->labelWalletStatus->setText("(" + tr("out of sync") + ")"); + ui->labelTransactionsStatus->setText("(" + tr("out of sync") + ")"); + + // start with displaying the "out of sync" warnings + showOutOfSyncWarning(true); + + if (fUseBlackTheme) + { + const char* whiteLabelQSS = "QLabel { color: rgb(28,28,28); }"; + ui->labelBalance->setStyleSheet(whiteLabelQSS); + ui->labelStake->setStyleSheet(whiteLabelQSS); + ui->labelUnconfirmed->setStyleSheet(whiteLabelQSS); + ui->labelImmature->setStyleSheet(whiteLabelQSS); + ui->labelTotal->setStyleSheet(whiteLabelQSS); + } +} + +void OverviewPage::handleTransactionClicked(const QModelIndex &index) +{ + if(filter) + emit transactionClicked(filter->mapToSource(index)); +} + +OverviewPage::~OverviewPage() +{ + delete ui; +} + +void OverviewPage::setBalance(qint64 balance, qint64 stake, qint64 unconfirmedBalance, qint64 immatureBalance) +{ + int unit = model->getOptionsModel()->getDisplayUnit(); + currentBalance = balance; + currentStake = stake; + currentUnconfirmedBalance = unconfirmedBalance; + currentImmatureBalance = immatureBalance; + ui->labelBalance->setText(BitcoinUnits::formatWithUnit(unit, balance)); + ui->labelStake->setText(BitcoinUnits::formatWithUnit(unit, stake)); + ui->labelUnconfirmed->setText(BitcoinUnits::formatWithUnit(unit, unconfirmedBalance)); + ui->labelImmature->setText(BitcoinUnits::formatWithUnit(unit, immatureBalance)); + ui->labelTotal->setText(BitcoinUnits::formatWithUnit(unit, balance + stake + unconfirmedBalance + immatureBalance)); + + // only show immature (newly mined) balance if it's non-zero, so as not to complicate things + // for the non-mining users + bool showImmature = immatureBalance != 0; + ui->labelImmature->setVisible(showImmature); + ui->labelImmatureText->setVisible(showImmature); +} + +void OverviewPage::setModel(WalletModel *model) +{ + this->model = model; + if(model && model->getOptionsModel()) + { + // Set up transaction list + filter = new TransactionFilterProxy(); + filter->setSourceModel(model->getTransactionTableModel()); + filter->setLimit(NUM_ITEMS); + filter->setDynamicSortFilter(true); + filter->setSortRole(Qt::EditRole); + filter->setShowInactive(false); + filter->sort(TransactionTableModel::Status, Qt::DescendingOrder); + + ui->listTransactions->setModel(filter); + ui->listTransactions->setModelColumn(TransactionTableModel::ToAddress); + + // Keep up to date with wallet + setBalance(model->getBalance(), model->getStake(), model->getUnconfirmedBalance(), model->getImmatureBalance()); + connect(model, SIGNAL(balanceChanged(qint64, qint64, qint64, qint64)), this, SLOT(setBalance(qint64, qint64, qint64, qint64))); + + connect(model->getOptionsModel(), SIGNAL(displayUnitChanged(int)), this, SLOT(updateDisplayUnit())); + } + + // update the display unit, to not use the default ("BTC") + updateDisplayUnit(); +} + +void OverviewPage::updateDisplayUnit() +{ + if(model && model->getOptionsModel()) + { + if(currentBalance != -1) + setBalance(currentBalance, model->getStake(), currentUnconfirmedBalance, currentImmatureBalance); + + // Update txdelegate->unit with the current unit + txdelegate->unit = model->getOptionsModel()->getDisplayUnit(); + + ui->listTransactions->update(); + } +} + +void OverviewPage::showOutOfSyncWarning(bool fShow) +{ + ui->labelWalletStatus->setVisible(fShow); + ui->labelTransactionsStatus->setVisible(fShow); +} diff --git a/src/qt/overviewpage.h b/src/qt/overviewpage.h new file mode 100755 index 0000000..5e7aa08 --- /dev/null +++ b/src/qt/overviewpage.h @@ -0,0 +1,51 @@ +#ifndef OVERVIEWPAGE_H +#define OVERVIEWPAGE_H + +#include + +QT_BEGIN_NAMESPACE +class QModelIndex; +QT_END_NAMESPACE + +namespace Ui { + class OverviewPage; +} +class WalletModel; +class TxViewDelegate; +class TransactionFilterProxy; + +/** Overview ("home") page widget */ +class OverviewPage : public QWidget +{ + Q_OBJECT + +public: + explicit OverviewPage(QWidget *parent = 0); + ~OverviewPage(); + + void setModel(WalletModel *model); + void showOutOfSyncWarning(bool fShow); + +public slots: + void setBalance(qint64 balance, qint64 stake, qint64 unconfirmedBalance, qint64 immatureBalance); + +signals: + void transactionClicked(const QModelIndex &index); + +private: + Ui::OverviewPage *ui; + WalletModel *model; + qint64 currentBalance; + qint64 currentStake; + qint64 currentUnconfirmedBalance; + qint64 currentImmatureBalance; + + TxViewDelegate *txdelegate; + TransactionFilterProxy *filter; + +private slots: + void updateDisplayUnit(); + void handleTransactionClicked(const QModelIndex &index); +}; + +#endif // OVERVIEWPAGE_H diff --git a/src/qt/qrcodedialog.cpp b/src/qt/qrcodedialog.cpp new file mode 100755 index 0000000..1644ee1 --- /dev/null +++ b/src/qt/qrcodedialog.cpp @@ -0,0 +1,171 @@ +#include "qrcodedialog.h" +#include "ui_qrcodedialog.h" + +#include "bitcoinunits.h" +#include "guiconstants.h" +#include "guiutil.h" +#include "optionsmodel.h" + +#include +#include + +#include + +QRCodeDialog::QRCodeDialog(const QString &addr, const QString &label, bool enableReq, QWidget *parent) : + QDialog(parent), + ui(new Ui::QRCodeDialog), + model(0), + address(addr) +{ + ui->setupUi(this); + + setWindowTitle(QString("%1").arg(address)); + + ui->chkReqPayment->setVisible(enableReq); + ui->lblAmount->setVisible(enableReq); + ui->lnReqAmount->setVisible(enableReq); + + ui->lnLabel->setText(label); + + ui->btnSaveAs->setEnabled(false); + + genCode(); +} + +QRCodeDialog::~QRCodeDialog() +{ + delete ui; +} + +void QRCodeDialog::setModel(OptionsModel *model) +{ + this->model = model; + + if (model) + connect(model, SIGNAL(displayUnitChanged(int)), this, SLOT(updateDisplayUnit())); + + // update the display unit, to not use the default ("BTC") + updateDisplayUnit(); +} + +void QRCodeDialog::genCode() +{ + QString uri = getURI(); + + if (uri != "") + { + ui->lblQRCode->setText(""); + + QRcode *code = QRcode_encodeString(uri.toUtf8().constData(), 0, QR_ECLEVEL_L, QR_MODE_8, 1); + if (!code) + { + ui->lblQRCode->setText(tr("Error encoding URI into QR Code.")); + return; + } + myImage = QImage(code->width + 8, code->width + 8, QImage::Format_RGB32); + myImage.fill(0xffffff); + unsigned char *p = code->data; + for (int y = 0; y < code->width; y++) + { + for (int x = 0; x < code->width; x++) + { + myImage.setPixel(x + 4, y + 4, ((*p & 1) ? 0x0 : 0xffffff)); + p++; + } + } + QRcode_free(code); + + ui->lblQRCode->setPixmap(QPixmap::fromImage(myImage).scaled(300, 300)); + + ui->outUri->setPlainText(uri); + } +} + +QString QRCodeDialog::getURI() +{ + QString ret = QString("arepacoin:%1").arg(address); + int paramCount = 0; + + ui->outUri->clear(); + + if (ui->chkReqPayment->isChecked()) + { + if (ui->lnReqAmount->validate()) + { + // even if we allow a non BTC unit input in lnReqAmount, we generate the URI with BTC as unit (as defined in BIP21) + ret += QString("?amount=%1").arg(BitcoinUnits::format(BitcoinUnits::BTC, ui->lnReqAmount->value())); + paramCount++; + } + else + { + ui->btnSaveAs->setEnabled(false); + ui->lblQRCode->setText(tr("The entered amount is invalid, please check.")); + return QString(""); + } + } + + if (!ui->lnLabel->text().isEmpty()) + { + QString lbl(QUrl::toPercentEncoding(ui->lnLabel->text())); + ret += QString("%1label=%2").arg(paramCount == 0 ? "?" : "&").arg(lbl); + paramCount++; + } + + if (!ui->lnMessage->text().isEmpty()) + { + QString msg(QUrl::toPercentEncoding(ui->lnMessage->text())); + ret += QString("%1message=%2").arg(paramCount == 0 ? "?" : "&").arg(msg); + paramCount++; + } + + // limit URI length to prevent a DoS against the QR-Code dialog + if (ret.length() > MAX_URI_LENGTH) + { + ui->btnSaveAs->setEnabled(false); + ui->lblQRCode->setText(tr("Resulting URI too long, try to reduce the text for label / message.")); + return QString(""); + } + + ui->btnSaveAs->setEnabled(true); + return ret; +} + +void QRCodeDialog::on_lnReqAmount_textChanged() +{ + genCode(); +} + +void QRCodeDialog::on_lnLabel_textChanged() +{ + genCode(); +} + +void QRCodeDialog::on_lnMessage_textChanged() +{ + genCode(); +} + +void QRCodeDialog::on_btnSaveAs_clicked() +{ + QString fn = GUIUtil::getSaveFileName(this, tr("Save QR Code"), QString(), tr("PNG Images (*.png)")); + if (!fn.isEmpty()) + myImage.scaled(EXPORT_IMAGE_SIZE, EXPORT_IMAGE_SIZE).save(fn); +} + +void QRCodeDialog::on_chkReqPayment_toggled(bool fChecked) +{ + if (!fChecked) + // if chkReqPayment is not active, don't display lnReqAmount as invalid + ui->lnReqAmount->setValid(true); + + genCode(); +} + +void QRCodeDialog::updateDisplayUnit() +{ + if (model) + { + // Update lnReqAmount with the current unit + ui->lnReqAmount->setDisplayUnit(model->getDisplayUnit()); + } +} diff --git a/src/qt/qrcodedialog.h b/src/qt/qrcodedialog.h new file mode 100755 index 0000000..c55c34b --- /dev/null +++ b/src/qt/qrcodedialog.h @@ -0,0 +1,41 @@ +#ifndef QRCODEDIALOG_H +#define QRCODEDIALOG_H + +#include +#include + +namespace Ui { + class QRCodeDialog; +} +class OptionsModel; + +class QRCodeDialog : public QDialog +{ + Q_OBJECT + +public: + explicit QRCodeDialog(const QString &addr, const QString &label, bool enableReq, QWidget *parent = 0); + ~QRCodeDialog(); + + void setModel(OptionsModel *model); + +private slots: + void on_lnReqAmount_textChanged(); + void on_lnLabel_textChanged(); + void on_lnMessage_textChanged(); + void on_btnSaveAs_clicked(); + void on_chkReqPayment_toggled(bool fChecked); + + void updateDisplayUnit(); + +private: + Ui::QRCodeDialog *ui; + OptionsModel *model; + QString address; + QImage myImage; + + void genCode(); + QString getURI(); +}; + +#endif // QRCODEDIALOG_H diff --git a/src/qt/qtipcserver.cpp b/src/qt/qtipcserver.cpp new file mode 100755 index 0000000..fc613fd --- /dev/null +++ b/src/qt/qtipcserver.cpp @@ -0,0 +1,162 @@ +// Copyright (c) 2009-2012 The Bitcoin developers +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include +#if defined(WIN32) && BOOST_VERSION == 104900 +#define BOOST_INTERPROCESS_HAS_WINDOWS_KERNEL_BOOTTIME +#define BOOST_INTERPROCESS_HAS_KERNEL_BOOTTIME +#endif + +#include "qtipcserver.h" +#include "guiconstants.h" +#include "ui_interface.h" +#include "util.h" + +#include +#include +#include +#include + +#if defined(WIN32) && (!defined(BOOST_INTERPROCESS_HAS_WINDOWS_KERNEL_BOOTTIME) || !defined(BOOST_INTERPROCESS_HAS_KERNEL_BOOTTIME) || BOOST_VERSION < 104900) +#warning Compiling without BOOST_INTERPROCESS_HAS_WINDOWS_KERNEL_BOOTTIME and BOOST_INTERPROCESS_HAS_KERNEL_BOOTTIME uncommented in boost/interprocess/detail/tmp_dir_helpers.hpp or using a boost version before 1.49 may have unintended results see svn.boost.org/trac/boost/ticket/5392 +#endif + +using namespace boost; +using namespace boost::interprocess; +using namespace boost::posix_time; + +#if defined MAC_OSX || defined __FreeBSD__ +// URI handling not implemented on OSX yet + +void ipcScanRelay(int argc, char *argv[]) { } +void ipcInit(int argc, char *argv[]) { } + +#else + +static void ipcThread2(void* pArg); + +static bool ipcScanCmd(int argc, char *argv[], bool fRelay) +{ + // Check for URI in argv + bool fSent = false; + for (int i = 1; i < argc; i++) + { + if (boost::algorithm::istarts_with(argv[i], "arepacoin:")) + { + const char *strURI = argv[i]; + try { + boost::interprocess::message_queue mq(boost::interprocess::open_only, BITCOINURI_QUEUE_NAME); + if (mq.try_send(strURI, strlen(strURI), 0)) + fSent = true; + else if (fRelay) + break; + } + catch (boost::interprocess::interprocess_exception &ex) { + // don't log the "file not found" exception, because that's normal for + // the first start of the first instance + if (ex.get_error_code() != boost::interprocess::not_found_error || !fRelay) + { + printf("main() - boost interprocess exception #%d: %s\n", ex.get_error_code(), ex.what()); + break; + } + } + } + } + return fSent; +} + +void ipcScanRelay(int argc, char *argv[]) +{ + if (ipcScanCmd(argc, argv, true)) + exit(0); +} + +static void ipcThread(void* pArg) +{ + // Make this thread recognisable as the GUI-IPC thread + RenameThread("arepacoin-gui-ipc"); + + try + { + ipcThread2(pArg); + } + catch (std::exception& e) { + PrintExceptionContinue(&e, "ipcThread()"); + } catch (...) { + PrintExceptionContinue(NULL, "ipcThread()"); + } + printf("ipcThread exited\n"); +} + +static void ipcThread2(void* pArg) +{ + printf("ipcThread started\n"); + + message_queue* mq = (message_queue*)pArg; + char buffer[MAX_URI_LENGTH + 1] = ""; + size_t nSize = 0; + unsigned int nPriority = 0; + + while (true) + { + ptime d = boost::posix_time::microsec_clock::universal_time() + millisec(100); + if (mq->timed_receive(&buffer, sizeof(buffer), nSize, nPriority, d)) + { + uiInterface.ThreadSafeHandleURI(std::string(buffer, nSize)); + MilliSleep(1000); + } + + if (fShutdown) + break; + } + + // Remove message queue + message_queue::remove(BITCOINURI_QUEUE_NAME); + // Cleanup allocated memory + delete mq; +} + +void ipcInit(int argc, char *argv[]) +{ + message_queue* mq = NULL; + char buffer[MAX_URI_LENGTH + 1] = ""; + size_t nSize = 0; + unsigned int nPriority = 0; + + try { + mq = new message_queue(open_or_create, BITCOINURI_QUEUE_NAME, 2, MAX_URI_LENGTH); + + // Make sure we don't lose any bitcoin: URIs + for (int i = 0; i < 2; i++) + { + ptime d = boost::posix_time::microsec_clock::universal_time() + millisec(1); + if (mq->timed_receive(&buffer, sizeof(buffer), nSize, nPriority, d)) + { + uiInterface.ThreadSafeHandleURI(std::string(buffer, nSize)); + } + else + break; + } + + // Make sure only one bitcoin instance is listening + message_queue::remove(BITCOINURI_QUEUE_NAME); + delete mq; + + mq = new message_queue(open_or_create, BITCOINURI_QUEUE_NAME, 2, MAX_URI_LENGTH); + } + catch (interprocess_exception &ex) { + printf("ipcInit() - boost interprocess exception #%d: %s\n", ex.get_error_code(), ex.what()); + return; + } + + if (!NewThread(ipcThread, mq)) + { + delete mq; + return; + } + + ipcScanCmd(argc, argv, false); +} + +#endif diff --git a/src/qt/qtipcserver.h b/src/qt/qtipcserver.h new file mode 100755 index 0000000..46a0c41 --- /dev/null +++ b/src/qt/qtipcserver.h @@ -0,0 +1,10 @@ +#ifndef QTIPCSERVER_H +#define QTIPCSERVER_H + +// Define Arepacoin-Qt message queue name +#define BITCOINURI_QUEUE_NAME "ArepacoinURI" + +void ipcScanRelay(int argc, char *argv[]); +void ipcInit(int argc, char *argv[]); + +#endif // QTIPCSERVER_H diff --git a/src/qt/qvalidatedlineedit.cpp b/src/qt/qvalidatedlineedit.cpp new file mode 100755 index 0000000..8ca230c --- /dev/null +++ b/src/qt/qvalidatedlineedit.cpp @@ -0,0 +1,45 @@ +#include "qvalidatedlineedit.h" + +#include "guiconstants.h" + +QValidatedLineEdit::QValidatedLineEdit(QWidget *parent) : + QLineEdit(parent), valid(true) +{ + connect(this, SIGNAL(textChanged(QString)), this, SLOT(markValid())); +} + +void QValidatedLineEdit::setValid(bool valid) +{ + if(valid == this->valid) + { + return; + } + + if(valid) + { + setStyleSheet(""); + } + else + { + setStyleSheet(STYLE_INVALID); + } + this->valid = valid; +} + +void QValidatedLineEdit::focusInEvent(QFocusEvent *evt) +{ + // Clear invalid flag on focus + setValid(true); + QLineEdit::focusInEvent(evt); +} + +void QValidatedLineEdit::markValid() +{ + setValid(true); +} + +void QValidatedLineEdit::clear() +{ + setValid(true); + QLineEdit::clear(); +} diff --git a/src/qt/qvalidatedlineedit.h b/src/qt/qvalidatedlineedit.h new file mode 100755 index 0000000..66e26be --- /dev/null +++ b/src/qt/qvalidatedlineedit.h @@ -0,0 +1,29 @@ +#ifndef QVALIDATEDLINEEDIT_H +#define QVALIDATEDLINEEDIT_H + +#include + +/** Line edit that can be marked as "invalid" to show input validation feedback. When marked as invalid, + it will get a red background until it is focused. + */ +class QValidatedLineEdit : public QLineEdit +{ + Q_OBJECT +public: + explicit QValidatedLineEdit(QWidget *parent = 0); + void clear(); + +protected: + void focusInEvent(QFocusEvent *evt); + +private: + bool valid; + +public slots: + void setValid(bool valid); + +private slots: + void markValid(); +}; + +#endif // QVALIDATEDLINEEDIT_H diff --git a/src/qt/qvaluecombobox.cpp b/src/qt/qvaluecombobox.cpp new file mode 100755 index 0000000..d7ce3d0 --- /dev/null +++ b/src/qt/qvaluecombobox.cpp @@ -0,0 +1,27 @@ +#include "qvaluecombobox.h" + +QValueComboBox::QValueComboBox(QWidget *parent) : + QComboBox(parent), role(Qt::UserRole) +{ + connect(this, SIGNAL(currentIndexChanged(int)), this, SLOT(handleSelectionChanged(int))); +} + +QVariant QValueComboBox::value() const +{ + return itemData(currentIndex(), role); +} + +void QValueComboBox::setValue(const QVariant &value) +{ + setCurrentIndex(findData(value, role)); +} + +void QValueComboBox::setRole(int role) +{ + this->role = role; +} + +void QValueComboBox::handleSelectionChanged(int idx) +{ + emit valueChanged(); +} diff --git a/src/qt/qvaluecombobox.h b/src/qt/qvaluecombobox.h new file mode 100755 index 0000000..1a47bb6 --- /dev/null +++ b/src/qt/qvaluecombobox.h @@ -0,0 +1,33 @@ +#ifndef QVALUECOMBOBOX_H +#define QVALUECOMBOBOX_H + +#include +#include + +/* QComboBox that can be used with QDataWidgetMapper to select ordinal values from a model. */ +class QValueComboBox : public QComboBox +{ + Q_OBJECT + Q_PROPERTY(QVariant value READ value WRITE setValue NOTIFY valueChanged USER true) +public: + explicit QValueComboBox(QWidget *parent = 0); + + QVariant value() const; + void setValue(const QVariant &value); + + /** Specify model role to use as ordinal value (defaults to Qt::UserRole) */ + void setRole(int role); + +signals: + void valueChanged(); + +public slots: + +private: + int role; + +private slots: + void handleSelectionChanged(int idx); +}; + +#endif // QVALUECOMBOBOX_H diff --git a/src/qt/res/bitcoin-qt.rc b/src/qt/res/bitcoin-qt.rc new file mode 100755 index 0000000..8224d53 --- /dev/null +++ b/src/qt/res/bitcoin-qt.rc @@ -0,0 +1,37 @@ +IDI_ICON1 ICON DISCARDABLE "icons/arepacoin.ico" + +#include // needed for VERSIONINFO +#include "../../clientversion.h" // holds the needed client version information + +#define VER_PRODUCTVERSION CLIENT_VERSION_MAJOR,CLIENT_VERSION_MINOR,CLIENT_VERSION_REVISION,CLIENT_VERSION_BUILD +#define VER_PRODUCTVERSION_STR STRINGIZE(CLIENT_VERSION_MAJOR) "." STRINGIZE(CLIENT_VERSION_MINOR) "." STRINGIZE(CLIENT_VERSION_REVISION) "." STRINGIZE(CLIENT_VERSION_BUILD) +#define VER_FILEVERSION VER_PRODUCTVERSION +#define VER_FILEVERSION_STR VER_PRODUCTVERSION_STR + +VS_VERSION_INFO VERSIONINFO +FILEVERSION VER_FILEVERSION +PRODUCTVERSION VER_PRODUCTVERSION +FILEOS VOS_NT_WINDOWS32 +FILETYPE VFT_APP +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904E4" // U.S. English - multilingual (hex) + BEGIN + VALUE "CompanyName", "Arepacoin" + VALUE "FileDescription", "Arepacoin-Qt (OSS GUI client for Arepacoin)" + VALUE "FileVersion", VER_FILEVERSION_STR + VALUE "InternalName", "arepacoin-qt" + VALUE "LegalCopyright", "2009-2014 The Bitcoin developers, 2012-2014 The NovaCoin & PPCoin developers, 2014 The Arepacoin developers" + VALUE "LegalTrademarks1", "Distributed under the MIT/X11 software license, see the accompanying file COPYING or http://www.opensource.org/licenses/mit-license.php." + VALUE "OriginalFilename", "arepacoin-qt.exe" + VALUE "ProductName", "Arepacoin-Qt" + VALUE "ProductVersion", VER_PRODUCTVERSION_STR + END + END + + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x0, 1252 // language neutral - multilingual (decimal) + END +END diff --git a/src/qt/res/icons/about_qt.png b/src/qt/res/icons/about_qt.png new file mode 100755 index 0000000..c40abfd Binary files /dev/null and b/src/qt/res/icons/about_qt.png differ diff --git a/src/qt/res/icons/add.png b/src/qt/res/icons/add.png new file mode 100755 index 0000000..1442b4e Binary files /dev/null and b/src/qt/res/icons/add.png differ diff --git a/src/qt/res/icons/address-book.png b/src/qt/res/icons/address-book.png new file mode 100755 index 0000000..b11c7d5 Binary files /dev/null and b/src/qt/res/icons/address-book.png differ diff --git a/src/qt/res/icons/arepacoin-128.png b/src/qt/res/icons/arepacoin-128.png new file mode 100755 index 0000000..1914d35 Binary files /dev/null and b/src/qt/res/icons/arepacoin-128.png differ diff --git a/src/qt/res/icons/arepacoin-16.png b/src/qt/res/icons/arepacoin-16.png new file mode 100755 index 0000000..d380340 Binary files /dev/null and b/src/qt/res/icons/arepacoin-16.png differ diff --git a/src/qt/res/icons/arepacoin-32.png b/src/qt/res/icons/arepacoin-32.png new file mode 100755 index 0000000..8f0ca1a Binary files /dev/null and b/src/qt/res/icons/arepacoin-32.png differ diff --git a/src/qt/res/icons/arepacoin-48.png b/src/qt/res/icons/arepacoin-48.png new file mode 100755 index 0000000..76ff5a7 Binary files /dev/null and b/src/qt/res/icons/arepacoin-48.png differ diff --git a/src/qt/res/icons/arepacoin-80.png b/src/qt/res/icons/arepacoin-80.png new file mode 100755 index 0000000..04986ab Binary files /dev/null and b/src/qt/res/icons/arepacoin-80.png differ diff --git a/src/qt/res/icons/arepacoin.ico b/src/qt/res/icons/arepacoin.ico new file mode 100755 index 0000000..ab773f1 Binary files /dev/null and b/src/qt/res/icons/arepacoin.ico differ diff --git a/src/qt/res/icons/arepacoin.png b/src/qt/res/icons/arepacoin.png new file mode 100755 index 0000000..0e23ff6 Binary files /dev/null and b/src/qt/res/icons/arepacoin.png differ diff --git a/src/qt/res/icons/bitcoin.icns b/src/qt/res/icons/bitcoin.icns new file mode 100755 index 0000000..c95a8ea Binary files /dev/null and b/src/qt/res/icons/bitcoin.icns differ diff --git a/src/qt/res/icons/bitcoin.png b/src/qt/res/icons/bitcoin.png new file mode 100755 index 0000000..0e23ff6 Binary files /dev/null and b/src/qt/res/icons/bitcoin.png differ diff --git a/src/qt/res/icons/bitcoin_testnet.png b/src/qt/res/icons/bitcoin_testnet.png new file mode 100755 index 0000000..1914d35 Binary files /dev/null and b/src/qt/res/icons/bitcoin_testnet.png differ diff --git a/src/qt/res/icons/clock1.png b/src/qt/res/icons/clock1.png new file mode 100755 index 0000000..162204d Binary files /dev/null and b/src/qt/res/icons/clock1.png differ diff --git a/src/qt/res/icons/clock2.png b/src/qt/res/icons/clock2.png new file mode 100755 index 0000000..8f4263a Binary files /dev/null and b/src/qt/res/icons/clock2.png differ diff --git a/src/qt/res/icons/clock3.png b/src/qt/res/icons/clock3.png new file mode 100755 index 0000000..7f11a75 Binary files /dev/null and b/src/qt/res/icons/clock3.png differ diff --git a/src/qt/res/icons/clock4.png b/src/qt/res/icons/clock4.png new file mode 100755 index 0000000..fdd1a0f Binary files /dev/null and b/src/qt/res/icons/clock4.png differ diff --git a/src/qt/res/icons/clock5.png b/src/qt/res/icons/clock5.png new file mode 100755 index 0000000..7d6556c Binary files /dev/null and b/src/qt/res/icons/clock5.png differ diff --git a/src/qt/res/icons/configure.png b/src/qt/res/icons/configure.png new file mode 100755 index 0000000..5333c83 Binary files /dev/null and b/src/qt/res/icons/configure.png differ diff --git a/src/qt/res/icons/connect0_16.png b/src/qt/res/icons/connect0_16.png new file mode 100755 index 0000000..ef708d8 Binary files /dev/null and b/src/qt/res/icons/connect0_16.png differ diff --git a/src/qt/res/icons/connect1_16.png b/src/qt/res/icons/connect1_16.png new file mode 100755 index 0000000..ed358e6 Binary files /dev/null and b/src/qt/res/icons/connect1_16.png differ diff --git a/src/qt/res/icons/connect2_16.png b/src/qt/res/icons/connect2_16.png new file mode 100755 index 0000000..3bbb0d3 Binary files /dev/null and b/src/qt/res/icons/connect2_16.png differ diff --git a/src/qt/res/icons/connect3_16.png b/src/qt/res/icons/connect3_16.png new file mode 100755 index 0000000..0db99ad Binary files /dev/null and b/src/qt/res/icons/connect3_16.png differ diff --git a/src/qt/res/icons/connect4_16.png b/src/qt/res/icons/connect4_16.png new file mode 100755 index 0000000..9dd19fc Binary files /dev/null and b/src/qt/res/icons/connect4_16.png differ diff --git a/src/qt/res/icons/debugwindow.png b/src/qt/res/icons/debugwindow.png new file mode 100755 index 0000000..290fe60 Binary files /dev/null and b/src/qt/res/icons/debugwindow.png differ diff --git a/src/qt/res/icons/edit.png b/src/qt/res/icons/edit.png new file mode 100755 index 0000000..4658271 Binary files /dev/null and b/src/qt/res/icons/edit.png differ diff --git a/src/qt/res/icons/editcopy.png b/src/qt/res/icons/editcopy.png new file mode 100755 index 0000000..74ac8b2 Binary files /dev/null and b/src/qt/res/icons/editcopy.png differ diff --git a/src/qt/res/icons/editpaste.png b/src/qt/res/icons/editpaste.png new file mode 100755 index 0000000..7b47f4d Binary files /dev/null and b/src/qt/res/icons/editpaste.png differ diff --git a/src/qt/res/icons/export.png b/src/qt/res/icons/export.png new file mode 100755 index 0000000..ac76cc1 Binary files /dev/null and b/src/qt/res/icons/export.png differ diff --git a/src/qt/res/icons/filesave.png b/src/qt/res/icons/filesave.png new file mode 100755 index 0000000..779cca1 Binary files /dev/null and b/src/qt/res/icons/filesave.png differ diff --git a/src/qt/res/icons/history.png b/src/qt/res/icons/history.png new file mode 100755 index 0000000..68d841f Binary files /dev/null and b/src/qt/res/icons/history.png differ diff --git a/src/qt/res/icons/key.png b/src/qt/res/icons/key.png new file mode 100755 index 0000000..f301c4f Binary files /dev/null and b/src/qt/res/icons/key.png differ diff --git a/src/qt/res/icons/lock_closed.png b/src/qt/res/icons/lock_closed.png new file mode 100755 index 0000000..1bd98b2 Binary files /dev/null and b/src/qt/res/icons/lock_closed.png differ diff --git a/src/qt/res/icons/lock_open.png b/src/qt/res/icons/lock_open.png new file mode 100755 index 0000000..a704513 Binary files /dev/null and b/src/qt/res/icons/lock_open.png differ diff --git a/src/qt/res/icons/notsynced.png b/src/qt/res/icons/notsynced.png new file mode 100755 index 0000000..6bc5ac7 Binary files /dev/null and b/src/qt/res/icons/notsynced.png differ diff --git a/src/qt/res/icons/open.png b/src/qt/res/icons/open.png new file mode 100755 index 0000000..4d958f0 Binary files /dev/null and b/src/qt/res/icons/open.png differ diff --git a/src/qt/res/icons/overview.png b/src/qt/res/icons/overview.png new file mode 100755 index 0000000..4115954 Binary files /dev/null and b/src/qt/res/icons/overview.png differ diff --git a/src/qt/res/icons/qrcode.png b/src/qt/res/icons/qrcode.png new file mode 100755 index 0000000..1fe51a0 Binary files /dev/null and b/src/qt/res/icons/qrcode.png differ diff --git a/src/qt/res/icons/quit.png b/src/qt/res/icons/quit.png new file mode 100755 index 0000000..55e34de Binary files /dev/null and b/src/qt/res/icons/quit.png differ diff --git a/src/qt/res/icons/receive.png b/src/qt/res/icons/receive.png new file mode 100755 index 0000000..f4e6f58 Binary files /dev/null and b/src/qt/res/icons/receive.png differ diff --git a/src/qt/res/icons/remove.png b/src/qt/res/icons/remove.png new file mode 100755 index 0000000..8e738d6 Binary files /dev/null and b/src/qt/res/icons/remove.png differ diff --git a/src/qt/res/icons/send.png b/src/qt/res/icons/send.png new file mode 100755 index 0000000..ac76cc1 Binary files /dev/null and b/src/qt/res/icons/send.png differ diff --git a/src/qt/res/icons/staking_off.png b/src/qt/res/icons/staking_off.png new file mode 100755 index 0000000..795bf64 Binary files /dev/null and b/src/qt/res/icons/staking_off.png differ diff --git a/src/qt/res/icons/staking_on.png b/src/qt/res/icons/staking_on.png new file mode 100755 index 0000000..eaab692 Binary files /dev/null and b/src/qt/res/icons/staking_on.png differ diff --git a/src/qt/res/icons/synced.png b/src/qt/res/icons/synced.png new file mode 100755 index 0000000..5ac28d3 Binary files /dev/null and b/src/qt/res/icons/synced.png differ diff --git a/src/qt/res/icons/telegram.png b/src/qt/res/icons/telegram.png new file mode 100644 index 0000000..6151a4a Binary files /dev/null and b/src/qt/res/icons/telegram.png differ diff --git a/src/qt/res/icons/transaction0.png b/src/qt/res/icons/transaction0.png new file mode 100755 index 0000000..72c4456 Binary files /dev/null and b/src/qt/res/icons/transaction0.png differ diff --git a/src/qt/res/icons/transaction2.png b/src/qt/res/icons/transaction2.png new file mode 100755 index 0000000..5ac28d3 Binary files /dev/null and b/src/qt/res/icons/transaction2.png differ diff --git a/src/qt/res/icons/transaction_conflicted.png b/src/qt/res/icons/transaction_conflicted.png new file mode 100755 index 0000000..55e34de Binary files /dev/null and b/src/qt/res/icons/transaction_conflicted.png differ diff --git a/src/qt/res/icons/twitter.png b/src/qt/res/icons/twitter.png new file mode 100644 index 0000000..b551acc Binary files /dev/null and b/src/qt/res/icons/twitter.png differ diff --git a/src/qt/res/icons/tx_inout.png b/src/qt/res/icons/tx_inout.png new file mode 100755 index 0000000..0a6e72a Binary files /dev/null and b/src/qt/res/icons/tx_inout.png differ diff --git a/src/qt/res/icons/tx_input.png b/src/qt/res/icons/tx_input.png new file mode 100755 index 0000000..9e9ee92 Binary files /dev/null and b/src/qt/res/icons/tx_input.png differ diff --git a/src/qt/res/icons/tx_mined.png b/src/qt/res/icons/tx_mined.png new file mode 100755 index 0000000..5a6ef52 Binary files /dev/null and b/src/qt/res/icons/tx_mined.png differ diff --git a/src/qt/res/icons/tx_output.png b/src/qt/res/icons/tx_output.png new file mode 100755 index 0000000..6f66ab6 Binary files /dev/null and b/src/qt/res/icons/tx_output.png differ diff --git a/src/qt/res/images/about.png b/src/qt/res/images/about.png new file mode 100755 index 0000000..e8cc5af Binary files /dev/null and b/src/qt/res/images/about.png differ diff --git a/src/qt/res/images/header.png b/src/qt/res/images/header.png new file mode 100755 index 0000000..1914d35 Binary files /dev/null and b/src/qt/res/images/header.png differ diff --git a/src/qt/res/images/splash.png b/src/qt/res/images/splash.png new file mode 100755 index 0000000..143570d Binary files /dev/null and b/src/qt/res/images/splash.png differ diff --git a/src/qt/res/images/splash2.jpg b/src/qt/res/images/splash2.jpg new file mode 100755 index 0000000..db929c2 Binary files /dev/null and b/src/qt/res/images/splash2.jpg differ diff --git a/src/qt/res/movies/spinner-000.png b/src/qt/res/movies/spinner-000.png new file mode 100644 index 0000000..0dc48d0 Binary files /dev/null and b/src/qt/res/movies/spinner-000.png differ diff --git a/src/qt/res/movies/spinner-001.png b/src/qt/res/movies/spinner-001.png new file mode 100644 index 0000000..d167f20 Binary files /dev/null and b/src/qt/res/movies/spinner-001.png differ diff --git a/src/qt/res/movies/spinner-002.png b/src/qt/res/movies/spinner-002.png new file mode 100644 index 0000000..4a1f1f8 Binary files /dev/null and b/src/qt/res/movies/spinner-002.png differ diff --git a/src/qt/res/movies/spinner-003.png b/src/qt/res/movies/spinner-003.png new file mode 100644 index 0000000..fb1c2cd Binary files /dev/null and b/src/qt/res/movies/spinner-003.png differ diff --git a/src/qt/res/movies/spinner-004.png b/src/qt/res/movies/spinner-004.png new file mode 100644 index 0000000..4df2132 Binary files /dev/null and b/src/qt/res/movies/spinner-004.png differ diff --git a/src/qt/res/movies/spinner-005.png b/src/qt/res/movies/spinner-005.png new file mode 100644 index 0000000..5d6f41e Binary files /dev/null and b/src/qt/res/movies/spinner-005.png differ diff --git a/src/qt/res/movies/spinner-006.png b/src/qt/res/movies/spinner-006.png new file mode 100644 index 0000000..c1f7d18 Binary files /dev/null and b/src/qt/res/movies/spinner-006.png differ diff --git a/src/qt/res/movies/spinner-007.png b/src/qt/res/movies/spinner-007.png new file mode 100644 index 0000000..1e794b2 Binary files /dev/null and b/src/qt/res/movies/spinner-007.png differ diff --git a/src/qt/res/movies/spinner-008.png b/src/qt/res/movies/spinner-008.png new file mode 100644 index 0000000..df12ea8 Binary files /dev/null and b/src/qt/res/movies/spinner-008.png differ diff --git a/src/qt/res/movies/spinner-009.png b/src/qt/res/movies/spinner-009.png new file mode 100644 index 0000000..18fc3a7 Binary files /dev/null and b/src/qt/res/movies/spinner-009.png differ diff --git a/src/qt/res/movies/spinner-010.png b/src/qt/res/movies/spinner-010.png new file mode 100644 index 0000000..a79c845 Binary files /dev/null and b/src/qt/res/movies/spinner-010.png differ diff --git a/src/qt/res/movies/spinner-011.png b/src/qt/res/movies/spinner-011.png new file mode 100644 index 0000000..57baf66 Binary files /dev/null and b/src/qt/res/movies/spinner-011.png differ diff --git a/src/qt/res/movies/spinner-012.png b/src/qt/res/movies/spinner-012.png new file mode 100644 index 0000000..9deae78 Binary files /dev/null and b/src/qt/res/movies/spinner-012.png differ diff --git a/src/qt/res/movies/spinner-013.png b/src/qt/res/movies/spinner-013.png new file mode 100644 index 0000000..0659d48 Binary files /dev/null and b/src/qt/res/movies/spinner-013.png differ diff --git a/src/qt/res/movies/spinner-014.png b/src/qt/res/movies/spinner-014.png new file mode 100644 index 0000000..bc1ef51 Binary files /dev/null and b/src/qt/res/movies/spinner-014.png differ diff --git a/src/qt/res/movies/spinner-015.png b/src/qt/res/movies/spinner-015.png new file mode 100644 index 0000000..24b57b6 Binary files /dev/null and b/src/qt/res/movies/spinner-015.png differ diff --git a/src/qt/res/movies/spinner-016.png b/src/qt/res/movies/spinner-016.png new file mode 100644 index 0000000..d622872 Binary files /dev/null and b/src/qt/res/movies/spinner-016.png differ diff --git a/src/qt/res/movies/spinner-017.png b/src/qt/res/movies/spinner-017.png new file mode 100644 index 0000000..f48f688 Binary files /dev/null and b/src/qt/res/movies/spinner-017.png differ diff --git a/src/qt/res/movies/spinner-018.png b/src/qt/res/movies/spinner-018.png new file mode 100644 index 0000000..a2c8f38 Binary files /dev/null and b/src/qt/res/movies/spinner-018.png differ diff --git a/src/qt/res/movies/spinner-019.png b/src/qt/res/movies/spinner-019.png new file mode 100644 index 0000000..9d7cc35 Binary files /dev/null and b/src/qt/res/movies/spinner-019.png differ diff --git a/src/qt/res/movies/spinner-020.png b/src/qt/res/movies/spinner-020.png new file mode 100644 index 0000000..1a07acc Binary files /dev/null and b/src/qt/res/movies/spinner-020.png differ diff --git a/src/qt/res/movies/spinner-021.png b/src/qt/res/movies/spinner-021.png new file mode 100644 index 0000000..9cea8f2 Binary files /dev/null and b/src/qt/res/movies/spinner-021.png differ diff --git a/src/qt/res/movies/spinner-022.png b/src/qt/res/movies/spinner-022.png new file mode 100644 index 0000000..60250f6 Binary files /dev/null and b/src/qt/res/movies/spinner-022.png differ diff --git a/src/qt/res/movies/spinner-023.png b/src/qt/res/movies/spinner-023.png new file mode 100644 index 0000000..fc290a0 Binary files /dev/null and b/src/qt/res/movies/spinner-023.png differ diff --git a/src/qt/res/movies/spinner-024.png b/src/qt/res/movies/spinner-024.png new file mode 100644 index 0000000..c5dcf1e Binary files /dev/null and b/src/qt/res/movies/spinner-024.png differ diff --git a/src/qt/res/movies/spinner-025.png b/src/qt/res/movies/spinner-025.png new file mode 100644 index 0000000..7f3577a Binary files /dev/null and b/src/qt/res/movies/spinner-025.png differ diff --git a/src/qt/res/movies/spinner-026.png b/src/qt/res/movies/spinner-026.png new file mode 100644 index 0000000..1663ddf Binary files /dev/null and b/src/qt/res/movies/spinner-026.png differ diff --git a/src/qt/res/movies/spinner-027.png b/src/qt/res/movies/spinner-027.png new file mode 100644 index 0000000..d0e6da4 Binary files /dev/null and b/src/qt/res/movies/spinner-027.png differ diff --git a/src/qt/res/movies/spinner-028.png b/src/qt/res/movies/spinner-028.png new file mode 100644 index 0000000..2a7aba5 Binary files /dev/null and b/src/qt/res/movies/spinner-028.png differ diff --git a/src/qt/res/movies/spinner-029.png b/src/qt/res/movies/spinner-029.png new file mode 100644 index 0000000..c8ca15c Binary files /dev/null and b/src/qt/res/movies/spinner-029.png differ diff --git a/src/qt/res/movies/spinner-030.png b/src/qt/res/movies/spinner-030.png new file mode 100644 index 0000000..c847c99 Binary files /dev/null and b/src/qt/res/movies/spinner-030.png differ diff --git a/src/qt/res/movies/spinner-031.png b/src/qt/res/movies/spinner-031.png new file mode 100644 index 0000000..4034431 Binary files /dev/null and b/src/qt/res/movies/spinner-031.png differ diff --git a/src/qt/res/movies/spinner-032.png b/src/qt/res/movies/spinner-032.png new file mode 100644 index 0000000..f9db080 Binary files /dev/null and b/src/qt/res/movies/spinner-032.png differ diff --git a/src/qt/res/movies/spinner-033.png b/src/qt/res/movies/spinner-033.png new file mode 100644 index 0000000..43f5771 Binary files /dev/null and b/src/qt/res/movies/spinner-033.png differ diff --git a/src/qt/res/movies/spinner-034.png b/src/qt/res/movies/spinner-034.png new file mode 100644 index 0000000..c26656f Binary files /dev/null and b/src/qt/res/movies/spinner-034.png differ diff --git a/src/qt/res/movies/spinner-035.png b/src/qt/res/movies/spinner-035.png new file mode 100644 index 0000000..e471f95 Binary files /dev/null and b/src/qt/res/movies/spinner-035.png differ diff --git a/src/qt/res/src/bitcoin.svg b/src/qt/res/src/bitcoin.svg new file mode 100755 index 0000000..96f1017 --- /dev/null +++ b/src/qt/res/src/bitcoin.svg @@ -0,0 +1,115 @@ + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/qt/res/src/clock1.svg b/src/qt/res/src/clock1.svg new file mode 100755 index 0000000..793dc7f --- /dev/null +++ b/src/qt/res/src/clock1.svg @@ -0,0 +1,261 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/qt/res/src/clock2.svg b/src/qt/res/src/clock2.svg new file mode 100755 index 0000000..6a78adf --- /dev/null +++ b/src/qt/res/src/clock2.svg @@ -0,0 +1,262 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/qt/res/src/clock3.svg b/src/qt/res/src/clock3.svg new file mode 100755 index 0000000..09ccc25 --- /dev/null +++ b/src/qt/res/src/clock3.svg @@ -0,0 +1,261 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/qt/res/src/clock4.svg b/src/qt/res/src/clock4.svg new file mode 100755 index 0000000..7d9dc37 --- /dev/null +++ b/src/qt/res/src/clock4.svg @@ -0,0 +1,261 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/qt/res/src/clock5.svg b/src/qt/res/src/clock5.svg new file mode 100755 index 0000000..9fd58d9 --- /dev/null +++ b/src/qt/res/src/clock5.svg @@ -0,0 +1,262 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/qt/res/src/clock_green.svg b/src/qt/res/src/clock_green.svg new file mode 100755 index 0000000..e31f0e7 --- /dev/null +++ b/src/qt/res/src/clock_green.svg @@ -0,0 +1,262 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/qt/res/src/inout.svg b/src/qt/res/src/inout.svg new file mode 100755 index 0000000..bfab8ef --- /dev/null +++ b/src/qt/res/src/inout.svg @@ -0,0 +1,122 @@ + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + diff --git a/src/qt/res/src/questionmark.svg b/src/qt/res/src/questionmark.svg new file mode 100755 index 0000000..c03c159 --- /dev/null +++ b/src/qt/res/src/questionmark.svg @@ -0,0 +1,159 @@ + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + ? + ? + + + ? + + diff --git a/src/qt/rpcconsole.cpp b/src/qt/rpcconsole.cpp new file mode 100755 index 0000000..6d8f6f5 --- /dev/null +++ b/src/qt/rpcconsole.cpp @@ -0,0 +1,490 @@ +#include "rpcconsole.h" +#include "ui_rpcconsole.h" + +#include "clientmodel.h" +#include "bitcoinrpc.h" +#include "guiutil.h" + +#include +#include +#include +#include +#include +#include +#include + +#include + +// TODO: make it possible to filter out categories (esp debug messages when implemented) +// TODO: receive errors and debug messages through ClientModel + +const int CONSOLE_SCROLLBACK = 50; +const int CONSOLE_HISTORY = 50; + +const QSize ICON_SIZE(24, 24); + +const int INITIAL_TRAFFIC_GRAPH_MINS = 30; + +const struct { + const char *url; + const char *source; +} ICON_MAPPING[] = { + {"cmd-request", ":/icons/tx_input"}, + {"cmd-reply", ":/icons/tx_output"}, + {"cmd-error", ":/icons/tx_output"}, + {"misc", ":/icons/tx_inout"}, + {NULL, NULL} +}; + +/* Object for executing console RPC commands in a separate thread. +*/ +class RPCExecutor: public QObject +{ + Q_OBJECT +public slots: + void start(); + void request(const QString &command); +signals: + void reply(int category, const QString &command); +}; + +#include "rpcconsole.moc" + +void RPCExecutor::start() +{ + // Nothing to do +} + +/** + * Split shell command line into a list of arguments. Aims to emulate \c bash and friends. + * + * - Arguments are delimited with whitespace + * - Extra whitespace at the beginning and end and between arguments will be ignored + * - Text can be "double" or 'single' quoted + * - The backslash \c \ is used as escape character + * - Outside quotes, any character can be escaped + * - Within double quotes, only escape \c " and backslashes before a \c " or another backslash + * - Within single quotes, no escaping is possible and no special interpretation takes place + * + * @param[out] args Parsed arguments will be appended to this list + * @param[in] strCommand Command line to split + */ +bool parseCommandLine(std::vector &args, const std::string &strCommand) +{ + enum CmdParseState + { + STATE_EATING_SPACES, + STATE_ARGUMENT, + STATE_SINGLEQUOTED, + STATE_DOUBLEQUOTED, + STATE_ESCAPE_OUTER, + STATE_ESCAPE_DOUBLEQUOTED + } state = STATE_EATING_SPACES; + std::string curarg; + foreach(char ch, strCommand) + { + switch(state) + { + case STATE_ARGUMENT: // In or after argument + case STATE_EATING_SPACES: // Handle runs of whitespace + switch(ch) + { + case '"': state = STATE_DOUBLEQUOTED; break; + case '\'': state = STATE_SINGLEQUOTED; break; + case '\\': state = STATE_ESCAPE_OUTER; break; + case ' ': case '\n': case '\t': + if(state == STATE_ARGUMENT) // Space ends argument + { + args.push_back(curarg); + curarg.clear(); + } + state = STATE_EATING_SPACES; + break; + default: curarg += ch; state = STATE_ARGUMENT; + } + break; + case STATE_SINGLEQUOTED: // Single-quoted string + switch(ch) + { + case '\'': state = STATE_ARGUMENT; break; + default: curarg += ch; + } + break; + case STATE_DOUBLEQUOTED: // Double-quoted string + switch(ch) + { + case '"': state = STATE_ARGUMENT; break; + case '\\': state = STATE_ESCAPE_DOUBLEQUOTED; break; + default: curarg += ch; + } + break; + case STATE_ESCAPE_OUTER: // '\' outside quotes + curarg += ch; state = STATE_ARGUMENT; + break; + case STATE_ESCAPE_DOUBLEQUOTED: // '\' in double-quoted text + if(ch != '"' && ch != '\\') curarg += '\\'; // keep '\' for everything but the quote and '\' itself + curarg += ch; state = STATE_DOUBLEQUOTED; + break; + } + } + switch(state) // final state + { + case STATE_EATING_SPACES: + return true; + case STATE_ARGUMENT: + args.push_back(curarg); + return true; + default: // ERROR to end in one of the other states + return false; + } +} + +void RPCExecutor::request(const QString &command) +{ + std::vector args; + if(!parseCommandLine(args, command.toStdString())) + { + emit reply(RPCConsole::CMD_ERROR, QString("Parse error: unbalanced ' or \"")); + return; + } + if(args.empty()) + return; // Nothing to do + try + { + std::string strPrint; + // Convert argument list to JSON objects in method-dependent way, + // and pass it along with the method name to the dispatcher. + json_spirit::Value result = tableRPC.execute( + args[0], + RPCConvertValues(args[0], std::vector(args.begin() + 1, args.end()))); + + // Format result reply + if (result.type() == json_spirit::null_type) + strPrint = ""; + else if (result.type() == json_spirit::str_type) + strPrint = result.get_str(); + else + strPrint = write_string(result, true); + + emit reply(RPCConsole::CMD_REPLY, QString::fromStdString(strPrint)); + } + catch (json_spirit::Object& objError) + { + try // Nice formatting for standard-format error + { + int code = find_value(objError, "code").get_int(); + std::string message = find_value(objError, "message").get_str(); + emit reply(RPCConsole::CMD_ERROR, QString::fromStdString(message) + " (code " + QString::number(code) + ")"); + } + catch(std::runtime_error &) // raised when converting to invalid type, i.e. missing code or message + { // Show raw JSON object + emit reply(RPCConsole::CMD_ERROR, QString::fromStdString(write_string(json_spirit::Value(objError), false))); + } + } + catch (std::exception& e) + { + emit reply(RPCConsole::CMD_ERROR, QString("Error: ") + QString::fromStdString(e.what())); + } +} + +RPCConsole::RPCConsole(QWidget *parent) : + QDialog(parent), + ui(new Ui::RPCConsole), + historyPtr(0) +{ + ui->setupUi(this); + +#ifndef Q_OS_MAC + ui->openDebugLogfileButton->setIcon(QIcon(":/icons/export")); + ui->showCLOptionsButton->setIcon(QIcon(":/icons/options")); +#endif + + // Install event filter for up and down arrow + ui->lineEdit->installEventFilter(this); + ui->messagesWidget->installEventFilter(this); + + connect(ui->clearButton, SIGNAL(clicked()), this, SLOT(clear())); + + // set OpenSSL version label + ui->openSSLVersion->setText(SSLeay_version(SSLEAY_VERSION)); + + startExecutor(); + setTrafficGraphRange(INITIAL_TRAFFIC_GRAPH_MINS); + + clear(); +} + +RPCConsole::~RPCConsole() +{ + emit stopExecutor(); + delete ui; +} + +bool RPCConsole::eventFilter(QObject* obj, QEvent *event) +{ + if(event->type() == QEvent::KeyPress) // Special key handling + { + QKeyEvent *keyevt = static_cast(event); + int key = keyevt->key(); + Qt::KeyboardModifiers mod = keyevt->modifiers(); + switch(key) + { + case Qt::Key_Up: if(obj == ui->lineEdit) { browseHistory(-1); return true; } break; + case Qt::Key_Down: if(obj == ui->lineEdit) { browseHistory(1); return true; } break; + case Qt::Key_PageUp: /* pass paging keys to messages widget */ + case Qt::Key_PageDown: + if(obj == ui->lineEdit) + { + QApplication::postEvent(ui->messagesWidget, new QKeyEvent(*keyevt)); + return true; + } + break; + default: + // Typing in messages widget brings focus to line edit, and redirects key there + // Exclude most combinations and keys that emit no text, except paste shortcuts + if(obj == ui->messagesWidget && ( + (!mod && !keyevt->text().isEmpty() && key != Qt::Key_Tab) || + ((mod & Qt::ControlModifier) && key == Qt::Key_V) || + ((mod & Qt::ShiftModifier) && key == Qt::Key_Insert))) + { + ui->lineEdit->setFocus(); + QApplication::postEvent(ui->lineEdit, new QKeyEvent(*keyevt)); + return true; + } + } + } + return QDialog::eventFilter(obj, event); +} + +void RPCConsole::setClientModel(ClientModel *model) +{ + clientModel = model; + ui->trafficGraph->setClientModel(model); + if(model) + { + // Subscribe to information, replies, messages, errors + connect(model, SIGNAL(numConnectionsChanged(int)), this, SLOT(setNumConnections(int))); + connect(model, SIGNAL(numBlocksChanged(int,int)), this, SLOT(setNumBlocks(int,int))); + + updateTrafficStats(model->getTotalBytesRecv(), model->getTotalBytesSent()); + connect(model, SIGNAL(bytesChanged(quint64,quint64)), this, SLOT(updateTrafficStats(quint64, quint64))); + + // Provide initial values + ui->clientVersion->setText(model->formatFullVersion()); + ui->clientName->setText(model->clientName()); + ui->buildDate->setText(model->formatBuildDate()); + ui->startupTime->setText(model->formatClientStartupTime()); + + setNumConnections(model->getNumConnections()); + ui->isTestNet->setChecked(model->isTestNet()); + + setNumBlocks(model->getNumBlocks(), model->getNumBlocksOfPeers()); + } +} + +static QString categoryClass(int category) +{ + switch(category) + { + case RPCConsole::CMD_REQUEST: return "cmd-request"; break; + case RPCConsole::CMD_REPLY: return "cmd-reply"; break; + case RPCConsole::CMD_ERROR: return "cmd-error"; break; + default: return "misc"; + } +} + +void RPCConsole::clear() +{ + ui->messagesWidget->clear(); + ui->lineEdit->clear(); + ui->lineEdit->setFocus(); + + // Add smoothly scaled icon images. + // (when using width/height on an img, Qt uses nearest instead of linear interpolation) + for(int i=0; ICON_MAPPING[i].url; ++i) + { + ui->messagesWidget->document()->addResource( + QTextDocument::ImageResource, + QUrl(ICON_MAPPING[i].url), + QImage(ICON_MAPPING[i].source).scaled(ICON_SIZE, Qt::IgnoreAspectRatio, Qt::SmoothTransformation)); + } + + // Set default style sheet + ui->messagesWidget->document()->setDefaultStyleSheet( + "table { }" + "td.time { color: #808080; padding-top: 3px; } " + "td.message { font-family: Monospace; font-size: 12px; } " + "td.cmd-request { color: #006060; } " + "td.cmd-error { color: red; } " + "b { color: #006060; } " + ); + + message(CMD_REPLY, (tr("Welcome to the Arepacoin RPC console.") + "
" + + tr("Use up and down arrows to navigate history, and Ctrl-L to clear screen.") + "
" + + tr("Type help for an overview of available commands.")), true); +} + +void RPCConsole::message(int category, const QString &message, bool html) +{ + QTime time = QTime::currentTime(); + QString timeString = time.toString(); + QString out; + out += ""; + out += ""; + out += "
" + timeString + ""; + if(html) + out += message; + else + out += GUIUtil::HtmlEscape(message, true); + out += "
"; + ui->messagesWidget->append(out); +} + +void RPCConsole::setNumConnections(int count) +{ + ui->numberOfConnections->setText(QString::number(count)); +} + +void RPCConsole::setNumBlocks(int count, int countOfPeers) +{ + ui->numberOfBlocks->setText(QString::number(count)); + ui->totalBlocks->setText(QString::number(countOfPeers)); + if(clientModel) + { + // If there is no current number available display N/A instead of 0, which can't ever be true + ui->totalBlocks->setText(clientModel->getNumBlocksOfPeers() == 0 ? tr("N/A") : QString::number(clientModel->getNumBlocksOfPeers())); + ui->lastBlockTime->setText(clientModel->getLastBlockDate().toString()); + } +} + +void RPCConsole::on_lineEdit_returnPressed() +{ + QString cmd = ui->lineEdit->text(); + ui->lineEdit->clear(); + + if(!cmd.isEmpty()) + { + message(CMD_REQUEST, cmd); + emit cmdRequest(cmd); + // Remove command, if already in history + history.removeOne(cmd); + // Append command to history + history.append(cmd); + // Enforce maximum history size + while(history.size() > CONSOLE_HISTORY) + history.removeFirst(); + // Set pointer to end of history + historyPtr = history.size(); + // Scroll console view to end + scrollToEnd(); + } +} + +void RPCConsole::browseHistory(int offset) +{ + historyPtr += offset; + if(historyPtr < 0) + historyPtr = 0; + if(historyPtr > history.size()) + historyPtr = history.size(); + QString cmd; + if(historyPtr < history.size()) + cmd = history.at(historyPtr); + ui->lineEdit->setText(cmd); +} + +void RPCConsole::startExecutor() +{ + QThread* thread = new QThread; + RPCExecutor *executor = new RPCExecutor(); + executor->moveToThread(thread); + + // Notify executor when thread started (in executor thread) + connect(thread, SIGNAL(started()), executor, SLOT(start())); + // Replies from executor object must go to this object + connect(executor, SIGNAL(reply(int,QString)), this, SLOT(message(int,QString))); + // Requests from this object must go to executor + connect(this, SIGNAL(cmdRequest(QString)), executor, SLOT(request(QString))); + // On stopExecutor signal + // - queue executor for deletion (in execution thread) + // - quit the Qt event loop in the execution thread + connect(this, SIGNAL(stopExecutor()), executor, SLOT(deleteLater())); + connect(this, SIGNAL(stopExecutor()), thread, SLOT(quit())); + // Queue the thread for deletion (in this thread) when it is finished + connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater())); + + // Default implementation of QThread::run() simply spins up an event loop in the thread, + // which is what we want. + thread->start(); +} + +void RPCConsole::on_tabWidget_currentChanged(int index) +{ + if(ui->tabWidget->widget(index) == ui->tab_console) + { + ui->lineEdit->setFocus(); + } +} + +void RPCConsole::on_openDebugLogfileButton_clicked() +{ + GUIUtil::openDebugLogfile(); +} + +void RPCConsole::scrollToEnd() +{ + QScrollBar *scrollbar = ui->messagesWidget->verticalScrollBar(); + scrollbar->setValue(scrollbar->maximum()); +} + +void RPCConsole::on_showCLOptionsButton_clicked() +{ + GUIUtil::HelpMessageBox help; + help.exec(); +} + +void RPCConsole::on_sldGraphRange_valueChanged(int value) +{ + const int multiplier = 5; // each position on the slider represents 5 min + int mins = value * multiplier; + setTrafficGraphRange(mins); +} + +QString RPCConsole::FormatBytes(quint64 bytes) +{ + if(bytes < 1024) + return QString(tr("%1 B")).arg(bytes); + if(bytes < 1024 * 1024) + return QString(tr("%1 KB")).arg(bytes / 1024); + if(bytes < 1024 * 1024 * 1024) + return QString(tr("%1 MB")).arg(bytes / 1024 / 1024); + + return QString(tr("%1 GB")).arg(bytes / 1024 / 1024 / 1024); +} + +void RPCConsole::setTrafficGraphRange(int mins) +{ + ui->trafficGraph->setGraphRangeMins(mins); + if(mins < 60) { + ui->lblGraphRange->setText(QString(tr("%1 m")).arg(mins)); + } else { + int hours = mins / 60; + int minsLeft = mins % 60; + if(minsLeft == 0) { + ui->lblGraphRange->setText(QString(tr("%1 h")).arg(hours)); + } else { + ui->lblGraphRange->setText(QString(tr("%1 h %2 m")).arg(hours).arg(minsLeft)); + } + } +} + +void RPCConsole::updateTrafficStats(quint64 totalBytesIn, quint64 totalBytesOut) +{ + ui->lblBytesIn->setText(FormatBytes(totalBytesIn)); + ui->lblBytesOut->setText(FormatBytes(totalBytesOut)); +} + +void RPCConsole::on_btnClearTrafficGraph_clicked() +{ + ui->trafficGraph->clear(); +} \ No newline at end of file diff --git a/src/qt/rpcconsole.h b/src/qt/rpcconsole.h new file mode 100755 index 0000000..af92b55 --- /dev/null +++ b/src/qt/rpcconsole.h @@ -0,0 +1,75 @@ +#ifndef RPCCONSOLE_H +#define RPCCONSOLE_H + +#include + +namespace Ui { + class RPCConsole; +} +class ClientModel; + +/** Local Bitcoin RPC console. */ +class RPCConsole: public QDialog +{ + Q_OBJECT + +public: + explicit RPCConsole(QWidget *parent = 0); + ~RPCConsole(); + + void setClientModel(ClientModel *model); + + enum MessageClass { + MC_ERROR, + MC_DEBUG, + CMD_REQUEST, + CMD_REPLY, + CMD_ERROR + }; + +protected: + virtual bool eventFilter(QObject* obj, QEvent *event); + +private slots: + void on_lineEdit_returnPressed(); + void on_tabWidget_currentChanged(int index); + /** open the debug.log from the current datadir */ + void on_openDebugLogfileButton_clicked(); + /** display messagebox with program parameters (same as bitcoin-qt --help) */ + void on_showCLOptionsButton_clicked(); + /** change the time range of the network traffic graph */ + void on_sldGraphRange_valueChanged(int value); + /** update traffic statistics */ + void updateTrafficStats(quint64 totalBytesIn, quint64 totalBytesOut); + /** clear traffic graph */ + void on_btnClearTrafficGraph_clicked(); + +public slots: + void clear(); + void message(int category, const QString &message, bool html = false); + /** Set number of connections shown in the UI */ + void setNumConnections(int count); + /** Set number of blocks shown in the UI */ + void setNumBlocks(int count, int countOfPeers); + /** Go forward or back in history */ + void browseHistory(int offset); + /** Scroll console view to end */ + void scrollToEnd(); +signals: + // For RPC command executor + void stopExecutor(); + void cmdRequest(const QString &command); + +private: + static QString FormatBytes(quint64 bytes); + void setTrafficGraphRange(int mins); + + Ui::RPCConsole *ui; + ClientModel *clientModel; + QStringList history; + int historyPtr; + + void startExecutor(); +}; + +#endif // RPCCONSOLE_H diff --git a/src/qt/sendcoinsdialog.cpp b/src/qt/sendcoinsdialog.cpp new file mode 100755 index 0000000..292769c --- /dev/null +++ b/src/qt/sendcoinsdialog.cpp @@ -0,0 +1,520 @@ +#include "sendcoinsdialog.h" +#include "ui_sendcoinsdialog.h" + +#include "init.h" +#include "walletmodel.h" +#include "addresstablemodel.h" +#include "addressbookpage.h" + +#include "bitcoinunits.h" +#include "addressbookpage.h" +#include "optionsmodel.h" +#include "sendcoinsentry.h" +#include "guiutil.h" +#include "askpassphrasedialog.h" + +#include "coincontrol.h" +#include "coincontroldialog.h" + +#include +#include +#include +#include +#include + +SendCoinsDialog::SendCoinsDialog(QWidget *parent) : + QDialog(parent), + ui(new Ui::SendCoinsDialog), + model(0) +{ + ui->setupUi(this); + +#ifdef Q_OS_MAC // Icons on push buttons are very uncommon on Mac + ui->addButton->setIcon(QIcon()); + ui->clearButton->setIcon(QIcon()); + ui->sendButton->setIcon(QIcon()); +#endif + +#if QT_VERSION >= 0x040700 + /* Do not move this to the XML file, Qt before 4.7 will choke on it */ + ui->lineEditCoinControlChange->setPlaceholderText(tr("Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD)")); +#endif + + addEntry(); + + connect(ui->addButton, SIGNAL(clicked()), this, SLOT(addEntry())); + connect(ui->clearButton, SIGNAL(clicked()), this, SLOT(clear())); + + // Coin Control + ui->lineEditCoinControlChange->setFont(GUIUtil::bitcoinAddressFont()); + connect(ui->pushButtonCoinControl, SIGNAL(clicked()), this, SLOT(coinControlButtonClicked())); + connect(ui->checkBoxCoinControlChange, SIGNAL(stateChanged(int)), this, SLOT(coinControlChangeChecked(int))); + connect(ui->lineEditCoinControlChange, SIGNAL(textEdited(const QString &)), this, SLOT(coinControlChangeEdited(const QString &))); + + // Coin Control: clipboard actions + QAction *clipboardQuantityAction = new QAction(tr("Copy quantity"), this); + QAction *clipboardAmountAction = new QAction(tr("Copy amount"), this); + QAction *clipboardFeeAction = new QAction(tr("Copy fee"), this); + QAction *clipboardAfterFeeAction = new QAction(tr("Copy after fee"), this); + QAction *clipboardBytesAction = new QAction(tr("Copy bytes"), this); + QAction *clipboardPriorityAction = new QAction(tr("Copy priority"), this); + QAction *clipboardLowOutputAction = new QAction(tr("Copy low output"), this); + QAction *clipboardChangeAction = new QAction(tr("Copy change"), this); + connect(clipboardQuantityAction, SIGNAL(triggered()), this, SLOT(coinControlClipboardQuantity())); + connect(clipboardAmountAction, SIGNAL(triggered()), this, SLOT(coinControlClipboardAmount())); + connect(clipboardFeeAction, SIGNAL(triggered()), this, SLOT(coinControlClipboardFee())); + connect(clipboardAfterFeeAction, SIGNAL(triggered()), this, SLOT(coinControlClipboardAfterFee())); + connect(clipboardBytesAction, SIGNAL(triggered()), this, SLOT(coinControlClipboardBytes())); + connect(clipboardPriorityAction, SIGNAL(triggered()), this, SLOT(coinControlClipboardPriority())); + connect(clipboardLowOutputAction, SIGNAL(triggered()), this, SLOT(coinControlClipboardLowOutput())); + connect(clipboardChangeAction, SIGNAL(triggered()), this, SLOT(coinControlClipboardChange())); + ui->labelCoinControlQuantity->addAction(clipboardQuantityAction); + ui->labelCoinControlAmount->addAction(clipboardAmountAction); + ui->labelCoinControlFee->addAction(clipboardFeeAction); + ui->labelCoinControlAfterFee->addAction(clipboardAfterFeeAction); + ui->labelCoinControlBytes->addAction(clipboardBytesAction); + ui->labelCoinControlPriority->addAction(clipboardPriorityAction); + ui->labelCoinControlLowOutput->addAction(clipboardLowOutputAction); + ui->labelCoinControlChange->addAction(clipboardChangeAction); + + fNewRecipientAllowed = true; +} + +void SendCoinsDialog::setModel(WalletModel *model) +{ + this->model = model; + + for(int i = 0; i < ui->entries->count(); ++i) + { + SendCoinsEntry *entry = qobject_cast(ui->entries->itemAt(i)->widget()); + if(entry) + { + entry->setModel(model); + } + } + if(model && model->getOptionsModel()) + { + setBalance(model->getBalance(), model->getStake(), model->getUnconfirmedBalance(), model->getImmatureBalance()); + connect(model, SIGNAL(balanceChanged(qint64, qint64, qint64, qint64)), this, SLOT(setBalance(qint64, qint64, qint64, qint64))); + connect(model->getOptionsModel(), SIGNAL(displayUnitChanged(int)), this, SLOT(updateDisplayUnit())); + + // Coin Control + connect(model->getOptionsModel(), SIGNAL(displayUnitChanged(int)), this, SLOT(coinControlUpdateLabels())); + connect(model->getOptionsModel(), SIGNAL(coinControlFeaturesChanged(bool)), this, SLOT(coinControlFeatureChanged(bool))); + connect(model->getOptionsModel(), SIGNAL(transactionFeeChanged(qint64)), this, SLOT(coinControlUpdateLabels())); + ui->frameCoinControl->setVisible(model->getOptionsModel()->getCoinControlFeatures()); + coinControlUpdateLabels(); + } +} + +SendCoinsDialog::~SendCoinsDialog() +{ + delete ui; +} + +void SendCoinsDialog::on_sendButton_clicked() +{ + QList recipients; + bool valid = true; + + if(!model) + return; + + for(int i = 0; i < ui->entries->count(); ++i) + { + SendCoinsEntry *entry = qobject_cast(ui->entries->itemAt(i)->widget()); + if(entry) + { + if(entry->validate()) + { + recipients.append(entry->getValue()); + } + else + { + valid = false; + } + } + } + + if(!valid || recipients.isEmpty()) + { + return; + } + + // Format confirmation message + QStringList formatted; + foreach(const SendCoinsRecipient &rcp, recipients) + { + formatted.append(tr("%1 to %2 (%3)").arg(BitcoinUnits::formatWithUnit(BitcoinUnits::BTC, rcp.amount), Qt::escape(rcp.label), rcp.address)); + } + + fNewRecipientAllowed = false; + + QMessageBox::StandardButton retval = QMessageBox::question(this, tr("Confirm send coins"), + tr("Are you sure you want to send %1?").arg(formatted.join(tr(" and "))), + QMessageBox::Yes|QMessageBox::Cancel, + QMessageBox::Cancel); + + if(retval != QMessageBox::Yes) + { + fNewRecipientAllowed = true; + return; + } + + WalletModel::UnlockContext ctx(model->requestUnlock()); + if(!ctx.isValid()) + { + // Unlock wallet was cancelled + fNewRecipientAllowed = true; + return; + } + + WalletModel::SendCoinsReturn sendstatus; + + if (!model->getOptionsModel() || !model->getOptionsModel()->getCoinControlFeatures()) + sendstatus = model->sendCoins(recipients); + else + sendstatus = model->sendCoins(recipients, CoinControlDialog::coinControl); + + switch(sendstatus.status) + { + case WalletModel::InvalidAddress: + QMessageBox::warning(this, tr("Send Coins"), + tr("The recipient address is not valid, please recheck."), + QMessageBox::Ok, QMessageBox::Ok); + break; + case WalletModel::InvalidAmount: + QMessageBox::warning(this, tr("Send Coins"), + tr("The amount to pay must be larger than 0."), + QMessageBox::Ok, QMessageBox::Ok); + break; + case WalletModel::AmountExceedsBalance: + QMessageBox::warning(this, tr("Send Coins"), + tr("The amount exceeds your balance."), + QMessageBox::Ok, QMessageBox::Ok); + break; + case WalletModel::AmountWithFeeExceedsBalance: + QMessageBox::warning(this, tr("Send Coins"), + tr("The total exceeds your balance when the %1 transaction fee is included."). + arg(BitcoinUnits::formatWithUnit(BitcoinUnits::BTC, sendstatus.fee)), + QMessageBox::Ok, QMessageBox::Ok); + break; + case WalletModel::DuplicateAddress: + QMessageBox::warning(this, tr("Send Coins"), + tr("Duplicate address found, can only send to each address once per send operation."), + QMessageBox::Ok, QMessageBox::Ok); + break; + case WalletModel::TransactionCreationFailed: + QMessageBox::warning(this, tr("Send Coins"), + tr("Error: Transaction creation failed."), + QMessageBox::Ok, QMessageBox::Ok); + break; + case WalletModel::TransactionCommitFailed: + QMessageBox::warning(this, tr("Send Coins"), + tr("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."), + QMessageBox::Ok, QMessageBox::Ok); + break; + case WalletModel::Aborted: // User aborted, nothing to do + break; + case WalletModel::OK: + accept(); + CoinControlDialog::coinControl->UnSelectAll(); + coinControlUpdateLabels(); + break; + } + fNewRecipientAllowed = true; +} + +void SendCoinsDialog::clear() +{ + // Remove entries until only one left + while(ui->entries->count()) + { + delete ui->entries->takeAt(0)->widget(); + } + addEntry(); + + updateRemoveEnabled(); + + ui->sendButton->setDefault(true); +} + +void SendCoinsDialog::reject() +{ + clear(); +} + +void SendCoinsDialog::accept() +{ + clear(); +} + +SendCoinsEntry *SendCoinsDialog::addEntry() +{ + SendCoinsEntry *entry = new SendCoinsEntry(this); + entry->setModel(model); + ui->entries->addWidget(entry); + connect(entry, SIGNAL(removeEntry(SendCoinsEntry*)), this, SLOT(removeEntry(SendCoinsEntry*))); + connect(entry, SIGNAL(payAmountChanged()), this, SLOT(coinControlUpdateLabels())); + + updateRemoveEnabled(); + + // Focus the field, so that entry can start immediately + entry->clear(); + entry->setFocus(); + ui->scrollAreaWidgetContents->resize(ui->scrollAreaWidgetContents->sizeHint()); + QCoreApplication::instance()->processEvents(); + QScrollBar* bar = ui->scrollArea->verticalScrollBar(); + if(bar) + bar->setSliderPosition(bar->maximum()); + return entry; +} + +void SendCoinsDialog::updateRemoveEnabled() +{ + // Remove buttons are enabled as soon as there is more than one send-entry + bool enabled = (ui->entries->count() > 1); + for(int i = 0; i < ui->entries->count(); ++i) + { + SendCoinsEntry *entry = qobject_cast(ui->entries->itemAt(i)->widget()); + if(entry) + { + entry->setRemoveEnabled(enabled); + } + } + setupTabChain(0); + coinControlUpdateLabels(); +} + +void SendCoinsDialog::removeEntry(SendCoinsEntry* entry) +{ + delete entry; + updateRemoveEnabled(); +} + +QWidget *SendCoinsDialog::setupTabChain(QWidget *prev) +{ + for(int i = 0; i < ui->entries->count(); ++i) + { + SendCoinsEntry *entry = qobject_cast(ui->entries->itemAt(i)->widget()); + if(entry) + { + prev = entry->setupTabChain(prev); + } + } + QWidget::setTabOrder(prev, ui->addButton); + QWidget::setTabOrder(ui->addButton, ui->sendButton); + return ui->sendButton; +} + +void SendCoinsDialog::pasteEntry(const SendCoinsRecipient &rv) +{ + if(!fNewRecipientAllowed) + return; + + SendCoinsEntry *entry = 0; + // Replace the first entry if it is still unused + if(ui->entries->count() == 1) + { + SendCoinsEntry *first = qobject_cast(ui->entries->itemAt(0)->widget()); + if(first->isClear()) + { + entry = first; + } + } + if(!entry) + { + entry = addEntry(); + } + + entry->setValue(rv); +} + +bool SendCoinsDialog::handleURI(const QString &uri) +{ + SendCoinsRecipient rv; + // URI has to be valid + if (GUIUtil::parseBitcoinURI(uri, &rv)) + { + CBitcoinAddress address(rv.address.toStdString()); + if (!address.IsValid()) + return false; + pasteEntry(rv); + return true; + } + + return false; +} + +void SendCoinsDialog::setBalance(qint64 balance, qint64 stake, qint64 unconfirmedBalance, qint64 immatureBalance) +{ + Q_UNUSED(stake); + Q_UNUSED(unconfirmedBalance); + Q_UNUSED(immatureBalance); + if(!model || !model->getOptionsModel()) + return; + + int unit = model->getOptionsModel()->getDisplayUnit(); + ui->labelBalance->setText(BitcoinUnits::formatWithUnit(unit, balance)); +} + +void SendCoinsDialog::updateDisplayUnit() +{ + if(model && model->getOptionsModel()) + { + // Update labelBalance with the current balance and the current unit + ui->labelBalance->setText(BitcoinUnits::formatWithUnit(model->getOptionsModel()->getDisplayUnit(), model->getBalance())); + } +} + +// Coin Control: copy label "Quantity" to clipboard +void SendCoinsDialog::coinControlClipboardQuantity() +{ + QApplication::clipboard()->setText(ui->labelCoinControlQuantity->text()); +} + +// Coin Control: copy label "Amount" to clipboard +void SendCoinsDialog::coinControlClipboardAmount() +{ + QApplication::clipboard()->setText(ui->labelCoinControlAmount->text().left(ui->labelCoinControlAmount->text().indexOf(" "))); +} + +// Coin Control: copy label "Fee" to clipboard +void SendCoinsDialog::coinControlClipboardFee() +{ + QApplication::clipboard()->setText(ui->labelCoinControlFee->text().left(ui->labelCoinControlFee->text().indexOf(" "))); +} + +// Coin Control: copy label "After fee" to clipboard +void SendCoinsDialog::coinControlClipboardAfterFee() +{ + QApplication::clipboard()->setText(ui->labelCoinControlAfterFee->text().left(ui->labelCoinControlAfterFee->text().indexOf(" "))); +} + +// Coin Control: copy label "Bytes" to clipboard +void SendCoinsDialog::coinControlClipboardBytes() +{ + QApplication::clipboard()->setText(ui->labelCoinControlBytes->text()); +} + +// Coin Control: copy label "Priority" to clipboard +void SendCoinsDialog::coinControlClipboardPriority() +{ + QApplication::clipboard()->setText(ui->labelCoinControlPriority->text()); +} + +// Coin Control: copy label "Low output" to clipboard +void SendCoinsDialog::coinControlClipboardLowOutput() +{ + QApplication::clipboard()->setText(ui->labelCoinControlLowOutput->text()); +} + +// Coin Control: copy label "Change" to clipboard +void SendCoinsDialog::coinControlClipboardChange() +{ + QApplication::clipboard()->setText(ui->labelCoinControlChange->text().left(ui->labelCoinControlChange->text().indexOf(" "))); +} + +// Coin Control: settings menu - coin control enabled/disabled by user +void SendCoinsDialog::coinControlFeatureChanged(bool checked) +{ + ui->frameCoinControl->setVisible(checked); + + if (!checked && model) // coin control features disabled + CoinControlDialog::coinControl->SetNull(); +} + +// Coin Control: button inputs -> show actual coin control dialog +void SendCoinsDialog::coinControlButtonClicked() +{ + CoinControlDialog dlg; + dlg.setModel(model); + dlg.exec(); + coinControlUpdateLabels(); +} + +// Coin Control: checkbox custom change address +void SendCoinsDialog::coinControlChangeChecked(int state) +{ + if (model) + { + if (state == Qt::Checked) + CoinControlDialog::coinControl->destChange = CBitcoinAddress(ui->lineEditCoinControlChange->text().toStdString()).Get(); + else + CoinControlDialog::coinControl->destChange = CNoDestination(); + } + + ui->lineEditCoinControlChange->setEnabled((state == Qt::Checked)); + ui->labelCoinControlChangeLabel->setEnabled((state == Qt::Checked)); +} + +// Coin Control: custom change address changed +void SendCoinsDialog::coinControlChangeEdited(const QString & text) +{ + if (model) + { + CoinControlDialog::coinControl->destChange = CBitcoinAddress(text.toStdString()).Get(); + + // label for the change address + ui->labelCoinControlChangeLabel->setStyleSheet("QLabel{color:black;}"); + if (text.isEmpty()) + ui->labelCoinControlChangeLabel->setText(""); + else if (!CBitcoinAddress(text.toStdString()).IsValid()) + { + ui->labelCoinControlChangeLabel->setStyleSheet("QLabel{color:red;}"); + ui->labelCoinControlChangeLabel->setText(tr("WARNING: Invalid Arepacoin address")); + } + else + { + QString associatedLabel = model->getAddressTableModel()->labelForAddress(text); + if (!associatedLabel.isEmpty()) + ui->labelCoinControlChangeLabel->setText(associatedLabel); + else + { + CPubKey pubkey; + CKeyID keyid; + CBitcoinAddress(text.toStdString()).GetKeyID(keyid); + if (model->getPubKey(keyid, pubkey)) + ui->labelCoinControlChangeLabel->setText(tr("(no label)")); + else + { + ui->labelCoinControlChangeLabel->setStyleSheet("QLabel{color:red;}"); + ui->labelCoinControlChangeLabel->setText(tr("WARNING: unknown change address")); + } + } + } + } +} + +// Coin Control: update labels +void SendCoinsDialog::coinControlUpdateLabels() +{ + if (!model || !model->getOptionsModel() || !model->getOptionsModel()->getCoinControlFeatures()) + return; + + // set pay amounts + CoinControlDialog::payAmounts.clear(); + for(int i = 0; i < ui->entries->count(); ++i) + { + SendCoinsEntry *entry = qobject_cast(ui->entries->itemAt(i)->widget()); + if(entry) + CoinControlDialog::payAmounts.append(entry->getValue().amount); + } + + if (CoinControlDialog::coinControl->HasSelected()) + { + // actual coin control calculation + CoinControlDialog::updateLabels(model, this); + + // show coin control stats + ui->labelCoinControlAutomaticallySelected->hide(); + ui->widgetCoinControl->show(); + } + else + { + // hide coin control stats + ui->labelCoinControlAutomaticallySelected->show(); + ui->widgetCoinControl->hide(); + ui->labelCoinControlInsuffFunds->hide(); + } +} diff --git a/src/qt/sendcoinsdialog.h b/src/qt/sendcoinsdialog.h new file mode 100755 index 0000000..68424bb --- /dev/null +++ b/src/qt/sendcoinsdialog.h @@ -0,0 +1,68 @@ +#ifndef SENDCOINSDIALOG_H +#define SENDCOINSDIALOG_H + +#include +#include + +namespace Ui { + class SendCoinsDialog; +} +class WalletModel; +class SendCoinsEntry; +class SendCoinsRecipient; + +QT_BEGIN_NAMESPACE +class QUrl; +QT_END_NAMESPACE + +/** Dialog for sending bitcoins */ +class SendCoinsDialog : public QDialog +{ + Q_OBJECT + +public: + explicit SendCoinsDialog(QWidget *parent = 0); + ~SendCoinsDialog(); + + void setModel(WalletModel *model); + + /** Set up the tab chain manually, as Qt messes up the tab chain by default in some cases (issue https://bugreports.qt-project.org/browse/QTBUG-10907). + */ + QWidget *setupTabChain(QWidget *prev); + + void pasteEntry(const SendCoinsRecipient &rv); + bool handleURI(const QString &uri); + +public slots: + void clear(); + void reject(); + void accept(); + SendCoinsEntry *addEntry(); + void updateRemoveEnabled(); + void setBalance(qint64 balance, qint64 stake, qint64 unconfirmedBalance, qint64 immatureBalance); + +private: + Ui::SendCoinsDialog *ui; + WalletModel *model; + bool fNewRecipientAllowed; + +private slots: + void on_sendButton_clicked(); + void removeEntry(SendCoinsEntry* entry); + void updateDisplayUnit(); + void coinControlFeatureChanged(bool); + void coinControlButtonClicked(); + void coinControlChangeChecked(int); + void coinControlChangeEdited(const QString &); + void coinControlUpdateLabels(); + void coinControlClipboardQuantity(); + void coinControlClipboardAmount(); + void coinControlClipboardFee(); + void coinControlClipboardAfterFee(); + void coinControlClipboardBytes(); + void coinControlClipboardPriority(); + void coinControlClipboardLowOutput(); + void coinControlClipboardChange(); +}; + +#endif // SENDCOINSDIALOG_H diff --git a/src/qt/sendcoinsentry.cpp b/src/qt/sendcoinsentry.cpp new file mode 100755 index 0000000..bc556b9 --- /dev/null +++ b/src/qt/sendcoinsentry.cpp @@ -0,0 +1,174 @@ +#include "sendcoinsentry.h" +#include "ui_sendcoinsentry.h" +#include "guiutil.h" +#include "bitcoinunits.h" +#include "addressbookpage.h" +#include "walletmodel.h" +#include "optionsmodel.h" +#include "addresstablemodel.h" + +#include +#include + +SendCoinsEntry::SendCoinsEntry(QWidget *parent) : + QFrame(parent), + ui(new Ui::SendCoinsEntry), + model(0) +{ + ui->setupUi(this); + +#ifdef Q_OS_MAC + ui->payToLayout->setSpacing(4); +#endif +#if QT_VERSION >= 0x040700 + /* Do not move this to the XML file, Qt before 4.7 will choke on it */ + ui->addAsLabel->setPlaceholderText(tr("Enter a label for this address to add it to your address book")); + ui->payTo->setPlaceholderText(tr("Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD)")); +#endif + setFocusPolicy(Qt::TabFocus); + setFocusProxy(ui->payTo); + + GUIUtil::setupAddressWidget(ui->payTo, this); +} + +SendCoinsEntry::~SendCoinsEntry() +{ + delete ui; +} + +void SendCoinsEntry::on_pasteButton_clicked() +{ + // Paste text from clipboard into recipient field + ui->payTo->setText(QApplication::clipboard()->text()); +} + +void SendCoinsEntry::on_addressBookButton_clicked() +{ + if(!model) + return; + AddressBookPage dlg(AddressBookPage::ForSending, AddressBookPage::SendingTab, this); + dlg.setModel(model->getAddressTableModel()); + if(dlg.exec()) + { + ui->payTo->setText(dlg.getReturnValue()); + ui->payAmount->setFocus(); + } +} + +void SendCoinsEntry::on_payTo_textChanged(const QString &address) +{ + if(!model) + return; + // Fill in label from address book, if address has an associated label + QString associatedLabel = model->getAddressTableModel()->labelForAddress(address); + if(!associatedLabel.isEmpty()) + ui->addAsLabel->setText(associatedLabel); +} + +void SendCoinsEntry::setModel(WalletModel *model) +{ + this->model = model; + + if(model && model->getOptionsModel()) + connect(model->getOptionsModel(), SIGNAL(displayUnitChanged(int)), this, SLOT(updateDisplayUnit())); + + connect(ui->payAmount, SIGNAL(textChanged()), this, SIGNAL(payAmountChanged())); + + clear(); +} + +void SendCoinsEntry::setRemoveEnabled(bool enabled) +{ + ui->deleteButton->setEnabled(enabled); +} + +void SendCoinsEntry::clear() +{ + ui->payTo->clear(); + ui->addAsLabel->clear(); + ui->payAmount->clear(); + ui->payTo->setFocus(); + // update the display unit, to not use the default ("BTC") + updateDisplayUnit(); +} + +void SendCoinsEntry::on_deleteButton_clicked() +{ + emit removeEntry(this); +} + +bool SendCoinsEntry::validate() +{ + // Check input validity + bool retval = true; + + if(!ui->payAmount->validate()) + { + retval = false; + } + else + { + if(ui->payAmount->value() <= 0) + { + // Cannot send 0 coins or less + ui->payAmount->setValid(false); + retval = false; + } + } + + if(!ui->payTo->hasAcceptableInput() || + (model && !model->validateAddress(ui->payTo->text()))) + { + ui->payTo->setValid(false); + retval = false; + } + + return retval; +} + +SendCoinsRecipient SendCoinsEntry::getValue() +{ + SendCoinsRecipient rv; + + rv.address = ui->payTo->text(); + rv.label = ui->addAsLabel->text(); + rv.amount = ui->payAmount->value(); + + return rv; +} + +QWidget *SendCoinsEntry::setupTabChain(QWidget *prev) +{ + QWidget::setTabOrder(prev, ui->payTo); + QWidget::setTabOrder(ui->payTo, ui->addressBookButton); + QWidget::setTabOrder(ui->addressBookButton, ui->pasteButton); + QWidget::setTabOrder(ui->pasteButton, ui->deleteButton); + QWidget::setTabOrder(ui->deleteButton, ui->addAsLabel); + return ui->payAmount->setupTabChain(ui->addAsLabel); +} + +void SendCoinsEntry::setValue(const SendCoinsRecipient &value) +{ + ui->payTo->setText(value.address); + ui->addAsLabel->setText(value.label); + ui->payAmount->setValue(value.amount); +} + +bool SendCoinsEntry::isClear() +{ + return ui->payTo->text().isEmpty(); +} + +void SendCoinsEntry::setFocus() +{ + ui->payTo->setFocus(); +} + +void SendCoinsEntry::updateDisplayUnit() +{ + if(model && model->getOptionsModel()) + { + // Update payAmount with the current unit + ui->payAmount->setDisplayUnit(model->getOptionsModel()->getDisplayUnit()); + } +} diff --git a/src/qt/sendcoinsentry.h b/src/qt/sendcoinsentry.h new file mode 100755 index 0000000..3271e0d --- /dev/null +++ b/src/qt/sendcoinsentry.h @@ -0,0 +1,56 @@ +#ifndef SENDCOINSENTRY_H +#define SENDCOINSENTRY_H + +#include + +namespace Ui { + class SendCoinsEntry; +} +class WalletModel; +class SendCoinsRecipient; + +/** A single entry in the dialog for sending bitcoins. */ +class SendCoinsEntry : public QFrame +{ + Q_OBJECT + +public: + explicit SendCoinsEntry(QWidget *parent = 0); + ~SendCoinsEntry(); + + void setModel(WalletModel *model); + bool validate(); + SendCoinsRecipient getValue(); + + /** Return whether the entry is still empty and unedited */ + bool isClear(); + + void setValue(const SendCoinsRecipient &value); + + /** Set up the tab chain manually, as Qt messes up the tab chain by default in some cases (issue https://bugreports.qt-project.org/browse/QTBUG-10907). + */ + QWidget *setupTabChain(QWidget *prev); + + void setFocus(); + +public slots: + void setRemoveEnabled(bool enabled); + void clear(); + +signals: + void removeEntry(SendCoinsEntry *entry); + void payAmountChanged(); + +private slots: + void on_deleteButton_clicked(); + void on_payTo_textChanged(const QString &address); + void on_addressBookButton_clicked(); + void on_pasteButton_clicked(); + void updateDisplayUnit(); + +private: + Ui::SendCoinsEntry *ui; + WalletModel *model; +}; + +#endif // SENDCOINSENTRY_H diff --git a/src/qt/signverifymessagedialog.cpp b/src/qt/signverifymessagedialog.cpp new file mode 100755 index 0000000..a9f33da --- /dev/null +++ b/src/qt/signverifymessagedialog.cpp @@ -0,0 +1,274 @@ +#include "signverifymessagedialog.h" +#include "ui_signverifymessagedialog.h" + +#include "addressbookpage.h" +#include "base58.h" +#include "guiutil.h" +#include "init.h" +#include "main.h" +#include "optionsmodel.h" +#include "walletmodel.h" +#include "wallet.h" + +#include +#include + +#include + +SignVerifyMessageDialog::SignVerifyMessageDialog(QWidget *parent) : + QDialog(parent), + ui(new Ui::SignVerifyMessageDialog), + model(0) +{ + ui->setupUi(this); + +#if (QT_VERSION >= 0x040700) + /* Do not move this to the XML file, Qt before 4.7 will choke on it */ + ui->addressIn_SM->setPlaceholderText(tr("Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD)")); + ui->signatureOut_SM->setPlaceholderText(tr("Click \"Sign Message\" to generate signature")); + + ui->addressIn_VM->setPlaceholderText(tr("Enter a Arepacoin address (e.g. AHgvRTKezeHmUtVS1hjW65X7JQGjrThDbD)")); + ui->signatureIn_VM->setPlaceholderText(tr("Enter Arepacoin signature")); +#endif + + GUIUtil::setupAddressWidget(ui->addressIn_SM, this); + GUIUtil::setupAddressWidget(ui->addressIn_VM, this); + + ui->addressIn_SM->installEventFilter(this); + ui->messageIn_SM->installEventFilter(this); + ui->signatureOut_SM->installEventFilter(this); + ui->addressIn_VM->installEventFilter(this); + ui->messageIn_VM->installEventFilter(this); + ui->signatureIn_VM->installEventFilter(this); + + ui->signatureOut_SM->setFont(GUIUtil::bitcoinAddressFont()); + ui->signatureIn_VM->setFont(GUIUtil::bitcoinAddressFont()); +} + +SignVerifyMessageDialog::~SignVerifyMessageDialog() +{ + delete ui; +} + +void SignVerifyMessageDialog::setModel(WalletModel *model) +{ + this->model = model; +} + +void SignVerifyMessageDialog::setAddress_SM(QString address) +{ + ui->addressIn_SM->setText(address); + ui->messageIn_SM->setFocus(); +} + +void SignVerifyMessageDialog::setAddress_VM(QString address) +{ + ui->addressIn_VM->setText(address); + ui->messageIn_VM->setFocus(); +} + +void SignVerifyMessageDialog::showTab_SM(bool fShow) +{ + ui->tabWidget->setCurrentIndex(0); + + if (fShow) + this->show(); +} + +void SignVerifyMessageDialog::showTab_VM(bool fShow) +{ + ui->tabWidget->setCurrentIndex(1); + if (fShow) + this->show(); +} + +void SignVerifyMessageDialog::on_addressBookButton_SM_clicked() +{ + if (model && model->getAddressTableModel()) + { + AddressBookPage dlg(AddressBookPage::ForSending, AddressBookPage::ReceivingTab, this); + dlg.setModel(model->getAddressTableModel()); + if (dlg.exec()) + { + setAddress_SM(dlg.getReturnValue()); + } + } +} + +void SignVerifyMessageDialog::on_pasteButton_SM_clicked() +{ + setAddress_SM(QApplication::clipboard()->text()); +} + +void SignVerifyMessageDialog::on_signMessageButton_SM_clicked() +{ + /* Clear old signature to ensure users don't get confused on error with an old signature displayed */ + ui->signatureOut_SM->clear(); + + CBitcoinAddress addr(ui->addressIn_SM->text().toStdString()); + if (!addr.IsValid()) + { + ui->addressIn_SM->setValid(false); + ui->statusLabel_SM->setStyleSheet("QLabel { color: red; }"); + ui->statusLabel_SM->setText(tr("The entered address is invalid.") + QString(" ") + tr("Please check the address and try again.")); + return; + } + CKeyID keyID; + if (!addr.GetKeyID(keyID)) + { + ui->addressIn_SM->setValid(false); + ui->statusLabel_SM->setStyleSheet("QLabel { color: red; }"); + ui->statusLabel_SM->setText(tr("The entered address does not refer to a key.") + QString(" ") + tr("Please check the address and try again.")); + return; + } + + WalletModel::UnlockContext ctx(model->requestUnlock()); + if (!ctx.isValid()) + { + ui->statusLabel_SM->setStyleSheet("QLabel { color: red; }"); + ui->statusLabel_SM->setText(tr("Wallet unlock was cancelled.")); + return; + } + + CKey key; + if (!pwalletMain->GetKey(keyID, key)) + { + ui->statusLabel_SM->setStyleSheet("QLabel { color: red; }"); + ui->statusLabel_SM->setText(tr("Private key for the entered address is not available.")); + return; + } + + CDataStream ss(SER_GETHASH, 0); + ss << strMessageMagic; + ss << ui->messageIn_SM->document()->toPlainText().toStdString(); + + std::vector vchSig; + if (!key.SignCompact(Hash(ss.begin(), ss.end()), vchSig)) + { + ui->statusLabel_SM->setStyleSheet("QLabel { color: red; }"); + ui->statusLabel_SM->setText(QString("") + tr("Message signing failed.") + QString("")); + return; + } + + ui->statusLabel_SM->setStyleSheet("QLabel { color: green; }"); + ui->statusLabel_SM->setText(QString("") + tr("Message signed.") + QString("")); + + ui->signatureOut_SM->setText(QString::fromStdString(EncodeBase64(&vchSig[0], vchSig.size()))); +} + +void SignVerifyMessageDialog::on_copySignatureButton_SM_clicked() +{ + QApplication::clipboard()->setText(ui->signatureOut_SM->text()); +} + +void SignVerifyMessageDialog::on_clearButton_SM_clicked() +{ + ui->addressIn_SM->clear(); + ui->messageIn_SM->clear(); + ui->signatureOut_SM->clear(); + ui->statusLabel_SM->clear(); + + ui->addressIn_SM->setFocus(); +} + +void SignVerifyMessageDialog::on_addressBookButton_VM_clicked() +{ + if (model && model->getAddressTableModel()) + { + AddressBookPage dlg(AddressBookPage::ForSending, AddressBookPage::SendingTab, this); + dlg.setModel(model->getAddressTableModel()); + if (dlg.exec()) + { + setAddress_VM(dlg.getReturnValue()); + } + } +} + +void SignVerifyMessageDialog::on_verifyMessageButton_VM_clicked() +{ + CBitcoinAddress addr(ui->addressIn_VM->text().toStdString()); + if (!addr.IsValid()) + { + ui->addressIn_VM->setValid(false); + ui->statusLabel_VM->setStyleSheet("QLabel { color: red; }"); + ui->statusLabel_VM->setText(tr("The entered address is invalid.") + QString(" ") + tr("Please check the address and try again.")); + return; + } + CKeyID keyID; + if (!addr.GetKeyID(keyID)) + { + ui->addressIn_VM->setValid(false); + ui->statusLabel_VM->setStyleSheet("QLabel { color: red; }"); + ui->statusLabel_VM->setText(tr("The entered address does not refer to a key.") + QString(" ") + tr("Please check the address and try again.")); + return; + } + + bool fInvalid = false; + std::vector vchSig = DecodeBase64(ui->signatureIn_VM->text().toStdString().c_str(), &fInvalid); + + if (fInvalid) + { + ui->signatureIn_VM->setValid(false); + ui->statusLabel_VM->setStyleSheet("QLabel { color: red; }"); + ui->statusLabel_VM->setText(tr("The signature could not be decoded.") + QString(" ") + tr("Please check the signature and try again.")); + return; + } + + CDataStream ss(SER_GETHASH, 0); + ss << strMessageMagic; + ss << ui->messageIn_VM->document()->toPlainText().toStdString(); + + CKey key; + if (!key.SetCompactSignature(Hash(ss.begin(), ss.end()), vchSig)) + { + ui->signatureIn_VM->setValid(false); + ui->statusLabel_VM->setStyleSheet("QLabel { color: red; }"); + ui->statusLabel_VM->setText(tr("The signature did not match the message digest.") + QString(" ") + tr("Please check the signature and try again.")); + return; + } + + if (!(CBitcoinAddress(key.GetPubKey().GetID()) == addr)) + { + ui->statusLabel_VM->setStyleSheet("QLabel { color: red; }"); + ui->statusLabel_VM->setText(QString("") + tr("Message verification failed.") + QString("")); + return; + } + + ui->statusLabel_VM->setStyleSheet("QLabel { color: green; }"); + ui->statusLabel_VM->setText(QString("") + tr("Message verified.") + QString("")); +} + +void SignVerifyMessageDialog::on_clearButton_VM_clicked() +{ + ui->addressIn_VM->clear(); + ui->signatureIn_VM->clear(); + ui->messageIn_VM->clear(); + ui->statusLabel_VM->clear(); + + ui->addressIn_VM->setFocus(); +} + +bool SignVerifyMessageDialog::eventFilter(QObject *object, QEvent *event) +{ + if (event->type() == QEvent::MouseButtonPress || event->type() == QEvent::FocusIn) + { + if (ui->tabWidget->currentIndex() == 0) + { + /* Clear status message on focus change */ + ui->statusLabel_SM->clear(); + + /* Select generated signature */ + if (object == ui->signatureOut_SM) + { + ui->signatureOut_SM->selectAll(); + return true; + } + } + else if (ui->tabWidget->currentIndex() == 1) + { + /* Clear status message on focus change */ + ui->statusLabel_VM->clear(); + } + } + return QDialog::eventFilter(object, event); +} diff --git a/src/qt/signverifymessagedialog.h b/src/qt/signverifymessagedialog.h new file mode 100755 index 0000000..5569c8b --- /dev/null +++ b/src/qt/signverifymessagedialog.h @@ -0,0 +1,49 @@ +#ifndef SIGNVERIFYMESSAGEDIALOG_H +#define SIGNVERIFYMESSAGEDIALOG_H + +#include + +namespace Ui { + class SignVerifyMessageDialog; +} +class WalletModel; + +QT_BEGIN_NAMESPACE +QT_END_NAMESPACE + +class SignVerifyMessageDialog : public QDialog +{ + Q_OBJECT + +public: + explicit SignVerifyMessageDialog(QWidget *parent = 0); + ~SignVerifyMessageDialog(); + + void setModel(WalletModel *model); + void setAddress_SM(QString address); + void setAddress_VM(QString address); + + void showTab_SM(bool fShow); + void showTab_VM(bool fShow); + +protected: + bool eventFilter(QObject *object, QEvent *event); + +private: + Ui::SignVerifyMessageDialog *ui; + WalletModel *model; + +private slots: + /* sign message */ + void on_addressBookButton_SM_clicked(); + void on_pasteButton_SM_clicked(); + void on_signMessageButton_SM_clicked(); + void on_copySignatureButton_SM_clicked(); + void on_clearButton_SM_clicked(); + /* verify message */ + void on_addressBookButton_VM_clicked(); + void on_verifyMessageButton_VM_clicked(); + void on_clearButton_VM_clicked(); +}; + +#endif // SIGNVERIFYMESSAGEDIALOG_H diff --git a/src/qt/test/test_main.cpp b/src/qt/test/test_main.cpp new file mode 100755 index 0000000..3c7794b --- /dev/null +++ b/src/qt/test/test_main.cpp @@ -0,0 +1,16 @@ +#include +#include + +#include "uritests.h" + +// This is all you need to run all the tests +int main(int argc, char *argv[]) +{ + bool fInvalid = false; + + URITests test1; + if (QTest::qExec(&test1) != 0) + fInvalid = true; + + return fInvalid; +} diff --git a/src/qt/test/uritests.cpp b/src/qt/test/uritests.cpp new file mode 100755 index 0000000..4662f5e --- /dev/null +++ b/src/qt/test/uritests.cpp @@ -0,0 +1,71 @@ +#include "uritests.h" +#include "../guiutil.h" +#include "../walletmodel.h" + +#include + +/* +struct SendCoinsRecipient +{ + QString address; + QString label; + qint64 amount; +}; +*/ + +void URITests::uriTests() +{ + SendCoinsRecipient rv; + QUrl uri; + uri.setUrl(QString("bitcoin:175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W?req-dontexist=")); + QVERIFY(!GUIUtil::parseBitcoinURI(uri, &rv)); + + uri.setUrl(QString("bitcoin:175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W?dontexist=")); + QVERIFY(GUIUtil::parseBitcoinURI(uri, &rv)); + QVERIFY(rv.address == QString("175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W")); + QVERIFY(rv.label == QString()); + QVERIFY(rv.amount == 0); + + uri.setUrl(QString("bitcoin:175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W?label=Wikipedia Example Address")); + QVERIFY(GUIUtil::parseBitcoinURI(uri, &rv)); + QVERIFY(rv.address == QString("175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W")); + QVERIFY(rv.label == QString("Wikipedia Example Address")); + QVERIFY(rv.amount == 0); + + uri.setUrl(QString("bitcoin:175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W?amount=0.001")); + QVERIFY(GUIUtil::parseBitcoinURI(uri, &rv)); + QVERIFY(rv.address == QString("175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W")); + QVERIFY(rv.label == QString()); + QVERIFY(rv.amount == 100000); + + uri.setUrl(QString("bitcoin:175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W?amount=1.001")); + QVERIFY(GUIUtil::parseBitcoinURI(uri, &rv)); + QVERIFY(rv.address == QString("175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W")); + QVERIFY(rv.label == QString()); + QVERIFY(rv.amount == 100100000); + + uri.setUrl(QString("bitcoin:175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W?amount=100&label=Wikipedia Example")); + QVERIFY(GUIUtil::parseBitcoinURI(uri, &rv)); + QVERIFY(rv.address == QString("175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W")); + QVERIFY(rv.amount == 10000000000LL); + QVERIFY(rv.label == QString("Wikipedia Example")); + + uri.setUrl(QString("bitcoin:175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W?message=Wikipedia Example Address")); + QVERIFY(GUIUtil::parseBitcoinURI(uri, &rv)); + QVERIFY(rv.address == QString("175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W")); + QVERIFY(rv.label == QString()); + + QVERIFY(GUIUtil::parseBitcoinURI("bitcoin://175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W?message=Wikipedia Example Address", &rv)); + QVERIFY(rv.address == QString("175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W")); + QVERIFY(rv.label == QString()); + + // We currently don't implement the message parameter (ok, yea, we break spec...) + uri.setUrl(QString("bitcoin:175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W?req-message=Wikipedia Example Address")); + QVERIFY(!GUIUtil::parseBitcoinURI(uri, &rv)); + + uri.setUrl(QString("bitcoin:175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W?amount=1,000&label=Wikipedia Example")); + QVERIFY(!GUIUtil::parseBitcoinURI(uri, &rv)); + + uri.setUrl(QString("bitcoin:175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W?amount=1,000.0&label=Wikipedia Example")); + QVERIFY(!GUIUtil::parseBitcoinURI(uri, &rv)); +} diff --git a/src/qt/test/uritests.h b/src/qt/test/uritests.h new file mode 100755 index 0000000..1237516 --- /dev/null +++ b/src/qt/test/uritests.h @@ -0,0 +1,15 @@ +#ifndef URITESTS_H +#define URITESTS_H + +#include +#include + +class URITests : public QObject +{ + Q_OBJECT + +private slots: + void uriTests(); +}; + +#endif // URITESTS_H diff --git a/src/qt/trafficgraphwidget.cpp b/src/qt/trafficgraphwidget.cpp new file mode 100644 index 0000000..6fc63b6 --- /dev/null +++ b/src/qt/trafficgraphwidget.cpp @@ -0,0 +1,170 @@ +#include "trafficgraphwidget.h" +#include "clientmodel.h" + +#include +#include +#include + +#include + +#define DESIRED_SAMPLES 800 + +#define XMARGIN 10 +#define YMARGIN 10 + +TrafficGraphWidget::TrafficGraphWidget(QWidget *parent) : + QWidget(parent), + timer(0), + fMax(0.0f), + nMins(0), + vSamplesIn(), + vSamplesOut(), + nLastBytesIn(0), + nLastBytesOut(0), + clientModel(0) +{ + timer = new QTimer(this); + connect(timer, SIGNAL(timeout()), SLOT(updateRates())); +} + +void TrafficGraphWidget::setClientModel(ClientModel *model) +{ + clientModel = model; + if(model) { + nLastBytesIn = model->getTotalBytesRecv(); + nLastBytesOut = model->getTotalBytesSent(); + } +} + +int TrafficGraphWidget::getGraphRangeMins() const +{ + return nMins; +} + +void TrafficGraphWidget::paintPath(QPainterPath &path, QQueue &samples) +{ + int h = height() - YMARGIN * 2, w = width() - XMARGIN * 2; + int sampleCount = samples.size(), x = XMARGIN + w, y; + if(sampleCount > 0) { + path.moveTo(x, YMARGIN + h); + for(int i = 0; i < sampleCount; ++i) { + x = XMARGIN + w - w * i / DESIRED_SAMPLES; + y = YMARGIN + h - (int)(h * samples.at(i) / fMax); + path.lineTo(x, y); + } + path.lineTo(x, YMARGIN + h); + } +} + +void TrafficGraphWidget::paintEvent(QPaintEvent *) +{ + QPainter painter(this); + painter.fillRect(rect(), Qt::black); + + if(fMax <= 0.0f) return; + + QColor axisCol(Qt::gray); + int h = height() - YMARGIN * 2; + painter.setPen(axisCol); + painter.drawLine(XMARGIN, YMARGIN + h, width() - XMARGIN, YMARGIN + h); + + // decide what order of magnitude we are + int base = floor(log10(fMax)); + float val = pow(10.0f, base); + + const QString units = tr("KB/s"); + // draw lines + painter.setPen(axisCol); + painter.drawText(XMARGIN, YMARGIN + h - h * val / fMax, QString("%1 %2").arg(val).arg(units)); + for(float y = val; y < fMax; y += val) { + int yy = YMARGIN + h - h * y / fMax; + painter.drawLine(XMARGIN, yy, width() - XMARGIN, yy); + } + // if we drew 3 or fewer lines, break them up at the next lower order of magnitude + if(fMax / val <= 3.0f) { + axisCol = axisCol.darker(); + val = pow(10.0f, base - 1); + painter.setPen(axisCol); + painter.drawText(XMARGIN, YMARGIN + h - h * val / fMax, QString("%1 %2").arg(val).arg(units)); + int count = 1; + for(float y = val; y < fMax; y += val, count++) { + // don't overwrite lines drawn above + if(count % 10 == 0) + continue; + int yy = YMARGIN + h - h * y / fMax; + painter.drawLine(XMARGIN, yy, width() - XMARGIN, yy); + } + } + + if(!vSamplesIn.empty()) { + QPainterPath p; + paintPath(p, vSamplesIn); + painter.fillPath(p, QColor(0, 255, 0, 128)); + painter.setPen(Qt::green); + painter.drawPath(p); + } + if(!vSamplesOut.empty()) { + QPainterPath p; + paintPath(p, vSamplesOut); + painter.fillPath(p, QColor(255, 0, 0, 128)); + painter.setPen(Qt::red); + painter.drawPath(p); + } +} + +void TrafficGraphWidget::updateRates() +{ + if(!clientModel) return; + + quint64 bytesIn = clientModel->getTotalBytesRecv(), + bytesOut = clientModel->getTotalBytesSent(); + float inRate = (bytesIn - nLastBytesIn) / 1024.0f * 1000 / timer->interval(); + float outRate = (bytesOut - nLastBytesOut) / 1024.0f * 1000 / timer->interval(); + vSamplesIn.push_front(inRate); + vSamplesOut.push_front(outRate); + nLastBytesIn = bytesIn; + nLastBytesOut = bytesOut; + + while(vSamplesIn.size() > DESIRED_SAMPLES) { + vSamplesIn.pop_back(); + } + while(vSamplesOut.size() > DESIRED_SAMPLES) { + vSamplesOut.pop_back(); + } + + float tmax = 0.0f; + foreach(float f, vSamplesIn) { + if(f > tmax) tmax = f; + } + foreach(float f, vSamplesOut) { + if(f > tmax) tmax = f; + } + fMax = tmax; + update(); +} + +void TrafficGraphWidget::setGraphRangeMins(int mins) +{ + nMins = mins; + int msecsPerSample = nMins * 60 * 1000 / DESIRED_SAMPLES; + timer->stop(); + timer->setInterval(msecsPerSample); + + clear(); +} + +void TrafficGraphWidget::clear() +{ + timer->stop(); + + vSamplesOut.clear(); + vSamplesIn.clear(); + fMax = 0.0f; + + if(clientModel) { + nLastBytesIn = clientModel->getTotalBytesRecv(); + nLastBytesOut = clientModel->getTotalBytesSent(); + } + timer->start(); +} + diff --git a/src/qt/trafficgraphwidget.h b/src/qt/trafficgraphwidget.h new file mode 100644 index 0000000..ff37458 --- /dev/null +++ b/src/qt/trafficgraphwidget.h @@ -0,0 +1,45 @@ +#ifndef TRAFFICGRAPHWIDGET_H +#define TRAFFICGRAPHWIDGET_H + +#include +#include + +class ClientModel; + +QT_BEGIN_NAMESPACE +class QPaintEvent; +class QTimer; +QT_END_NAMESPACE + +class TrafficGraphWidget : public QWidget +{ + Q_OBJECT + +public: + explicit TrafficGraphWidget(QWidget *parent = 0); + void setClientModel(ClientModel *model); + int getGraphRangeMins() const; + +protected: + void paintEvent(QPaintEvent *); + +public slots: + void updateRates(); + void setGraphRangeMins(int mins); + void clear(); + +private: + void paintPath(QPainterPath &path, QQueue &samples); + + QTimer *timer; + float fMax; + int nMins; + QQueue vSamplesIn; + QQueue vSamplesOut; + quint64 nLastBytesIn; + quint64 nLastBytesOut; + ClientModel *clientModel; +}; + +#endif // TRAFFICGRAPHWIDGET_H + diff --git a/src/qt/transactiondesc.cpp b/src/qt/transactiondesc.cpp new file mode 100755 index 0000000..2422513 --- /dev/null +++ b/src/qt/transactiondesc.cpp @@ -0,0 +1,273 @@ +#include "transactiondesc.h" + +#include "guiutil.h" +#include "bitcoinunits.h" + +#include "main.h" +#include "wallet.h" +#include "txdb.h" +#include "ui_interface.h" +#include "base58.h" + +QString TransactionDesc::FormatTxStatus(const CWalletTx& wtx) +{ + AssertLockHeld(cs_main); + if (!IsFinalTx(wtx, nBestHeight + 1)) + { + if (wtx.nLockTime < LOCKTIME_THRESHOLD) + return tr("Open for %n more block(s)", "", wtx.nLockTime - nBestHeight); + else + return tr("Open until %1").arg(GUIUtil::dateTimeStr(wtx.nLockTime)); + } + else + { + int nDepth = wtx.GetDepthInMainChain(); + if (nDepth < 0) + return tr("conflicted"); + else if (GetAdjustedTime() - wtx.nTimeReceived > 2 * 60 && wtx.GetRequestCount() == 0) + return tr("%1/offline").arg(nDepth); + else if (nDepth < 10) + return tr("%1/unconfirmed").arg(nDepth); + else + return tr("%1 confirmations").arg(nDepth); + } +} + +QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx) +{ + QString strHTML; + + LOCK2(cs_main, wallet->cs_wallet); + strHTML.reserve(4000); + strHTML += ""; + + int64_t nTime = wtx.GetTxTime(); + int64_t nCredit = wtx.GetCredit(); + int64_t nDebit = wtx.GetDebit(); + int64_t nNet = nCredit - nDebit; + + strHTML += "" + tr("Status") + ": " + FormatTxStatus(wtx); + int nRequests = wtx.GetRequestCount(); + if (nRequests != -1) + { + if (nRequests == 0) + strHTML += tr(", has not been successfully broadcast yet"); + else if (nRequests > 0) + strHTML += tr(", broadcast through %n node(s)", "", nRequests); + } + strHTML += "
"; + + strHTML += "" + tr("Date") + ": " + (nTime ? GUIUtil::dateTimeStr(nTime) : "") + "
"; + + // + // From + // + if (wtx.IsCoinBase() || wtx.IsCoinStake()) + { + strHTML += "" + tr("Source") + ": " + tr("Generated") + "
"; + } + else if (wtx.mapValue.count("from") && !wtx.mapValue["from"].empty()) + { + // Online transaction + strHTML += "" + tr("From") + ": " + GUIUtil::HtmlEscape(wtx.mapValue["from"]) + "
"; + } + else + { + // Offline transaction + if (nNet > 0) + { + // Credit + BOOST_FOREACH(const CTxOut& txout, wtx.vout) + { + if (wallet->IsMine(txout)) + { + CTxDestination address; + if (ExtractDestination(txout.scriptPubKey, address) && IsMine(*wallet, address)) + { + if (wallet->mapAddressBook.count(address)) + { + strHTML += "" + tr("From") + ": " + tr("unknown") + "
"; + strHTML += "" + tr("To") + ": "; + strHTML += GUIUtil::HtmlEscape(CBitcoinAddress(address).ToString()); + if (!wallet->mapAddressBook[address].empty()) + strHTML += " (" + tr("own address") + ", " + tr("label") + ": " + GUIUtil::HtmlEscape(wallet->mapAddressBook[address]) + ")"; + else + strHTML += " (" + tr("own address") + ")"; + strHTML += "
"; + } + } + break; + } + } + } + } + + // + // To + // + if (wtx.mapValue.count("to") && !wtx.mapValue["to"].empty()) + { + // Online transaction + std::string strAddress = wtx.mapValue["to"]; + strHTML += "" + tr("To") + ": "; + CTxDestination dest = CBitcoinAddress(strAddress).Get(); + if (wallet->mapAddressBook.count(dest) && !wallet->mapAddressBook[dest].empty()) + strHTML += GUIUtil::HtmlEscape(wallet->mapAddressBook[dest]) + " "; + strHTML += GUIUtil::HtmlEscape(strAddress) + "
"; + } + + // + // Amount + // + if (wtx.IsCoinBase() && nCredit == 0) + { + // + // Coinbase + // + int64_t nUnmatured = 0; + BOOST_FOREACH(const CTxOut& txout, wtx.vout) + nUnmatured += wallet->GetCredit(txout); + strHTML += "" + tr("Credit") + ": "; + if (wtx.IsInMainChain()) + strHTML += BitcoinUnits::formatWithUnit(BitcoinUnits::BTC, nUnmatured)+ " (" + tr("matures in %n more block(s)", "", wtx.GetBlocksToMaturity()) + ")"; + else + strHTML += "(" + tr("not accepted") + ")"; + strHTML += "
"; + } + else if (nNet > 0) + { + // + // Credit + // + strHTML += "" + tr("Credit") + ": " + BitcoinUnits::formatWithUnit(BitcoinUnits::BTC, nNet) + "
"; + } + else + { + bool fAllFromMe = true; + BOOST_FOREACH(const CTxIn& txin, wtx.vin) + fAllFromMe = fAllFromMe && wallet->IsMine(txin); + + bool fAllToMe = true; + BOOST_FOREACH(const CTxOut& txout, wtx.vout) + fAllToMe = fAllToMe && wallet->IsMine(txout); + + if (fAllFromMe) + { + // + // Debit + // + BOOST_FOREACH(const CTxOut& txout, wtx.vout) + { + if (wallet->IsMine(txout)) + continue; + + if (!wtx.mapValue.count("to") || wtx.mapValue["to"].empty()) + { + // Offline transaction + CTxDestination address; + if (ExtractDestination(txout.scriptPubKey, address)) + { + strHTML += "" + tr("To") + ": "; + if (wallet->mapAddressBook.count(address) && !wallet->mapAddressBook[address].empty()) + strHTML += GUIUtil::HtmlEscape(wallet->mapAddressBook[address]) + " "; + strHTML += GUIUtil::HtmlEscape(CBitcoinAddress(address).ToString()); + strHTML += "
"; + } + } + + strHTML += "" + tr("Debit") + ": " + BitcoinUnits::formatWithUnit(BitcoinUnits::BTC, -txout.nValue) + "
"; + } + + if (fAllToMe) + { + // Payment to self + int64_t nChange = wtx.GetChange(); + int64_t nValue = nCredit - nChange; + strHTML += "" + tr("Debit") + ": " + BitcoinUnits::formatWithUnit(BitcoinUnits::BTC, -nValue) + "
"; + strHTML += "" + tr("Credit") + ": " + BitcoinUnits::formatWithUnit(BitcoinUnits::BTC, nValue) + "
"; + } + + int64_t nTxFee = nDebit - wtx.GetValueOut(); + if (nTxFee > 0) + strHTML += "" + tr("Transaction fee") + ": " + BitcoinUnits::formatWithUnit(BitcoinUnits::BTC, -nTxFee) + "
"; + } + else + { + // + // Mixed debit transaction + // + BOOST_FOREACH(const CTxIn& txin, wtx.vin) + if (wallet->IsMine(txin)) + strHTML += "" + tr("Debit") + ": " + BitcoinUnits::formatWithUnit(BitcoinUnits::BTC, -wallet->GetDebit(txin)) + "
"; + BOOST_FOREACH(const CTxOut& txout, wtx.vout) + if (wallet->IsMine(txout)) + strHTML += "" + tr("Credit") + ": " + BitcoinUnits::formatWithUnit(BitcoinUnits::BTC, wallet->GetCredit(txout)) + "
"; + } + } + + strHTML += "" + tr("Net amount") + ": " + BitcoinUnits::formatWithUnit(BitcoinUnits::BTC, nNet, true) + "
"; + + // + // Message + // + if (wtx.mapValue.count("message") && !wtx.mapValue["message"].empty()) + strHTML += "
" + tr("Message") + ":
" + GUIUtil::HtmlEscape(wtx.mapValue["message"], true) + "
"; + if (wtx.mapValue.count("comment") && !wtx.mapValue["comment"].empty()) + strHTML += "
" + tr("Comment") + ":
" + GUIUtil::HtmlEscape(wtx.mapValue["comment"], true) + "
"; + + strHTML += "" + tr("Transaction ID") + ": " + wtx.GetHash().ToString().c_str() + "
"; + + if (wtx.IsCoinBase() || wtx.IsCoinStake()) + strHTML += "
" + tr("Generated coins must mature 120 blocks before they can be spent. When you generated this block, it was broadcast to the network to be added to the block chain. If it fails to get into the chain, its state will change to \"not accepted\" and it won't be spendable. This may occasionally happen if another node generates a block within a few seconds of yours.") + "
"; + + // + // Debug view + // + if (fDebug) + { + strHTML += "

" + tr("Debug information") + "

"; + BOOST_FOREACH(const CTxIn& txin, wtx.vin) + if(wallet->IsMine(txin)) + strHTML += "" + tr("Debit") + ": " + BitcoinUnits::formatWithUnit(BitcoinUnits::BTC, -wallet->GetDebit(txin)) + "
"; + BOOST_FOREACH(const CTxOut& txout, wtx.vout) + if(wallet->IsMine(txout)) + strHTML += "" + tr("Credit") + ": " + BitcoinUnits::formatWithUnit(BitcoinUnits::BTC, wallet->GetCredit(txout)) + "
"; + + strHTML += "
" + tr("Transaction") + ":
"; + strHTML += GUIUtil::HtmlEscape(wtx.ToString(), true); + + CTxDB txdb("r"); // To fetch source txouts + + strHTML += "
" + tr("Inputs") + ":"; + strHTML += "
    "; + + BOOST_FOREACH(const CTxIn& txin, wtx.vin) + { + COutPoint prevout = txin.prevout; + + CTransaction prev; + if(txdb.ReadDiskTx(prevout.hash, prev)) + { + if (prevout.n < prev.vout.size()) + { + strHTML += "
  • "; + const CTxOut &vout = prev.vout[prevout.n]; + CTxDestination address; + if (ExtractDestination(vout.scriptPubKey, address)) + { + if (wallet->mapAddressBook.count(address) && !wallet->mapAddressBook[address].empty()) + strHTML += GUIUtil::HtmlEscape(wallet->mapAddressBook[address]) + " "; + strHTML += QString::fromStdString(CBitcoinAddress(address).ToString()); + } + strHTML = strHTML + " " + tr("Amount") + "=" + BitcoinUnits::formatWithUnit(BitcoinUnits::BTC, vout.nValue); + strHTML = strHTML + " IsMine=" + (wallet->IsMine(vout) ? tr("true") : tr("false")) + "
  • "; + } + } + } + + strHTML += "
"; + } + + strHTML += "
"; + return strHTML; +} diff --git a/src/qt/transactiondesc.h b/src/qt/transactiondesc.h new file mode 100755 index 0000000..2523f9a --- /dev/null +++ b/src/qt/transactiondesc.h @@ -0,0 +1,24 @@ +#ifndef TRANSACTIONDESC_H +#define TRANSACTIONDESC_H + +#include +#include +#include + +class CWallet; +class CWalletTx; + +/** Provide a human-readable extended HTML description of a transaction. + */ +class TransactionDesc: public QObject +{ + Q_OBJECT +public: + static QString toHTML(CWallet *wallet, CWalletTx &wtx); +private: + TransactionDesc() {} + + static QString FormatTxStatus(const CWalletTx& wtx); +}; + +#endif // TRANSACTIONDESC_H diff --git a/src/qt/transactiondescdialog.cpp b/src/qt/transactiondescdialog.cpp new file mode 100755 index 0000000..3bd4808 --- /dev/null +++ b/src/qt/transactiondescdialog.cpp @@ -0,0 +1,20 @@ +#include "transactiondescdialog.h" +#include "ui_transactiondescdialog.h" + +#include "transactiontablemodel.h" + +#include + +TransactionDescDialog::TransactionDescDialog(const QModelIndex &idx, QWidget *parent) : + QDialog(parent), + ui(new Ui::TransactionDescDialog) +{ + ui->setupUi(this); + QString desc = idx.data(TransactionTableModel::LongDescriptionRole).toString(); + ui->detailText->setHtml(desc); +} + +TransactionDescDialog::~TransactionDescDialog() +{ + delete ui; +} diff --git a/src/qt/transactiondescdialog.h b/src/qt/transactiondescdialog.h new file mode 100755 index 0000000..e86fb58 --- /dev/null +++ b/src/qt/transactiondescdialog.h @@ -0,0 +1,26 @@ +#ifndef TRANSACTIONDESCDIALOG_H +#define TRANSACTIONDESCDIALOG_H + +#include + +namespace Ui { + class TransactionDescDialog; +} +QT_BEGIN_NAMESPACE +class QModelIndex; +QT_END_NAMESPACE + +/** Dialog showing transaction details. */ +class TransactionDescDialog : public QDialog +{ + Q_OBJECT + +public: + explicit TransactionDescDialog(const QModelIndex &idx, QWidget *parent = 0); + ~TransactionDescDialog(); + +private: + Ui::TransactionDescDialog *ui; +}; + +#endif // TRANSACTIONDESCDIALOG_H diff --git a/src/qt/transactionfilterproxy.cpp b/src/qt/transactionfilterproxy.cpp new file mode 100755 index 0000000..69c2fc9 --- /dev/null +++ b/src/qt/transactionfilterproxy.cpp @@ -0,0 +1,98 @@ +#include "transactionfilterproxy.h" + +#include "transactiontablemodel.h" +#include "transactionrecord.h" + +#include + +#include + +// Earliest date that can be represented (far in the past) +const QDateTime TransactionFilterProxy::MIN_DATE = QDateTime::fromTime_t(0); +// Last date that can be represented (far in the future) +const QDateTime TransactionFilterProxy::MAX_DATE = QDateTime::fromTime_t(0xFFFFFFFF); + +TransactionFilterProxy::TransactionFilterProxy(QObject *parent) : + QSortFilterProxyModel(parent), + dateFrom(MIN_DATE), + dateTo(MAX_DATE), + addrPrefix(), + typeFilter(ALL_TYPES), + minAmount(0), + limitRows(-1), + showInactive(true) +{ +} + +bool TransactionFilterProxy::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const +{ + QModelIndex index = sourceModel()->index(sourceRow, 0, sourceParent); + + int type = index.data(TransactionTableModel::TypeRole).toInt(); + QDateTime datetime = index.data(TransactionTableModel::DateRole).toDateTime(); + QString address = index.data(TransactionTableModel::AddressRole).toString(); + QString label = index.data(TransactionTableModel::LabelRole).toString(); + qint64 amount = llabs(index.data(TransactionTableModel::AmountRole).toLongLong()); + int status = index.data(TransactionTableModel::StatusRole).toInt(); + + if(!showInactive && (status == TransactionStatus::Conflicted || status == TransactionStatus::NotAccepted)) + return false; + if(!(TYPE(type) & typeFilter)) + return false; + if(datetime < dateFrom || datetime > dateTo) + return false; + if (!address.contains(addrPrefix, Qt::CaseInsensitive) && !label.contains(addrPrefix, Qt::CaseInsensitive)) + return false; + if(amount < minAmount) + return false; + + return true; +} + +void TransactionFilterProxy::setDateRange(const QDateTime &from, const QDateTime &to) +{ + this->dateFrom = from; + this->dateTo = to; + invalidateFilter(); +} + +void TransactionFilterProxy::setAddressPrefix(const QString &addrPrefix) +{ + this->addrPrefix = addrPrefix; + invalidateFilter(); +} + +void TransactionFilterProxy::setTypeFilter(quint32 modes) +{ + this->typeFilter = modes; + invalidateFilter(); +} + +void TransactionFilterProxy::setMinAmount(qint64 minimum) +{ + this->minAmount = minimum; + invalidateFilter(); +} + +void TransactionFilterProxy::setLimit(int limit) +{ + this->limitRows = limit; +} + +void TransactionFilterProxy::setShowInactive(bool showInactive) +{ + this->showInactive = showInactive; + invalidateFilter(); +} + +int TransactionFilterProxy::rowCount(const QModelIndex &parent) const +{ + if(limitRows != -1) + { + return std::min(QSortFilterProxyModel::rowCount(parent), limitRows); + } + else + { + return QSortFilterProxyModel::rowCount(parent); + } +} diff --git a/src/qt/transactionfilterproxy.h b/src/qt/transactionfilterproxy.h new file mode 100755 index 0000000..2c86f62 --- /dev/null +++ b/src/qt/transactionfilterproxy.h @@ -0,0 +1,56 @@ +#ifndef TRANSACTIONFILTERPROXY_H +#define TRANSACTIONFILTERPROXY_H + +#include +#include + +/** Filter the transaction list according to pre-specified rules. */ +class TransactionFilterProxy : public QSortFilterProxyModel +{ + Q_OBJECT +public: + explicit TransactionFilterProxy(QObject *parent = 0); + + /** Earliest date that can be represented (far in the past) */ + static const QDateTime MIN_DATE; + /** Last date that can be represented (far in the future) */ + static const QDateTime MAX_DATE; + /** Type filter bit field (all types) */ + static const quint32 ALL_TYPES = 0xFFFFFFFF; + + static quint32 TYPE(int type) { return 1< TransactionRecord::decomposeTransaction(const CWallet *wallet, const CWalletTx &wtx) +{ + QList parts; + int64_t nTime = wtx.GetTxTime(); + int64_t nCredit = wtx.GetCredit(true); + int64_t nDebit = wtx.GetDebit(); + int64_t nNet = nCredit - nDebit; + uint256 hash = wtx.GetHash(), hashPrev = 0; + std::map mapValue = wtx.mapValue; + + if (nNet > 0 || wtx.IsCoinBase() || wtx.IsCoinStake()) + { + // + // Credit + // + BOOST_FOREACH(const CTxOut& txout, wtx.vout) + { + if(wallet->IsMine(txout)) + { + TransactionRecord sub(hash, nTime); + CTxDestination address; + sub.idx = parts.size(); // sequence number + sub.credit = txout.nValue; + if (ExtractDestination(txout.scriptPubKey, address) && IsMine(*wallet, address)) + { + // Received by Bitcoin Address + sub.type = TransactionRecord::RecvWithAddress; + sub.address = CBitcoinAddress(address).ToString(); + } + else + { + // Received by IP connection (deprecated features), or a multisignature or other non-simple transaction + sub.type = TransactionRecord::RecvFromOther; + sub.address = mapValue["from"]; + } + if (wtx.IsCoinBase()) + { + // Generated (proof-of-work) + sub.type = TransactionRecord::Generated; + } + if (wtx.IsCoinStake()) + { + // Generated (proof-of-stake) + + if (hashPrev == hash) + continue; // last coinstake output + + sub.type = TransactionRecord::Generated; + sub.credit = nNet > 0 ? nNet : wtx.GetValueOut() - nDebit; + hashPrev = hash; + } + + parts.append(sub); + } + } + } + else + { + bool fAllFromMe = true; + BOOST_FOREACH(const CTxIn& txin, wtx.vin) + fAllFromMe = fAllFromMe && wallet->IsMine(txin); + + bool fAllToMe = true; + BOOST_FOREACH(const CTxOut& txout, wtx.vout) + fAllToMe = fAllToMe && wallet->IsMine(txout); + + if (fAllFromMe && fAllToMe) + { + // Payment to self + int64_t nChange = wtx.GetChange(); + + parts.append(TransactionRecord(hash, nTime, TransactionRecord::SendToSelf, "", + -(nDebit - nChange), nCredit - nChange)); + } + else if (fAllFromMe) + { + // + // Debit + // + int64_t nTxFee = nDebit - wtx.GetValueOut(); + + for (unsigned int nOut = 0; nOut < wtx.vout.size(); nOut++) + { + const CTxOut& txout = wtx.vout[nOut]; + TransactionRecord sub(hash, nTime); + sub.idx = parts.size(); + + if(wallet->IsMine(txout)) + { + // Ignore parts sent to self, as this is usually the change + // from a transaction sent back to our own address. + continue; + } + + CTxDestination address; + if (ExtractDestination(txout.scriptPubKey, address)) + { + // Sent to Bitcoin Address + sub.type = TransactionRecord::SendToAddress; + sub.address = CBitcoinAddress(address).ToString(); + } + else + { + // Sent to IP, or other non-address transaction like OP_EVAL + sub.type = TransactionRecord::SendToOther; + sub.address = mapValue["to"]; + } + + int64_t nValue = txout.nValue; + /* Add fee to first output */ + if (nTxFee > 0) + { + nValue += nTxFee; + nTxFee = 0; + } + sub.debit = -nValue; + + parts.append(sub); + } + } + else + { + // + // Mixed debit transaction, can't break down payees + // + parts.append(TransactionRecord(hash, nTime, TransactionRecord::Other, "", nNet, 0)); + } + } + + return parts; +} + +void TransactionRecord::updateStatus(const CWalletTx &wtx) +{ + AssertLockHeld(cs_main); + // Determine transaction status + + // Find the block the tx is in + CBlockIndex* pindex = NULL; + std::map::iterator mi = mapBlockIndex.find(wtx.hashBlock); + if (mi != mapBlockIndex.end()) + pindex = (*mi).second; + + // Sort order, unrecorded transactions sort to the top + status.sortKey = strprintf("%010d-%01d-%010u-%03d", + (pindex ? pindex->nHeight : std::numeric_limits::max()), + (wtx.IsCoinBase() ? 1 : 0), + wtx.nTimeReceived, + idx); + status.countsForBalance = wtx.IsTrusted() && !(wtx.GetBlocksToMaturity() > 0); + status.depth = wtx.GetDepthInMainChain(); + status.cur_num_blocks = nBestHeight; + + if (!IsFinalTx(wtx, nBestHeight + 1)) + { + if (wtx.nLockTime < LOCKTIME_THRESHOLD) + { + status.status = TransactionStatus::OpenUntilBlock; + status.open_for = wtx.nLockTime - nBestHeight; + } + else + { + status.status = TransactionStatus::OpenUntilDate; + status.open_for = wtx.nLockTime; + } + } + + // For generated transactions, determine maturity + else if(type == TransactionRecord::Generated) + { + if (wtx.GetBlocksToMaturity() > 0) + { + status.status = TransactionStatus::Immature; + + if (wtx.IsInMainChain()) + { + status.matures_in = wtx.GetBlocksToMaturity(); + + // Check if the block was requested by anyone + if (GetAdjustedTime() - wtx.nTimeReceived > 2 * 60 && wtx.GetRequestCount() == 0) + status.status = TransactionStatus::MaturesWarning; + } + else + { + status.status = TransactionStatus::NotAccepted; + } + } + else + { + status.status = TransactionStatus::Confirmed; + } + } + else + { + if (status.depth < 0) + { + status.status = TransactionStatus::Conflicted; + } + else if (GetAdjustedTime() - wtx.nTimeReceived > 2 * 60 && wtx.GetRequestCount() == 0) + { + status.status = TransactionStatus::Offline; + } + else if (status.depth == 0) + { + status.status = TransactionStatus::Unconfirmed; + } + else if (status.depth < RecommendedNumConfirmations) + { + status.status = TransactionStatus::Confirming; + } + else + { + status.status = TransactionStatus::Confirmed; + } + } +} + +bool TransactionRecord::statusUpdateNeeded() +{ + AssertLockHeld(cs_main); + return status.cur_num_blocks != nBestHeight; +} + +std::string TransactionRecord::getTxID() +{ + return hash.ToString() + strprintf("-%03d", idx); +} + diff --git a/src/qt/transactionrecord.h b/src/qt/transactionrecord.h new file mode 100755 index 0000000..10dc2b1 --- /dev/null +++ b/src/qt/transactionrecord.h @@ -0,0 +1,131 @@ +#ifndef TRANSACTIONRECORD_H +#define TRANSACTIONRECORD_H + +#include "uint256.h" + +#include + +class CWallet; +class CWalletTx; + +/** UI model for transaction status. The transaction status is the part of a transaction that will change over time. + */ +class TransactionStatus +{ +public: + TransactionStatus(): + countsForBalance(false), sortKey(""), + matures_in(0), status(Offline), depth(0), open_for(0), cur_num_blocks(-1) + { } + + enum Status { + Confirmed, /**< Have 6 or more confirmations (normal tx) or fully mature (mined tx) **/ + /// Normal (sent/received) transactions + OpenUntilDate, /**< Transaction not yet final, waiting for date */ + OpenUntilBlock, /**< Transaction not yet final, waiting for block */ + Offline, /**< Not sent to any other nodes **/ + Unconfirmed, /**< Not yet mined into a block **/ + Confirming, /**< Confirmed, but waiting for the recommended number of confirmations **/ + Conflicted, /**< Conflicts with other transaction or mempool **/ + /// Generated (mined) transactions + Immature, /**< Mined but waiting for maturity */ + MaturesWarning, /**< Transaction will likely not mature because no nodes have confirmed */ + NotAccepted /**< Mined but not accepted */ + }; + + /// Transaction counts towards available balance + bool countsForBalance; + /// Sorting key based on status + std::string sortKey; + + /** @name Generated (mined) transactions + @{*/ + int matures_in; + /**@}*/ + + /** @name Reported status + @{*/ + Status status; + int64_t depth; + int64_t open_for; /**< Timestamp if status==OpenUntilDate, otherwise number + of additional blocks that need to be mined before + finalization */ + /**@}*/ + + /** Current number of blocks (to know whether cached status is still valid) */ + int cur_num_blocks; +}; + +/** UI model for a transaction. A core transaction can be represented by multiple UI transactions if it has + multiple outputs. + */ +class TransactionRecord +{ +public: + enum Type + { + Other, + Generated, + SendToAddress, + SendToOther, + RecvWithAddress, + RecvFromOther, + SendToSelf + }; + + /** Number of confirmation recommended for accepting a transaction */ + static const int RecommendedNumConfirmations = 6; + + TransactionRecord(): + hash(), time(0), type(Other), address(""), debit(0), credit(0), idx(0) + { + } + + TransactionRecord(uint256 hash, int64_t time): + hash(hash), time(time), type(Other), address(""), debit(0), + credit(0), idx(0) + { + } + + TransactionRecord(uint256 hash, int64_t time, + Type type, const std::string &address, + int64_t debit, int64_t credit): + hash(hash), time(time), type(type), address(address), debit(debit), credit(credit), + idx(0) + { + } + + /** Decompose CWallet transaction to model transaction records. + */ + static bool showTransaction(const CWalletTx &wtx); + static QList decomposeTransaction(const CWallet *wallet, const CWalletTx &wtx); + + /** @name Immutable transaction attributes + @{*/ + uint256 hash; + qint64 time; + Type type; + std::string address; + qint64 debit; + qint64 credit; + /**@}*/ + + /** Subtransaction index, for sort key */ + int idx; + + /** Status: can change with block chain update */ + TransactionStatus status; + + /** Return the unique identifier for this transaction (part) */ + std::string getTxID(); + + /** Update status from core wallet tx. + */ + void updateStatus(const CWalletTx &wtx); + + /** Return whether a status update is needed. + */ + bool statusUpdateNeeded(); +}; + +#endif // TRANSACTIONRECORD_H diff --git a/src/qt/transactiontablemodel.cpp b/src/qt/transactiontablemodel.cpp new file mode 100755 index 0000000..a59f68c --- /dev/null +++ b/src/qt/transactiontablemodel.cpp @@ -0,0 +1,622 @@ +#include "transactiontablemodel.h" +#include "guiutil.h" +#include "transactionrecord.h" +#include "guiconstants.h" +#include "transactiondesc.h" +#include "walletmodel.h" +#include "optionsmodel.h" +#include "addresstablemodel.h" +#include "bitcoinunits.h" + +#include "wallet.h" +#include "ui_interface.h" + +#include +#include +#include +#include +#include +#include + +// Amount column is right-aligned it contains numbers +static int column_alignments[] = { + Qt::AlignLeft|Qt::AlignVCenter, + Qt::AlignLeft|Qt::AlignVCenter, + Qt::AlignLeft|Qt::AlignVCenter, + Qt::AlignLeft|Qt::AlignVCenter, + Qt::AlignRight|Qt::AlignVCenter + }; + +// Comparison operator for sort/binary search of model tx list +struct TxLessThan +{ + bool operator()(const TransactionRecord &a, const TransactionRecord &b) const + { + return a.hash < b.hash; + } + bool operator()(const TransactionRecord &a, const uint256 &b) const + { + return a.hash < b; + } + bool operator()(const uint256 &a, const TransactionRecord &b) const + { + return a < b.hash; + } +}; + +// Private implementation +class TransactionTablePriv +{ +public: + TransactionTablePriv(CWallet *wallet, TransactionTableModel *parent): + wallet(wallet), + parent(parent) + { + } + CWallet *wallet; + TransactionTableModel *parent; + + /* Local cache of wallet. + * As it is in the same order as the CWallet, by definition + * this is sorted by sha256. + */ + QList cachedWallet; + + /* Query entire wallet anew from core. + */ + void refreshWallet() + { + OutputDebugStringF("refreshWallet\n"); + cachedWallet.clear(); + { + LOCK2(cs_main, wallet->cs_wallet); + for(std::map::iterator it = wallet->mapWallet.begin(); it != wallet->mapWallet.end(); ++it) + { + if(TransactionRecord::showTransaction(it->second)) + cachedWallet.append(TransactionRecord::decomposeTransaction(wallet, it->second)); + } + } + } + + /* Update our model of the wallet incrementally, to synchronize our model of the wallet + with that of the core. + + Call with transaction that was added, removed or changed. + */ + void updateWallet(const uint256 &hash, int status) + { + OutputDebugStringF("updateWallet %s %i\n", hash.ToString().c_str(), status); + { + LOCK2(cs_main, wallet->cs_wallet); + + // Find transaction in wallet + std::map::iterator mi = wallet->mapWallet.find(hash); + bool inWallet = mi != wallet->mapWallet.end(); + + // Find bounds of this transaction in model + QList::iterator lower = qLowerBound( + cachedWallet.begin(), cachedWallet.end(), hash, TxLessThan()); + QList::iterator upper = qUpperBound( + cachedWallet.begin(), cachedWallet.end(), hash, TxLessThan()); + int lowerIndex = (lower - cachedWallet.begin()); + int upperIndex = (upper - cachedWallet.begin()); + bool inModel = (lower != upper); + + // Determine whether to show transaction or not + bool showTransaction = (inWallet && TransactionRecord::showTransaction(mi->second)); + + if(status == CT_UPDATED) + { + if(showTransaction && !inModel) + status = CT_NEW; /* Not in model, but want to show, treat as new */ + if(!showTransaction && inModel) + status = CT_DELETED; /* In model, but want to hide, treat as deleted */ + } + + OutputDebugStringF(" inWallet=%i inModel=%i Index=%i-%i showTransaction=%i derivedStatus=%i\n", + inWallet, inModel, lowerIndex, upperIndex, showTransaction, status); + + switch(status) + { + case CT_NEW: + if(inModel) + { + OutputDebugStringF("Warning: updateWallet: Got CT_NEW, but transaction is already in model\n"); + break; + } + if(!inWallet) + { + OutputDebugStringF("Warning: updateWallet: Got CT_NEW, but transaction is not in wallet\n"); + break; + } + if(showTransaction) + { + // Added -- insert at the right position + QList toInsert = + TransactionRecord::decomposeTransaction(wallet, mi->second); + if(!toInsert.isEmpty()) /* only if something to insert */ + { + parent->beginInsertRows(QModelIndex(), lowerIndex, lowerIndex+toInsert.size()-1); + int insert_idx = lowerIndex; + foreach(const TransactionRecord &rec, toInsert) + { + cachedWallet.insert(insert_idx, rec); + insert_idx += 1; + } + parent->endInsertRows(); + } + } + break; + case CT_DELETED: + if(!inModel) + { + OutputDebugStringF("Warning: updateWallet: Got CT_DELETED, but transaction is not in model\n"); + break; + } + // Removed -- remove entire transaction from table + parent->beginRemoveRows(QModelIndex(), lowerIndex, upperIndex-1); + cachedWallet.erase(lower, upper); + parent->endRemoveRows(); + break; + case CT_UPDATED: + // Miscellaneous updates -- nothing to do, status update will take care of this, and is only computed for + // visible transactions. + break; + } + } + } + + int size() + { + return cachedWallet.size(); + } + + TransactionRecord *index(int idx) + { + if(idx >= 0 && idx < cachedWallet.size()) + { + TransactionRecord *rec = &cachedWallet[idx]; + + // Get required locks upfront. This avoids the GUI from getting + // stuck if the core is holding the locks for a longer time - for + // example, during a wallet rescan. + // + // If a status update is needed (blocks came in since last check), + // update the status of this transaction from the wallet. Otherwise, + // simply re-use the cached status. + TRY_LOCK(cs_main, lockMain); + if(lockMain) + { + TRY_LOCK(wallet->cs_wallet, lockWallet); + if(lockWallet && rec->statusUpdateNeeded()) + { + std::map::iterator mi = wallet->mapWallet.find(rec->hash); + + if(mi != wallet->mapWallet.end()) + { + rec->updateStatus(mi->second); + } + } + } + return rec; + } + else + { + return 0; + } + } + + QString describe(TransactionRecord *rec) + { + { + LOCK2(cs_main, wallet->cs_wallet); + std::map::iterator mi = wallet->mapWallet.find(rec->hash); + if(mi != wallet->mapWallet.end()) + { + return TransactionDesc::toHTML(wallet, mi->second); + } + } + return QString(""); + } + +}; + +TransactionTableModel::TransactionTableModel(CWallet* wallet, WalletModel *parent): + QAbstractTableModel(parent), + wallet(wallet), + walletModel(parent), + priv(new TransactionTablePriv(wallet, this)) +{ + columns << QString() << tr("Date") << tr("Type") << tr("Address") << tr("Amount"); + + priv->refreshWallet(); + + connect(walletModel->getOptionsModel(), SIGNAL(displayUnitChanged(int)), this, SLOT(updateDisplayUnit())); +} + +TransactionTableModel::~TransactionTableModel() +{ + delete priv; +} + +void TransactionTableModel::updateTransaction(const QString &hash, int status) +{ + uint256 updated; + updated.SetHex(hash.toStdString()); + + priv->updateWallet(updated, status); +} + +void TransactionTableModel::updateConfirmations() +{ + // Blocks came in since last poll. + // Invalidate status (number of confirmations) and (possibly) description + // for all rows. Qt is smart enough to only actually request the data for the + // visible rows. + emit dataChanged(index(0, Status), index(priv->size()-1, Status)); + emit dataChanged(index(0, ToAddress), index(priv->size()-1, ToAddress)); +} + +int TransactionTableModel::rowCount(const QModelIndex &parent) const +{ + Q_UNUSED(parent); + return priv->size(); +} + +int TransactionTableModel::columnCount(const QModelIndex &parent) const +{ + Q_UNUSED(parent); + return columns.length(); +} + +QString TransactionTableModel::formatTxStatus(const TransactionRecord *wtx) const +{ + QString status; + + switch(wtx->status.status) + { + case TransactionStatus::OpenUntilBlock: + status = tr("Open for %n more block(s)","",wtx->status.open_for); + break; + case TransactionStatus::OpenUntilDate: + status = tr("Open until %1").arg(GUIUtil::dateTimeStr(wtx->status.open_for)); + break; + case TransactionStatus::Offline: + status = tr("Offline"); + break; + case TransactionStatus::Unconfirmed: + status = tr("Unconfirmed"); + break; + case TransactionStatus::Confirming: + status = tr("Confirming (%1 of %2 recommended confirmations)").arg(wtx->status.depth).arg(TransactionRecord::RecommendedNumConfirmations); + break; + case TransactionStatus::Confirmed: + status = tr("Confirmed (%1 confirmations)").arg(wtx->status.depth); + break; + case TransactionStatus::Conflicted: + status = tr("Conflicted"); + break; + case TransactionStatus::Immature: + status = tr("Immature (%1 confirmations, will be available after %2)").arg(wtx->status.depth).arg(wtx->status.depth + wtx->status.matures_in); + break; + case TransactionStatus::MaturesWarning: + status = tr("This block was not received by any other nodes and will probably not be accepted!"); + break; + case TransactionStatus::NotAccepted: + status = tr("Generated but not accepted"); + break; + } + + return status; +} + +QString TransactionTableModel::formatTxDate(const TransactionRecord *wtx) const +{ + if(wtx->time) + { + return GUIUtil::dateTimeStr(wtx->time); + } + else + { + return QString(); + } +} + +/* Look up address in address book, if found return label (address) + otherwise just return (address) + */ +QString TransactionTableModel::lookupAddress(const std::string &address, bool tooltip) const +{ + QString label = walletModel->getAddressTableModel()->labelForAddress(QString::fromStdString(address)); + QString description; + if(!label.isEmpty()) + { + description += label + QString(" "); + } + if(label.isEmpty() || walletModel->getOptionsModel()->getDisplayAddresses() || tooltip) + { + description += QString("(") + QString::fromStdString(address) + QString(")"); + } + return description; +} + +QString TransactionTableModel::formatTxType(const TransactionRecord *wtx) const +{ + switch(wtx->type) + { + case TransactionRecord::RecvWithAddress: + return tr("Received with"); + case TransactionRecord::RecvFromOther: + return tr("Received from"); + case TransactionRecord::SendToAddress: + case TransactionRecord::SendToOther: + return tr("Sent to"); + case TransactionRecord::SendToSelf: + return tr("Payment to yourself"); + case TransactionRecord::Generated: + return tr("Mined"); + default: + return QString(); + } +} + +QVariant TransactionTableModel::txAddressDecoration(const TransactionRecord *wtx) const +{ + switch(wtx->type) + { + case TransactionRecord::Generated: + return QIcon(":/icons/tx_mined"); + case TransactionRecord::RecvWithAddress: + case TransactionRecord::RecvFromOther: + return QIcon(":/icons/tx_input"); + case TransactionRecord::SendToAddress: + case TransactionRecord::SendToOther: + return QIcon(":/icons/tx_output"); + default: + return QIcon(":/icons/tx_inout"); + } + return QVariant(); +} + +QString TransactionTableModel::formatTxToAddress(const TransactionRecord *wtx, bool tooltip) const +{ + switch(wtx->type) + { + case TransactionRecord::RecvFromOther: + return QString::fromStdString(wtx->address); + case TransactionRecord::RecvWithAddress: + case TransactionRecord::SendToAddress: + case TransactionRecord::Generated: + return lookupAddress(wtx->address, tooltip); + case TransactionRecord::SendToOther: + return QString::fromStdString(wtx->address); + case TransactionRecord::SendToSelf: + default: + return tr("(n/a)"); + } +} + +QVariant TransactionTableModel::addressColor(const TransactionRecord *wtx) const +{ + // Show addresses without label in a less visible color + switch(wtx->type) + { + case TransactionRecord::RecvWithAddress: + case TransactionRecord::SendToAddress: + case TransactionRecord::Generated: + { + QString label = walletModel->getAddressTableModel()->labelForAddress(QString::fromStdString(wtx->address)); + if(label.isEmpty()) + return COLOR_BAREADDRESS; + } break; + case TransactionRecord::SendToSelf: + return COLOR_BAREADDRESS; + default: + break; + } + return QVariant(); +} + +QString TransactionTableModel::formatTxAmount(const TransactionRecord *wtx, bool showUnconfirmed) const +{ + QString str = BitcoinUnits::format(walletModel->getOptionsModel()->getDisplayUnit(), wtx->credit + wtx->debit); + if(showUnconfirmed) + { + if(!wtx->status.countsForBalance) + { + str = QString("[") + str + QString("]"); + } + } + return QString(str); +} + +QVariant TransactionTableModel::txStatusDecoration(const TransactionRecord *wtx) const +{ + switch(wtx->status.status) + { + case TransactionStatus::OpenUntilBlock: + case TransactionStatus::OpenUntilDate: + return QColor(64,64,255); + case TransactionStatus::Offline: + return QColor(192,192,192); + case TransactionStatus::Unconfirmed: + return QIcon(":/icons/transaction_0"); + case TransactionStatus::Confirming: + switch(wtx->status.depth) + { + case 1: return QIcon(":/icons/transaction_1"); + case 2: return QIcon(":/icons/transaction_2"); + case 3: return QIcon(":/icons/transaction_3"); + case 4: return QIcon(":/icons/transaction_4"); + default: return QIcon(":/icons/transaction_5"); + }; + case TransactionStatus::Confirmed: + return QIcon(":/icons/transaction_confirmed"); + case TransactionStatus::Conflicted: + return QIcon(":/icons/transaction_conflicted"); + case TransactionStatus::Immature: { + int total = wtx->status.depth + wtx->status.matures_in; + int part = (wtx->status.depth * 4 / total) + 1; + return QIcon(QString(":/icons/transaction_%1").arg(part)); + } + case TransactionStatus::MaturesWarning: + case TransactionStatus::NotAccepted: + return QIcon(":/icons/transaction_0"); + } + return QColor(0,0,0); +} + +QString TransactionTableModel::formatTooltip(const TransactionRecord *rec) const +{ + QString tooltip = formatTxStatus(rec) + QString("\n") + formatTxType(rec); + if(rec->type==TransactionRecord::RecvFromOther || rec->type==TransactionRecord::SendToOther || + rec->type==TransactionRecord::SendToAddress || rec->type==TransactionRecord::RecvWithAddress) + { + tooltip += QString(" ") + formatTxToAddress(rec, true); + } + return tooltip; +} + +QVariant TransactionTableModel::data(const QModelIndex &index, int role) const +{ + if(!index.isValid()) + return QVariant(); + TransactionRecord *rec = static_cast(index.internalPointer()); + + switch(role) + { + case Qt::DecorationRole: + switch(index.column()) + { + case Status: + return txStatusDecoration(rec); + case ToAddress: + return txAddressDecoration(rec); + } + break; + case Qt::DisplayRole: + switch(index.column()) + { + case Date: + return formatTxDate(rec); + case Type: + return formatTxType(rec); + case ToAddress: + return formatTxToAddress(rec, false); + case Amount: + return formatTxAmount(rec); + } + break; + case Qt::EditRole: + // Edit role is used for sorting, so return the unformatted values + switch(index.column()) + { + case Status: + return QString::fromStdString(rec->status.sortKey); + case Date: + return rec->time; + case Type: + return formatTxType(rec); + case ToAddress: + return formatTxToAddress(rec, true); + case Amount: + return rec->credit + rec->debit; + } + break; + case Qt::ToolTipRole: + return formatTooltip(rec); + case Qt::TextAlignmentRole: + return column_alignments[index.column()]; + case Qt::ForegroundRole: + // Non-confirmed (but not immature) as transactions are grey + if(!rec->status.countsForBalance && rec->status.status != TransactionStatus::Immature) + { + return COLOR_UNCONFIRMED; + } + if(index.column() == Amount && (rec->credit+rec->debit) < 0) + { + return COLOR_NEGATIVE; + } + if(index.column() == Amount && rec->type != TransactionRecord::Generated && (rec->credit+rec->debit) > 0) + { + return fUseBlackTheme ? QColor(0, 255, 0) : QColor(0, 128, 0); + } + if(index.column() == ToAddress) + { + return addressColor(rec); + } + break; + case TypeRole: + return rec->type; + case DateRole: + return QDateTime::fromTime_t(static_cast(rec->time)); + case LongDescriptionRole: + return priv->describe(rec); + case AddressRole: + return QString::fromStdString(rec->address); + case LabelRole: + return walletModel->getAddressTableModel()->labelForAddress(QString::fromStdString(rec->address)); + case AmountRole: + return rec->credit + rec->debit; + case TxIDRole: + return QString::fromStdString(rec->getTxID()); + case ConfirmedRole: + return rec->status.countsForBalance; + case FormattedAmountRole: + return formatTxAmount(rec, false); + case StatusRole: + return rec->status.status; + } + return QVariant(); +} + +QVariant TransactionTableModel::headerData(int section, Qt::Orientation orientation, int role) const +{ + if(orientation == Qt::Horizontal) + { + if(role == Qt::DisplayRole) + { + return columns[section]; + } + else if (role == Qt::TextAlignmentRole) + { + return column_alignments[section]; + } else if (role == Qt::ToolTipRole) + { + switch(section) + { + case Status: + return tr("Transaction status. Hover over this field to show number of confirmations."); + case Date: + return tr("Date and time that the transaction was received."); + case Type: + return tr("Type of transaction."); + case ToAddress: + return tr("Destination address of transaction."); + case Amount: + return tr("Amount removed from or added to balance."); + } + } + } + return QVariant(); +} + +QModelIndex TransactionTableModel::index(int row, int column, const QModelIndex &parent) const +{ + Q_UNUSED(parent); + TransactionRecord *data = priv->index(row); + if(data) + { + return createIndex(row, column, priv->index(row)); + } + else + { + return QModelIndex(); + } +} + +void TransactionTableModel::updateDisplayUnit() +{ + // emit dataChanged to update Amount column with the current unit + emit dataChanged(index(0, Amount), index(priv->size()-1, Amount)); +} diff --git a/src/qt/transactiontablemodel.h b/src/qt/transactiontablemodel.h new file mode 100755 index 0000000..779bd3b --- /dev/null +++ b/src/qt/transactiontablemodel.h @@ -0,0 +1,86 @@ +#ifndef TRANSACTIONTABLEMODEL_H +#define TRANSACTIONTABLEMODEL_H + +#include +#include + +class CWallet; +class TransactionTablePriv; +class TransactionRecord; +class WalletModel; + +/** UI model for the transaction table of a wallet. + */ +class TransactionTableModel : public QAbstractTableModel +{ + Q_OBJECT +public: + explicit TransactionTableModel(CWallet* wallet, WalletModel *parent = 0); + ~TransactionTableModel(); + + enum ColumnIndex { + Status = 0, + Date = 1, + Type = 2, + ToAddress = 3, + Amount = 4 + }; + + /** Roles to get specific information from a transaction row. + These are independent of column. + */ + enum RoleIndex { + /** Type of transaction */ + TypeRole = Qt::UserRole, + /** Date and time this transaction was created */ + DateRole, + /** Long description (HTML format) */ + LongDescriptionRole, + /** Address of transaction */ + AddressRole, + /** Label of address related to transaction */ + LabelRole, + /** Net amount of transaction */ + AmountRole, + /** Unique identifier */ + TxIDRole, + /** Is transaction confirmed? */ + ConfirmedRole, + /** Formatted amount, without brackets when unconfirmed */ + FormattedAmountRole, + /** Transaction status (TransactionRecord::Status) */ + StatusRole + }; + + int rowCount(const QModelIndex &parent) const; + int columnCount(const QModelIndex &parent) const; + QVariant data(const QModelIndex &index, int role) const; + QVariant headerData(int section, Qt::Orientation orientation, int role) const; + QModelIndex index(int row, int column, const QModelIndex & parent = QModelIndex()) const; +private: + CWallet* wallet; + WalletModel *walletModel; + QStringList columns; + TransactionTablePriv *priv; + + QString lookupAddress(const std::string &address, bool tooltip) const; + QVariant addressColor(const TransactionRecord *wtx) const; + QString formatTxStatus(const TransactionRecord *wtx) const; + QString formatTxDate(const TransactionRecord *wtx) const; + QString formatTxType(const TransactionRecord *wtx) const; + QString formatTxToAddress(const TransactionRecord *wtx, bool tooltip) const; + QString formatTxAmount(const TransactionRecord *wtx, bool showUnconfirmed=true) const; + QString formatTooltip(const TransactionRecord *rec) const; + QVariant txStatusDecoration(const TransactionRecord *wtx) const; + QVariant txAddressDecoration(const TransactionRecord *wtx) const; + +public slots: + void updateTransaction(const QString &hash, int status); + void updateConfirmations(); + void updateDisplayUnit(); + + friend class TransactionTablePriv; +}; + +#endif + diff --git a/src/qt/transactionview.cpp b/src/qt/transactionview.cpp new file mode 100755 index 0000000..a4eb9f7 --- /dev/null +++ b/src/qt/transactionview.cpp @@ -0,0 +1,439 @@ +#include "transactionview.h" + +#include "transactionfilterproxy.h" +#include "transactionrecord.h" +#include "walletmodel.h" +#include "addresstablemodel.h" +#include "transactiontablemodel.h" +#include "bitcoinunits.h" +#include "csvmodelwriter.h" +#include "transactiondescdialog.h" +#include "editaddressdialog.h" +#include "optionsmodel.h" +#include "guiutil.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +TransactionView::TransactionView(QWidget *parent) : + QWidget(parent), model(0), transactionProxyModel(0), + transactionView(0) +{ + // Build filter row + setContentsMargins(0,0,0,0); + + QHBoxLayout *hlayout = new QHBoxLayout(); + hlayout->setContentsMargins(0,0,0,0); +#ifdef Q_OS_MAC + hlayout->setSpacing(5); + hlayout->addSpacing(26); +#else + hlayout->setSpacing(0); + hlayout->addSpacing(23); +#endif + + dateWidget = new QComboBox(this); +#ifdef Q_OS_MAC + dateWidget->setFixedWidth(121); +#else + dateWidget->setFixedWidth(120); +#endif + dateWidget->addItem(tr("All"), All); + dateWidget->addItem(tr("Today"), Today); + dateWidget->addItem(tr("This week"), ThisWeek); + dateWidget->addItem(tr("This month"), ThisMonth); + dateWidget->addItem(tr("Last month"), LastMonth); + dateWidget->addItem(tr("This year"), ThisYear); + dateWidget->addItem(tr("Range..."), Range); + hlayout->addWidget(dateWidget); + + typeWidget = new QComboBox(this); +#ifdef Q_OS_MAC + typeWidget->setFixedWidth(121); +#else + typeWidget->setFixedWidth(120); +#endif + + typeWidget->addItem(tr("All"), TransactionFilterProxy::ALL_TYPES); + typeWidget->addItem(tr("Received with"), TransactionFilterProxy::TYPE(TransactionRecord::RecvWithAddress) | + TransactionFilterProxy::TYPE(TransactionRecord::RecvFromOther)); + typeWidget->addItem(tr("Sent to"), TransactionFilterProxy::TYPE(TransactionRecord::SendToAddress) | + TransactionFilterProxy::TYPE(TransactionRecord::SendToOther)); + typeWidget->addItem(tr("To yourself"), TransactionFilterProxy::TYPE(TransactionRecord::SendToSelf)); + typeWidget->addItem(tr("Mined"), TransactionFilterProxy::TYPE(TransactionRecord::Generated)); + typeWidget->addItem(tr("Other"), TransactionFilterProxy::TYPE(TransactionRecord::Other)); + + hlayout->addWidget(typeWidget); + + addressWidget = new QLineEdit(this); +#if QT_VERSION >= 0x040700 + /* Do not move this to the XML file, Qt before 4.7 will choke on it */ + addressWidget->setPlaceholderText(tr("Enter address or label to search")); +#endif + hlayout->addWidget(addressWidget); + + amountWidget = new QLineEdit(this); +#if QT_VERSION >= 0x040700 + /* Do not move this to the XML file, Qt before 4.7 will choke on it */ + amountWidget->setPlaceholderText(tr("Min amount")); +#endif +#ifdef Q_OS_MAC + amountWidget->setFixedWidth(97); +#else + amountWidget->setFixedWidth(100); +#endif + amountWidget->setValidator(new QDoubleValidator(0, 1e20, 8, this)); + hlayout->addWidget(amountWidget); + + QVBoxLayout *vlayout = new QVBoxLayout(this); + vlayout->setContentsMargins(0,0,0,0); + vlayout->setSpacing(0); + + QTableView *view = new QTableView(this); + vlayout->addLayout(hlayout); + vlayout->addWidget(createDateRangeWidget()); + vlayout->addWidget(view); + vlayout->setSpacing(0); + int width = view->verticalScrollBar()->sizeHint().width(); + // Cover scroll bar width with spacing +#ifdef Q_OS_MAC + hlayout->addSpacing(width+2); +#else + hlayout->addSpacing(width); +#endif + // Always show scroll bar + view->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn); + view->setTabKeyNavigation(false); + view->setContextMenuPolicy(Qt::CustomContextMenu); + + transactionView = view; + + // Actions + QAction *copyAddressAction = new QAction(tr("Copy address"), this); + QAction *copyLabelAction = new QAction(tr("Copy label"), this); + QAction *copyAmountAction = new QAction(tr("Copy amount"), this); + QAction *copyTxIDAction = new QAction(tr("Copy transaction ID"), this); + QAction *editLabelAction = new QAction(tr("Edit label"), this); + QAction *showDetailsAction = new QAction(tr("Show transaction details"), this); + + contextMenu = new QMenu(); + contextMenu->addAction(copyAddressAction); + contextMenu->addAction(copyLabelAction); + contextMenu->addAction(copyAmountAction); + contextMenu->addAction(copyTxIDAction); + contextMenu->addAction(editLabelAction); + contextMenu->addAction(showDetailsAction); + + // Connect actions + connect(dateWidget, SIGNAL(activated(int)), this, SLOT(chooseDate(int))); + connect(typeWidget, SIGNAL(activated(int)), this, SLOT(chooseType(int))); + connect(addressWidget, SIGNAL(textChanged(QString)), this, SLOT(changedPrefix(QString))); + connect(amountWidget, SIGNAL(textChanged(QString)), this, SLOT(changedAmount(QString))); + + connect(view, SIGNAL(doubleClicked(QModelIndex)), this, SIGNAL(doubleClicked(QModelIndex))); + connect(view, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(contextualMenu(QPoint))); + + connect(copyAddressAction, SIGNAL(triggered()), this, SLOT(copyAddress())); + connect(copyLabelAction, SIGNAL(triggered()), this, SLOT(copyLabel())); + connect(copyAmountAction, SIGNAL(triggered()), this, SLOT(copyAmount())); + connect(copyTxIDAction, SIGNAL(triggered()), this, SLOT(copyTxID())); + connect(editLabelAction, SIGNAL(triggered()), this, SLOT(editLabel())); + connect(showDetailsAction, SIGNAL(triggered()), this, SLOT(showDetails())); +} + +void TransactionView::setModel(WalletModel *model) +{ + this->model = model; + if(model) + { + transactionProxyModel = new TransactionFilterProxy(this); + transactionProxyModel->setSourceModel(model->getTransactionTableModel()); + transactionProxyModel->setDynamicSortFilter(true); + transactionProxyModel->setSortCaseSensitivity(Qt::CaseInsensitive); + transactionProxyModel->setFilterCaseSensitivity(Qt::CaseInsensitive); + + transactionProxyModel->setSortRole(Qt::EditRole); + + transactionView->setModel(transactionProxyModel); + transactionView->setAlternatingRowColors(true); + transactionView->setSelectionBehavior(QAbstractItemView::SelectRows); + transactionView->setSelectionMode(QAbstractItemView::ExtendedSelection); + transactionView->setSortingEnabled(true); + transactionView->sortByColumn(TransactionTableModel::Date, Qt::DescendingOrder); + transactionView->verticalHeader()->hide(); + + transactionView->horizontalHeader()->resizeSection( + TransactionTableModel::Status, 23); + transactionView->horizontalHeader()->resizeSection( + TransactionTableModel::Date, 120); + transactionView->horizontalHeader()->resizeSection( + TransactionTableModel::Type, 120); + transactionView->horizontalHeader()->setResizeMode( + TransactionTableModel::ToAddress, QHeaderView::Stretch); + transactionView->horizontalHeader()->resizeSection( + TransactionTableModel::Amount, 100); + } +} + +void TransactionView::chooseDate(int idx) +{ + if(!transactionProxyModel) + return; + QDate current = QDate::currentDate(); + dateRangeWidget->setVisible(false); + switch(dateWidget->itemData(idx).toInt()) + { + case All: + transactionProxyModel->setDateRange( + TransactionFilterProxy::MIN_DATE, + TransactionFilterProxy::MAX_DATE); + break; + case Today: + transactionProxyModel->setDateRange( + QDateTime(current), + TransactionFilterProxy::MAX_DATE); + break; + case ThisWeek: { + // Find last Monday + QDate startOfWeek = current.addDays(-(current.dayOfWeek()-1)); + transactionProxyModel->setDateRange( + QDateTime(startOfWeek), + TransactionFilterProxy::MAX_DATE); + + } break; + case ThisMonth: + transactionProxyModel->setDateRange( + QDateTime(QDate(current.year(), current.month(), 1)), + TransactionFilterProxy::MAX_DATE); + break; + case LastMonth: + transactionProxyModel->setDateRange( + QDateTime(QDate(current.year(), current.month()-1, 1)), + QDateTime(QDate(current.year(), current.month(), 1))); + break; + case ThisYear: + transactionProxyModel->setDateRange( + QDateTime(QDate(current.year(), 1, 1)), + TransactionFilterProxy::MAX_DATE); + break; + case Range: + dateRangeWidget->setVisible(true); + dateRangeChanged(); + break; + } +} + +void TransactionView::chooseType(int idx) +{ + if(!transactionProxyModel) + return; + transactionProxyModel->setTypeFilter( + typeWidget->itemData(idx).toInt()); +} + +void TransactionView::changedPrefix(const QString &prefix) +{ + if(!transactionProxyModel) + return; + transactionProxyModel->setAddressPrefix(prefix); +} + +void TransactionView::changedAmount(const QString &amount) +{ + if(!transactionProxyModel) + return; + qint64 amount_parsed = 0; + if(BitcoinUnits::parse(model->getOptionsModel()->getDisplayUnit(), amount, &amount_parsed)) + { + transactionProxyModel->setMinAmount(amount_parsed); + } + else + { + transactionProxyModel->setMinAmount(0); + } +} + +void TransactionView::exportClicked() +{ + // CSV is currently the only supported format + QString filename = GUIUtil::getSaveFileName( + this, + tr("Export Transaction Data"), QString(), + tr("Comma separated file (*.csv)")); + + if (filename.isNull()) return; + + CSVModelWriter writer(filename); + + // name, column, role + writer.setModel(transactionProxyModel); + writer.addColumn(tr("Confirmed"), 0, TransactionTableModel::ConfirmedRole); + writer.addColumn(tr("Date"), 0, TransactionTableModel::DateRole); + writer.addColumn(tr("Type"), TransactionTableModel::Type, Qt::EditRole); + writer.addColumn(tr("Label"), 0, TransactionTableModel::LabelRole); + writer.addColumn(tr("Address"), 0, TransactionTableModel::AddressRole); + writer.addColumn(tr("Amount"), 0, TransactionTableModel::FormattedAmountRole); + writer.addColumn(tr("ID"), 0, TransactionTableModel::TxIDRole); + + if(!writer.write()) + { + QMessageBox::critical(this, tr("Error exporting"), tr("Could not write to file %1.").arg(filename), + QMessageBox::Abort, QMessageBox::Abort); + } +} + +void TransactionView::contextualMenu(const QPoint &point) +{ + QModelIndex index = transactionView->indexAt(point); + if(index.isValid()) + { + contextMenu->exec(QCursor::pos()); + } +} + +void TransactionView::copyAddress() +{ + GUIUtil::copyEntryData(transactionView, 0, TransactionTableModel::AddressRole); +} + +void TransactionView::copyLabel() +{ + GUIUtil::copyEntryData(transactionView, 0, TransactionTableModel::LabelRole); +} + +void TransactionView::copyAmount() +{ + GUIUtil::copyEntryData(transactionView, 0, TransactionTableModel::FormattedAmountRole); +} + +void TransactionView::copyTxID() +{ + GUIUtil::copyEntryData(transactionView, 0, TransactionTableModel::TxIDRole); +} + +void TransactionView::editLabel() +{ + if(!transactionView->selectionModel() ||!model) + return; + QModelIndexList selection = transactionView->selectionModel()->selectedRows(); + if(!selection.isEmpty()) + { + AddressTableModel *addressBook = model->getAddressTableModel(); + if(!addressBook) + return; + QString address = selection.at(0).data(TransactionTableModel::AddressRole).toString(); + if(address.isEmpty()) + { + // If this transaction has no associated address, exit + return; + } + // Is address in address book? Address book can miss address when a transaction is + // sent from outside the UI. + int idx = addressBook->lookupAddress(address); + if(idx != -1) + { + // Edit sending / receiving address + QModelIndex modelIdx = addressBook->index(idx, 0, QModelIndex()); + // Determine type of address, launch appropriate editor dialog type + QString type = modelIdx.data(AddressTableModel::TypeRole).toString(); + + EditAddressDialog dlg(type==AddressTableModel::Receive + ? EditAddressDialog::EditReceivingAddress + : EditAddressDialog::EditSendingAddress, + this); + dlg.setModel(addressBook); + dlg.loadRow(idx); + dlg.exec(); + } + else + { + // Add sending address + EditAddressDialog dlg(EditAddressDialog::NewSendingAddress, + this); + dlg.setModel(addressBook); + dlg.setAddress(address); + dlg.exec(); + } + } +} + +void TransactionView::showDetails() +{ + if(!transactionView->selectionModel()) + return; + QModelIndexList selection = transactionView->selectionModel()->selectedRows(); + if(!selection.isEmpty()) + { + TransactionDescDialog dlg(selection.at(0)); + dlg.exec(); + } +} + +QWidget *TransactionView::createDateRangeWidget() +{ + dateRangeWidget = new QFrame(); + dateRangeWidget->setFrameStyle(QFrame::Panel | QFrame::Raised); + dateRangeWidget->setContentsMargins(1,1,1,1); + QHBoxLayout *layout = new QHBoxLayout(dateRangeWidget); + layout->setContentsMargins(0,0,0,0); + layout->addSpacing(23); + layout->addWidget(new QLabel(tr("Range:"))); + + dateFrom = new QDateTimeEdit(this); + dateFrom->setDisplayFormat("dd/MM/yy"); + dateFrom->setCalendarPopup(true); + dateFrom->setMinimumWidth(100); + dateFrom->setDate(QDate::currentDate().addDays(-7)); + layout->addWidget(dateFrom); + layout->addWidget(new QLabel(tr("to"))); + + dateTo = new QDateTimeEdit(this); + dateTo->setDisplayFormat("dd/MM/yy"); + dateTo->setCalendarPopup(true); + dateTo->setMinimumWidth(100); + dateTo->setDate(QDate::currentDate()); + layout->addWidget(dateTo); + layout->addStretch(); + + // Hide by default + dateRangeWidget->setVisible(false); + + // Notify on change + connect(dateFrom, SIGNAL(dateChanged(QDate)), this, SLOT(dateRangeChanged())); + connect(dateTo, SIGNAL(dateChanged(QDate)), this, SLOT(dateRangeChanged())); + + return dateRangeWidget; +} + +void TransactionView::dateRangeChanged() +{ + if(!transactionProxyModel) + return; + transactionProxyModel->setDateRange( + QDateTime(dateFrom->date()), + QDateTime(dateTo->date()).addDays(1)); +} + +void TransactionView::focusTransaction(const QModelIndex &idx) +{ + if(!transactionProxyModel) + return; + QModelIndex targetIdx = transactionProxyModel->mapFromSource(idx); + transactionView->scrollTo(targetIdx); + transactionView->setCurrentIndex(targetIdx); + transactionView->setFocus(); +} diff --git a/src/qt/transactionview.h b/src/qt/transactionview.h new file mode 100755 index 0000000..81b4f05 --- /dev/null +++ b/src/qt/transactionview.h @@ -0,0 +1,83 @@ +#ifndef TRANSACTIONVIEW_H +#define TRANSACTIONVIEW_H + +#include + +class WalletModel; +class TransactionFilterProxy; + +QT_BEGIN_NAMESPACE +class QTableView; +class QComboBox; +class QLineEdit; +class QModelIndex; +class QMenu; +class QFrame; +class QDateTimeEdit; +QT_END_NAMESPACE + +/** Widget showing the transaction list for a wallet, including a filter row. + Using the filter row, the user can view or export a subset of the transactions. + */ +class TransactionView : public QWidget +{ + Q_OBJECT +public: + explicit TransactionView(QWidget *parent = 0); + + void setModel(WalletModel *model); + + // Date ranges for filter + enum DateEnum + { + All, + Today, + ThisWeek, + ThisMonth, + LastMonth, + ThisYear, + Range + }; + +private: + WalletModel *model; + TransactionFilterProxy *transactionProxyModel; + QTableView *transactionView; + + QComboBox *dateWidget; + QComboBox *typeWidget; + QLineEdit *addressWidget; + QLineEdit *amountWidget; + + QMenu *contextMenu; + + QFrame *dateRangeWidget; + QDateTimeEdit *dateFrom; + QDateTimeEdit *dateTo; + + QWidget *createDateRangeWidget(); + +private slots: + void contextualMenu(const QPoint &); + void dateRangeChanged(); + void showDetails(); + void copyAddress(); + void editLabel(); + void copyLabel(); + void copyAmount(); + void copyTxID(); + +signals: + void doubleClicked(const QModelIndex&); + +public slots: + void chooseDate(int idx); + void chooseType(int idx); + void changedPrefix(const QString &prefix); + void changedAmount(const QString &amount); + void exportClicked(); + void focusTransaction(const QModelIndex&); + +}; + +#endif // TRANSACTIONVIEW_H diff --git a/src/qt/walletmodel.cpp b/src/qt/walletmodel.cpp new file mode 100755 index 0000000..9b5249a --- /dev/null +++ b/src/qt/walletmodel.cpp @@ -0,0 +1,484 @@ +#include "walletmodel.h" +#include "guiconstants.h" +#include "optionsmodel.h" +#include "addresstablemodel.h" +#include "transactiontablemodel.h" + +#include "ui_interface.h" +#include "wallet.h" +#include "walletdb.h" // for BackupWallet +#include "base58.h" + +#include +#include + +WalletModel::WalletModel(CWallet *wallet, OptionsModel *optionsModel, QObject *parent) : + QObject(parent), wallet(wallet), optionsModel(optionsModel), addressTableModel(0), + transactionTableModel(0), + cachedBalance(0), cachedStake(0), cachedUnconfirmedBalance(0), cachedImmatureBalance(0), + cachedNumTransactions(0), + cachedEncryptionStatus(Unencrypted), + cachedNumBlocks(0) +{ + addressTableModel = new AddressTableModel(wallet, this); + transactionTableModel = new TransactionTableModel(wallet, this); + + // This timer will be fired repeatedly to update the balance + pollTimer = new QTimer(this); + connect(pollTimer, SIGNAL(timeout()), this, SLOT(pollBalanceChanged())); + pollTimer->start(MODEL_UPDATE_DELAY); + + subscribeToCoreSignals(); +} + +WalletModel::~WalletModel() +{ + unsubscribeFromCoreSignals(); +} + +qint64 WalletModel::getBalance() const +{ + return wallet->GetBalance(); +} + +qint64 WalletModel::getUnconfirmedBalance() const +{ + return wallet->GetUnconfirmedBalance(); +} + +qint64 WalletModel::getStake() const +{ + return wallet->GetStake(); +} + +qint64 WalletModel::getImmatureBalance() const +{ + return wallet->GetImmatureBalance(); +} + +int WalletModel::getNumTransactions() const +{ + int numTransactions = 0; + { + LOCK(wallet->cs_wallet); + numTransactions = wallet->mapWallet.size(); + } + return numTransactions; +} + +void WalletModel::updateStatus() +{ + EncryptionStatus newEncryptionStatus = getEncryptionStatus(); + + if(cachedEncryptionStatus != newEncryptionStatus) + emit encryptionStatusChanged(newEncryptionStatus); +} + +void WalletModel::pollBalanceChanged() +{ + // Get required locks upfront. This avoids the GUI from getting stuck on + // periodical polls if the core is holding the locks for a longer time - + // for example, during a wallet rescan. + TRY_LOCK(cs_main, lockMain); + if(!lockMain) + return; + TRY_LOCK(wallet->cs_wallet, lockWallet); + if(!lockWallet) + return; + + if(nBestHeight != cachedNumBlocks) + { + // Balance and number of transactions might have changed + cachedNumBlocks = nBestHeight; + + checkBalanceChanged(); + if(transactionTableModel) + transactionTableModel->updateConfirmations(); + } +} + +void WalletModel::checkBalanceChanged() +{ + qint64 newBalance = getBalance(); + qint64 newStake = getStake(); + qint64 newUnconfirmedBalance = getUnconfirmedBalance(); + qint64 newImmatureBalance = getImmatureBalance(); + + if(cachedBalance != newBalance || cachedStake != newStake || cachedUnconfirmedBalance != newUnconfirmedBalance || cachedImmatureBalance != newImmatureBalance) + { + cachedBalance = newBalance; + cachedStake = newStake; + cachedUnconfirmedBalance = newUnconfirmedBalance; + cachedImmatureBalance = newImmatureBalance; + emit balanceChanged(newBalance, newStake, newUnconfirmedBalance, newImmatureBalance); + } +} + +void WalletModel::updateTransaction(const QString &hash, int status) +{ + if(transactionTableModel) + transactionTableModel->updateTransaction(hash, status); + + // Balance and number of transactions might have changed + checkBalanceChanged(); + + int newNumTransactions = getNumTransactions(); + if(cachedNumTransactions != newNumTransactions) + { + cachedNumTransactions = newNumTransactions; + emit numTransactionsChanged(newNumTransactions); + } +} + +void WalletModel::updateAddressBook(const QString &address, const QString &label, bool isMine, int status) +{ + if(addressTableModel) + addressTableModel->updateEntry(address, label, isMine, status); +} + +bool WalletModel::validateAddress(const QString &address) +{ + CBitcoinAddress addressParsed(address.toStdString()); + return addressParsed.IsValid(); +} + +WalletModel::SendCoinsReturn WalletModel::sendCoins(const QList &recipients, const CCoinControl *coinControl) +{ + qint64 total = 0; + QSet setAddress; + QString hex; + + if(recipients.empty()) + { + return OK; + } + + // Pre-check input data for validity + foreach(const SendCoinsRecipient &rcp, recipients) + { + if(!validateAddress(rcp.address)) + { + return InvalidAddress; + } + setAddress.insert(rcp.address); + + if(rcp.amount <= 0) + { + return InvalidAmount; + } + total += rcp.amount; + } + + if(recipients.size() > setAddress.size()) + { + return DuplicateAddress; + } + + int64_t nBalance = 0; + std::vector vCoins; + wallet->AvailableCoins(vCoins, true, coinControl); + + BOOST_FOREACH(const COutput& out, vCoins) + nBalance += out.tx->vout[out.i].nValue; + + if(total > nBalance) + { + return AmountExceedsBalance; + } + + if((total + nTransactionFee) > nBalance) + { + return SendCoinsReturn(AmountWithFeeExceedsBalance, nTransactionFee); + } + + { + LOCK2(cs_main, wallet->cs_wallet); + + // Sendmany + std::vector > vecSend; + foreach(const SendCoinsRecipient &rcp, recipients) + { + CScript scriptPubKey; + scriptPubKey.SetDestination(CBitcoinAddress(rcp.address.toStdString()).Get()); + vecSend.push_back(make_pair(scriptPubKey, rcp.amount)); + } + + CWalletTx wtx; + CReserveKey keyChange(wallet); + int64_t nFeeRequired = 0; + bool fCreated = wallet->CreateTransaction(vecSend, wtx, keyChange, nFeeRequired, coinControl); + + if(!fCreated) + { + if((total + nFeeRequired) > nBalance) // FIXME: could cause collisions in the future + { + return SendCoinsReturn(AmountWithFeeExceedsBalance, nFeeRequired); + } + return TransactionCreationFailed; + } + if(!uiInterface.ThreadSafeAskFee(nFeeRequired, tr("Sending...").toStdString())) + { + return Aborted; + } + if(!wallet->CommitTransaction(wtx, keyChange)) + { + return TransactionCommitFailed; + } + hex = QString::fromStdString(wtx.GetHash().GetHex()); + } + + // Add addresses / update labels that we've sent to to the address book + foreach(const SendCoinsRecipient &rcp, recipients) + { + std::string strAddress = rcp.address.toStdString(); + CTxDestination dest = CBitcoinAddress(strAddress).Get(); + std::string strLabel = rcp.label.toStdString(); + { + LOCK(wallet->cs_wallet); + + std::map::iterator mi = wallet->mapAddressBook.find(dest); + + // Check if we have a new address or an updated label + if (mi == wallet->mapAddressBook.end() || mi->second != strLabel) + { + wallet->SetAddressBookName(dest, strLabel); + } + } + } + + return SendCoinsReturn(OK, 0, hex); +} + +OptionsModel *WalletModel::getOptionsModel() +{ + return optionsModel; +} + +AddressTableModel *WalletModel::getAddressTableModel() +{ + return addressTableModel; +} + +TransactionTableModel *WalletModel::getTransactionTableModel() +{ + return transactionTableModel; +} + +WalletModel::EncryptionStatus WalletModel::getEncryptionStatus() const +{ + if(!wallet->IsCrypted()) + { + return Unencrypted; + } + else if(wallet->IsLocked()) + { + return Locked; + } + else + { + return Unlocked; + } +} + +bool WalletModel::setWalletEncrypted(bool encrypted, const SecureString &passphrase) +{ + if(encrypted) + { + // Encrypt + return wallet->EncryptWallet(passphrase); + } + else + { + // Decrypt -- TODO; not supported yet + return false; + } +} + +bool WalletModel::setWalletLocked(bool locked, const SecureString &passPhrase) +{ + if(locked) + { + // Lock + return wallet->Lock(); + } + else + { + // Unlock + return wallet->Unlock(passPhrase); + } +} + +bool WalletModel::changePassphrase(const SecureString &oldPass, const SecureString &newPass) +{ + bool retval; + { + LOCK(wallet->cs_wallet); + wallet->Lock(); // Make sure wallet is locked before attempting pass change + retval = wallet->ChangeWalletPassphrase(oldPass, newPass); + } + return retval; +} + +bool WalletModel::backupWallet(const QString &filename) +{ + return BackupWallet(*wallet, filename.toLocal8Bit().data()); +} + +// Handlers for core signals +static void NotifyKeyStoreStatusChanged(WalletModel *walletmodel, CCryptoKeyStore *wallet) +{ + OutputDebugStringF("NotifyKeyStoreStatusChanged\n"); + QMetaObject::invokeMethod(walletmodel, "updateStatus", Qt::QueuedConnection); +} + +static void NotifyAddressBookChanged(WalletModel *walletmodel, CWallet *wallet, const CTxDestination &address, const std::string &label, bool isMine, ChangeType status) +{ + OutputDebugStringF("NotifyAddressBookChanged %s %s isMine=%i status=%i\n", CBitcoinAddress(address).ToString().c_str(), label.c_str(), isMine, status); + QMetaObject::invokeMethod(walletmodel, "updateAddressBook", Qt::QueuedConnection, + Q_ARG(QString, QString::fromStdString(CBitcoinAddress(address).ToString())), + Q_ARG(QString, QString::fromStdString(label)), + Q_ARG(bool, isMine), + Q_ARG(int, status)); +} + +static void NotifyTransactionChanged(WalletModel *walletmodel, CWallet *wallet, const uint256 &hash, ChangeType status) +{ + OutputDebugStringF("NotifyTransactionChanged %s status=%i\n", hash.GetHex().c_str(), status); + QMetaObject::invokeMethod(walletmodel, "updateTransaction", Qt::QueuedConnection, + Q_ARG(QString, QString::fromStdString(hash.GetHex())), + Q_ARG(int, status)); +} + +void WalletModel::subscribeToCoreSignals() +{ + // Connect signals to wallet + wallet->NotifyStatusChanged.connect(boost::bind(&NotifyKeyStoreStatusChanged, this, _1)); + wallet->NotifyAddressBookChanged.connect(boost::bind(NotifyAddressBookChanged, this, _1, _2, _3, _4, _5)); + wallet->NotifyTransactionChanged.connect(boost::bind(NotifyTransactionChanged, this, _1, _2, _3)); +} + +void WalletModel::unsubscribeFromCoreSignals() +{ + // Disconnect signals from wallet + wallet->NotifyStatusChanged.disconnect(boost::bind(&NotifyKeyStoreStatusChanged, this, _1)); + wallet->NotifyAddressBookChanged.disconnect(boost::bind(NotifyAddressBookChanged, this, _1, _2, _3, _4, _5)); + wallet->NotifyTransactionChanged.disconnect(boost::bind(NotifyTransactionChanged, this, _1, _2, _3)); +} + +// WalletModel::UnlockContext implementation +WalletModel::UnlockContext WalletModel::requestUnlock() +{ + bool was_locked = getEncryptionStatus() == Locked; + + if ((!was_locked) && fWalletUnlockStakingOnly) + { + setWalletLocked(true); + was_locked = getEncryptionStatus() == Locked; + + } + if(was_locked) + { + // Request UI to unlock wallet + emit requireUnlock(); + } + // If wallet is still locked, unlock was failed or cancelled, mark context as invalid + bool valid = getEncryptionStatus() != Locked; + + return UnlockContext(this, valid, was_locked && !fWalletUnlockStakingOnly); +} + +WalletModel::UnlockContext::UnlockContext(WalletModel *wallet, bool valid, bool relock): + wallet(wallet), + valid(valid), + relock(relock) +{ +} + +WalletModel::UnlockContext::~UnlockContext() +{ + if(valid && relock) + { + wallet->setWalletLocked(true); + } +} + +void WalletModel::UnlockContext::CopyFrom(const UnlockContext& rhs) +{ + // Transfer context; old object no longer relocks wallet + *this = rhs; + rhs.relock = false; +} + +bool WalletModel::getPubKey(const CKeyID &address, CPubKey& vchPubKeyOut) const +{ + return wallet->GetPubKey(address, vchPubKeyOut); +} + +// returns a list of COutputs from COutPoints +void WalletModel::getOutputs(const std::vector& vOutpoints, std::vector& vOutputs) +{ + LOCK2(cs_main, wallet->cs_wallet); + BOOST_FOREACH(const COutPoint& outpoint, vOutpoints) + { + if (!wallet->mapWallet.count(outpoint.hash)) continue; + int nDepth = wallet->mapWallet[outpoint.hash].GetDepthInMainChain(); + if (nDepth < 0) continue; + COutput out(&wallet->mapWallet[outpoint.hash], outpoint.n, nDepth); + vOutputs.push_back(out); + } +} + +// AvailableCoins + LockedCoins grouped by wallet address (put change in one group with wallet address) +void WalletModel::listCoins(std::map >& mapCoins) const +{ + std::vector vCoins; + wallet->AvailableCoins(vCoins); + + LOCK2(cs_main, wallet->cs_wallet); // ListLockedCoins, mapWallet + std::vector vLockedCoins; + + // add locked coins + BOOST_FOREACH(const COutPoint& outpoint, vLockedCoins) + { + if (!wallet->mapWallet.count(outpoint.hash)) continue; + int nDepth = wallet->mapWallet[outpoint.hash].GetDepthInMainChain(); + if (nDepth < 0) continue; + COutput out(&wallet->mapWallet[outpoint.hash], outpoint.n, nDepth); + vCoins.push_back(out); + } + + BOOST_FOREACH(const COutput& out, vCoins) + { + COutput cout = out; + + while (wallet->IsChange(cout.tx->vout[cout.i]) && cout.tx->vin.size() > 0 && wallet->IsMine(cout.tx->vin[0])) + { + if (!wallet->mapWallet.count(cout.tx->vin[0].prevout.hash)) break; + cout = COutput(&wallet->mapWallet[cout.tx->vin[0].prevout.hash], cout.tx->vin[0].prevout.n, 0); + } + + CTxDestination address; + if(!ExtractDestination(cout.tx->vout[cout.i].scriptPubKey, address)) continue; + mapCoins[CBitcoinAddress(address).ToString().c_str()].push_back(out); + } +} + +bool WalletModel::isLockedCoin(uint256 hash, unsigned int n) const +{ + return false; +} + +void WalletModel::lockCoin(COutPoint& output) +{ + return; +} + +void WalletModel::unlockCoin(COutPoint& output) +{ + return; +} + +void WalletModel::listLockedCoins(std::vector& vOutpts) +{ + return; +} diff --git a/src/qt/walletmodel.h b/src/qt/walletmodel.h new file mode 100755 index 0000000..b33ff75 --- /dev/null +++ b/src/qt/walletmodel.h @@ -0,0 +1,185 @@ +#ifndef WALLETMODEL_H +#define WALLETMODEL_H + +#include +#include +#include + +#include "allocators.h" /* for SecureString */ + +class OptionsModel; +class AddressTableModel; +class TransactionTableModel; +class CWallet; +class CKeyID; +class CPubKey; +class COutput; +class COutPoint; +class uint256; +class CCoinControl; + +QT_BEGIN_NAMESPACE +class QTimer; +QT_END_NAMESPACE + +class SendCoinsRecipient +{ +public: + QString address; + QString label; + qint64 amount; +}; + +/** Interface to Bitcoin wallet from Qt view code. */ +class WalletModel : public QObject +{ + Q_OBJECT + +public: + explicit WalletModel(CWallet *wallet, OptionsModel *optionsModel, QObject *parent = 0); + ~WalletModel(); + + enum StatusCode // Returned by sendCoins + { + OK, + InvalidAmount, + InvalidAddress, + AmountExceedsBalance, + AmountWithFeeExceedsBalance, + DuplicateAddress, + TransactionCreationFailed, // Error returned when wallet is still locked + TransactionCommitFailed, + Aborted + }; + + enum EncryptionStatus + { + Unencrypted, // !wallet->IsCrypted() + Locked, // wallet->IsCrypted() && wallet->IsLocked() + Unlocked // wallet->IsCrypted() && !wallet->IsLocked() + }; + + OptionsModel *getOptionsModel(); + AddressTableModel *getAddressTableModel(); + TransactionTableModel *getTransactionTableModel(); + + qint64 getBalance() const; + qint64 getStake() const; + qint64 getUnconfirmedBalance() const; + qint64 getImmatureBalance() const; + int getNumTransactions() const; + EncryptionStatus getEncryptionStatus() const; + + // Check address for validity + bool validateAddress(const QString &address); + + // Return status record for SendCoins, contains error id + information + struct SendCoinsReturn + { + SendCoinsReturn(StatusCode status=Aborted, + qint64 fee=0, + QString hex=QString()): + status(status), fee(fee), hex(hex) {} + StatusCode status; + qint64 fee; // is used in case status is "AmountWithFeeExceedsBalance" + QString hex; // is filled with the transaction hash if status is "OK" + }; + + // Send coins to a list of recipients + SendCoinsReturn sendCoins(const QList &recipients, const CCoinControl *coinControl=NULL); + + // Wallet encryption + bool setWalletEncrypted(bool encrypted, const SecureString &passphrase); + // Passphrase only needed when unlocking + bool setWalletLocked(bool locked, const SecureString &passPhrase=SecureString()); + bool changePassphrase(const SecureString &oldPass, const SecureString &newPass); + // Wallet backup + bool backupWallet(const QString &filename); + + // RAI object for unlocking wallet, returned by requestUnlock() + class UnlockContext + { + public: + UnlockContext(WalletModel *wallet, bool valid, bool relock); + ~UnlockContext(); + + bool isValid() const { return valid; } + + // Copy operator and constructor transfer the context + UnlockContext(const UnlockContext& obj) { CopyFrom(obj); } + UnlockContext& operator=(const UnlockContext& rhs) { CopyFrom(rhs); return *this; } + private: + WalletModel *wallet; + bool valid; + mutable bool relock; // mutable, as it can be set to false by copying + + void CopyFrom(const UnlockContext& rhs); + }; + + UnlockContext requestUnlock(); + + bool getPubKey(const CKeyID &address, CPubKey& vchPubKeyOut) const; + void getOutputs(const std::vector& vOutpoints, std::vector& vOutputs); + void listCoins(std::map >& mapCoins) const; + bool isLockedCoin(uint256 hash, unsigned int n) const; + void lockCoin(COutPoint& output); + void unlockCoin(COutPoint& output); + void listLockedCoins(std::vector& vOutpts); + +private: + CWallet *wallet; + + // Wallet has an options model for wallet-specific options + // (transaction fee, for example) + OptionsModel *optionsModel; + + AddressTableModel *addressTableModel; + TransactionTableModel *transactionTableModel; + + // Cache some values to be able to detect changes + qint64 cachedBalance; + qint64 cachedStake; + qint64 cachedUnconfirmedBalance; + qint64 cachedImmatureBalance; + qint64 cachedNumTransactions; + EncryptionStatus cachedEncryptionStatus; + int cachedNumBlocks; + + QTimer *pollTimer; + + void subscribeToCoreSignals(); + void unsubscribeFromCoreSignals(); + void checkBalanceChanged(); + + +public slots: + /* Wallet status might have changed */ + void updateStatus(); + /* New transaction, or transaction changed status */ + void updateTransaction(const QString &hash, int status); + /* New, updated or removed address book entry */ + void updateAddressBook(const QString &address, const QString &label, bool isMine, int status); + /* Current, immature or unconfirmed balance might have changed - emit 'balanceChanged' if so */ + void pollBalanceChanged(); + +signals: + // Signal that balance in wallet changed + void balanceChanged(qint64 balance, qint64 stake, qint64 unconfirmedBalance, qint64 immatureBalance); + + // Number of transactions in wallet changed + void numTransactionsChanged(int count); + + // Encryption status of wallet changed + void encryptionStatusChanged(int status); + + // Signal emitted when wallet needs to be unlocked + // It is valid behaviour for listeners to keep the wallet locked after this signal; + // this means that the unlocking failed or was cancelled. + void requireUnlock(); + + // Asynchronous error notification + void error(const QString &title, const QString &message, bool modal); +}; + + +#endif // WALLETMODEL_H diff --git a/src/rpcblockchain.cpp b/src/rpcblockchain.cpp new file mode 100644 index 0000000..ebb133e --- /dev/null +++ b/src/rpcblockchain.cpp @@ -0,0 +1,307 @@ +// Copyright (c) 2010 Satoshi Nakamoto +// Copyright (c) 2009-2012 The Bitcoin developers +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include "main.h" +#include "bitcoinrpc.h" + +using namespace json_spirit; +using namespace std; + +extern void TxToJSON(const CTransaction& tx, const uint256 hashBlock, json_spirit::Object& entry); +extern enum Checkpoints::CPMode CheckpointsMode; + +double GetDifficulty(const CBlockIndex* blockindex) +{ + // Floating point number that is a multiple of the minimum difficulty, + // minimum difficulty = 1.0. + if (blockindex == NULL) + { + if (pindexBest == NULL) + return 1.0; + else + blockindex = GetLastBlockIndex(pindexBest, false); + } + + int nShift = (blockindex->nBits >> 24) & 0xff; + + double dDiff = + (double)0x0000ffff / (double)(blockindex->nBits & 0x00ffffff); + + while (nShift < 29) + { + dDiff *= 256.0; + nShift++; + } + while (nShift > 29) + { + dDiff /= 256.0; + nShift--; + } + + return dDiff; +} + +double GetPoWMHashPS() +{ + if (pindexBest->nHeight >= LAST_POW_BLOCK) + return 0; + + int nPoWInterval = 72; + int64_t nTargetSpacingWorkMin = 30, nTargetSpacingWork = 30; + + CBlockIndex* pindex = pindexGenesisBlock; + CBlockIndex* pindexPrevWork = pindexGenesisBlock; + + while (pindex) + { + if (pindex->IsProofOfWork()) + { + int64_t nActualSpacingWork = pindex->GetBlockTime() - pindexPrevWork->GetBlockTime(); + nTargetSpacingWork = ((nPoWInterval - 1) * nTargetSpacingWork + nActualSpacingWork + nActualSpacingWork) / (nPoWInterval + 1); + nTargetSpacingWork = max(nTargetSpacingWork, nTargetSpacingWorkMin); + pindexPrevWork = pindex; + } + + pindex = pindex->pnext; + } + + return GetDifficulty() * 4294.967296 / nTargetSpacingWork; +} + +double GetPoSKernelPS() +{ + int nPoSInterval = 72; + double dStakeKernelsTriedAvg = 0; + int nStakesHandled = 0, nStakesTime = 0; + + CBlockIndex* pindex = pindexBest;; + CBlockIndex* pindexPrevStake = NULL; + + while (pindex && nStakesHandled < nPoSInterval) + { + if (pindex->IsProofOfStake()) + { + dStakeKernelsTriedAvg += GetDifficulty(pindex) * 4294967296.0; + nStakesTime += pindexPrevStake ? (pindexPrevStake->nTime - pindex->nTime) : 0; + pindexPrevStake = pindex; + nStakesHandled++; + } + + pindex = pindex->pprev; + } + + return nStakesTime ? dStakeKernelsTriedAvg / nStakesTime : 0; +} + +Object blockToJSON(const CBlock& block, const CBlockIndex* blockindex, bool fPrintTransactionDetail) +{ + Object result; + result.push_back(Pair("hash", block.GetHash().GetHex())); + CMerkleTx txGen(block.vtx[0]); + txGen.SetMerkleBranch(&block); + result.push_back(Pair("confirmations", (int)txGen.GetDepthInMainChain())); + result.push_back(Pair("size", (int)::GetSerializeSize(block, SER_NETWORK, PROTOCOL_VERSION))); + result.push_back(Pair("height", blockindex->nHeight)); + result.push_back(Pair("version", block.nVersion)); + result.push_back(Pair("merkleroot", block.hashMerkleRoot.GetHex())); + result.push_back(Pair("mint", ValueFromAmount(blockindex->nMint))); + result.push_back(Pair("time", (int64_t)block.GetBlockTime())); + result.push_back(Pair("nonce", (uint64_t)block.nNonce)); + result.push_back(Pair("bits", strprintf("%08x", block.nBits))); + result.push_back(Pair("difficulty", GetDifficulty(blockindex))); + result.push_back(Pair("blocktrust", leftTrim(blockindex->GetBlockTrust().GetHex(), '0'))); + result.push_back(Pair("chaintrust", leftTrim(blockindex->nChainTrust.GetHex(), '0'))); + if (blockindex->pprev) + result.push_back(Pair("previousblockhash", blockindex->pprev->GetBlockHash().GetHex())); + if (blockindex->pnext) + result.push_back(Pair("nextblockhash", blockindex->pnext->GetBlockHash().GetHex())); + + result.push_back(Pair("flags", strprintf("%s%s", blockindex->IsProofOfStake()? "proof-of-stake" : "proof-of-work", blockindex->GeneratedStakeModifier()? " stake-modifier": ""))); + result.push_back(Pair("proofhash", blockindex->hashProof.GetHex())); + result.push_back(Pair("entropybit", (int)blockindex->GetStakeEntropyBit())); + result.push_back(Pair("modifier", strprintf("%016" PRIx64, blockindex->nStakeModifier))); + result.push_back(Pair("modifierchecksum", strprintf("%08x", blockindex->nStakeModifierChecksum))); + Array txinfo; + BOOST_FOREACH (const CTransaction& tx, block.vtx) + { + if (fPrintTransactionDetail) + { + Object entry; + + entry.push_back(Pair("txid", tx.GetHash().GetHex())); + TxToJSON(tx, 0, entry); + + txinfo.push_back(entry); + } + else + txinfo.push_back(tx.GetHash().GetHex()); + } + + result.push_back(Pair("tx", txinfo)); + + if (block.IsProofOfStake()) + result.push_back(Pair("signature", HexStr(block.vchBlockSig.begin(), block.vchBlockSig.end()))); + + return result; +} + +Value getbestblockhash(const Array& params, bool fHelp) +{ + if (fHelp || params.size() != 0) + throw runtime_error( + "getbestblockhash\n" + "Returns the hash of the best block in the longest block chain."); + + return hashBestChain.GetHex(); +} + +Value getblockcount(const Array& params, bool fHelp) +{ + if (fHelp || params.size() != 0) + throw runtime_error( + "getblockcount\n" + "Returns the number of blocks in the longest block chain."); + + return nBestHeight; +} + + +Value getdifficulty(const Array& params, bool fHelp) +{ + if (fHelp || params.size() != 0) + throw runtime_error( + "getdifficulty\n" + "Returns the difficulty as a multiple of the minimum difficulty."); + + Object obj; + obj.push_back(Pair("proof-of-work", GetDifficulty())); + obj.push_back(Pair("proof-of-stake", GetDifficulty(GetLastBlockIndex(pindexBest, true)))); + obj.push_back(Pair("search-interval", (int)nLastCoinStakeSearchInterval)); + return obj; +} + + +Value settxfee(const Array& params, bool fHelp) +{ + if (fHelp || params.size() < 1 || params.size() > 1 || AmountFromValue(params[0]) < MIN_TX_FEE) + throw runtime_error( + "settxfee \n" + " is a real and is rounded to the nearest 0.01"); + + nTransactionFee = AmountFromValue(params[0]); + nTransactionFee = (nTransactionFee / CENT) * CENT; // round to cent + + return true; +} + +Value getrawmempool(const Array& params, bool fHelp) +{ + if (fHelp || params.size() != 0) + throw runtime_error( + "getrawmempool\n" + "Returns all transaction ids in memory pool."); + + vector vtxid; + mempool.queryHashes(vtxid); + + Array a; + BOOST_FOREACH(const uint256& hash, vtxid) + a.push_back(hash.ToString()); + + return a; +} + +Value getblockhash(const Array& params, bool fHelp) +{ + if (fHelp || params.size() != 1) + throw runtime_error( + "getblockhash \n" + "Returns hash of block in best-block-chain at ."); + + int nHeight = params[0].get_int(); + if (nHeight < 0 || nHeight > nBestHeight) + throw runtime_error("Block number out of range."); + + CBlockIndex* pblockindex = FindBlockByHeight(nHeight); + return pblockindex->phashBlock->GetHex(); +} + +Value getblock(const Array& params, bool fHelp) +{ + if (fHelp || params.size() < 1 || params.size() > 2) + throw runtime_error( + "getblock [txinfo]\n" + "txinfo optional to print more detailed tx info\n" + "Returns details of a block with given block-hash."); + + std::string strHash = params[0].get_str(); + uint256 hash(strHash); + + if (mapBlockIndex.count(hash) == 0) + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found"); + + CBlock block; + CBlockIndex* pblockindex = mapBlockIndex[hash]; + block.ReadFromDisk(pblockindex, true); + + return blockToJSON(block, pblockindex, params.size() > 1 ? params[1].get_bool() : false); +} + +Value getblockbynumber(const Array& params, bool fHelp) +{ + if (fHelp || params.size() < 1 || params.size() > 2) + throw runtime_error( + "getblockbynumber [txinfo]\n" + "txinfo optional to print more detailed tx info\n" + "Returns details of a block with given block-number."); + + int nHeight = params[0].get_int(); + if (nHeight < 0 || nHeight > nBestHeight) + throw runtime_error("Block number out of range."); + + CBlock block; + CBlockIndex* pblockindex = mapBlockIndex[hashBestChain]; + while (pblockindex->nHeight > nHeight) + pblockindex = pblockindex->pprev; + + uint256 hash = *pblockindex->phashBlock; + + pblockindex = mapBlockIndex[hash]; + block.ReadFromDisk(pblockindex, true); + + return blockToJSON(block, pblockindex, params.size() > 1 ? params[1].get_bool() : false); +} + +// ppcoin: get information of sync-checkpoint +Value getcheckpoint(const Array& params, bool fHelp) +{ + if (fHelp || params.size() != 0) + throw runtime_error( + "getcheckpoint\n" + "Show info of synchronized checkpoint.\n"); + + Object result; + CBlockIndex* pindexCheckpoint; + + result.push_back(Pair("synccheckpoint", Checkpoints::hashSyncCheckpoint.ToString().c_str())); + pindexCheckpoint = mapBlockIndex[Checkpoints::hashSyncCheckpoint]; + result.push_back(Pair("height", pindexCheckpoint->nHeight)); + result.push_back(Pair("timestamp", DateTimeStrFormat(pindexCheckpoint->GetBlockTime()).c_str())); + + // Check that the block satisfies synchronized checkpoint + if (CheckpointsMode == Checkpoints::STRICT) + result.push_back(Pair("policy", "strict")); + + if (CheckpointsMode == Checkpoints::ADVISORY) + result.push_back(Pair("policy", "advisory")); + + if (CheckpointsMode == Checkpoints::PERMISSIVE) + result.push_back(Pair("policy", "permissive")); + + if (mapArgs.count("-checkpointkey")) + result.push_back(Pair("checkpointmaster", true)); + + return result; +} diff --git a/src/rpcdump.cpp b/src/rpcdump.cpp new file mode 100644 index 0000000..b00b755 --- /dev/null +++ b/src/rpcdump.cpp @@ -0,0 +1,329 @@ +// Copyright (c) 2009-2012 Bitcoin Developers +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include +#include + +#include "init.h" // for pwalletMain +#include "bitcoinrpc.h" +#include "ui_interface.h" +#include "base58.h" + +#include +#include +#include + +#define printf OutputDebugStringF + +using namespace json_spirit; +using namespace std; + +void EnsureWalletIsUnlocked(); + +namespace bt = boost::posix_time; + +// Extended DecodeDumpTime implementation, see this page for details: +// http://stackoverflow.com/questions/3786201/parsing-of-date-time-from-string-boost +const std::locale formats[] = { + std::locale(std::locale::classic(),new bt::time_input_facet("%Y-%m-%dT%H:%M:%SZ")), + std::locale(std::locale::classic(),new bt::time_input_facet("%Y-%m-%d %H:%M:%S")), + std::locale(std::locale::classic(),new bt::time_input_facet("%Y/%m/%d %H:%M:%S")), + std::locale(std::locale::classic(),new bt::time_input_facet("%d.%m.%Y %H:%M:%S")), + std::locale(std::locale::classic(),new bt::time_input_facet("%Y-%m-%d")) +}; + +const size_t formats_n = sizeof(formats)/sizeof(formats[0]); + +std::time_t pt_to_time_t(const bt::ptime& pt) +{ + bt::ptime timet_start(boost::gregorian::date(1970,1,1)); + bt::time_duration diff = pt - timet_start; + return diff.ticks()/bt::time_duration::rep_type::ticks_per_second; +} + +int64_t DecodeDumpTime(const std::string& s) +{ + bt::ptime pt; + + for(size_t i=0; i> pt; + if(pt != bt::ptime()) break; + } + + return pt_to_time_t(pt); +} + +std::string static EncodeDumpTime(int64_t nTime) { + return DateTimeStrFormat("%Y-%m-%dT%H:%M:%SZ", nTime); +} + +std::string static EncodeDumpString(const std::string &str) { + std::stringstream ret; + BOOST_FOREACH(unsigned char c, str) { + if (c <= 32 || c >= 128 || c == '%') { + ret << '%' << HexStr(&c, &c + 1); + } else { + ret << c; + } + } + return ret.str(); +} + +std::string DecodeDumpString(const std::string &str) { + std::stringstream ret; + for (unsigned int pos = 0; pos < str.length(); pos++) { + unsigned char c = str[pos]; + if (c == '%' && pos+2 < str.length()) { + c = (((str[pos+1]>>6)*9+((str[pos+1]-'0')&15)) << 4) | + ((str[pos+2]>>6)*9+((str[pos+2]-'0')&15)); + pos += 2; + } + ret << c; + } + return ret.str(); +} + +class CTxDump +{ +public: + CBlockIndex *pindex; + int64_t nValue; + bool fSpent; + CWalletTx* ptx; + int nOut; + CTxDump(CWalletTx* ptx = NULL, int nOut = -1) + { + pindex = NULL; + nValue = 0; + fSpent = false; + this->ptx = ptx; + this->nOut = nOut; + } +}; + +Value importprivkey(const Array& params, bool fHelp) +{ + if (fHelp || params.size() < 1 || params.size() > 2) + throw runtime_error( + "importprivkey [label]\n" + "Adds a private key (as returned by dumpprivkey) to your wallet."); + + string strSecret = params[0].get_str(); + string strLabel = ""; + if (params.size() > 1) + strLabel = params[1].get_str(); + CBitcoinSecret vchSecret; + bool fGood = vchSecret.SetString(strSecret); + + if (!fGood) throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid private key"); + if (fWalletUnlockStakingOnly) + throw JSONRPCError(RPC_WALLET_UNLOCK_NEEDED, "Wallet is unlocked for staking only."); + + CKey key; + bool fCompressed; + CSecret secret = vchSecret.GetSecret(fCompressed); + key.SetSecret(secret, fCompressed); + CKeyID vchAddress = key.GetPubKey().GetID(); + { + LOCK2(cs_main, pwalletMain->cs_wallet); + + pwalletMain->MarkDirty(); + pwalletMain->SetAddressBookName(vchAddress, strLabel); + + // Don't throw error in case a key is already there + if (pwalletMain->HaveKey(vchAddress)) + return Value::null; + + pwalletMain->mapKeyMetadata[vchAddress].nCreateTime = 1; + + if (!pwalletMain->AddKey(key)) + throw JSONRPCError(RPC_WALLET_ERROR, "Error adding key to wallet"); + + // whenever a key is imported, we need to scan the whole chain + pwalletMain->nTimeFirstKey = 1; // 0 would be considered 'no value' + + pwalletMain->ScanForWalletTransactions(pindexGenesisBlock, true); + pwalletMain->ReacceptWalletTransactions(); + } + + return Value::null; +} + +Value importwallet(const Array& params, bool fHelp) +{ + if (fHelp || params.size() != 1) + throw runtime_error( + "importwallet \n" + "Imports keys from a wallet dump file (see dumpwallet)."); + + EnsureWalletIsUnlocked(); + + ifstream file; + file.open(params[0].get_str().c_str()); + if (!file.is_open()) + throw JSONRPCError(RPC_INVALID_PARAMETER, "Cannot open wallet dump file"); + + int64_t nTimeBegin = pindexBest->nTime; + + bool fGood = true; + + while (file.good()) { + std::string line; + std::getline(file, line); + if (line.empty() || line[0] == '#') + continue; + + std::vector vstr; + boost::split(vstr, line, boost::is_any_of(" ")); + if (vstr.size() < 2) + continue; + CBitcoinSecret vchSecret; + if (!vchSecret.SetString(vstr[0])) + continue; + + bool fCompressed; + CKey key; + CSecret secret = vchSecret.GetSecret(fCompressed); + key.SetSecret(secret, fCompressed); + CKeyID keyid = key.GetPubKey().GetID(); + + if (pwalletMain->HaveKey(keyid)) { + printf("Skipping import of %s (key already present)\n", CBitcoinAddress(keyid).ToString().c_str()); + continue; + } + int64_t nTime = DecodeDumpTime(vstr[1]); + std::string strLabel; + bool fLabel = true; + for (unsigned int nStr = 2; nStr < vstr.size(); nStr++) { + if (boost::algorithm::starts_with(vstr[nStr], "#")) + break; + if (vstr[nStr] == "change=1") + fLabel = false; + if (vstr[nStr] == "reserve=1") + fLabel = false; + if (boost::algorithm::starts_with(vstr[nStr], "label=")) { + strLabel = DecodeDumpString(vstr[nStr].substr(6)); + fLabel = true; + } + } + printf("Importing %s...\n", CBitcoinAddress(keyid).ToString().c_str()); + if (!pwalletMain->AddKey(key)) { + fGood = false; + continue; + } + pwalletMain->mapKeyMetadata[keyid].nCreateTime = nTime; + if (fLabel) + pwalletMain->SetAddressBookName(keyid, strLabel); + nTimeBegin = std::min(nTimeBegin, nTime); + } + file.close(); + + CBlockIndex *pindex = pindexBest; + while (pindex && pindex->pprev && pindex->nTime > nTimeBegin - 7200) + pindex = pindex->pprev; + + if (!pwalletMain->nTimeFirstKey || nTimeBegin < pwalletMain->nTimeFirstKey) + pwalletMain->nTimeFirstKey = nTimeBegin; + + printf("Rescanning last %i blocks\n", pindexBest->nHeight - pindex->nHeight + 1); + pwalletMain->ScanForWalletTransactions(pindex); + pwalletMain->ReacceptWalletTransactions(); + pwalletMain->MarkDirty(); + + if (!fGood) + throw JSONRPCError(RPC_WALLET_ERROR, "Error adding some keys to wallet"); + + return Value::null; +} + + +Value dumpprivkey(const Array& params, bool fHelp) +{ + if (fHelp || params.size() != 1) + throw runtime_error( + "dumpprivkey \n" + "Reveals the private key corresponding to ."); + + EnsureWalletIsUnlocked(); + + string strAddress = params[0].get_str(); + CBitcoinAddress address; + if (!address.SetString(strAddress)) + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid arepacoin address"); + if (fWalletUnlockStakingOnly) + throw JSONRPCError(RPC_WALLET_UNLOCK_NEEDED, "Wallet is unlocked for staking only."); + CKeyID keyID; + if (!address.GetKeyID(keyID)) + throw JSONRPCError(RPC_TYPE_ERROR, "Address does not refer to a key"); + CSecret vchSecret; + bool fCompressed; + if (!pwalletMain->GetSecret(keyID, vchSecret, fCompressed)) + throw JSONRPCError(RPC_WALLET_ERROR, "Private key for address " + strAddress + " is not known"); + return CBitcoinSecret(vchSecret, fCompressed).ToString(); +} + +Value dumpwallet(const Array& params, bool fHelp) +{ + if (fHelp || params.size() != 1) + throw runtime_error( + "dumpwallet \n" + "Dumps all wallet keys in a human-readable format."); + + EnsureWalletIsUnlocked(); + + ofstream file; + file.open(params[0].get_str().c_str()); + if (!file.is_open()) + throw JSONRPCError(RPC_INVALID_PARAMETER, "Cannot open wallet dump file"); + + std::map mapKeyBirth; + + std::set setKeyPool; + + pwalletMain->GetKeyBirthTimes(mapKeyBirth); + + pwalletMain->GetAllReserveKeys(setKeyPool); + + // sort time/key pairs + std::vector > vKeyBirth; + for (std::map::const_iterator it = mapKeyBirth.begin(); it != mapKeyBirth.end(); it++) { + vKeyBirth.push_back(std::make_pair(it->second, it->first)); + } + mapKeyBirth.clear(); + std::sort(vKeyBirth.begin(), vKeyBirth.end()); + + // produce output + file << strprintf("# Wallet dump created by arepacoin %s (%s)\n", CLIENT_BUILD.c_str(), CLIENT_DATE.c_str()); + file << strprintf("# * Created on %s\n", EncodeDumpTime(GetTime()).c_str()); + file << strprintf("# * Best block at time of backup was %i (%s),\n", nBestHeight, hashBestChain.ToString().c_str()); + file << strprintf("# mined on %s\n", EncodeDumpTime(pindexBest->nTime).c_str()); + file << "\n"; + for (std::vector >::const_iterator it = vKeyBirth.begin(); it != vKeyBirth.end(); it++) { + const CKeyID &keyid = it->second; + std::string strTime = EncodeDumpTime(it->first); + std::string strAddr = CBitcoinAddress(keyid).ToString(); + bool IsCompressed; + + CKey key; + if (pwalletMain->GetKey(keyid, key)) { + if (pwalletMain->mapAddressBook.count(keyid)) { + CSecret secret = key.GetSecret(IsCompressed); + file << strprintf("%s %s label=%s # addr=%s\n", CBitcoinSecret(secret, IsCompressed).ToString().c_str(), strTime.c_str(), EncodeDumpString(pwalletMain->mapAddressBook[keyid]).c_str(), strAddr.c_str()); + } else if (setKeyPool.count(keyid)) { + CSecret secret = key.GetSecret(IsCompressed); + file << strprintf("%s %s reserve=1 # addr=%s\n", CBitcoinSecret(secret, IsCompressed).ToString().c_str(), strTime.c_str(), strAddr.c_str()); + } else { + CSecret secret = key.GetSecret(IsCompressed); + file << strprintf("%s %s change=1 # addr=%s\n", CBitcoinSecret(secret, IsCompressed).ToString().c_str(), strTime.c_str(), strAddr.c_str()); + } + } + } + file << "\n"; + file << "# End of dump\n"; + file.close(); + return Value::null; +} diff --git a/src/rpcmining.cpp b/src/rpcmining.cpp new file mode 100644 index 0000000..b7e0988 --- /dev/null +++ b/src/rpcmining.cpp @@ -0,0 +1,528 @@ +// Copyright (c) 2010 Satoshi Nakamoto +// Copyright (c) 2009-2012 The Bitcoin developers +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include "main.h" +#include "db.h" +#include "txdb.h" +#include "init.h" +#include "miner.h" +#include "bitcoinrpc.h" + +using namespace json_spirit; +using namespace std; + +Value getsubsidy(const Array& params, bool fHelp) +{ + if (fHelp || params.size() > 1) + throw runtime_error( + "getsubsidy [nTarget]\n" + "Returns proof-of-work subsidy value for the specified value of target."); + + return (uint64_t)GetProofOfWorkReward(0); +} + +Value getmininginfo(const Array& params, bool fHelp) +{ + if (fHelp || params.size() != 0) + throw runtime_error( + "getmininginfo\n" + "Returns an object containing mining-related information."); + + uint64_t nMinWeight = 0, nMaxWeight = 0, nWeight = 0; + pwalletMain->GetStakeWeight(*pwalletMain, nMinWeight, nMaxWeight, nWeight); + + Object obj, diff, weight; + obj.push_back(Pair("blocks", (int)nBestHeight)); + obj.push_back(Pair("currentblocksize",(uint64_t)nLastBlockSize)); + obj.push_back(Pair("currentblocktx",(uint64_t)nLastBlockTx)); + + diff.push_back(Pair("proof-of-work", GetDifficulty())); + diff.push_back(Pair("proof-of-stake", GetDifficulty(GetLastBlockIndex(pindexBest, true)))); + diff.push_back(Pair("search-interval", (int)nLastCoinStakeSearchInterval)); + obj.push_back(Pair("difficulty", diff)); + + obj.push_back(Pair("blockvalue", (uint64_t)GetProofOfWorkReward(0))); + obj.push_back(Pair("netmhashps", GetPoWMHashPS())); + obj.push_back(Pair("netstakeweight", GetPoSKernelPS())); + obj.push_back(Pair("errors", GetWarnings("statusbar"))); + obj.push_back(Pair("pooledtx", (uint64_t)mempool.size())); + + weight.push_back(Pair("minimum", (uint64_t)nMinWeight)); + weight.push_back(Pair("maximum", (uint64_t)nMaxWeight)); + weight.push_back(Pair("combined", (uint64_t)nWeight)); + obj.push_back(Pair("stakeweight", weight)); + + obj.push_back(Pair("stakeinterest", (uint64_t)COIN_YEAR_REWARD)); + obj.push_back(Pair("testnet", fTestNet)); + return obj; +} + +Value getstakinginfo(const Array& params, bool fHelp) +{ + if (fHelp || params.size() != 0) + throw runtime_error( + "getstakinginfo\n" + "Returns an object containing staking-related information."); + + uint64_t nMinWeight = 0, nMaxWeight = 0, nWeight = 0; + pwalletMain->GetStakeWeight(*pwalletMain, nMinWeight, nMaxWeight, nWeight); + + uint64_t nNetworkWeight = GetPoSKernelPS(); + bool staking = nLastCoinStakeSearchInterval && nWeight; + uint64_t nExpectedTime = staking ? (nTargetSpacing * nNetworkWeight / nWeight) : 0; + + Object obj; + + obj.push_back(Pair("enabled", GetBoolArg("-staking", true))); + obj.push_back(Pair("staking", staking)); + obj.push_back(Pair("errors", GetWarnings("statusbar"))); + + obj.push_back(Pair("currentblocksize", (uint64_t)nLastBlockSize)); + obj.push_back(Pair("currentblocktx", (uint64_t)nLastBlockTx)); + obj.push_back(Pair("pooledtx", (uint64_t)mempool.size())); + + obj.push_back(Pair("difficulty", GetDifficulty(GetLastBlockIndex(pindexBest, true)))); + obj.push_back(Pair("search-interval", (int)nLastCoinStakeSearchInterval)); + + obj.push_back(Pair("weight", (uint64_t)nWeight)); + obj.push_back(Pair("netstakeweight", (uint64_t)nNetworkWeight)); + + obj.push_back(Pair("expectedtime", nExpectedTime)); + + return obj; +} + +Value getworkex(const Array& params, bool fHelp) +{ + if (fHelp || params.size() > 2) + throw runtime_error( + "getworkex [data, coinbase]\n" + "If [data, coinbase] is not specified, returns extended work data.\n" + ); + + if (vNodes.empty()) + throw JSONRPCError(-9, "arepacoin is not connected!"); + + if (IsInitialBlockDownload()) + throw JSONRPCError(-10, "arepacoin is downloading blocks..."); + + if (pindexBest->nHeight >= LAST_POW_BLOCK) + throw JSONRPCError(RPC_MISC_ERROR, "No more PoW blocks"); + + typedef map > mapNewBlock_t; + static mapNewBlock_t mapNewBlock; + static vector vNewBlock; + static CReserveKey reservekey(pwalletMain); + + if (params.size() == 0) + { + // Update block + static unsigned int nTransactionsUpdatedLast; + static CBlockIndex* pindexPrev; + static int64_t nStart; + static CBlock* pblock; + if (pindexPrev != pindexBest || + (nTransactionsUpdated != nTransactionsUpdatedLast && GetTime() - nStart > 60)) + { + if (pindexPrev != pindexBest) + { + // Deallocate old blocks since they're obsolete now + mapNewBlock.clear(); + BOOST_FOREACH(CBlock* pblock, vNewBlock) + delete pblock; + vNewBlock.clear(); + } + nTransactionsUpdatedLast = nTransactionsUpdated; + pindexPrev = pindexBest; + nStart = GetTime(); + + // Create new block + pblock = CreateNewBlock(pwalletMain); + if (!pblock) + throw JSONRPCError(-7, "Out of memory"); + vNewBlock.push_back(pblock); + } + + // Update nTime + pblock->nTime = max(pindexPrev->GetPastTimeLimit()+1, GetAdjustedTime()); + pblock->nNonce = 0; + + // Update nExtraNonce + static unsigned int nExtraNonce = 0; + IncrementExtraNonce(pblock, pindexPrev, nExtraNonce); + + // Save + mapNewBlock[pblock->hashMerkleRoot] = make_pair(pblock, pblock->vtx[0].vin[0].scriptSig); + + // Prebuild hash buffers + char pmidstate[32]; + char pdata[128]; + char phash1[64]; + FormatHashBuffers(pblock, pmidstate, pdata, phash1); + + uint256 hashTarget = CBigNum().SetCompact(pblock->nBits).getuint256(); + + CTransaction coinbaseTx = pblock->vtx[0]; + std::vector merkle = pblock->GetMerkleBranch(0); + + Object result; + result.push_back(Pair("data", HexStr(BEGIN(pdata), END(pdata)))); + result.push_back(Pair("target", HexStr(BEGIN(hashTarget), END(hashTarget)))); + + CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION); + ssTx << coinbaseTx; + result.push_back(Pair("coinbase", HexStr(ssTx.begin(), ssTx.end()))); + + Array merkle_arr; + + BOOST_FOREACH(uint256 merkleh, merkle) { + merkle_arr.push_back(HexStr(BEGIN(merkleh), END(merkleh))); + } + + result.push_back(Pair("merkle", merkle_arr)); + + + return result; + } + else + { + // Parse parameters + vector vchData = ParseHex(params[0].get_str()); + vector coinbase; + + if(params.size() == 2) + coinbase = ParseHex(params[1].get_str()); + + if (vchData.size() != 128) + throw JSONRPCError(-8, "Invalid parameter"); + + CBlock* pdata = (CBlock*)&vchData[0]; + + // Byte reverse + for (int i = 0; i < 128/4; i++) + ((unsigned int*)pdata)[i] = ByteReverse(((unsigned int*)pdata)[i]); + + // Get saved block + if (!mapNewBlock.count(pdata->hashMerkleRoot)) + return false; + CBlock* pblock = mapNewBlock[pdata->hashMerkleRoot].first; + + pblock->nTime = pdata->nTime; + pblock->nNonce = pdata->nNonce; + + if(coinbase.size() == 0) + pblock->vtx[0].vin[0].scriptSig = mapNewBlock[pdata->hashMerkleRoot].second; + else + CDataStream(coinbase, SER_NETWORK, PROTOCOL_VERSION) >> pblock->vtx[0]; // FIXME - HACK! + + pblock->hashMerkleRoot = pblock->BuildMerkleTree(); + + return CheckWork(pblock, *pwalletMain, reservekey); + } +} + + +Value getwork(const Array& params, bool fHelp) +{ + if (fHelp || params.size() > 1) + throw runtime_error( + "getwork [data]\n" + "If [data] is not specified, returns formatted hash data to work on:\n" + " \"midstate\" : precomputed hash state after hashing the first half of the data (DEPRECATED)\n" // deprecated + " \"data\" : block data\n" + " \"hash1\" : formatted hash buffer for second hash (DEPRECATED)\n" // deprecated + " \"target\" : little endian hash target\n" + "If [data] is specified, tries to solve the block and returns true if it was successful."); + + if (vNodes.empty()) + throw JSONRPCError(RPC_CLIENT_NOT_CONNECTED, "arepacoin is not connected!"); + + if (IsInitialBlockDownload()) + throw JSONRPCError(RPC_CLIENT_IN_INITIAL_DOWNLOAD, "arepacoin is downloading blocks..."); + + if (pindexBest->nHeight >= LAST_POW_BLOCK) + throw JSONRPCError(RPC_MISC_ERROR, "No more PoW blocks"); + + typedef map > mapNewBlock_t; + static mapNewBlock_t mapNewBlock; // FIXME: thread safety + static vector vNewBlock; + static CReserveKey reservekey(pwalletMain); + + if (params.size() == 0) + { + // Update block + static unsigned int nTransactionsUpdatedLast; + static CBlockIndex* pindexPrev; + static int64_t nStart; + static CBlock* pblock; + if (pindexPrev != pindexBest || + (nTransactionsUpdated != nTransactionsUpdatedLast && GetTime() - nStart > 60)) + { + if (pindexPrev != pindexBest) + { + // Deallocate old blocks since they're obsolete now + mapNewBlock.clear(); + BOOST_FOREACH(CBlock* pblock, vNewBlock) + delete pblock; + vNewBlock.clear(); + } + + // Clear pindexPrev so future getworks make a new block, despite any failures from here on + pindexPrev = NULL; + + // Store the pindexBest used before CreateNewBlock, to avoid races + nTransactionsUpdatedLast = nTransactionsUpdated; + CBlockIndex* pindexPrevNew = pindexBest; + nStart = GetTime(); + + // Create new block + pblock = CreateNewBlock(pwalletMain); + if (!pblock) + throw JSONRPCError(RPC_OUT_OF_MEMORY, "Out of memory"); + vNewBlock.push_back(pblock); + + // Need to update only after we know CreateNewBlock succeeded + pindexPrev = pindexPrevNew; + } + + // Update nTime + pblock->UpdateTime(pindexPrev); + pblock->nNonce = 0; + + // Update nExtraNonce + static unsigned int nExtraNonce = 0; + IncrementExtraNonce(pblock, pindexPrev, nExtraNonce); + + // Save + mapNewBlock[pblock->hashMerkleRoot] = make_pair(pblock, pblock->vtx[0].vin[0].scriptSig); + + // Pre-build hash buffers + char pmidstate[32]; + char pdata[128]; + char phash1[64]; + FormatHashBuffers(pblock, pmidstate, pdata, phash1); + + uint256 hashTarget = CBigNum().SetCompact(pblock->nBits).getuint256(); + + Object result; + result.push_back(Pair("midstate", HexStr(BEGIN(pmidstate), END(pmidstate)))); // deprecated + result.push_back(Pair("data", HexStr(BEGIN(pdata), END(pdata)))); + result.push_back(Pair("hash1", HexStr(BEGIN(phash1), END(phash1)))); // deprecated + result.push_back(Pair("target", HexStr(BEGIN(hashTarget), END(hashTarget)))); + return result; + } + else + { + // Parse parameters + vector vchData = ParseHex(params[0].get_str()); + if (vchData.size() != 128) + throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter"); + CBlock* pdata = (CBlock*)&vchData[0]; + + // Byte reverse + for (int i = 0; i < 128/4; i++) + ((unsigned int*)pdata)[i] = ByteReverse(((unsigned int*)pdata)[i]); + + // Get saved block + if (!mapNewBlock.count(pdata->hashMerkleRoot)) + return false; + CBlock* pblock = mapNewBlock[pdata->hashMerkleRoot].first; + + pblock->nTime = pdata->nTime; + pblock->nNonce = pdata->nNonce; + pblock->vtx[0].vin[0].scriptSig = mapNewBlock[pdata->hashMerkleRoot].second; + pblock->hashMerkleRoot = pblock->BuildMerkleTree(); + + return CheckWork(pblock, *pwalletMain, reservekey); + } +} + + +Value getblocktemplate(const Array& params, bool fHelp) +{ + if (fHelp || params.size() > 1) + throw runtime_error( + "getblocktemplate [params]\n" + "Returns data needed to construct a block to work on:\n" + " \"version\" : block version\n" + " \"previousblockhash\" : hash of current highest block\n" + " \"transactions\" : contents of non-coinbase transactions that should be included in the next block\n" + " \"coinbaseaux\" : data that should be included in coinbase\n" + " \"coinbasevalue\" : maximum allowable input to coinbase transaction, including the generation award and transaction fees\n" + " \"target\" : hash target\n" + " \"mintime\" : minimum timestamp appropriate for next block\n" + " \"curtime\" : current timestamp\n" + " \"mutable\" : list of ways the block template may be changed\n" + " \"noncerange\" : range of valid nonces\n" + " \"sigoplimit\" : limit of sigops in blocks\n" + " \"sizelimit\" : limit of block size\n" + " \"bits\" : compressed target of next block\n" + " \"height\" : height of the next block\n" + "See https://en.bitcoin.it/wiki/BIP_0022 for full specification."); + + std::string strMode = "template"; + if (params.size() > 0) + { + const Object& oparam = params[0].get_obj(); + const Value& modeval = find_value(oparam, "mode"); + if (modeval.type() == str_type) + strMode = modeval.get_str(); + else if (modeval.type() == null_type) + { + /* Do nothing */ + } + else + throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid mode"); + } + + if (strMode != "template") + throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid mode"); + + if (vNodes.empty()) + throw JSONRPCError(RPC_CLIENT_NOT_CONNECTED, "arepacoin is not connected!"); + + if (IsInitialBlockDownload()) + throw JSONRPCError(RPC_CLIENT_IN_INITIAL_DOWNLOAD, "arepacoin is downloading blocks..."); + + if (pindexBest->nHeight >= LAST_POW_BLOCK) + throw JSONRPCError(RPC_MISC_ERROR, "No more PoW blocks"); + + static CReserveKey reservekey(pwalletMain); + + // Update block + static unsigned int nTransactionsUpdatedLast; + static CBlockIndex* pindexPrev; + static int64_t nStart; + static CBlock* pblock; + if (pindexPrev != pindexBest || + (nTransactionsUpdated != nTransactionsUpdatedLast && GetTime() - nStart > 5)) + { + // Clear pindexPrev so future calls make a new block, despite any failures from here on + pindexPrev = NULL; + + // Store the pindexBest used before CreateNewBlock, to avoid races + nTransactionsUpdatedLast = nTransactionsUpdated; + CBlockIndex* pindexPrevNew = pindexBest; + nStart = GetTime(); + + // Create new block + if(pblock) + { + delete pblock; + pblock = NULL; + } + pblock = CreateNewBlock(pwalletMain); + if (!pblock) + throw JSONRPCError(RPC_OUT_OF_MEMORY, "Out of memory"); + + // Need to update only after we know CreateNewBlock succeeded + pindexPrev = pindexPrevNew; + } + + // Update nTime + pblock->UpdateTime(pindexPrev); + pblock->nNonce = 0; + + Array transactions; + map setTxIndex; + int i = 0; + CTxDB txdb("r"); + BOOST_FOREACH (CTransaction& tx, pblock->vtx) + { + uint256 txHash = tx.GetHash(); + setTxIndex[txHash] = i++; + + if (tx.IsCoinBase() || tx.IsCoinStake()) + continue; + + Object entry; + + CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION); + ssTx << tx; + entry.push_back(Pair("data", HexStr(ssTx.begin(), ssTx.end()))); + + entry.push_back(Pair("hash", txHash.GetHex())); + + MapPrevTx mapInputs; + map mapUnused; + bool fInvalid = false; + if (tx.FetchInputs(txdb, mapUnused, false, false, mapInputs, fInvalid)) + { + entry.push_back(Pair("fee", (int64_t)(tx.GetValueIn(mapInputs) - tx.GetValueOut()))); + + Array deps; + BOOST_FOREACH (MapPrevTx::value_type& inp, mapInputs) + { + if (setTxIndex.count(inp.first)) + deps.push_back(setTxIndex[inp.first]); + } + entry.push_back(Pair("depends", deps)); + + int64_t nSigOps = tx.GetLegacySigOpCount(); + nSigOps += tx.GetP2SHSigOpCount(mapInputs); + entry.push_back(Pair("sigops", nSigOps)); + } + + transactions.push_back(entry); + } + + Object aux; + aux.push_back(Pair("flags", HexStr(COINBASE_FLAGS.begin(), COINBASE_FLAGS.end()))); + + uint256 hashTarget = CBigNum().SetCompact(pblock->nBits).getuint256(); + + static Array aMutable; + if (aMutable.empty()) + { + aMutable.push_back("time"); + aMutable.push_back("transactions"); + aMutable.push_back("prevblock"); + } + + Object result; + result.push_back(Pair("version", pblock->nVersion)); + result.push_back(Pair("previousblockhash", pblock->hashPrevBlock.GetHex())); + result.push_back(Pair("transactions", transactions)); + result.push_back(Pair("coinbaseaux", aux)); + result.push_back(Pair("coinbasevalue", (int64_t)pblock->vtx[0].vout[0].nValue)); + result.push_back(Pair("target", hashTarget.GetHex())); + result.push_back(Pair("mintime", (int64_t)pindexPrev->GetPastTimeLimit()+1)); + result.push_back(Pair("mutable", aMutable)); + result.push_back(Pair("noncerange", "00000000ffffffff")); + result.push_back(Pair("sigoplimit", (int64_t)MAX_BLOCK_SIGOPS)); + result.push_back(Pair("sizelimit", (int64_t)MAX_BLOCK_SIZE)); + result.push_back(Pair("curtime", (int64_t)pblock->nTime)); + result.push_back(Pair("bits", strprintf("%08x", pblock->nBits))); + result.push_back(Pair("height", (int64_t)(pindexPrev->nHeight+1))); + + return result; +} + +Value submitblock(const Array& params, bool fHelp) +{ + if (fHelp || params.size() < 1 || params.size() > 2) + throw runtime_error( + "submitblock [optional-params-obj]\n" + "[optional-params-obj] parameter is currently ignored.\n" + "Attempts to submit new block to network.\n" + "See https://en.bitcoin.it/wiki/BIP_0022 for full specification."); + + vector blockData(ParseHex(params[0].get_str())); + CDataStream ssBlock(blockData, SER_NETWORK, PROTOCOL_VERSION); + CBlock block; + try { + ssBlock >> block; + } + catch (std::exception &e) { + throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "Block decode failed"); + } + + bool fAccepted = ProcessBlock(NULL, &block); + if (!fAccepted) + return "rejected"; + + return Value::null; +} + diff --git a/src/rpcnet.cpp b/src/rpcnet.cpp new file mode 100644 index 0000000..a9df770 --- /dev/null +++ b/src/rpcnet.cpp @@ -0,0 +1,189 @@ +// Copyright (c) 2009-2012 Bitcoin Developers +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include "net.h" +#include "bitcoinrpc.h" +#include "alert.h" +#include "wallet.h" +#include "db.h" +#include "walletdb.h" + +using namespace json_spirit; +using namespace std; + +Value getconnectioncount(const Array& params, bool fHelp) +{ + if (fHelp || params.size() != 0) + throw runtime_error( + "getconnectioncount\n" + "Returns the number of connections to other nodes."); + + LOCK(cs_vNodes); + return (int)vNodes.size(); +} + +static void CopyNodeStats(std::vector& vstats) +{ + vstats.clear(); + + LOCK(cs_vNodes); + vstats.reserve(vNodes.size()); + BOOST_FOREACH(CNode* pnode, vNodes) { + CNodeStats stats; + pnode->copyStats(stats); + vstats.push_back(stats); + } +} + +Value getpeerinfo(const Array& params, bool fHelp) +{ + if (fHelp || params.size() != 0) + throw runtime_error( + "getpeerinfo\n" + "Returns data about each connected network node."); + + vector vstats; + CopyNodeStats(vstats); + + Array ret; + + BOOST_FOREACH(const CNodeStats& stats, vstats) { + Object obj; + + obj.push_back(Pair("addr", stats.addrName)); + obj.push_back(Pair("services", strprintf("%08" PRIx64, stats.nServices))); + obj.push_back(Pair("lastsend", (int64_t)stats.nLastSend)); + obj.push_back(Pair("lastrecv", (int64_t)stats.nLastRecv)); + obj.push_back(Pair("conntime", (int64_t)stats.nTimeConnected)); + obj.push_back(Pair("version", stats.nVersion)); + obj.push_back(Pair("subver", stats.strSubVer)); + obj.push_back(Pair("inbound", stats.fInbound)); + obj.push_back(Pair("startingheight", stats.nStartingHeight)); + obj.push_back(Pair("banscore", stats.nMisbehavior)); + + ret.push_back(obj); + } + + return ret; +} + +Value addnode(const Array& params, bool fHelp) +{ + string strCommand; + if (params.size() == 2) + strCommand = params[1].get_str(); + if (fHelp || params.size() != 2 || + (strCommand != "onetry" && strCommand != "add" && strCommand != "remove")) + throw runtime_error( + "addnode \n" + "Attempts add or remove from the addnode list or try a connection to once."); + + string strNode = params[0].get_str(); + + if (strCommand == "onetry") + { + CAddress addr; + ConnectNode(addr, strNode.c_str()); + return Value::null; + } + + LOCK(cs_vAddedNodes); + vector::iterator it = vAddedNodes.begin(); + for(; it != vAddedNodes.end(); it++) + if (strNode == *it) + break; + + if (strCommand == "add") + { + if (it != vAddedNodes.end()) + throw JSONRPCError(-23, "Error: Node already added"); + vAddedNodes.push_back(strNode); + } + else if(strCommand == "remove") + { + if (it == vAddedNodes.end()) + throw JSONRPCError(-24, "Error: Node has not been added."); + vAddedNodes.erase(it); + } + + return Value::null; +} + +// ppcoin: send alert. +// There is a known deadlock situation with ThreadMessageHandler +// ThreadMessageHandler: holds cs_vSend and acquiring cs_main in SendMessages() +// ThreadRPCServer: holds cs_main and acquiring cs_vSend in alert.RelayTo()/PushMessage()/BeginMessage() +Value sendalert(const Array& params, bool fHelp) +{ + if (fHelp || params.size() < 6) + throw runtime_error( + "sendalert [cancelupto]\n" + " is the alert text message\n" + " is hex string of alert master private key\n" + " is the minimum applicable internal client version\n" + " is the maximum applicable internal client version\n" + " is integer priority number\n" + " is the alert id\n" + "[cancelupto] cancels all alert id's up to this number\n" + "Returns true or false."); + + CAlert alert; + CKey key; + + alert.strStatusBar = params[0].get_str(); + alert.nMinVer = params[2].get_int(); + alert.nMaxVer = params[3].get_int(); + alert.nPriority = params[4].get_int(); + alert.nID = params[5].get_int(); + if (params.size() > 6) + alert.nCancel = params[6].get_int(); + alert.nVersion = PROTOCOL_VERSION; + alert.nRelayUntil = GetAdjustedTime() + 365*24*60*60; + alert.nExpiration = GetAdjustedTime() + 365*24*60*60; + + CDataStream sMsg(SER_NETWORK, PROTOCOL_VERSION); + sMsg << (CUnsignedAlert)alert; + alert.vchMsg = vector(sMsg.begin(), sMsg.end()); + + vector vchPrivKey = ParseHex(params[1].get_str()); + key.SetPrivKey(CPrivKey(vchPrivKey.begin(), vchPrivKey.end())); // if key is not correct openssl may crash + if (!key.Sign(Hash(alert.vchMsg.begin(), alert.vchMsg.end()), alert.vchSig)) + throw runtime_error( + "Unable to sign alert, check private key?\n"); + if(!alert.ProcessAlert()) + throw runtime_error( + "Failed to process alert.\n"); + // Relay alert + { + LOCK(cs_vNodes); + BOOST_FOREACH(CNode* pnode, vNodes) + alert.RelayTo(pnode); + } + + Object result; + result.push_back(Pair("strStatusBar", alert.strStatusBar)); + result.push_back(Pair("nVersion", alert.nVersion)); + result.push_back(Pair("nMinVer", alert.nMinVer)); + result.push_back(Pair("nMaxVer", alert.nMaxVer)); + result.push_back(Pair("nPriority", alert.nPriority)); + result.push_back(Pair("nID", alert.nID)); + if (alert.nCancel > 0) + result.push_back(Pair("nCancel", alert.nCancel)); + return result; +} + +Value getnettotals(const Array& params, bool fHelp) +{ + if (fHelp || params.size() > 0) + throw runtime_error( + "getnettotals\n" + "Returns information about network traffic, including bytes in, bytes out,\n" + "and current time."); + + Object obj; + obj.push_back(Pair("totalbytesrecv", CNode::GetTotalBytesRecv())); + obj.push_back(Pair("totalbytessent", CNode::GetTotalBytesSent())); + obj.push_back(Pair("timemillis", GetTimeMillis())); + return obj; +} \ No newline at end of file diff --git a/src/rpcrawtransaction.cpp b/src/rpcrawtransaction.cpp new file mode 100644 index 0000000..796f4c1 --- /dev/null +++ b/src/rpcrawtransaction.cpp @@ -0,0 +1,562 @@ +// Copyright (c) 2010 Satoshi Nakamoto +// Copyright (c) 2009-2012 The Bitcoin developers +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include + +#include "base58.h" +#include "bitcoinrpc.h" +#include "txdb.h" +#include "init.h" +#include "main.h" +#include "net.h" +#include "wallet.h" + +using namespace std; +using namespace boost; +using namespace boost::assign; +using namespace json_spirit; + +void ScriptPubKeyToJSON(const CScript& scriptPubKey, Object& out, bool fIncludeHex) +{ + txnouttype type; + vector addresses; + int nRequired; + + out.push_back(Pair("asm", scriptPubKey.ToString())); + + if (fIncludeHex) + out.push_back(Pair("hex", HexStr(scriptPubKey.begin(), scriptPubKey.end()))); + + if (!ExtractDestinations(scriptPubKey, type, addresses, nRequired)) + { + out.push_back(Pair("type", GetTxnOutputType(type))); + return; + } + + out.push_back(Pair("reqSigs", nRequired)); + out.push_back(Pair("type", GetTxnOutputType(type))); + + Array a; + BOOST_FOREACH(const CTxDestination& addr, addresses) + a.push_back(CBitcoinAddress(addr).ToString()); + out.push_back(Pair("addresses", a)); +} + +void TxToJSON(const CTransaction& tx, const uint256 hashBlock, Object& entry) +{ + entry.push_back(Pair("txid", tx.GetHash().GetHex())); + entry.push_back(Pair("version", tx.nVersion)); + entry.push_back(Pair("locktime", (int64_t)tx.nLockTime)); + Array vin; + BOOST_FOREACH(const CTxIn& txin, tx.vin) + { + Object in; + if (tx.IsCoinBase()) + in.push_back(Pair("coinbase", HexStr(txin.scriptSig.begin(), txin.scriptSig.end()))); + else + { + in.push_back(Pair("txid", txin.prevout.hash.GetHex())); + in.push_back(Pair("vout", (int64_t)txin.prevout.n)); + Object o; + o.push_back(Pair("asm", txin.scriptSig.ToString())); + o.push_back(Pair("hex", HexStr(txin.scriptSig.begin(), txin.scriptSig.end()))); + in.push_back(Pair("scriptSig", o)); + } + in.push_back(Pair("sequence", (int64_t)txin.nSequence)); + vin.push_back(in); + } + entry.push_back(Pair("vin", vin)); + Array vout; + for (unsigned int i = 0; i < tx.vout.size(); i++) + { + const CTxOut& txout = tx.vout[i]; + Object out; + out.push_back(Pair("value", ValueFromAmount(txout.nValue))); + out.push_back(Pair("n", (int64_t)i)); + Object o; + ScriptPubKeyToJSON(txout.scriptPubKey, o, false); + out.push_back(Pair("scriptPubKey", o)); + vout.push_back(out); + } + entry.push_back(Pair("vout", vout)); + + if (hashBlock != 0) + { + entry.push_back(Pair("blockhash", hashBlock.GetHex())); + map::iterator mi = mapBlockIndex.find(hashBlock); + if (mi != mapBlockIndex.end() && (*mi).second) + { + CBlockIndex* pindex = (*mi).second; + if (pindex->IsInMainChain()) + { + entry.push_back(Pair("confirmations", 1 + nBestHeight - pindex->nHeight)); + entry.push_back(Pair("time", (int64_t)pindex->nTime)); + entry.push_back(Pair("blocktime", (int64_t)pindex->nTime)); + } + else + entry.push_back(Pair("confirmations", 0)); + } + } +} + +Value getrawtransaction(const Array& params, bool fHelp) +{ + if (fHelp || params.size() < 1 || params.size() > 2) + throw runtime_error( + "getrawtransaction [verbose=0]\n" + "If verbose=0, returns a string that is\n" + "serialized, hex-encoded data for .\n" + "If verbose is non-zero, returns an Object\n" + "with information about ."); + + uint256 hash; + hash.SetHex(params[0].get_str()); + + bool fVerbose = false; + if (params.size() > 1) + fVerbose = (params[1].get_int() != 0); + + CTransaction tx; + uint256 hashBlock = 0; + if (!GetTransaction(hash, tx, hashBlock)) + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "No information available about transaction"); + + CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION); + ssTx << tx; + string strHex = HexStr(ssTx.begin(), ssTx.end()); + + if (!fVerbose) + return strHex; + + Object result; + result.push_back(Pair("hex", strHex)); + TxToJSON(tx, hashBlock, result); + return result; +} + +Value listunspent(const Array& params, bool fHelp) +{ + if (fHelp || params.size() > 3) + throw runtime_error( + "listunspent [minconf=1] [maxconf=9999999] [\"address\",...]\n" + "Returns array of unspent transaction outputs\n" + "with between minconf and maxconf (inclusive) confirmations.\n" + "Optionally filtered to only include txouts paid to specified addresses.\n" + "Results are an array of Objects, each of which has:\n" + "{txid, vout, scriptPubKey, amount, confirmations}"); + + RPCTypeCheck(params, list_of(int_type)(int_type)(array_type)); + + int nMinDepth = 1; + if (params.size() > 0) + nMinDepth = params[0].get_int(); + + int nMaxDepth = 9999999; + if (params.size() > 1) + nMaxDepth = params[1].get_int(); + + set setAddress; + if (params.size() > 2) + { + Array inputs = params[2].get_array(); + BOOST_FOREACH(Value& input, inputs) + { + CBitcoinAddress address(input.get_str()); + if (!address.IsValid()) + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, string("Invalid arepacoin address: ")+input.get_str()); + if (setAddress.count(address)) + throw JSONRPCError(RPC_INVALID_PARAMETER, string("Invalid parameter, duplicated address: ")+input.get_str()); + setAddress.insert(address); + } + } + + Array results; + vector vecOutputs; + pwalletMain->AvailableCoins(vecOutputs, false); + BOOST_FOREACH(const COutput& out, vecOutputs) + { + if (out.nDepth < nMinDepth || out.nDepth > nMaxDepth) + continue; + + if(setAddress.size()) + { + CTxDestination address; + if(!ExtractDestination(out.tx->vout[out.i].scriptPubKey, address)) + continue; + + if (!setAddress.count(address)) + continue; + } + + int64_t nValue = out.tx->vout[out.i].nValue; + const CScript& pk = out.tx->vout[out.i].scriptPubKey; + Object entry; + entry.push_back(Pair("txid", out.tx->GetHash().GetHex())); + entry.push_back(Pair("vout", out.i)); + CTxDestination address; + if (ExtractDestination(out.tx->vout[out.i].scriptPubKey, address)) + { + entry.push_back(Pair("address", CBitcoinAddress(address).ToString())); + if (pwalletMain->mapAddressBook.count(address)) + entry.push_back(Pair("account", pwalletMain->mapAddressBook[address])); + } + entry.push_back(Pair("scriptPubKey", HexStr(pk.begin(), pk.end()))); + entry.push_back(Pair("amount",ValueFromAmount(nValue))); + entry.push_back(Pair("confirmations",out.nDepth)); + results.push_back(entry); + } + + return results; +} + +Value createrawtransaction(const Array& params, bool fHelp) +{ + if (fHelp || params.size() != 2) + throw runtime_error( + "createrawtransaction [{\"txid\":txid,\"vout\":n},...] {address:amount,...}\n" + "Create a transaction spending given inputs\n" + "(array of objects containing transaction id and output number),\n" + "sending to given address(es).\n" + "Returns hex-encoded raw transaction.\n" + "Note that the transaction's inputs are not signed, and\n" + "it is not stored in the wallet or transmitted to the network."); + + RPCTypeCheck(params, list_of(array_type)(obj_type)); + + Array inputs = params[0].get_array(); + Object sendTo = params[1].get_obj(); + + CTransaction rawTx; + + BOOST_FOREACH(Value& input, inputs) + { + const Object& o = input.get_obj(); + + const Value& txid_v = find_value(o, "txid"); + if (txid_v.type() != str_type) + throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, missing txid key"); + string txid = txid_v.get_str(); + if (!IsHex(txid)) + throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, expected hex txid"); + + const Value& vout_v = find_value(o, "vout"); + if (vout_v.type() != int_type) + throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, missing vout key"); + int nOutput = vout_v.get_int(); + if (nOutput < 0) + throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, vout must be positive"); + + CTxIn in(COutPoint(uint256(txid), nOutput)); + rawTx.vin.push_back(in); + } + + set setAddress; + BOOST_FOREACH(const Pair& s, sendTo) + { + CBitcoinAddress address(s.name_); + if (!address.IsValid()) + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, string("Invalid arepacoin address: ")+s.name_); + + if (setAddress.count(address)) + throw JSONRPCError(RPC_INVALID_PARAMETER, string("Invalid parameter, duplicated address: ")+s.name_); + setAddress.insert(address); + + CScript scriptPubKey; + scriptPubKey.SetDestination(address.Get()); + int64_t nAmount = AmountFromValue(s.value_); + + CTxOut out(nAmount, scriptPubKey); + rawTx.vout.push_back(out); + } + + CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); + ss << rawTx; + return HexStr(ss.begin(), ss.end()); +} + +Value decoderawtransaction(const Array& params, bool fHelp) +{ + if (fHelp || params.size() != 1) + throw runtime_error( + "decoderawtransaction \n" + "Return a JSON object representing the serialized, hex-encoded transaction."); + + RPCTypeCheck(params, list_of(str_type)); + + vector txData(ParseHex(params[0].get_str())); + CDataStream ssData(txData, SER_NETWORK, PROTOCOL_VERSION); + CTransaction tx; + try { + ssData >> tx; + } + catch (std::exception &e) { + throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX decode failed"); + } + + Object result; + TxToJSON(tx, 0, result); + + return result; +} + +Value decodescript(const Array& params, bool fHelp) +{ + if (fHelp || params.size() != 1) + throw runtime_error( + "decodescript \n" + "Decode a hex-encoded script."); + + RPCTypeCheck(params, list_of(str_type)); + + Object r; + CScript script; + if (params[0].get_str().size() > 0){ + vector scriptData(ParseHexV(params[0], "argument")); + script = CScript(scriptData.begin(), scriptData.end()); + } else { + // Empty scripts are valid + } + ScriptPubKeyToJSON(script, r, false); + + r.push_back(Pair("p2sh", CBitcoinAddress(script.GetID()).ToString())); + return r; +} + +Value signrawtransaction(const Array& params, bool fHelp) +{ + if (fHelp || params.size() < 1 || params.size() > 4) + throw runtime_error( + "signrawtransaction [{\"txid\":txid,\"vout\":n,\"scriptPubKey\":hex},...] [,...] [sighashtype=\"ALL\"]\n" + "Sign inputs for raw transaction (serialized, hex-encoded).\n" + "Second optional argument (may be null) is an array of previous transaction outputs that\n" + "this transaction depends on but may not yet be in the blockchain.\n" + "Third optional argument (may be null) is an array of base58-encoded private\n" + "keys that, if given, will be the only keys used to sign the transaction.\n" + "Fourth optional argument is a string that is one of six values; ALL, NONE, SINGLE or\n" + "ALL|ANYONECANPAY, NONE|ANYONECANPAY, SINGLE|ANYONECANPAY.\n" + "Returns json object with keys:\n" + " hex : raw transaction with signature(s) (hex-encoded string)\n" + " complete : 1 if transaction has a complete set of signature (0 if not)" + + HelpRequiringPassphrase()); + + RPCTypeCheck(params, list_of(str_type)(array_type)(array_type)(str_type), true); + + vector txData(ParseHex(params[0].get_str())); + CDataStream ssData(txData, SER_NETWORK, PROTOCOL_VERSION); + vector txVariants; + while (!ssData.empty()) + { + try { + CTransaction tx; + ssData >> tx; + txVariants.push_back(tx); + } + catch (std::exception &e) { + throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX decode failed"); + } + } + + if (txVariants.empty()) + throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "Missing transaction"); + + // mergedTx will end up with all the signatures; it + // starts as a clone of the rawtx: + CTransaction mergedTx(txVariants[0]); + bool fComplete = true; + + // Fetch previous transactions (inputs): + map mapPrevOut; + for (unsigned int i = 0; i < mergedTx.vin.size(); i++) + { + CTransaction tempTx; + MapPrevTx mapPrevTx; + CTxDB txdb("r"); + map unused; + bool fInvalid; + + // FetchInputs aborts on failure, so we go one at a time. + tempTx.vin.push_back(mergedTx.vin[i]); + tempTx.FetchInputs(txdb, unused, false, false, mapPrevTx, fInvalid); + + // Copy results into mapPrevOut: + BOOST_FOREACH(const CTxIn& txin, tempTx.vin) + { + const uint256& prevHash = txin.prevout.hash; + if (mapPrevTx.count(prevHash) && mapPrevTx[prevHash].second.vout.size()>txin.prevout.n) + mapPrevOut[txin.prevout] = mapPrevTx[prevHash].second.vout[txin.prevout.n].scriptPubKey; + } + } + + // Add previous txouts given in the RPC call: + if (params.size() > 1 && params[1].type() != null_type) + { + Array prevTxs = params[1].get_array(); + BOOST_FOREACH(Value& p, prevTxs) + { + if (p.type() != obj_type) + throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "expected object with {\"txid'\",\"vout\",\"scriptPubKey\"}"); + + Object prevOut = p.get_obj(); + + RPCTypeCheck(prevOut, map_list_of("txid", str_type)("vout", int_type)("scriptPubKey", str_type)); + + string txidHex = find_value(prevOut, "txid").get_str(); + if (!IsHex(txidHex)) + throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "txid must be hexadecimal"); + uint256 txid; + txid.SetHex(txidHex); + + int nOut = find_value(prevOut, "vout").get_int(); + if (nOut < 0) + throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "vout must be positive"); + + string pkHex = find_value(prevOut, "scriptPubKey").get_str(); + if (!IsHex(pkHex)) + throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "scriptPubKey must be hexadecimal"); + vector pkData(ParseHex(pkHex)); + CScript scriptPubKey(pkData.begin(), pkData.end()); + + COutPoint outpoint(txid, nOut); + if (mapPrevOut.count(outpoint)) + { + // Complain if scriptPubKey doesn't match + if (mapPrevOut[outpoint] != scriptPubKey) + { + string err("Previous output scriptPubKey mismatch:\n"); + err = err + mapPrevOut[outpoint].ToString() + "\nvs:\n"+ + scriptPubKey.ToString(); + throw JSONRPCError(RPC_DESERIALIZATION_ERROR, err); + } + } + else + mapPrevOut[outpoint] = scriptPubKey; + } + } + + bool fGivenKeys = false; + CBasicKeyStore tempKeystore; + if (params.size() > 2 && params[2].type() != null_type) + { + fGivenKeys = true; + Array keys = params[2].get_array(); + BOOST_FOREACH(Value k, keys) + { + CBitcoinSecret vchSecret; + bool fGood = vchSecret.SetString(k.get_str()); + if (!fGood) + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY,"Invalid private key"); + CKey key; + bool fCompressed; + CSecret secret = vchSecret.GetSecret(fCompressed); + key.SetSecret(secret, fCompressed); + tempKeystore.AddKey(key); + } + } + else + EnsureWalletIsUnlocked(); + + const CKeyStore& keystore = (fGivenKeys ? tempKeystore : *pwalletMain); + + int nHashType = SIGHASH_ALL; + if (params.size() > 3 && params[3].type() != null_type) + { + static map mapSigHashValues = + boost::assign::map_list_of + (string("ALL"), int(SIGHASH_ALL)) + (string("ALL|ANYONECANPAY"), int(SIGHASH_ALL|SIGHASH_ANYONECANPAY)) + (string("NONE"), int(SIGHASH_NONE)) + (string("NONE|ANYONECANPAY"), int(SIGHASH_NONE|SIGHASH_ANYONECANPAY)) + (string("SINGLE"), int(SIGHASH_SINGLE)) + (string("SINGLE|ANYONECANPAY"), int(SIGHASH_SINGLE|SIGHASH_ANYONECANPAY)) + ; + string strHashType = params[3].get_str(); + if (mapSigHashValues.count(strHashType)) + nHashType = mapSigHashValues[strHashType]; + else + throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid sighash param"); + } + + bool fHashSingle = ((nHashType & ~SIGHASH_ANYONECANPAY) == SIGHASH_SINGLE); + + // Sign what we can: + for (unsigned int i = 0; i < mergedTx.vin.size(); i++) + { + CTxIn& txin = mergedTx.vin[i]; + if (mapPrevOut.count(txin.prevout) == 0) + { + fComplete = false; + continue; + } + const CScript& prevPubKey = mapPrevOut[txin.prevout]; + + txin.scriptSig.clear(); + // Only sign SIGHASH_SINGLE if there's a corresponding output: + if (!fHashSingle || (i < mergedTx.vout.size())) + SignSignature(keystore, prevPubKey, mergedTx, i, nHashType); + + // ... and merge in other signatures: + BOOST_FOREACH(const CTransaction& txv, txVariants) + { + txin.scriptSig = CombineSignatures(prevPubKey, mergedTx, i, txin.scriptSig, txv.vin[i].scriptSig); + } + if (!VerifyScript(txin.scriptSig, prevPubKey, mergedTx, i, 0)) + fComplete = false; + } + + Object result; + CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION); + ssTx << mergedTx; + result.push_back(Pair("hex", HexStr(ssTx.begin(), ssTx.end()))); + result.push_back(Pair("complete", fComplete)); + + return result; +} + +Value sendrawtransaction(const Array& params, bool fHelp) +{ + if (fHelp || params.size() < 1 || params.size() > 1) + throw runtime_error( + "sendrawtransaction \n" + "Submits raw transaction (serialized, hex-encoded) to local node and network."); + + RPCTypeCheck(params, list_of(str_type)); + + // parse hex string from parameter + vector txData(ParseHex(params[0].get_str())); + CDataStream ssData(txData, SER_NETWORK, PROTOCOL_VERSION); + CTransaction tx; + + // deserialize binary data stream + try { + ssData >> tx; + } + catch (std::exception &e) { + throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX decode failed"); + } + uint256 hashTx = tx.GetHash(); + + // See if the transaction is already in a block + // or in the memory pool: + CTransaction existingTx; + uint256 hashBlock = 0; + if (GetTransaction(hashTx, existingTx, hashBlock)) + { + if (hashBlock != 0) + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, string("transaction already in block ")+hashBlock.GetHex()); + // Not in block, but already in the memory pool; will drop + // through to re-relay it. + } + else + { + // push to local node + if (!AcceptToMemoryPool(mempool, tx, NULL)) + throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX rejected"); + + SyncWithWallets(tx, NULL, true); + } + RelayTransaction(tx, hashTx); + + return hashTx.GetHex(); +} diff --git a/src/rpcwallet.cpp b/src/rpcwallet.cpp new file mode 100644 index 0000000..654ee01 --- /dev/null +++ b/src/rpcwallet.cpp @@ -0,0 +1,1802 @@ +// Copyright (c) 2010 Satoshi Nakamoto +// Copyright (c) 2009-2012 The Bitcoin developers +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include "wallet.h" +#include "walletdb.h" +#include "bitcoinrpc.h" +#include "init.h" +#include "base58.h" + +using namespace json_spirit; +using namespace std; + +int64_t nWalletUnlockTime; +static CCriticalSection cs_nWalletUnlockTime; + +extern void TxToJSON(const CTransaction& tx, const uint256 hashBlock, json_spirit::Object& entry); + +static void accountingDeprecationCheck() +{ + if (!GetBoolArg("-enableaccounts", false)) + throw runtime_error( + "Accounting API is deprecated and will be removed in future.\n" + "It can easily result in negative or odd balances if misused or misunderstood, which has happened in the field.\n" + "If you still want to enable it, add to your config file enableaccounts=1\n"); + + if (GetBoolArg("-staking", true)) + throw runtime_error("If you want to use accounting API, staking must be disabled, add to your config file staking=0\n"); +} + +std::string HelpRequiringPassphrase() +{ + return pwalletMain->IsCrypted() + ? "\nrequires wallet passphrase to be set with walletpassphrase first" + : ""; +} + +void EnsureWalletIsUnlocked() +{ + if (pwalletMain->IsLocked()) + throw JSONRPCError(RPC_WALLET_UNLOCK_NEEDED, "Error: Please enter the wallet passphrase with walletpassphrase first."); + if (fWalletUnlockStakingOnly) + throw JSONRPCError(RPC_WALLET_UNLOCK_NEEDED, "Error: Wallet is unlocked for staking only."); +} + +void WalletTxToJSON(const CWalletTx& wtx, Object& entry) +{ + int confirms = wtx.GetDepthInMainChain(); + entry.push_back(Pair("confirmations", confirms)); + if (wtx.IsCoinBase() || wtx.IsCoinStake()) + entry.push_back(Pair("generated", true)); + if (confirms > 0) + { + entry.push_back(Pair("blockhash", wtx.hashBlock.GetHex())); + entry.push_back(Pair("blockindex", wtx.nIndex)); + entry.push_back(Pair("blocktime", (int64_t)(mapBlockIndex[wtx.hashBlock]->nTime))); + } + entry.push_back(Pair("txid", wtx.GetHash().GetHex())); + entry.push_back(Pair("time", (int64_t)wtx.GetTxTime())); + entry.push_back(Pair("timereceived", (int64_t)wtx.nTimeReceived)); + BOOST_FOREACH(const PAIRTYPE(string,string)& item, wtx.mapValue) + entry.push_back(Pair(item.first, item.second)); +} + +string AccountFromValue(const Value& value) +{ + string strAccount = value.get_str(); + if (strAccount == "*") + throw JSONRPCError(RPC_WALLET_INVALID_ACCOUNT_NAME, "Invalid account name"); + return strAccount; +} + +Value getinfo(const Array& params, bool fHelp) +{ + if (fHelp || params.size() != 0) + throw runtime_error( + "getinfo\n" + "Returns an object containing various state info."); + + proxyType proxy; + GetProxy(NET_IPV4, proxy); + + Object obj, diff; + obj.push_back(Pair("version", FormatFullVersion())); + obj.push_back(Pair("protocolversion",(int)PROTOCOL_VERSION)); + obj.push_back(Pair("walletversion", pwalletMain->GetVersion())); + obj.push_back(Pair("balance", ValueFromAmount(pwalletMain->GetBalance()))); + obj.push_back(Pair("newmint", ValueFromAmount(pwalletMain->GetNewMint()))); + obj.push_back(Pair("stake", ValueFromAmount(pwalletMain->GetStake()))); + obj.push_back(Pair("blocks", (int)nBestHeight)); + obj.push_back(Pair("timeoffset", (int64_t)GetTimeOffset())); + obj.push_back(Pair("moneysupply", ValueFromAmount(pindexBest->nMoneySupply))); + obj.push_back(Pair("connections", (int)vNodes.size())); + obj.push_back(Pair("proxy", (proxy.first.IsValid() ? proxy.first.ToStringIPPort() : string()))); + obj.push_back(Pair("ip", addrSeenByPeerIp.ToStringIP())); + obj.push_back(Pair("ipv4", addrSeenByPeerIpv4.ToStringIP())); + obj.push_back(Pair("ipv6", addrSeenByPeerIpv6.ToStringIP())); + + diff.push_back(Pair("proof-of-work", GetDifficulty())); + diff.push_back(Pair("proof-of-stake", GetDifficulty(GetLastBlockIndex(pindexBest, true)))); + obj.push_back(Pair("difficulty", diff)); + + obj.push_back(Pair("testnet", fTestNet)); + obj.push_back(Pair("keypoololdest", (int64_t)pwalletMain->GetOldestKeyPoolTime())); + obj.push_back(Pair("keypoolsize", (int)pwalletMain->GetKeyPoolSize())); + obj.push_back(Pair("paytxfee", ValueFromAmount(nTransactionFee))); + obj.push_back(Pair("mininput", ValueFromAmount(nMinimumInputValue))); + if (pwalletMain->IsCrypted()) + obj.push_back(Pair("unlocked_until", (int64_t)nWalletUnlockTime / 1000)); + obj.push_back(Pair("errors", GetWarnings("statusbar"))); + return obj; +} + + +Value getnewpubkey(const Array& params, bool fHelp) +{ + if (fHelp || params.size() > 1) + throw runtime_error( + "getnewpubkey [account]\n" + "Returns new public key for coinbase generation."); + + // Parse the account first so we don't generate a key if there's an error + string strAccount; + if (params.size() > 0) + strAccount = AccountFromValue(params[0]); + + if (!pwalletMain->IsLocked()) + pwalletMain->TopUpKeyPool(); + + // Generate a new key that is added to wallet + CPubKey newKey; + if (!pwalletMain->GetKeyFromPool(newKey, false)) + throw JSONRPCError(RPC_WALLET_KEYPOOL_RAN_OUT, "Error: Keypool ran out, please call keypoolrefill first"); + CKeyID keyID = newKey.GetID(); + + pwalletMain->SetAddressBookName(keyID, strAccount); + vector vchPubKey = newKey.Raw(); + + return HexStr(vchPubKey.begin(), vchPubKey.end()); +} + + +Value getnewaddress(const Array& params, bool fHelp) +{ + if (fHelp || params.size() > 1) + throw runtime_error( + "getnewaddress [account]\n" + "Returns a new arepacoin address for receiving payments. " + "If [account] is specified, it is added to the address book " + "so payments received with the address will be credited to [account]."); + + // Parse the account first so we don't generate a key if there's an error + string strAccount; + if (params.size() > 0) + strAccount = AccountFromValue(params[0]); + + if (!pwalletMain->IsLocked()) + pwalletMain->TopUpKeyPool(); + + // Generate a new key that is added to wallet + CPubKey newKey; + if (!pwalletMain->GetKeyFromPool(newKey, false)) + throw JSONRPCError(RPC_WALLET_KEYPOOL_RAN_OUT, "Error: Keypool ran out, please call keypoolrefill first"); + CKeyID keyID = newKey.GetID(); + + pwalletMain->SetAddressBookName(keyID, strAccount); + + return CBitcoinAddress(keyID).ToString(); +} + + +CBitcoinAddress GetAccountAddress(string strAccount, bool bForceNew=false) +{ + CWalletDB walletdb(pwalletMain->strWalletFile); + + CAccount account; + walletdb.ReadAccount(strAccount, account); + + bool bKeyUsed = false; + + // Check if the current key has been used + if (account.vchPubKey.IsValid()) + { + CScript scriptPubKey; + scriptPubKey.SetDestination(account.vchPubKey.GetID()); + for (map::iterator it = pwalletMain->mapWallet.begin(); + it != pwalletMain->mapWallet.end() && account.vchPubKey.IsValid(); + ++it) + { + const CWalletTx& wtx = (*it).second; + BOOST_FOREACH(const CTxOut& txout, wtx.vout) + if (txout.scriptPubKey == scriptPubKey) + bKeyUsed = true; + } + } + + // Generate a new key + if (!account.vchPubKey.IsValid() || bForceNew || bKeyUsed) + { + if (!pwalletMain->GetKeyFromPool(account.vchPubKey, false)) + throw JSONRPCError(RPC_WALLET_KEYPOOL_RAN_OUT, "Error: Keypool ran out, please call keypoolrefill first"); + + pwalletMain->SetAddressBookName(account.vchPubKey.GetID(), strAccount); + walletdb.WriteAccount(strAccount, account); + } + + return CBitcoinAddress(account.vchPubKey.GetID()); +} + +Value getaccountaddress(const Array& params, bool fHelp) +{ + if (fHelp || params.size() != 1) + throw runtime_error( + "getaccountaddress \n" + "Returns the current arepacoin address for receiving payments to this account."); + + // Parse the account first so we don't generate a key if there's an error + string strAccount = AccountFromValue(params[0]); + + Value ret; + + ret = GetAccountAddress(strAccount).ToString(); + + return ret; +} + + + +Value setaccount(const Array& params, bool fHelp) +{ + if (fHelp || params.size() < 1 || params.size() > 2) + throw runtime_error( + "setaccount \n" + "Sets the account associated with the given address."); + + CBitcoinAddress address(params[0].get_str()); + if (!address.IsValid()) + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid arepacoin address"); + + + string strAccount; + if (params.size() > 1) + strAccount = AccountFromValue(params[1]); + + // Detect when changing the account of an address that is the 'unused current key' of another account: + if (pwalletMain->mapAddressBook.count(address.Get())) + { + string strOldAccount = pwalletMain->mapAddressBook[address.Get()]; + if (address == GetAccountAddress(strOldAccount)) + GetAccountAddress(strOldAccount, true); + } + + pwalletMain->SetAddressBookName(address.Get(), strAccount); + + return Value::null; +} + + +Value getaccount(const Array& params, bool fHelp) +{ + if (fHelp || params.size() != 1) + throw runtime_error( + "getaccount \n" + "Returns the account associated with the given address."); + + CBitcoinAddress address(params[0].get_str()); + if (!address.IsValid()) + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid arepacoin address"); + + string strAccount; + map::iterator mi = pwalletMain->mapAddressBook.find(address.Get()); + if (mi != pwalletMain->mapAddressBook.end() && !(*mi).second.empty()) + strAccount = (*mi).second; + return strAccount; +} + + +Value getaddressesbyaccount(const Array& params, bool fHelp) +{ + if (fHelp || params.size() != 1) + throw runtime_error( + "getaddressesbyaccount \n" + "Returns the list of addresses for the given account."); + + string strAccount = AccountFromValue(params[0]); + + // Find all addresses that have the given account + Array ret; + BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& item, pwalletMain->mapAddressBook) + { + const CBitcoinAddress& address = item.first; + const string& strName = item.second; + if (strName == strAccount) + ret.push_back(address.ToString()); + } + return ret; +} + + +Value getaddresses(const Array& params, bool fHelp) +{ + if (fHelp || params.size() != 0) + throw runtime_error( + "getaddresses\n" + "Returns the list of addresses."); + + Object obj; + obj.push_back(Pair("flags", "accounts for receiving coins")); + BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& item, pwalletMain->mapAddressBook) + { + const CBitcoinAddress& address = item.first; + const string& strName = item.second; + obj.push_back(Pair(strName, address.ToString())); + } + return obj; +} + +Value sendtoaddress(const Array& params, bool fHelp) +{ + if (fHelp || params.size() < 2 || params.size() > 4) + throw runtime_error( + "sendtoaddress [comment] [comment-to]\n" + " is a real and is rounded to the nearest 0.000001" + + HelpRequiringPassphrase()); + + CBitcoinAddress address(params[0].get_str()); + if (!address.IsValid()) + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid arepacoin address"); + + // Amount + int64_t nAmount = AmountFromValue(params[1]); + + // Wallet comments + CWalletTx wtx; + if (params.size() > 2 && params[2].type() != null_type && !params[2].get_str().empty()) + wtx.mapValue["comment"] = 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(); + + if (pwalletMain->IsLocked()) + throw JSONRPCError(RPC_WALLET_UNLOCK_NEEDED, "Error: Please enter the wallet passphrase with walletpassphrase first."); + + string strError = pwalletMain->SendMoneyToDestination(address.Get(), nAmount, wtx); + if (strError != "") + throw JSONRPCError(RPC_WALLET_ERROR, strError); + + return wtx.GetHash().GetHex(); +} + +Value listaddressgroupings(const Array& params, bool fHelp) +{ + if (fHelp) + throw runtime_error( + "listaddressgroupings\n" + "Lists groups of addresses which have had their common ownership\n" + "made public by common use as inputs or as the resulting change\n" + "in past transactions"); + + Array jsonGroupings; + map balances = pwalletMain->GetAddressBalances(); + BOOST_FOREACH(set grouping, pwalletMain->GetAddressGroupings()) + { + Array jsonGrouping; + BOOST_FOREACH(CTxDestination address, grouping) + { + Array addressInfo; + addressInfo.push_back(CBitcoinAddress(address).ToString()); + addressInfo.push_back(ValueFromAmount(balances[address])); + { + LOCK(pwalletMain->cs_wallet); + if (pwalletMain->mapAddressBook.find(CBitcoinAddress(address).Get()) != pwalletMain->mapAddressBook.end()) + addressInfo.push_back(pwalletMain->mapAddressBook.find(CBitcoinAddress(address).Get())->second); + } + jsonGrouping.push_back(addressInfo); + } + jsonGroupings.push_back(jsonGrouping); + } + return jsonGroupings; +} + +Value signmessage(const Array& params, bool fHelp) +{ + if (fHelp || params.size() != 2) + throw runtime_error( + "signmessage \n" + "Sign a message with the private key of an address"); + + EnsureWalletIsUnlocked(); + + string strAddress = params[0].get_str(); + string strMessage = params[1].get_str(); + + CBitcoinAddress addr(strAddress); + if (!addr.IsValid()) + throw JSONRPCError(RPC_TYPE_ERROR, "Invalid address"); + + CKeyID keyID; + if (!addr.GetKeyID(keyID)) + throw JSONRPCError(RPC_TYPE_ERROR, "Address does not refer to key"); + + CKey key; + if (!pwalletMain->GetKey(keyID, key)) + throw JSONRPCError(RPC_WALLET_ERROR, "Private key not available"); + + CDataStream ss(SER_GETHASH, 0); + ss << strMessageMagic; + ss << strMessage; + + vector vchSig; + if (!key.SignCompact(Hash(ss.begin(), ss.end()), vchSig)) + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Sign failed"); + + return EncodeBase64(&vchSig[0], vchSig.size()); +} + +Value verifymessage(const Array& params, bool fHelp) +{ + if (fHelp || params.size() != 3) + throw runtime_error( + "verifymessage \n" + "Verify a signed message"); + + string strAddress = params[0].get_str(); + string strSign = params[1].get_str(); + string strMessage = params[2].get_str(); + + CBitcoinAddress addr(strAddress); + if (!addr.IsValid()) + throw JSONRPCError(RPC_TYPE_ERROR, "Invalid address"); + + CKeyID keyID; + if (!addr.GetKeyID(keyID)) + throw JSONRPCError(RPC_TYPE_ERROR, "Address does not refer to key"); + + bool fInvalid = false; + vector vchSig = DecodeBase64(strSign.c_str(), &fInvalid); + + if (fInvalid) + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Malformed base64 encoding"); + + CDataStream ss(SER_GETHASH, 0); + ss << strMessageMagic; + ss << strMessage; + + CKey key; + if (!key.SetCompactSignature(Hash(ss.begin(), ss.end()), vchSig)) + return false; + + return (key.GetPubKey().GetID() == keyID); +} + + +Value getreceivedbyaddress(const Array& params, bool fHelp) +{ + if (fHelp || params.size() < 1 || params.size() > 2) + throw runtime_error( + "getreceivedbyaddress [minconf=1]\n" + "Returns the total amount received by in transactions with at least [minconf] confirmations."); + + // Bitcoin address + CBitcoinAddress address = CBitcoinAddress(params[0].get_str()); + CScript scriptPubKey; + if (!address.IsValid()) + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid arepacoin address"); + scriptPubKey.SetDestination(address.Get()); + if (!IsMine(*pwalletMain,scriptPubKey)) + return (double)0.0; + + // Minimum confirmations + int nMinDepth = 1; + if (params.size() > 1) + nMinDepth = params[1].get_int(); + + // Tally + int64_t nAmount = 0; + for (map::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it) + { + const CWalletTx& wtx = (*it).second; + if (wtx.IsCoinBase() || wtx.IsCoinStake() || !IsFinalTx(wtx)) + continue; + + BOOST_FOREACH(const CTxOut& txout, wtx.vout) + if (txout.scriptPubKey == scriptPubKey) + if (wtx.GetDepthInMainChain() >= nMinDepth) + nAmount += txout.nValue; + } + + return ValueFromAmount(nAmount); +} + + +void GetAccountAddresses(string strAccount, set& setAddress) +{ + BOOST_FOREACH(const PAIRTYPE(CTxDestination, string)& item, pwalletMain->mapAddressBook) + { + const CTxDestination& address = item.first; + const string& strName = item.second; + if (strName == strAccount) + setAddress.insert(address); + } +} + +Value getreceivedbyaccount(const Array& params, bool fHelp) +{ + if (fHelp || params.size() < 1 || params.size() > 2) + throw runtime_error( + "getreceivedbyaccount [minconf=1]\n" + "Returns the total amount received by addresses with in transactions with at least [minconf] confirmations."); + + accountingDeprecationCheck(); + + // Minimum confirmations + int nMinDepth = 1; + if (params.size() > 1) + nMinDepth = params[1].get_int(); + + // Get the set of pub keys assigned to account + string strAccount = AccountFromValue(params[0]); + set setAddress; + GetAccountAddresses(strAccount, setAddress); + + // Tally + int64_t nAmount = 0; + for (map::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it) + { + const CWalletTx& wtx = (*it).second; + if (wtx.IsCoinBase() || wtx.IsCoinStake() || !IsFinalTx(wtx)) + continue; + + BOOST_FOREACH(const CTxOut& txout, wtx.vout) + { + CTxDestination address; + if (ExtractDestination(txout.scriptPubKey, address) && IsMine(*pwalletMain, address) && setAddress.count(address)) + if (wtx.GetDepthInMainChain() >= nMinDepth) + nAmount += txout.nValue; + } + } + + return (double)nAmount / (double)COIN; +} + + +int64_t GetAccountBalance(CWalletDB& walletdb, const string& strAccount, int nMinDepth) +{ + int64_t nBalance = 0; + + // Tally wallet transactions + for (map::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it) + { + const CWalletTx& wtx = (*it).second; + if (!IsFinalTx(wtx) || wtx.GetDepthInMainChain() < 0) + continue; + + int64_t nReceived, nSent, nFee; + wtx.GetAccountAmounts(strAccount, nReceived, nSent, nFee); + + if (nReceived != 0 && wtx.GetDepthInMainChain() >= nMinDepth && wtx.GetBlocksToMaturity() == 0) + nBalance += nReceived; + nBalance -= nSent + nFee; + } + + // Tally internal accounting entries + nBalance += walletdb.GetAccountCreditDebit(strAccount); + + return nBalance; +} + +int64_t GetAccountBalance(const string& strAccount, int nMinDepth) +{ + CWalletDB walletdb(pwalletMain->strWalletFile); + return GetAccountBalance(walletdb, strAccount, nMinDepth); +} + + +Value getbalance(const Array& params, bool fHelp) +{ + if (fHelp || params.size() > 2) + throw runtime_error( + "getbalance [account] [minconf=1]\n" + "If [account] is not specified, returns the server's total available balance.\n" + "If [account] is specified, returns the balance in the account."); + + if (params.size() == 0) + return ValueFromAmount(pwalletMain->GetBalance()); + + int nMinDepth = 1; + if (params.size() > 1) + nMinDepth = params[1].get_int(); + + if (params[0].get_str() == "*") { + // Calculate total balance a different way from GetBalance() + // (GetBalance() sums up all unspent TxOuts) + // getbalance and getbalance '*' 0 should return the same number. + int64_t nBalance = 0; + for (map::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it) + { + const CWalletTx& wtx = (*it).second; + if (!wtx.IsTrusted()) + continue; + + int64_t allFee; + string strSentAccount; + list > listReceived; + list > listSent; + wtx.GetAmounts(listReceived, listSent, allFee, strSentAccount); + if (wtx.GetDepthInMainChain() >= nMinDepth && wtx.GetBlocksToMaturity() == 0) + { + BOOST_FOREACH(const PAIRTYPE(CTxDestination,int64_t)& r, listReceived) + nBalance += r.second; + } + BOOST_FOREACH(const PAIRTYPE(CTxDestination,int64_t)& r, listSent) + nBalance -= r.second; + nBalance -= allFee; + } + return ValueFromAmount(nBalance); + } + + accountingDeprecationCheck(); + + string strAccount = AccountFromValue(params[0]); + + int64_t nBalance = GetAccountBalance(strAccount, nMinDepth); + + return ValueFromAmount(nBalance); +} + + +Value movecmd(const Array& params, bool fHelp) +{ + if (fHelp || params.size() < 3 || params.size() > 5) + throw runtime_error( + "move [minconf=1] [comment]\n" + "Move from one account in your wallet to another."); + + accountingDeprecationCheck(); + + string strFrom = AccountFromValue(params[0]); + string strTo = AccountFromValue(params[1]); + int64_t nAmount = AmountFromValue(params[2]); + + if (params.size() > 3) + // unused parameter, used to be nMinDepth, keep type-checking it though + (void)params[3].get_int(); + string strComment; + if (params.size() > 4) + strComment = params[4].get_str(); + + CWalletDB walletdb(pwalletMain->strWalletFile); + if (!walletdb.TxnBegin()) + throw JSONRPCError(RPC_DATABASE_ERROR, "database error"); + + int64_t nNow = GetAdjustedTime(); + + // Debit + CAccountingEntry debit; + debit.nOrderPos = pwalletMain->IncOrderPosNext(&walletdb); + debit.strAccount = strFrom; + debit.nCreditDebit = -nAmount; + debit.nTime = nNow; + debit.strOtherAccount = strTo; + debit.strComment = strComment; + walletdb.WriteAccountingEntry(debit); + + // Credit + CAccountingEntry credit; + credit.nOrderPos = pwalletMain->IncOrderPosNext(&walletdb); + credit.strAccount = strTo; + credit.nCreditDebit = nAmount; + credit.nTime = nNow; + credit.strOtherAccount = strFrom; + credit.strComment = strComment; + walletdb.WriteAccountingEntry(credit); + + if (!walletdb.TxnCommit()) + throw JSONRPCError(RPC_DATABASE_ERROR, "database error"); + + return true; +} + + +Value sendfrom(const Array& params, bool fHelp) +{ + if (fHelp || params.size() < 3 || params.size() > 6) + throw runtime_error( + "sendfrom [minconf=1] [comment] [comment-to]\n" + " is a real and is rounded to the nearest 0.000001" + + HelpRequiringPassphrase()); + + string strAccount = AccountFromValue(params[0]); + CBitcoinAddress address(params[1].get_str()); + if (!address.IsValid()) + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid arepacoin address"); + int64_t nAmount = AmountFromValue(params[2]); + + int nMinDepth = 1; + if (params.size() > 3) + nMinDepth = params[3].get_int(); + + CWalletTx wtx; + wtx.strFromAccount = strAccount; + if (params.size() > 4 && params[4].type() != null_type && !params[4].get_str().empty()) + wtx.mapValue["comment"] = params[4].get_str(); + if (params.size() > 5 && params[5].type() != null_type && !params[5].get_str().empty()) + wtx.mapValue["to"] = params[5].get_str(); + + EnsureWalletIsUnlocked(); + + // Check funds + int64_t nBalance = GetAccountBalance(strAccount, nMinDepth); + if (nAmount > nBalance) + throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, "Account has insufficient funds"); + + // Send + string strError = pwalletMain->SendMoneyToDestination(address.Get(), nAmount, wtx); + if (strError != "") + throw JSONRPCError(RPC_WALLET_ERROR, strError); + + return wtx.GetHash().GetHex(); +} + + +Value sendmany(const Array& params, bool fHelp) +{ + if (fHelp || params.size() < 2 || params.size() > 4) + throw runtime_error( + "sendmany {address:amount,...} [minconf=1] [comment]\n" + "amounts are double-precision floating point numbers" + + HelpRequiringPassphrase()); + + string strAccount = AccountFromValue(params[0]); + Object sendTo = params[1].get_obj(); + int nMinDepth = 1; + if (params.size() > 2) + nMinDepth = params[2].get_int(); + + CWalletTx wtx; + wtx.strFromAccount = strAccount; + if (params.size() > 3 && params[3].type() != null_type && !params[3].get_str().empty()) + wtx.mapValue["comment"] = params[3].get_str(); + + set setAddress; + vector > vecSend; + + int64_t totalAmount = 0; + BOOST_FOREACH(const Pair& s, sendTo) + { + CBitcoinAddress address(s.name_); + if (!address.IsValid()) + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, string("Invalid arepacoin address: ")+s.name_); + + if (setAddress.count(address)) + throw JSONRPCError(RPC_INVALID_PARAMETER, string("Invalid parameter, duplicated address: ")+s.name_); + setAddress.insert(address); + + CScript scriptPubKey; + scriptPubKey.SetDestination(address.Get()); + int64_t nAmount = AmountFromValue(s.value_); + + totalAmount += nAmount; + + vecSend.push_back(make_pair(scriptPubKey, nAmount)); + } + + EnsureWalletIsUnlocked(); + + // Check funds + int64_t nBalance = GetAccountBalance(strAccount, nMinDepth); + if (totalAmount > nBalance) + throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, "Account has insufficient funds"); + + // Send + CReserveKey keyChange(pwalletMain); + int64_t nFeeRequired = 0; + bool fCreated = pwalletMain->CreateTransaction(vecSend, wtx, keyChange, nFeeRequired); + if (!fCreated) + { + if (totalAmount + nFeeRequired > pwalletMain->GetBalance()) + throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, "Insufficient funds"); + throw JSONRPCError(RPC_WALLET_ERROR, "Transaction creation failed"); + } + if (!pwalletMain->CommitTransaction(wtx, keyChange)) + throw JSONRPCError(RPC_WALLET_ERROR, "Transaction commit failed"); + + return wtx.GetHash().GetHex(); +} + +Value addmultisigaddress(const Array& params, bool fHelp) +{ + if (fHelp || params.size() < 2 || params.size() > 3) + { + string msg = "addmultisigaddress <'[\"key\",\"key\"]'> [account]\n" + "Add a nrequired-to-sign multisignature address to the wallet\"\n" + "each key is a arepacoin address or hex-encoded public key\n" + "If [account] is specified, assign address to [account]."; + throw runtime_error(msg); + } + + int nRequired = params[0].get_int(); + const Array& keys = params[1].get_array(); + string strAccount; + if (params.size() > 2) + strAccount = AccountFromValue(params[2]); + + // Gather public keys + if (nRequired < 1) + throw runtime_error("a multisignature address must require at least one key to redeem"); + if ((int)keys.size() < nRequired) + throw runtime_error( + strprintf("not enough keys supplied " + "(got %" PRIszu" keys, but need at least %d to redeem)", keys.size(), nRequired)); + std::vector pubkeys; + pubkeys.resize(keys.size()); + for (unsigned int i = 0; i < keys.size(); i++) + { + const std::string& ks = keys[i].get_str(); + + // Case 1: Bitcoin address and we have full public key: + CBitcoinAddress address(ks); + if (address.IsValid()) + { + CKeyID keyID; + if (!address.GetKeyID(keyID)) + throw runtime_error( + strprintf("%s does not refer to a key",ks.c_str())); + CPubKey vchPubKey; + if (!pwalletMain->GetPubKey(keyID, vchPubKey)) + throw runtime_error( + strprintf("no full public key for address %s",ks.c_str())); + if (!vchPubKey.IsValid() || !pubkeys[i].SetPubKey(vchPubKey)) + throw runtime_error(" Invalid public key: "+ks); + } + + // Case 2: hex public key + else if (IsHex(ks)) + { + CPubKey vchPubKey(ParseHex(ks)); + if (!vchPubKey.IsValid() || !pubkeys[i].SetPubKey(vchPubKey)) + throw runtime_error(" Invalid public key: "+ks); + } + else + { + throw runtime_error(" Invalid public key: "+ks); + } + } + + // Construct using pay-to-script-hash: + CScript inner; + inner.SetMultisig(nRequired, pubkeys); + CScriptID innerID = inner.GetID(); + if (!pwalletMain->AddCScript(inner)) + throw runtime_error("AddCScript() failed"); + + pwalletMain->SetAddressBookName(innerID, strAccount); + return CBitcoinAddress(innerID).ToString(); +} + +Value addredeemscript(const Array& params, bool fHelp) +{ + if (fHelp || params.size() < 1 || params.size() > 2) + { + string msg = "addredeemscript [account]\n" + "Add a P2SH address with a specified redeemScript to the wallet.\n" + "If [account] is specified, assign address to [account]."; + throw runtime_error(msg); + } + + string strAccount; + if (params.size() > 1) + strAccount = AccountFromValue(params[1]); + + // Construct using pay-to-script-hash: + vector innerData = ParseHexV(params[0], "redeemScript"); + CScript inner(innerData.begin(), innerData.end()); + CScriptID innerID = inner.GetID(); + if (!pwalletMain->AddCScript(inner)) + throw runtime_error("AddCScript() failed"); + + pwalletMain->SetAddressBookName(innerID, strAccount); + return CBitcoinAddress(innerID).ToString(); +} + +struct tallyitem +{ + int64_t nAmount; + int nConf; + tallyitem() + { + nAmount = 0; + nConf = std::numeric_limits::max(); + } +}; + +Value ListReceived(const Array& params, bool fByAccounts) +{ + // Minimum confirmations + int nMinDepth = 1; + if (params.size() > 0) + nMinDepth = params[0].get_int(); + + // Whether to include empty accounts + bool fIncludeEmpty = false; + if (params.size() > 1) + fIncludeEmpty = params[1].get_bool(); + + // Tally + map mapTally; + for (map::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it) + { + const CWalletTx& wtx = (*it).second; + + if (wtx.IsCoinBase() || wtx.IsCoinStake() || !IsFinalTx(wtx)) + continue; + + int nDepth = wtx.GetDepthInMainChain(); + if (nDepth < nMinDepth) + continue; + + BOOST_FOREACH(const CTxOut& txout, wtx.vout) + { + CTxDestination address; + if (!ExtractDestination(txout.scriptPubKey, address) || !IsMine(*pwalletMain, address)) + continue; + + tallyitem& item = mapTally[address]; + item.nAmount += txout.nValue; + item.nConf = min(item.nConf, nDepth); + } + } + + // Reply + Array ret; + map mapAccountTally; + BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& item, pwalletMain->mapAddressBook) + { + const CBitcoinAddress& address = item.first; + const string& strAccount = item.second; + map::iterator it = mapTally.find(address); + if (it == mapTally.end() && !fIncludeEmpty) + continue; + + int64_t nAmount = 0; + int nConf = std::numeric_limits::max(); + if (it != mapTally.end()) + { + nAmount = (*it).second.nAmount; + nConf = (*it).second.nConf; + } + + if (fByAccounts) + { + tallyitem& item = mapAccountTally[strAccount]; + item.nAmount += nAmount; + item.nConf = min(item.nConf, nConf); + } + else + { + Object obj; + obj.push_back(Pair("flags", "coins received")); + obj.push_back(Pair("address", address.ToString())); + obj.push_back(Pair("account", strAccount)); + obj.push_back(Pair("amount", ValueFromAmount(nAmount))); + obj.push_back(Pair("confirmations", (nConf == std::numeric_limits::max() ? 0 : nConf))); + ret.push_back(obj); + } + } + + if (fByAccounts) + { + for (map::iterator it = mapAccountTally.begin(); it != mapAccountTally.end(); ++it) + { + int64_t nAmount = (*it).second.nAmount; + int nConf = (*it).second.nConf; + Object obj; + obj.push_back(Pair("flags", "coins received")); + obj.push_back(Pair("account", (*it).first)); + obj.push_back(Pair("amount", ValueFromAmount(nAmount))); + obj.push_back(Pair("confirmations", (nConf == std::numeric_limits::max() ? 0 : nConf))); + ret.push_back(obj); + } + } + + return ret; +} + +Value listreceivedbyaddress(const Array& params, bool fHelp) +{ + if (fHelp || params.size() > 2) + throw runtime_error( + "listreceivedbyaddress [minconf=1] [includeempty=false]\n" + "[minconf] is the minimum number of confirmations before payments are included.\n" + "[includeempty] whether to include addresses that haven't received any payments.\n" + "Returns an array of objects containing:\n" + " \"address\" : receiving address\n" + " \"account\" : the account of the receiving address\n" + " \"amount\" : total amount received by the address\n" + " \"confirmations\" : number of confirmations of the most recent transaction included"); + + return ListReceived(params, false); +} + +Value listreceivedbyaccount(const Array& params, bool fHelp) +{ + if (fHelp || params.size() > 2) + throw runtime_error( + "listreceivedbyaccount [minconf=1] [includeempty=false]\n" + "[minconf] is the minimum number of confirmations before payments are included.\n" + "[includeempty] whether to include accounts that haven't received any payments.\n" + "Returns an array of objects containing:\n" + " \"account\" : the account of the receiving addresses\n" + " \"amount\" : total amount received by addresses with this account\n" + " \"confirmations\" : number of confirmations of the most recent transaction included"); + + accountingDeprecationCheck(); + + return ListReceived(params, true); +} + +static void MaybePushAddress(Object & entry, const CTxDestination &dest) +{ + CBitcoinAddress addr; + if (addr.Set(dest)) + entry.push_back(Pair("address", addr.ToString())); +} + +void ListTransactions(const CWalletTx& wtx, const string& strAccount, int nMinDepth, bool fLong, Array& ret) +{ + int64_t nFee; + string strSentAccount; + list > listReceived; + list > listSent; + + wtx.GetAmounts(listReceived, listSent, nFee, strSentAccount); + + bool fAllAccounts = (strAccount == string("*")); + + // Sent + if ((!wtx.IsCoinStake()) && (!listSent.empty() || nFee != 0) && (fAllAccounts || strAccount == strSentAccount)) + { + BOOST_FOREACH(const PAIRTYPE(CTxDestination, int64_t)& s, listSent) + { + Object entry; + entry.push_back(Pair("account", strSentAccount)); + MaybePushAddress(entry, s.first); + entry.push_back(Pair("category", "send")); + entry.push_back(Pair("amount", ValueFromAmount(-s.second))); + entry.push_back(Pair("fee", ValueFromAmount(-nFee))); + if (fLong) + WalletTxToJSON(wtx, entry); + ret.push_back(entry); + } + } + + // Received + if (listReceived.size() > 0 && wtx.GetDepthInMainChain() >= nMinDepth) + { + bool stop = false; + BOOST_FOREACH(const PAIRTYPE(CTxDestination, int64_t)& r, listReceived) + { + string account; + if (pwalletMain->mapAddressBook.count(r.first)) + account = pwalletMain->mapAddressBook[r.first]; + if (fAllAccounts || (account == strAccount)) + { + Object entry; + entry.push_back(Pair("account", account)); + MaybePushAddress(entry, r.first); + if (wtx.IsCoinBase() || wtx.IsCoinStake()) + { + if (wtx.GetDepthInMainChain() < 1) + entry.push_back(Pair("category", "orphan")); + else if (wtx.GetBlocksToMaturity() > 0) + entry.push_back(Pair("category", "immature")); + else + entry.push_back(Pair("category", "generate")); + } + else + { + entry.push_back(Pair("category", "receive")); + } + if (!wtx.IsCoinStake()) + entry.push_back(Pair("amount", ValueFromAmount(r.second))); + else + { + entry.push_back(Pair("amount", ValueFromAmount(-nFee))); + stop = true; // only one coinstake output + } + if (fLong) + WalletTxToJSON(wtx, entry); + ret.push_back(entry); + } + if (stop) + break; + } + } +} + +void AcentryToJSON(const CAccountingEntry& acentry, const string& strAccount, Array& ret) +{ + bool fAllAccounts = (strAccount == string("*")); + + if (fAllAccounts || acentry.strAccount == strAccount) + { + Object entry; + entry.push_back(Pair("account", acentry.strAccount)); + entry.push_back(Pair("category", "move")); + entry.push_back(Pair("time", (int64_t)acentry.nTime)); + entry.push_back(Pair("amount", ValueFromAmount(acentry.nCreditDebit))); + entry.push_back(Pair("otheraccount", acentry.strOtherAccount)); + entry.push_back(Pair("comment", acentry.strComment)); + ret.push_back(entry); + } +} + +Value listtransactions(const Array& params, bool fHelp) +{ + if (fHelp || params.size() > 3) + throw runtime_error( + "listtransactions [account] [count=10] [from=0]\n" + "Returns up to [count] most recent transactions skipping the first [from] transactions for account [account]."); + + string strAccount = "*"; + if (params.size() > 0) + strAccount = params[0].get_str(); + int nCount = 10; + if (params.size() > 1) + nCount = params[1].get_int(); + int nFrom = 0; + if (params.size() > 2) + nFrom = params[2].get_int(); + + if (nCount < 0) + throw JSONRPCError(RPC_INVALID_PARAMETER, "Negative count"); + if (nFrom < 0) + throw JSONRPCError(RPC_INVALID_PARAMETER, "Negative from"); + + Array ret; + + std::list acentries; + CWallet::TxItems txOrdered = pwalletMain->OrderedTxItems(acentries, strAccount); + + // iterate backwards until we have nCount items to return: + for (CWallet::TxItems::reverse_iterator it = txOrdered.rbegin(); it != txOrdered.rend(); ++it) + { + CWalletTx *const pwtx = (*it).second.first; + if (pwtx != 0) + ListTransactions(*pwtx, strAccount, 0, true, ret); + CAccountingEntry *const pacentry = (*it).second.second; + if (pacentry != 0) + AcentryToJSON(*pacentry, strAccount, ret); + + if ((int)ret.size() >= (nCount+nFrom)) break; + } + // ret is newest to oldest + + if (nFrom > (int)ret.size()) + nFrom = ret.size(); + if ((nFrom + nCount) > (int)ret.size()) + nCount = ret.size() - nFrom; + Array::iterator first = ret.begin(); + std::advance(first, nFrom); + Array::iterator last = ret.begin(); + std::advance(last, nFrom+nCount); + + if (last != ret.end()) ret.erase(last, ret.end()); + if (first != ret.begin()) ret.erase(ret.begin(), first); + + std::reverse(ret.begin(), ret.end()); // Return oldest to newest + + return ret; +} + +Value listaccounts(const Array& params, bool fHelp) +{ + if (fHelp || params.size() > 1) + throw runtime_error( + "listaccounts [minconf=1]\n" + "Returns Object that has account names as keys, account balances as values."); + + accountingDeprecationCheck(); + + int nMinDepth = 1; + if (params.size() > 0) + nMinDepth = params[0].get_int(); + + map mapAccountBalances; + BOOST_FOREACH(const PAIRTYPE(CTxDestination, string)& entry, pwalletMain->mapAddressBook) { + if (IsMine(*pwalletMain, entry.first)) // This address belongs to me + mapAccountBalances[entry.second] = 0; + } + + for (map::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it) + { + const CWalletTx& wtx = (*it).second; + int64_t nFee; + string strSentAccount; + list > listReceived; + list > listSent; + int nDepth = wtx.GetDepthInMainChain(); + if (nDepth < 0) + continue; + wtx.GetAmounts(listReceived, listSent, nFee, strSentAccount); + mapAccountBalances[strSentAccount] -= nFee; + BOOST_FOREACH(const PAIRTYPE(CTxDestination, int64_t)& s, listSent) + mapAccountBalances[strSentAccount] -= s.second; + if (nDepth >= nMinDepth && wtx.GetBlocksToMaturity() == 0) + { + BOOST_FOREACH(const PAIRTYPE(CTxDestination, int64_t)& r, listReceived) + if (pwalletMain->mapAddressBook.count(r.first)) + mapAccountBalances[pwalletMain->mapAddressBook[r.first]] += r.second; + else + mapAccountBalances[""] += r.second; + } + } + + list acentries; + CWalletDB(pwalletMain->strWalletFile).ListAccountCreditDebit("*", acentries); + BOOST_FOREACH(const CAccountingEntry& entry, acentries) + mapAccountBalances[entry.strAccount] += entry.nCreditDebit; + + Object ret; + BOOST_FOREACH(const PAIRTYPE(string, int64_t)& accountBalance, mapAccountBalances) { + ret.push_back(Pair(accountBalance.first, ValueFromAmount(accountBalance.second))); + } + return ret; +} + +Value listsinceblock(const Array& params, bool fHelp) +{ + if (fHelp) + throw runtime_error( + "listsinceblock [blockhash] [target-confirmations]\n" + "Get all transactions in blocks since block [blockhash], or all transactions if omitted"); + + CBlockIndex *pindex = NULL; + int target_confirms = 1; + + if (params.size() > 0) + { + uint256 blockId = 0; + + blockId.SetHex(params[0].get_str()); + pindex = CBlockLocator(blockId).GetBlockIndex(); + } + + if (params.size() > 1) + { + target_confirms = params[1].get_int(); + + if (target_confirms < 1) + throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter"); + } + + int depth = pindex ? (1 + nBestHeight - pindex->nHeight) : -1; + + Array transactions; + + for (map::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); it++) + { + CWalletTx tx = (*it).second; + + if (depth == -1 || tx.GetDepthInMainChain() < depth) + ListTransactions(tx, "*", 0, true, transactions); + } + + uint256 lastblock; + + if (target_confirms == 1) + { + lastblock = hashBestChain; + } + else + { + int target_height = pindexBest->nHeight + 1 - target_confirms; + + CBlockIndex *block; + for (block = pindexBest; + block && block->nHeight > target_height; + block = block->pprev) { } + + lastblock = block ? block->GetBlockHash() : 0; + } + + Object ret; + ret.push_back(Pair("transactions", transactions)); + ret.push_back(Pair("lastblock", lastblock.GetHex())); + + return ret; +} + +Value gettransaction(const Array& params, bool fHelp) +{ + if (fHelp || params.size() != 1) + throw runtime_error( + "gettransaction \n" + "Get detailed information about "); + + uint256 hash; + hash.SetHex(params[0].get_str()); + + Object entry; + + if (pwalletMain->mapWallet.count(hash)) + { + const CWalletTx& wtx = pwalletMain->mapWallet[hash]; + + TxToJSON(wtx, 0, entry); + + int64_t nCredit = wtx.GetCredit(); + int64_t nDebit = wtx.GetDebit(); + int64_t nNet = nCredit - nDebit; + int64_t nFee = (wtx.IsFromMe() ? wtx.GetValueOut() - nDebit : 0); + + entry.push_back(Pair("amount", ValueFromAmount(nNet - nFee))); + if (wtx.IsFromMe()) + entry.push_back(Pair("fee", ValueFromAmount(nFee))); + + WalletTxToJSON(wtx, entry); + + Array details; + ListTransactions(pwalletMain->mapWallet[hash], "*", 0, false, details); + entry.push_back(Pair("details", details)); + } + else + { + CTransaction tx; + uint256 hashBlock = 0; + if (GetTransaction(hash, tx, hashBlock)) + { + TxToJSON(tx, 0, entry); + if (hashBlock == 0) + entry.push_back(Pair("confirmations", 0)); + else + { + entry.push_back(Pair("blockhash", hashBlock.GetHex())); + map::iterator mi = mapBlockIndex.find(hashBlock); + if (mi != mapBlockIndex.end() && (*mi).second) + { + CBlockIndex* pindex = (*mi).second; + if (pindex->IsInMainChain()) + entry.push_back(Pair("confirmations", 1 + nBestHeight - pindex->nHeight)); + else + entry.push_back(Pair("confirmations", 0)); + } + } + } + else + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "No information available about transaction"); + } + + return entry; +} + + +Value backupwallet(const Array& params, bool fHelp) +{ + if (fHelp || params.size() != 1) + throw runtime_error( + "backupwallet \n" + "Safely copies wallet.dat to destination, which can be a directory or a path with filename."); + + string strDest = params[0].get_str(); + if (!BackupWallet(*pwalletMain, strDest)) + throw JSONRPCError(RPC_WALLET_ERROR, "Error: Wallet backup failed!"); + + return Value::null; +} + + +Value keypoolrefill(const Array& params, bool fHelp) +{ + if (fHelp || params.size() > 1) + throw runtime_error( + "keypoolrefill [new-size]\n" + "Fills the keypool." + + HelpRequiringPassphrase()); + + unsigned int nSize = max(GetArg("-keypool", 100), (int64_t)0); + if (params.size() > 0) { + if (params[0].get_int() < 0) + throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, expected valid size"); + nSize = (unsigned int) params[0].get_int(); + } + + EnsureWalletIsUnlocked(); + + pwalletMain->TopUpKeyPool(nSize); + + if (pwalletMain->GetKeyPoolSize() < nSize) + throw JSONRPCError(RPC_WALLET_ERROR, "Error refreshing keypool."); + + return Value::null; +} + + +void ThreadTopUpKeyPool(void* parg) +{ + // Make this thread recognisable as the key-topping-up thread + RenameThread("arepacoin-key-top"); + + pwalletMain->TopUpKeyPool(); +} + +void ThreadCleanWalletPassphrase(void* parg) +{ + // Make this thread recognisable as the wallet relocking thread + RenameThread("arepacoin-lock-wa"); + + int64_t nMyWakeTime = GetTimeMillis() + *((int64_t*)parg) * 1000; + + ENTER_CRITICAL_SECTION(cs_nWalletUnlockTime); + + if (nWalletUnlockTime == 0) + { + nWalletUnlockTime = nMyWakeTime; + + do + { + if (nWalletUnlockTime==0) + break; + int64_t nToSleep = nWalletUnlockTime - GetTimeMillis(); + if (nToSleep <= 0) + break; + + LEAVE_CRITICAL_SECTION(cs_nWalletUnlockTime); + MilliSleep(nToSleep); + ENTER_CRITICAL_SECTION(cs_nWalletUnlockTime); + + } while(1); + + if (nWalletUnlockTime) + { + nWalletUnlockTime = 0; + pwalletMain->Lock(); + } + } + else + { + if (nWalletUnlockTime < nMyWakeTime) + nWalletUnlockTime = nMyWakeTime; + } + + LEAVE_CRITICAL_SECTION(cs_nWalletUnlockTime); + + delete (int64_t*)parg; +} + +Value walletpassphrase(const Array& params, bool fHelp) +{ + if (pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 3)) + throw runtime_error( + "walletpassphrase [stakingonly]\n" + "Stores the wallet decryption key in memory for seconds.\n" + "if [stakingonly] is true sending functions are disabled."); + if (fHelp) + return true; + if (!pwalletMain->IsCrypted()) + throw JSONRPCError(RPC_WALLET_WRONG_ENC_STATE, "Error: running with an unencrypted wallet, but walletpassphrase was called."); + + if (!pwalletMain->IsLocked()) + throw JSONRPCError(RPC_WALLET_ALREADY_UNLOCKED, "Error: Wallet is already unlocked, use walletlock first if need to change unlock settings."); + // Note that the walletpassphrase is stored in params[0] which is not mlock()ed + SecureString strWalletPass; + strWalletPass.reserve(100); + // TODO: get rid of this .c_str() by implementing SecureString::operator=(std::string) + // Alternately, find a way to make params[0] mlock()'d to begin with. + strWalletPass = params[0].get_str().c_str(); + + if (strWalletPass.length() > 0) + { + if (!pwalletMain->Unlock(strWalletPass)) + throw JSONRPCError(RPC_WALLET_PASSPHRASE_INCORRECT, "Error: The wallet passphrase entered was incorrect."); + } + else + throw runtime_error( + "walletpassphrase \n" + "Stores the wallet decryption key in memory for seconds."); + + NewThread(ThreadTopUpKeyPool, NULL); + int64_t* pnSleepTime = new int64_t(params[1].get_int64()); + NewThread(ThreadCleanWalletPassphrase, pnSleepTime); + + // ppcoin: if user OS account compromised prevent trivial sendmoney commands + if (params.size() > 2) + fWalletUnlockStakingOnly = params[2].get_bool(); + else + fWalletUnlockStakingOnly = false; + + return Value::null; +} + + +Value walletpassphrasechange(const Array& params, bool fHelp) +{ + if (pwalletMain->IsCrypted() && (fHelp || params.size() != 2)) + throw runtime_error( + "walletpassphrasechange \n" + "Changes the wallet passphrase from to ."); + if (fHelp) + return true; + if (!pwalletMain->IsCrypted()) + throw JSONRPCError(RPC_WALLET_WRONG_ENC_STATE, "Error: running with an unencrypted wallet, but walletpassphrasechange was called."); + + // TODO: get rid of these .c_str() calls by implementing SecureString::operator=(std::string) + // Alternately, find a way to make params[0] mlock()'d to begin with. + SecureString strOldWalletPass; + strOldWalletPass.reserve(100); + strOldWalletPass = params[0].get_str().c_str(); + + SecureString strNewWalletPass; + strNewWalletPass.reserve(100); + strNewWalletPass = params[1].get_str().c_str(); + + if (strOldWalletPass.length() < 1 || strNewWalletPass.length() < 1) + throw runtime_error( + "walletpassphrasechange \n" + "Changes the wallet passphrase from to ."); + + if (!pwalletMain->ChangeWalletPassphrase(strOldWalletPass, strNewWalletPass)) + throw JSONRPCError(RPC_WALLET_PASSPHRASE_INCORRECT, "Error: The wallet passphrase entered was incorrect."); + + return Value::null; +} + + +Value walletlock(const Array& params, bool fHelp) +{ + if (pwalletMain->IsCrypted() && (fHelp || params.size() != 0)) + throw runtime_error( + "walletlock\n" + "Removes the wallet encryption key from memory, locking the wallet.\n" + "After calling this method, you will need to call walletpassphrase again\n" + "before being able to call any methods which require the wallet to be unlocked."); + if (fHelp) + return true; + if (!pwalletMain->IsCrypted()) + throw JSONRPCError(RPC_WALLET_WRONG_ENC_STATE, "Error: running with an unencrypted wallet, but walletlock was called."); + + { + LOCK(cs_nWalletUnlockTime); + pwalletMain->Lock(); + nWalletUnlockTime = 0; + } + + return Value::null; +} + + +Value encryptwallet(const Array& params, bool fHelp) +{ + if (!pwalletMain->IsCrypted() && (fHelp || params.size() != 1)) + throw runtime_error( + "encryptwallet \n" + "Encrypts the wallet with ."); + if (fHelp) + return true; + if (pwalletMain->IsCrypted()) + throw JSONRPCError(RPC_WALLET_WRONG_ENC_STATE, "Error: running with an encrypted wallet, but encryptwallet was called."); + + // TODO: get rid of this .c_str() by implementing SecureString::operator=(std::string) + // Alternately, find a way to make params[0] mlock()'d to begin with. + SecureString strWalletPass; + strWalletPass.reserve(100); + strWalletPass = params[0].get_str().c_str(); + + if (strWalletPass.length() < 1) + throw runtime_error( + "encryptwallet \n" + "Encrypts the wallet with ."); + + if (!pwalletMain->EncryptWallet(strWalletPass)) + throw JSONRPCError(RPC_WALLET_ENCRYPTION_FAILED, "Error: Failed to encrypt the wallet."); + + // BDB seems to have a bad habit of writing old data into + // slack space in .dat files; that is bad if the old data is + // unencrypted private keys. So: + StartShutdown(); + return "wallet encrypted; arepacoin server stopping, restart to run with encrypted wallet. The keypool has been flushed, you need to make a new backup."; +} + +class DescribeAddressVisitor : public boost::static_visitor +{ +public: + Object operator()(const CNoDestination &dest) const { return Object(); } + + Object operator()(const CKeyID &keyID) const { + Object obj; + CPubKey vchPubKey; + pwalletMain->GetPubKey(keyID, vchPubKey); + obj.push_back(Pair("isscript", false)); + obj.push_back(Pair("pubkey", HexStr(vchPubKey.Raw()))); + obj.push_back(Pair("iscompressed", vchPubKey.IsCompressed())); + return obj; + } + + Object operator()(const CScriptID &scriptID) const { + Object obj; + obj.push_back(Pair("isscript", true)); + CScript subscript; + pwalletMain->GetCScript(scriptID, subscript); + std::vector addresses; + txnouttype whichType; + int nRequired; + ExtractDestinations(subscript, whichType, addresses, nRequired); + obj.push_back(Pair("script", GetTxnOutputType(whichType))); + obj.push_back(Pair("hex", HexStr(subscript.begin(), subscript.end()))); + Array a; + BOOST_FOREACH(const CTxDestination& addr, addresses) + a.push_back(CBitcoinAddress(addr).ToString()); + obj.push_back(Pair("addresses", a)); + if (whichType == TX_MULTISIG) + obj.push_back(Pair("sigsrequired", nRequired)); + return obj; + } +}; + +Value validateaddress(const Array& params, bool fHelp) +{ + if (fHelp || params.size() != 1) + throw runtime_error( + "validateaddress \n" + "Return information about ."); + + CBitcoinAddress address(params[0].get_str()); + bool isValid = address.IsValid(); + + Object ret; + ret.push_back(Pair("isvalid", isValid)); + if (isValid) + { + CTxDestination dest = address.Get(); + string currentAddress = address.ToString(); + ret.push_back(Pair("address", currentAddress)); + bool fMine = IsMine(*pwalletMain, dest); + ret.push_back(Pair("ismine", fMine)); + if (fMine) { + Object detail = boost::apply_visitor(DescribeAddressVisitor(), dest); + ret.insert(ret.end(), detail.begin(), detail.end()); + } + if (pwalletMain->mapAddressBook.count(dest)) + ret.push_back(Pair("account", pwalletMain->mapAddressBook[dest])); + } + return ret; +} + +Value validatepubkey(const Array& params, bool fHelp) +{ + if (fHelp || !params.size() || params.size() > 2) + throw runtime_error( + "validatepubkey \n" + "Return information about ."); + + std::vector vchPubKey = ParseHex(params[0].get_str()); + CPubKey pubKey(vchPubKey); + + bool isValid = pubKey.IsValid(); + bool isCompressed = pubKey.IsCompressed(); + CKeyID keyID = pubKey.GetID(); + + CBitcoinAddress address; + address.Set(keyID); + + Object ret; + ret.push_back(Pair("isvalid", isValid)); + if (isValid) + { + CTxDestination dest = address.Get(); + string currentAddress = address.ToString(); + ret.push_back(Pair("address", currentAddress)); + bool fMine = IsMine(*pwalletMain, dest); + ret.push_back(Pair("ismine", fMine)); + ret.push_back(Pair("iscompressed", isCompressed)); + if (fMine) { + Object detail = boost::apply_visitor(DescribeAddressVisitor(), dest); + ret.insert(ret.end(), detail.begin(), detail.end()); + } + if (pwalletMain->mapAddressBook.count(dest)) + ret.push_back(Pair("account", pwalletMain->mapAddressBook[dest])); + } + return ret; +} + +// ppcoin: reserve balance from being staked for network protection +Value reservebalance(const Array& params, bool fHelp) +{ + if (fHelp || params.size() > 2) + throw runtime_error( + "reservebalance [ [amount]]\n" + " is true or false to turn balance reserve on or off.\n" + " is a real and rounded to cent.\n" + "Set reserve amount not participating in network protection.\n" + "If no parameters provided current setting is printed.\n"); + + if (params.size() > 0) + { + bool fReserve = params[0].get_bool(); + if (fReserve) + { + if (params.size() == 1) + throw runtime_error("must provide amount to reserve balance.\n"); + int64_t nAmount = AmountFromValue(params[1]); + nAmount = (nAmount / CENT) * CENT; // round to cent + if (nAmount < 0) + throw runtime_error("amount cannot be negative.\n"); + nReserveBalance = nAmount; + } + else + { + if (params.size() > 1) + throw runtime_error("cannot specify amount to turn off reserve.\n"); + nReserveBalance = 0; + } + } + + Object result; + result.push_back(Pair("reserve", (nReserveBalance > 0))); + result.push_back(Pair("amount", ValueFromAmount(nReserveBalance))); + return result; +} + + +// ppcoin: check wallet integrity +Value checkwallet(const Array& params, bool fHelp) +{ + if (fHelp || params.size() > 0) + throw runtime_error( + "checkwallet\n" + "Check wallet for integrity.\n"); + + int nMismatchSpent; + int64_t nBalanceInQuestion; + pwalletMain->FixSpentCoins(nMismatchSpent, nBalanceInQuestion, true); + Object result; + if (nMismatchSpent == 0) + result.push_back(Pair("wallet check passed", true)); + else + { + result.push_back(Pair("mismatched spent coins", nMismatchSpent)); + result.push_back(Pair("amount in question", ValueFromAmount(nBalanceInQuestion))); + } + return result; +} + + +// ppcoin: repair wallet +Value repairwallet(const Array& params, bool fHelp) +{ + if (fHelp || params.size() > 0) + throw runtime_error( + "repairwallet\n" + "Repair wallet if checkwallet reports any problem.\n"); + + int nMismatchSpent; + int64_t nBalanceInQuestion; + pwalletMain->FixSpentCoins(nMismatchSpent, nBalanceInQuestion); + Object result; + if (nMismatchSpent == 0) + result.push_back(Pair("wallet check passed", true)); + else + { + result.push_back(Pair("mismatched spent coins", nMismatchSpent)); + result.push_back(Pair("amount affected by repair", ValueFromAmount(nBalanceInQuestion))); + } + return result; +} + +// NovaCoin: resend unconfirmed wallet transactions +Value resendtx(const Array& params, bool fHelp) +{ + if (fHelp || params.size() > 1) + throw runtime_error( + "resendtx\n" + "Re-send unconfirmed transactions.\n" + ); + + ResendWalletTransactions(true); + + return Value::null; +} + +// ppcoin: make a public-private key pair +Value makekeypair(const Array& params, bool fHelp) +{ + if (fHelp || params.size() > 1) + throw runtime_error( + "makekeypair [prefix]\n" + "Make a public/private key pair.\n" + "[prefix] is optional preferred prefix for the public key.\n"); + + string strPrefix = ""; + if (params.size() > 0) + strPrefix = params[0].get_str(); + + CKey key; + key.MakeNewKey(false); + + CPrivKey vchPrivKey = key.GetPrivKey(); + Object result; + result.push_back(Pair("PrivateKey", HexStr(vchPrivKey.begin(), vchPrivKey.end()))); + result.push_back(Pair("PublicKey", HexStr(key.GetPubKey().Raw()))); + return result; +} diff --git a/src/script.cpp b/src/script.cpp new file mode 100644 index 0000000..a8cb65d --- /dev/null +++ b/src/script.cpp @@ -0,0 +1,2031 @@ +// Copyright (c) 2009-2010 Satoshi Nakamoto +// Copyright (c) 2009-2012 The Bitcoin developers +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include +#include +#include + +using namespace std; +using namespace boost; + +#include "script.h" +#include "keystore.h" +#include "bignum.h" +#include "key.h" +#include "main.h" +#include "sync.h" +#include "util.h" + +bool CheckSig(vector vchSig, vector vchPubKey, CScript scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType); + +static const valtype vchFalse(0); +static const valtype vchZero(0); +static const valtype vchTrue(1, 1); +static const CBigNum bnZero(0); +static const CBigNum bnOne(1); +static const CBigNum bnFalse(0); +static const CBigNum bnTrue(1); +static const size_t nMaxNumSize = 4; + + +CBigNum CastToBigNum(const valtype& vch) +{ + if (vch.size() > nMaxNumSize) + throw runtime_error("CastToBigNum() : overflow"); + // Get rid of extra leading zeros + return CBigNum(CBigNum(vch).getvch()); +} + +bool CastToBool(const valtype& vch) +{ + for (unsigned int i = 0; i < vch.size(); i++) + { + if (vch[i] != 0) + { + // Can be negative zero + if (i == vch.size()-1 && vch[i] == 0x80) + return false; + return true; + } + } + return false; +} + +// +// WARNING: This does not work as expected for signed integers; the sign-bit +// is left in place as the integer is zero-extended. The correct behavior +// would be to move the most significant bit of the last byte during the +// resize process. MakeSameSize() is currently only used by the disabled +// opcodes OP_AND, OP_OR, and OP_XOR. +// +void MakeSameSize(valtype& vch1, valtype& vch2) +{ + // Lengthen the shorter one + if (vch1.size() < vch2.size()) + // PATCH: + // +unsigned char msb = vch1[vch1.size()-1]; + // +vch1[vch1.size()-1] &= 0x7f; + // vch1.resize(vch2.size(), 0); + // +vch1[vch1.size()-1] = msb; + vch1.resize(vch2.size(), 0); + if (vch2.size() < vch1.size()) + // PATCH: + // +unsigned char msb = vch2[vch2.size()-1]; + // +vch2[vch2.size()-1] &= 0x7f; + // vch2.resize(vch1.size(), 0); + // +vch2[vch2.size()-1] = msb; + vch2.resize(vch1.size(), 0); +} + + + +// +// Script is a stack machine (like Forth) that evaluates a predicate +// returning a bool indicating valid or not. There are no loops. +// +#define stacktop(i) (stack.at(stack.size()+(i))) +#define altstacktop(i) (altstack.at(altstack.size()+(i))) +static inline void popstack(vector& stack) +{ + if (stack.empty()) + throw runtime_error("popstack() : stack empty"); + stack.pop_back(); +} + + +const char* GetTxnOutputType(txnouttype t) +{ + switch (t) + { + case TX_NONSTANDARD: return "nonstandard"; + case TX_PUBKEY: return "pubkey"; + case TX_PUBKEYHASH: return "pubkeyhash"; + case TX_SCRIPTHASH: return "scripthash"; + case TX_MULTISIG: return "multisig"; + case TX_NULL_DATA: return "nulldata"; + } + return NULL; +} + + +const char* GetOpName(opcodetype opcode) +{ + switch (opcode) + { + // push value + case OP_0 : return "0"; + case OP_PUSHDATA1 : return "OP_PUSHDATA1"; + case OP_PUSHDATA2 : return "OP_PUSHDATA2"; + case OP_PUSHDATA4 : return "OP_PUSHDATA4"; + case OP_1NEGATE : return "-1"; + case OP_RESERVED : return "OP_RESERVED"; + case OP_1 : return "1"; + case OP_2 : return "2"; + case OP_3 : return "3"; + case OP_4 : return "4"; + case OP_5 : return "5"; + case OP_6 : return "6"; + case OP_7 : return "7"; + case OP_8 : return "8"; + case OP_9 : return "9"; + case OP_10 : return "10"; + case OP_11 : return "11"; + case OP_12 : return "12"; + case OP_13 : return "13"; + case OP_14 : return "14"; + case OP_15 : return "15"; + case OP_16 : return "16"; + + // control + case OP_NOP : return "OP_NOP"; + case OP_VER : return "OP_VER"; + case OP_IF : return "OP_IF"; + case OP_NOTIF : return "OP_NOTIF"; + case OP_VERIF : return "OP_VERIF"; + case OP_VERNOTIF : return "OP_VERNOTIF"; + case OP_ELSE : return "OP_ELSE"; + case OP_ENDIF : return "OP_ENDIF"; + case OP_VERIFY : return "OP_VERIFY"; + case OP_RETURN : return "OP_RETURN"; + + // stack ops + case OP_TOALTSTACK : return "OP_TOALTSTACK"; + case OP_FROMALTSTACK : return "OP_FROMALTSTACK"; + case OP_2DROP : return "OP_2DROP"; + case OP_2DUP : return "OP_2DUP"; + case OP_3DUP : return "OP_3DUP"; + case OP_2OVER : return "OP_2OVER"; + case OP_2ROT : return "OP_2ROT"; + case OP_2SWAP : return "OP_2SWAP"; + case OP_IFDUP : return "OP_IFDUP"; + case OP_DEPTH : return "OP_DEPTH"; + case OP_DROP : return "OP_DROP"; + case OP_DUP : return "OP_DUP"; + case OP_NIP : return "OP_NIP"; + case OP_OVER : return "OP_OVER"; + case OP_PICK : return "OP_PICK"; + case OP_ROLL : return "OP_ROLL"; + case OP_ROT : return "OP_ROT"; + case OP_SWAP : return "OP_SWAP"; + case OP_TUCK : return "OP_TUCK"; + + // splice ops + case OP_CAT : return "OP_CAT"; + case OP_SUBSTR : return "OP_SUBSTR"; + case OP_LEFT : return "OP_LEFT"; + case OP_RIGHT : return "OP_RIGHT"; + case OP_SIZE : return "OP_SIZE"; + + // bit logic + case OP_INVERT : return "OP_INVERT"; + case OP_AND : return "OP_AND"; + case OP_OR : return "OP_OR"; + case OP_XOR : return "OP_XOR"; + case OP_EQUAL : return "OP_EQUAL"; + case OP_EQUALVERIFY : return "OP_EQUALVERIFY"; + case OP_RESERVED1 : return "OP_RESERVED1"; + case OP_RESERVED2 : return "OP_RESERVED2"; + + // numeric + case OP_1ADD : return "OP_1ADD"; + case OP_1SUB : return "OP_1SUB"; + case OP_2MUL : return "OP_2MUL"; + case OP_2DIV : return "OP_2DIV"; + case OP_NEGATE : return "OP_NEGATE"; + case OP_ABS : return "OP_ABS"; + case OP_NOT : return "OP_NOT"; + case OP_0NOTEQUAL : return "OP_0NOTEQUAL"; + case OP_ADD : return "OP_ADD"; + case OP_SUB : return "OP_SUB"; + case OP_MUL : return "OP_MUL"; + case OP_DIV : return "OP_DIV"; + case OP_MOD : return "OP_MOD"; + case OP_LSHIFT : return "OP_LSHIFT"; + case OP_RSHIFT : return "OP_RSHIFT"; + case OP_BOOLAND : return "OP_BOOLAND"; + case OP_BOOLOR : return "OP_BOOLOR"; + case OP_NUMEQUAL : return "OP_NUMEQUAL"; + case OP_NUMEQUALVERIFY : return "OP_NUMEQUALVERIFY"; + case OP_NUMNOTEQUAL : return "OP_NUMNOTEQUAL"; + case OP_LESSTHAN : return "OP_LESSTHAN"; + case OP_GREATERTHAN : return "OP_GREATERTHAN"; + case OP_LESSTHANOREQUAL : return "OP_LESSTHANOREQUAL"; + case OP_GREATERTHANOREQUAL : return "OP_GREATERTHANOREQUAL"; + case OP_MIN : return "OP_MIN"; + case OP_MAX : return "OP_MAX"; + case OP_WITHIN : return "OP_WITHIN"; + + // crypto + case OP_RIPEMD160 : return "OP_RIPEMD160"; + case OP_SHA1 : return "OP_SHA1"; + case OP_SHA256 : return "OP_SHA256"; + case OP_HASH160 : return "OP_HASH160"; + case OP_HASH256 : return "OP_HASH256"; + case OP_CODESEPARATOR : return "OP_CODESEPARATOR"; + case OP_CHECKSIG : return "OP_CHECKSIG"; + case OP_CHECKSIGVERIFY : return "OP_CHECKSIGVERIFY"; + case OP_CHECKMULTISIG : return "OP_CHECKMULTISIG"; + case OP_CHECKMULTISIGVERIFY : return "OP_CHECKMULTISIGVERIFY"; + + // expanson + case OP_NOP1 : return "OP_NOP1"; + case OP_NOP2 : return "OP_NOP2"; + case OP_NOP3 : return "OP_NOP3"; + case OP_NOP4 : return "OP_NOP4"; + case OP_NOP5 : return "OP_NOP5"; + case OP_NOP6 : return "OP_NOP6"; + case OP_NOP7 : return "OP_NOP7"; + case OP_NOP8 : return "OP_NOP8"; + case OP_NOP9 : return "OP_NOP9"; + case OP_NOP10 : return "OP_NOP10"; + + case OP_INVALIDOPCODE : return "OP_INVALIDOPCODE"; + + // Note: + // The template matching params OP_SMALLDATA/etc are defined in opcodetype enum + // as kind of implementation hack, they are *NOT* real opcodes. If found in real + // Script, just let the default: case deal with them. + + default: + return "OP_UNKNOWN"; + } +} + +static bool IsCanonicalPubKey(const valtype &vchPubKey) { + if (vchPubKey.size() < 33) + return error("Non-canonical public key: too short"); + if (vchPubKey[0] == 0x04) { + if (vchPubKey.size() != 65) + return error("Non-canonical public key: invalid length for uncompressed key"); + } else if (vchPubKey[0] == 0x02 || vchPubKey[0] == 0x03) { + if (vchPubKey.size() != 33) + return error("Non-canonical public key: invalid length for compressed key"); + } else { + return error("Non-canonical public key: compressed nor uncompressed"); + } + return true; +} + +static bool IsCanonicalSignature(const valtype &vchSig) { + // See https://bitcointalk.org/index.php?topic=8392.msg127623#msg127623 + // A canonical signature exists of: <30> <02> <02> + // Where R and S are not negative (their first byte has its highest bit not set), and not + // excessively padded (do not start with a 0 byte, unless an otherwise negative number follows, + // in which case a single 0 byte is necessary and even required). + if (vchSig.size() < 9) + return error("Non-canonical signature: too short"); + if (vchSig.size() > 73) + return error("Non-canonical signature: too long"); + unsigned char nHashType = vchSig[vchSig.size() - 1] & (~(SIGHASH_ANYONECANPAY)); + if (nHashType < SIGHASH_ALL || nHashType > SIGHASH_SINGLE) + return error("Non-canonical signature: unknown hashtype byte"); + if (vchSig[0] != 0x30) + return error("Non-canonical signature: wrong type"); + if (vchSig[1] != vchSig.size()-3) + return error("Non-canonical signature: wrong length marker"); + unsigned int nLenR = vchSig[3]; + if (5 + nLenR >= vchSig.size()) + return error("Non-canonical signature: S length misplaced"); + unsigned int nLenS = vchSig[5+nLenR]; + if ((unsigned long)(nLenR+nLenS+7) != vchSig.size()) + return error("Non-canonical signature: R+S length mismatch"); + + const unsigned char *R = &vchSig[4]; + if (R[-2] != 0x02) + return error("Non-canonical signature: R value type mismatch"); + if (nLenR == 0) + return error("Non-canonical signature: R length is zero"); + if (R[0] & 0x80) + return error("Non-canonical signature: R value negative"); + if (nLenR > 1 && (R[0] == 0x00) && !(R[1] & 0x80)) + return error("Non-canonical signature: R value excessively padded"); + + const unsigned char *S = &vchSig[6+nLenR]; + if (S[-2] != 0x02) + return error("Non-canonical signature: S value type mismatch"); + if (nLenS == 0) + return error("Non-canonical signature: S length is zero"); + if (S[0] & 0x80) + return error("Non-canonical signature: S value negative"); + if (nLenS > 1 && (S[0] == 0x00) && !(S[1] & 0x80)) + return error("Non-canonical signature: S value excessively padded"); + + // If the S value is above the order of the curve divided by two, its + // complement modulo the order could have been used instead, which is + // one byte shorter when encoded correctly. + if (!CKey::CheckSignatureElement(S, nLenS, true)) + return error("Non-canonical signature: S value is unnecessarily high"); + + return true; +} + +bool EvalScript(vector >& stack, const CScript& script, const CTransaction& txTo, unsigned int nIn, int nHashType) +{ + CAutoBN_CTX pctx; + CScript::const_iterator pc = script.begin(); + CScript::const_iterator pend = script.end(); + CScript::const_iterator pbegincodehash = script.begin(); + opcodetype opcode; + valtype vchPushValue; + vector vfExec; + vector altstack; + if (script.size() > 10000) + return false; + int nOpCount = 0; + + + try + { + while (pc < pend) + { + bool fExec = !count(vfExec.begin(), vfExec.end(), false); + + // + // Read instruction + // + if (!script.GetOp(pc, opcode, vchPushValue)) + return false; + if (vchPushValue.size() > MAX_SCRIPT_ELEMENT_SIZE) + return false; + if (opcode > OP_16 && ++nOpCount > 201) + return false; + + if (opcode == OP_CAT || + opcode == OP_SUBSTR || + opcode == OP_LEFT || + opcode == OP_RIGHT || + opcode == OP_INVERT || + opcode == OP_AND || + opcode == OP_OR || + opcode == OP_XOR || + opcode == OP_2MUL || + opcode == OP_2DIV || + opcode == OP_MUL || + opcode == OP_DIV || + opcode == OP_MOD || + opcode == OP_LSHIFT || + opcode == OP_RSHIFT) + return false; + + if (fExec && 0 <= opcode && opcode <= OP_PUSHDATA4) + stack.push_back(vchPushValue); + else if (fExec || (OP_IF <= opcode && opcode <= OP_ENDIF)) + switch (opcode) + { + // + // Push value + // + case OP_1NEGATE: + case OP_1: + case OP_2: + case OP_3: + case OP_4: + case OP_5: + case OP_6: + case OP_7: + case OP_8: + case OP_9: + case OP_10: + case OP_11: + case OP_12: + case OP_13: + case OP_14: + case OP_15: + case OP_16: + { + // ( -- value) + CBigNum bn((int)opcode - (int)(OP_1 - 1)); + stack.push_back(bn.getvch()); + } + break; + + + // + // Control + // + case OP_NOP: + case OP_NOP1: case OP_NOP2: case OP_NOP3: case OP_NOP4: case OP_NOP5: + case OP_NOP6: case OP_NOP7: case OP_NOP8: case OP_NOP9: case OP_NOP10: + break; + + case OP_IF: + case OP_NOTIF: + { + // if [statements] [else [statements]] endif + bool fValue = false; + if (fExec) + { + if (stack.size() < 1) + return false; + valtype& vch = stacktop(-1); + fValue = CastToBool(vch); + if (opcode == OP_NOTIF) + fValue = !fValue; + popstack(stack); + } + vfExec.push_back(fValue); + } + break; + + case OP_ELSE: + { + if (vfExec.empty()) + return false; + vfExec.back() = !vfExec.back(); + } + break; + + case OP_ENDIF: + { + if (vfExec.empty()) + return false; + vfExec.pop_back(); + } + break; + + case OP_VERIFY: + { + // (true -- ) or + // (false -- false) and return + if (stack.size() < 1) + return false; + bool fValue = CastToBool(stacktop(-1)); + if (fValue) + popstack(stack); + else + return false; + } + break; + + case OP_RETURN: + { + return false; + } + break; + + + // + // Stack ops + // + case OP_TOALTSTACK: + { + if (stack.size() < 1) + return false; + altstack.push_back(stacktop(-1)); + popstack(stack); + } + break; + + case OP_FROMALTSTACK: + { + if (altstack.size() < 1) + return false; + stack.push_back(altstacktop(-1)); + popstack(altstack); + } + break; + + case OP_2DROP: + { + // (x1 x2 -- ) + if (stack.size() < 2) + return false; + popstack(stack); + popstack(stack); + } + break; + + case OP_2DUP: + { + // (x1 x2 -- x1 x2 x1 x2) + if (stack.size() < 2) + return false; + valtype vch1 = stacktop(-2); + valtype vch2 = stacktop(-1); + stack.push_back(vch1); + stack.push_back(vch2); + } + break; + + case OP_3DUP: + { + // (x1 x2 x3 -- x1 x2 x3 x1 x2 x3) + if (stack.size() < 3) + return false; + valtype vch1 = stacktop(-3); + valtype vch2 = stacktop(-2); + valtype vch3 = stacktop(-1); + stack.push_back(vch1); + stack.push_back(vch2); + stack.push_back(vch3); + } + break; + + case OP_2OVER: + { + // (x1 x2 x3 x4 -- x1 x2 x3 x4 x1 x2) + if (stack.size() < 4) + return false; + valtype vch1 = stacktop(-4); + valtype vch2 = stacktop(-3); + stack.push_back(vch1); + stack.push_back(vch2); + } + break; + + case OP_2ROT: + { + // (x1 x2 x3 x4 x5 x6 -- x3 x4 x5 x6 x1 x2) + if (stack.size() < 6) + return false; + valtype vch1 = stacktop(-6); + valtype vch2 = stacktop(-5); + stack.erase(stack.end()-6, stack.end()-4); + stack.push_back(vch1); + stack.push_back(vch2); + } + break; + + case OP_2SWAP: + { + // (x1 x2 x3 x4 -- x3 x4 x1 x2) + if (stack.size() < 4) + return false; + swap(stacktop(-4), stacktop(-2)); + swap(stacktop(-3), stacktop(-1)); + } + break; + + case OP_IFDUP: + { + // (x - 0 | x x) + if (stack.size() < 1) + return false; + valtype vch = stacktop(-1); + if (CastToBool(vch)) + stack.push_back(vch); + } + break; + + case OP_DEPTH: + { + // -- stacksize + CBigNum bn(stack.size()); + stack.push_back(bn.getvch()); + } + break; + + case OP_DROP: + { + // (x -- ) + if (stack.size() < 1) + return false; + popstack(stack); + } + break; + + case OP_DUP: + { + // (x -- x x) + if (stack.size() < 1) + return false; + valtype vch = stacktop(-1); + stack.push_back(vch); + } + break; + + case OP_NIP: + { + // (x1 x2 -- x2) + if (stack.size() < 2) + return false; + stack.erase(stack.end() - 2); + } + break; + + case OP_OVER: + { + // (x1 x2 -- x1 x2 x1) + if (stack.size() < 2) + return false; + valtype vch = stacktop(-2); + stack.push_back(vch); + } + break; + + case OP_PICK: + case OP_ROLL: + { + // (xn ... x2 x1 x0 n - xn ... x2 x1 x0 xn) + // (xn ... x2 x1 x0 n - ... x2 x1 x0 xn) + if (stack.size() < 2) + return false; + int n = CastToBigNum(stacktop(-1)).getint(); + popstack(stack); + if (n < 0 || n >= (int)stack.size()) + return false; + valtype vch = stacktop(-n-1); + if (opcode == OP_ROLL) + stack.erase(stack.end()-n-1); + stack.push_back(vch); + } + break; + + case OP_ROT: + { + // (x1 x2 x3 -- x2 x3 x1) + // x2 x1 x3 after first swap + // x2 x3 x1 after second swap + if (stack.size() < 3) + return false; + swap(stacktop(-3), stacktop(-2)); + swap(stacktop(-2), stacktop(-1)); + } + break; + + case OP_SWAP: + { + // (x1 x2 -- x2 x1) + if (stack.size() < 2) + return false; + swap(stacktop(-2), stacktop(-1)); + } + break; + + case OP_TUCK: + { + // (x1 x2 -- x2 x1 x2) + if (stack.size() < 2) + return false; + valtype vch = stacktop(-1); + stack.insert(stack.end()-2, vch); + } + break; + + + // + // Splice ops + // + case OP_CAT: + { + // (x1 x2 -- out) + if (stack.size() < 2) + return false; + valtype& vch1 = stacktop(-2); + valtype& vch2 = stacktop(-1); + vch1.insert(vch1.end(), vch2.begin(), vch2.end()); + popstack(stack); + if (stacktop(-1).size() > MAX_SCRIPT_ELEMENT_SIZE) + return false; + } + break; + + case OP_SUBSTR: + { + // (in begin size -- out) + if (stack.size() < 3) + return false; + valtype& vch = stacktop(-3); + int nBegin = CastToBigNum(stacktop(-2)).getint(); + int nEnd = nBegin + CastToBigNum(stacktop(-1)).getint(); + if (nBegin < 0 || nEnd < nBegin) + return false; + if (nBegin > (int)vch.size()) + nBegin = vch.size(); + if (nEnd > (int)vch.size()) + nEnd = vch.size(); + vch.erase(vch.begin() + nEnd, vch.end()); + vch.erase(vch.begin(), vch.begin() + nBegin); + popstack(stack); + popstack(stack); + } + break; + + case OP_LEFT: + case OP_RIGHT: + { + // (in size -- out) + if (stack.size() < 2) + return false; + valtype& vch = stacktop(-2); + int nSize = CastToBigNum(stacktop(-1)).getint(); + if (nSize < 0) + return false; + if (nSize > (int)vch.size()) + nSize = vch.size(); + if (opcode == OP_LEFT) + vch.erase(vch.begin() + nSize, vch.end()); + else + vch.erase(vch.begin(), vch.end() - nSize); + popstack(stack); + } + break; + + case OP_SIZE: + { + // (in -- in size) + if (stack.size() < 1) + return false; + CBigNum bn(stacktop(-1).size()); + stack.push_back(bn.getvch()); + } + break; + + + // + // Bitwise logic + // + case OP_INVERT: + { + // (in - out) + if (stack.size() < 1) + return false; + valtype& vch = stacktop(-1); + for (unsigned int i = 0; i < vch.size(); i++) + vch[i] = ~vch[i]; + } + break; + + // + // WARNING: These disabled opcodes exhibit unexpected behavior + // when used on signed integers due to a bug in MakeSameSize() + // [see definition of MakeSameSize() above]. + // + case OP_AND: + case OP_OR: + case OP_XOR: + { + // (x1 x2 - out) + if (stack.size() < 2) + return false; + valtype& vch1 = stacktop(-2); + valtype& vch2 = stacktop(-1); + MakeSameSize(vch1, vch2); // <-- NOT SAFE FOR SIGNED VALUES + if (opcode == OP_AND) + { + for (unsigned int i = 0; i < vch1.size(); i++) + vch1[i] &= vch2[i]; + } + else if (opcode == OP_OR) + { + for (unsigned int i = 0; i < vch1.size(); i++) + vch1[i] |= vch2[i]; + } + else if (opcode == OP_XOR) + { + for (unsigned int i = 0; i < vch1.size(); i++) + vch1[i] ^= vch2[i]; + } + popstack(stack); + } + break; + + case OP_EQUAL: + case OP_EQUALVERIFY: + //case OP_NOTEQUAL: // use OP_NUMNOTEQUAL + { + // (x1 x2 - bool) + if (stack.size() < 2) + return false; + valtype& vch1 = stacktop(-2); + valtype& vch2 = stacktop(-1); + bool fEqual = (vch1 == vch2); + // OP_NOTEQUAL is disabled because it would be too easy to say + // something like n != 1 and have some wiseguy pass in 1 with extra + // zero bytes after it (numerically, 0x01 == 0x0001 == 0x000001) + //if (opcode == OP_NOTEQUAL) + // fEqual = !fEqual; + popstack(stack); + popstack(stack); + stack.push_back(fEqual ? vchTrue : vchFalse); + if (opcode == OP_EQUALVERIFY) + { + if (fEqual) + popstack(stack); + else + return false; + } + } + break; + + + // + // Numeric + // + case OP_1ADD: + case OP_1SUB: + case OP_2MUL: + case OP_2DIV: + case OP_NEGATE: + case OP_ABS: + case OP_NOT: + case OP_0NOTEQUAL: + { + // (in -- out) + if (stack.size() < 1) + return false; + CBigNum bn = CastToBigNum(stacktop(-1)); + switch (opcode) + { + case OP_1ADD: bn += bnOne; break; + case OP_1SUB: bn -= bnOne; break; + case OP_2MUL: bn <<= 1; break; + case OP_2DIV: bn >>= 1; break; + case OP_NEGATE: bn = -bn; break; + case OP_ABS: if (bn < bnZero) bn = -bn; break; + case OP_NOT: bn = (bn == bnZero); break; + case OP_0NOTEQUAL: bn = (bn != bnZero); break; + default: assert(!"invalid opcode"); break; + } + popstack(stack); + stack.push_back(bn.getvch()); + } + break; + + case OP_ADD: + case OP_SUB: + case OP_MUL: + case OP_DIV: + case OP_MOD: + case OP_LSHIFT: + case OP_RSHIFT: + case OP_BOOLAND: + case OP_BOOLOR: + case OP_NUMEQUAL: + case OP_NUMEQUALVERIFY: + case OP_NUMNOTEQUAL: + case OP_LESSTHAN: + case OP_GREATERTHAN: + case OP_LESSTHANOREQUAL: + case OP_GREATERTHANOREQUAL: + case OP_MIN: + case OP_MAX: + { + // (x1 x2 -- out) + if (stack.size() < 2) + return false; + CBigNum bn1 = CastToBigNum(stacktop(-2)); + CBigNum bn2 = CastToBigNum(stacktop(-1)); + CBigNum bn; + switch (opcode) + { + case OP_ADD: + bn = bn1 + bn2; + break; + + case OP_SUB: + bn = bn1 - bn2; + break; + + case OP_MUL: + if (!BN_mul(&bn, &bn1, &bn2, pctx)) + return false; + break; + + case OP_DIV: + if (!BN_div(&bn, NULL, &bn1, &bn2, pctx)) + return false; + break; + + case OP_MOD: + if (!BN_mod(&bn, &bn1, &bn2, pctx)) + return false; + break; + + case OP_LSHIFT: + if (bn2 < bnZero || bn2 > CBigNum(2048)) + return false; + bn = bn1 << bn2.getulong(); + break; + + case OP_RSHIFT: + if (bn2 < bnZero || bn2 > CBigNum(2048)) + return false; + bn = bn1 >> bn2.getulong(); + break; + + case OP_BOOLAND: bn = (bn1 != bnZero && bn2 != bnZero); break; + case OP_BOOLOR: bn = (bn1 != bnZero || bn2 != bnZero); break; + case OP_NUMEQUAL: bn = (bn1 == bn2); break; + case OP_NUMEQUALVERIFY: bn = (bn1 == bn2); break; + case OP_NUMNOTEQUAL: bn = (bn1 != bn2); break; + case OP_LESSTHAN: bn = (bn1 < bn2); break; + case OP_GREATERTHAN: bn = (bn1 > bn2); break; + case OP_LESSTHANOREQUAL: bn = (bn1 <= bn2); break; + case OP_GREATERTHANOREQUAL: bn = (bn1 >= bn2); break; + case OP_MIN: bn = (bn1 < bn2 ? bn1 : bn2); break; + case OP_MAX: bn = (bn1 > bn2 ? bn1 : bn2); break; + default: assert(!"invalid opcode"); break; + } + popstack(stack); + popstack(stack); + stack.push_back(bn.getvch()); + + if (opcode == OP_NUMEQUALVERIFY) + { + if (CastToBool(stacktop(-1))) + popstack(stack); + else + return false; + } + } + break; + + case OP_WITHIN: + { + // (x min max -- out) + if (stack.size() < 3) + return false; + CBigNum bn1 = CastToBigNum(stacktop(-3)); + CBigNum bn2 = CastToBigNum(stacktop(-2)); + CBigNum bn3 = CastToBigNum(stacktop(-1)); + bool fValue = (bn2 <= bn1 && bn1 < bn3); + popstack(stack); + popstack(stack); + popstack(stack); + stack.push_back(fValue ? vchTrue : vchFalse); + } + break; + + + // + // Crypto + // + case OP_RIPEMD160: + case OP_SHA1: + case OP_SHA256: + case OP_HASH160: + case OP_HASH256: + { + // (in -- hash) + if (stack.size() < 1) + return false; + valtype& vch = stacktop(-1); + 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) + SHA1(&vch[0], vch.size(), &vchHash[0]); + else if (opcode == OP_SHA256) + SHA256(&vch[0], vch.size(), &vchHash[0]); + else if (opcode == OP_HASH160) + { + uint160 hash160 = Hash160(vch); + memcpy(&vchHash[0], &hash160, sizeof(hash160)); + } + else if (opcode == OP_HASH256) + { + uint256 hash = Hash(vch.begin(), vch.end()); + memcpy(&vchHash[0], &hash, sizeof(hash)); + } + popstack(stack); + stack.push_back(vchHash); + } + break; + + case OP_CODESEPARATOR: + { + // Hash starts after the code separator + pbegincodehash = pc; + } + break; + + case OP_CHECKSIG: + case OP_CHECKSIGVERIFY: + { + // (sig pubkey -- bool) + if (stack.size() < 2) + return false; + + valtype& vchSig = stacktop(-2); + valtype& vchPubKey = stacktop(-1); + + // Subset of script starting at the most recent codeseparator + CScript scriptCode(pbegincodehash, pend); + + // Drop the signature, since there's no way for a signature to sign itself + scriptCode.FindAndDelete(CScript(vchSig)); + + bool fSuccess = IsCanonicalSignature(vchSig) && IsCanonicalPubKey(vchPubKey) && + CheckSig(vchSig, vchPubKey, scriptCode, txTo, nIn, nHashType); + + popstack(stack); + popstack(stack); + stack.push_back(fSuccess ? vchTrue : vchFalse); + if (opcode == OP_CHECKSIGVERIFY) + { + if (fSuccess) + popstack(stack); + else + return false; + } + } + break; + + case OP_CHECKMULTISIG: + case OP_CHECKMULTISIGVERIFY: + { + // ([sig ...] num_of_signatures [pubkey ...] num_of_pubkeys -- bool) + + int i = 1; + if ((int)stack.size() < i) + return false; + + int nKeysCount = CastToBigNum(stacktop(-i)).getint(); + if (nKeysCount < 0 || nKeysCount > 20) + return false; + nOpCount += nKeysCount; + if (nOpCount > 201) + return false; + int ikey = ++i; + i += nKeysCount; + if ((int)stack.size() < i) + return false; + + int nSigsCount = CastToBigNum(stacktop(-i)).getint(); + if (nSigsCount < 0 || nSigsCount > nKeysCount) + return false; + int isig = ++i; + i += nSigsCount; + if ((int)stack.size() < i) + return false; + + // Subset of script starting at the most recent codeseparator + CScript scriptCode(pbegincodehash, pend); + + // Drop the signatures, since there's no way for a signature to sign itself + for (int k = 0; k < nSigsCount; k++) + { + valtype& vchSig = stacktop(-isig-k); + scriptCode.FindAndDelete(CScript(vchSig)); + } + + bool fSuccess = true; + while (fSuccess && nSigsCount > 0) + { + valtype& vchSig = stacktop(-isig); + valtype& vchPubKey = stacktop(-ikey); + + // Check signature + bool fOk = IsCanonicalSignature(vchSig) && IsCanonicalPubKey(vchPubKey) && + CheckSig(vchSig, vchPubKey, scriptCode, txTo, nIn, nHashType); + + if (fOk) + { + isig++; + nSigsCount--; + } + ikey++; + nKeysCount--; + + // If there are more signatures left than keys left, + // then too many signatures have failed + if (nSigsCount > nKeysCount) + fSuccess = false; + } + + while (i-- > 0) + popstack(stack); + stack.push_back(fSuccess ? vchTrue : vchFalse); + + if (opcode == OP_CHECKMULTISIGVERIFY) + { + if (fSuccess) + popstack(stack); + else + return false; + } + } + break; + + default: + return false; + } + + // Size limits + if (stack.size() + altstack.size() > 1000) + return false; + } + } + catch (...) + { + return false; + } + + + if (!vfExec.empty()) + return false; + + return true; +} + + + + + + + + + +uint256 SignatureHash(CScript scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType) +{ + if (nIn >= txTo.vin.size()) + { + printf("ERROR: SignatureHash() : nIn=%d out of range\n", nIn); + return 1; + } + CTransaction txTmp(txTo); + + // In case concatenating two scripts ends up with two codeseparators, + // or an extra one at the end, this prevents all those possible incompatibilities. + scriptCode.FindAndDelete(CScript(OP_CODESEPARATOR)); + + // Blank out other inputs' signatures + for (unsigned int i = 0; i < txTmp.vin.size(); i++) + txTmp.vin[i].scriptSig = CScript(); + txTmp.vin[nIn].scriptSig = scriptCode; + + // Blank out some of the outputs + if ((nHashType & 0x1f) == SIGHASH_NONE) + { + // Wildcard payee + txTmp.vout.clear(); + + // Let the others update at will + for (unsigned int i = 0; i < txTmp.vin.size(); i++) + if (i != nIn) + txTmp.vin[i].nSequence = 0; + } + else if ((nHashType & 0x1f) == SIGHASH_SINGLE) + { + // Only lock-in the txout payee at same index as txin + unsigned int nOut = nIn; + if (nOut >= txTmp.vout.size()) + { + printf("ERROR: SignatureHash() : nOut=%d out of range\n", nOut); + return 1; + } + txTmp.vout.resize(nOut+1); + for (unsigned int i = 0; i < nOut; i++) + txTmp.vout[i].SetNull(); + + // Let the others update at will + for (unsigned int i = 0; i < txTmp.vin.size(); i++) + if (i != nIn) + txTmp.vin[i].nSequence = 0; + } + + // Blank out other inputs completely, not recommended for open transactions + if (nHashType & SIGHASH_ANYONECANPAY) + { + txTmp.vin[0] = txTmp.vin[nIn]; + txTmp.vin.resize(1); + } + + // Serialize and hash + CDataStream ss(SER_GETHASH, 0); + ss.reserve(10000); + ss << txTmp << nHashType; + return Hash(ss.begin(), ss.end()); +} + + +// Valid signature cache, to avoid doing expensive ECDSA signature checking +// twice for every transaction (once when accepted into memory pool, and +// again when accepted into the block chain) + +class CSignatureCache +{ +private: + // sigdata_type is (signature hash, signature, public key): + typedef boost::tuple, std::vector > sigdata_type; + std::set< sigdata_type> setValid; + CCriticalSection cs_sigcache; + +public: + bool + Get(uint256 hash, const std::vector& vchSig, const std::vector& pubKey) + { + LOCK(cs_sigcache); + + sigdata_type k(hash, vchSig, pubKey); + std::set::iterator mi = setValid.find(k); + if (mi != setValid.end()) + return true; + return false; + } + + void Set(uint256 hash, const std::vector& vchSig, const std::vector& pubKey) + { + // DoS prevention: limit cache size to less than 10MB + // (~200 bytes per cache entry times 50,000 entries) + // Since there are a maximum of 20,000 signature operations per block + // 50,000 is a reasonable default. + int64_t nMaxCacheSize = GetArg("-maxsigcachesize", 50000); + if (nMaxCacheSize <= 0) return; + + LOCK(cs_sigcache); + + while (static_cast(setValid.size()) > nMaxCacheSize) + { + // Evict a random entry. Random because that helps + // foil would-be DoS attackers who might try to pre-generate + // and re-use a set of valid signatures just-slightly-greater + // than our cache size. + uint256 randomHash = GetRandHash(); + std::vector unused; + std::set::iterator it = + setValid.lower_bound(sigdata_type(randomHash, unused, unused)); + if (it == setValid.end()) + it = setValid.begin(); + setValid.erase(*it); + } + + sigdata_type k(hash, vchSig, pubKey); + setValid.insert(k); + } +}; + +bool CheckSig(vector vchSig, vector vchPubKey, CScript scriptCode, + const CTransaction& txTo, unsigned int nIn, int nHashType) +{ + static CSignatureCache signatureCache; + + // Hash type is one byte tacked on to the end of the signature + if (vchSig.empty()) + return false; + if (nHashType == 0) + nHashType = vchSig.back(); + else if (nHashType != vchSig.back()) + return false; + vchSig.pop_back(); + + uint256 sighash = SignatureHash(scriptCode, txTo, nIn, nHashType); + + if (signatureCache.Get(sighash, vchSig, vchPubKey)) + return true; + + CKey key; + if (!key.SetPubKey(vchPubKey)) + return false; + + if (!key.Verify(sighash, vchSig)) + return false; + + signatureCache.Set(sighash, vchSig, vchPubKey); + return true; +} + + + + + + + + + +// +// Return public keys or hashes from scriptPubKey, for 'standard' transaction types. +// +bool Solver(const CScript& scriptPubKey, txnouttype& typeRet, vector >& vSolutionsRet) +{ + // Templates + static multimap mTemplates; + if (mTemplates.empty()) + { + // Standard tx, sender provides pubkey, receiver adds signature + mTemplates.insert(make_pair(TX_PUBKEY, CScript() << OP_PUBKEY << OP_CHECKSIG)); + + // Bitcoin address tx, sender provides hash of pubkey, receiver provides signature and pubkey + mTemplates.insert(make_pair(TX_PUBKEYHASH, CScript() << OP_DUP << OP_HASH160 << OP_PUBKEYHASH << OP_EQUALVERIFY << OP_CHECKSIG)); + + // Sender provides N pubkeys, receivers provides M signatures + mTemplates.insert(make_pair(TX_MULTISIG, CScript() << OP_SMALLINTEGER << OP_PUBKEYS << OP_SMALLINTEGER << OP_CHECKMULTISIG)); + + // Empty, provably prunable, data-carrying output + mTemplates.insert(make_pair(TX_NULL_DATA, CScript() << OP_RETURN)); + } + + // Shortcut for pay-to-script-hash, which are more constrained than the other types: + // it is always OP_HASH160 20 [20 byte hash] OP_EQUAL + if (scriptPubKey.IsPayToScriptHash()) + { + typeRet = TX_SCRIPTHASH; + vector hashBytes(scriptPubKey.begin()+2, scriptPubKey.begin()+22); + vSolutionsRet.push_back(hashBytes); + return true; + } + + // Scan templates + const CScript& script1 = scriptPubKey; + BOOST_FOREACH(const PAIRTYPE(txnouttype, CScript)& tplate, mTemplates) + { + const CScript& script2 = tplate.second; + vSolutionsRet.clear(); + + opcodetype opcode1, opcode2; + vector vch1, vch2; + + // Compare + CScript::const_iterator pc1 = script1.begin(); + CScript::const_iterator pc2 = script2.begin(); + while (true) + { + if (pc1 == script1.end() && pc2 == script2.end()) + { + // Found a match + typeRet = tplate.first; + if (typeRet == TX_MULTISIG) + { + // Additional checks for TX_MULTISIG: + unsigned char m = vSolutionsRet.front()[0]; + unsigned char n = vSolutionsRet.back()[0]; + if (m < 1 || n < 1 || m > n || vSolutionsRet.size()-2 != n) + return false; + } + return true; + } + if (!script1.GetOp(pc1, opcode1, vch1)) + break; + if (!script2.GetOp(pc2, opcode2, vch2)) + break; + + // Template matching opcodes: + if (opcode2 == OP_PUBKEYS) + { + while (vch1.size() >= 33 && vch1.size() <= 120) + { + vSolutionsRet.push_back(vch1); + if (!script1.GetOp(pc1, opcode1, vch1)) + break; + } + if (!script2.GetOp(pc2, opcode2, vch2)) + break; + // Normal situation is to fall through + // to other if/else statements + } + + if (opcode2 == OP_PUBKEY) + { + if (vch1.size() < 33 || vch1.size() > 120) + break; + vSolutionsRet.push_back(vch1); + } + else if (opcode2 == OP_PUBKEYHASH) + { + if (vch1.size() != sizeof(uint160)) + break; + vSolutionsRet.push_back(vch1); + } + else if (opcode2 == OP_SMALLINTEGER) + { // Single-byte small integer pushed onto vSolutions + if (opcode1 == OP_0 || + (opcode1 >= OP_1 && opcode1 <= OP_16)) + { + char n = (char)CScript::DecodeOP_N(opcode1); + vSolutionsRet.push_back(valtype(1, n)); + } + else + break; + } + else if (opcode1 != opcode2 || vch1 != vch2) + { + // Others must match exactly + break; + } + } + } + + vSolutionsRet.clear(); + typeRet = TX_NONSTANDARD; + return false; +} + + +bool Sign1(const CKeyID& address, const CKeyStore& keystore, uint256 hash, int nHashType, CScript& scriptSigRet) +{ + CKey key; + if (!keystore.GetKey(address, key)) + return false; + + vector vchSig; + if (!key.Sign(hash, vchSig)) + return false; + vchSig.push_back((unsigned char)nHashType); + scriptSigRet << vchSig; + + return true; +} + +bool SignN(const vector& multisigdata, const CKeyStore& keystore, uint256 hash, int nHashType, CScript& scriptSigRet) +{ + int nSigned = 0; + int nRequired = multisigdata.front()[0]; + for (unsigned int i = 1; i < multisigdata.size()-1 && nSigned < nRequired; i++) + { + const valtype& pubkey = multisigdata[i]; + CKeyID keyID = CPubKey(pubkey).GetID(); + if (Sign1(keyID, keystore, hash, nHashType, scriptSigRet)) + ++nSigned; + } + return nSigned==nRequired; +} + +// +// Sign scriptPubKey with private keys stored in keystore, given transaction hash and hash type. +// Signatures are returned in scriptSigRet (or returns false if scriptPubKey can't be signed), +// unless whichTypeRet is TX_SCRIPTHASH, in which case scriptSigRet is the redemption script. +// Returns false if scriptPubKey could not be completely satisfied. +// +bool Solver(const CKeyStore& keystore, const CScript& scriptPubKey, uint256 hash, int nHashType, + CScript& scriptSigRet, txnouttype& whichTypeRet) +{ + scriptSigRet.clear(); + + vector vSolutions; + if (!Solver(scriptPubKey, whichTypeRet, vSolutions)) + return false; + + CKeyID keyID; + switch (whichTypeRet) + { + case TX_NONSTANDARD: + case TX_NULL_DATA: + return false; + case TX_PUBKEY: + keyID = CPubKey(vSolutions[0]).GetID(); + return Sign1(keyID, keystore, hash, nHashType, scriptSigRet); + case TX_PUBKEYHASH: + keyID = CKeyID(uint160(vSolutions[0])); + if (!Sign1(keyID, keystore, hash, nHashType, scriptSigRet)) + return false; + else + { + CPubKey vch; + keystore.GetPubKey(keyID, vch); + scriptSigRet << vch; + } + return true; + case TX_SCRIPTHASH: + return keystore.GetCScript(uint160(vSolutions[0]), scriptSigRet); + + case TX_MULTISIG: + scriptSigRet << OP_0; // workaround CHECKMULTISIG bug + return (SignN(vSolutions, keystore, hash, nHashType, scriptSigRet)); + } + return false; +} + +int ScriptSigArgsExpected(txnouttype t, const std::vector >& vSolutions) +{ + switch (t) + { + case TX_NONSTANDARD: + case TX_NULL_DATA: + return -1; + case TX_PUBKEY: + return 1; + case TX_PUBKEYHASH: + return 2; + case TX_MULTISIG: + if (vSolutions.size() < 1 || vSolutions[0].size() < 1) + return -1; + return vSolutions[0][0] + 1; + case TX_SCRIPTHASH: + return 1; // doesn't include args needed by the script + } + return -1; +} + +bool IsStandard(const CScript& scriptPubKey, txnouttype& whichType) +{ + vector vSolutions; + if (!Solver(scriptPubKey, whichType, vSolutions)) + return false; + + if (whichType == TX_MULTISIG) + { + unsigned char m = vSolutions.front()[0]; + unsigned char n = vSolutions.back()[0]; + // Support up to x-of-3 multisig txns as standard + if (n < 1 || n > 3) + return false; + if (m < 1 || m > n) + return false; + } + + return whichType != TX_NONSTANDARD; +} + + +unsigned int HaveKeys(const vector& pubkeys, const CKeyStore& keystore) +{ + unsigned int nResult = 0; + BOOST_FOREACH(const valtype& pubkey, pubkeys) + { + CKeyID keyID = CPubKey(pubkey).GetID(); + if (keystore.HaveKey(keyID)) + ++nResult; + } + return nResult; +} + + +class CKeyStoreIsMineVisitor : public boost::static_visitor +{ +private: + const CKeyStore *keystore; +public: + CKeyStoreIsMineVisitor(const CKeyStore *keystoreIn) : keystore(keystoreIn) { } + bool operator()(const CNoDestination &dest) const { return false; } + bool operator()(const CKeyID &keyID) const { return keystore->HaveKey(keyID); } + bool operator()(const CScriptID &scriptID) const { return keystore->HaveCScript(scriptID); } +}; + +bool IsMine(const CKeyStore &keystore, const CTxDestination &dest) +{ + return boost::apply_visitor(CKeyStoreIsMineVisitor(&keystore), dest); +} + +bool IsMine(const CKeyStore &keystore, const CScript& scriptPubKey) +{ + vector vSolutions; + txnouttype whichType; + if (!Solver(scriptPubKey, whichType, vSolutions)) + return false; + + CKeyID keyID; + switch (whichType) + { + case TX_NONSTANDARD: + case TX_NULL_DATA: + return false; + case TX_PUBKEY: + keyID = CPubKey(vSolutions[0]).GetID(); + return keystore.HaveKey(keyID); + case TX_PUBKEYHASH: + keyID = CKeyID(uint160(vSolutions[0])); + return keystore.HaveKey(keyID); + case TX_SCRIPTHASH: + { + CScript subscript; + if (!keystore.GetCScript(CScriptID(uint160(vSolutions[0])), subscript)) + return false; + return IsMine(keystore, subscript); + } + case TX_MULTISIG: + { + // Only consider transactions "mine" if we own ALL the + // keys involved. multi-signature transactions that are + // partially owned (somebody else has a key that can spend + // them) enable spend-out-from-under-you attacks, especially + // in shared-wallet situations. + vector keys(vSolutions.begin()+1, vSolutions.begin()+vSolutions.size()-1); + return HaveKeys(keys, keystore) == keys.size(); + } + } + return false; +} + +bool ExtractDestination(const CScript& scriptPubKey, CTxDestination& addressRet) +{ + vector vSolutions; + txnouttype whichType; + if (!Solver(scriptPubKey, whichType, vSolutions)) + return false; + + if (whichType == TX_PUBKEY) + { + addressRet = CPubKey(vSolutions[0]).GetID(); + return true; + } + else if (whichType == TX_PUBKEYHASH) + { + addressRet = CKeyID(uint160(vSolutions[0])); + return true; + } + else if (whichType == TX_SCRIPTHASH) + { + addressRet = CScriptID(uint160(vSolutions[0])); + return true; + } + // Multisig txns have more than one address... + return false; +} + +class CAffectedKeysVisitor : public boost::static_visitor { +private: + const CKeyStore &keystore; + std::vector &vKeys; + +public: + CAffectedKeysVisitor(const CKeyStore &keystoreIn, std::vector &vKeysIn) : keystore(keystoreIn), vKeys(vKeysIn) {} + + void Process(const CScript &script) { + txnouttype type; + std::vector vDest; + int nRequired; + if (ExtractDestinations(script, type, vDest, nRequired)) { + BOOST_FOREACH(const CTxDestination &dest, vDest) + boost::apply_visitor(*this, dest); + } + } + + void operator()(const CKeyID &keyId) { + if (keystore.HaveKey(keyId)) + vKeys.push_back(keyId); + } + + void operator()(const CScriptID &scriptId) { + CScript script; + if (keystore.GetCScript(scriptId, script)) + Process(script); + } + + void operator()(const CNoDestination &none) {} +}; + + +void ExtractAffectedKeys(const CKeyStore &keystore, const CScript& scriptPubKey, std::vector &vKeys) { + CAffectedKeysVisitor(keystore, vKeys).Process(scriptPubKey); +} + +bool ExtractDestinations(const CScript& scriptPubKey, txnouttype& typeRet, vector& addressRet, int& nRequiredRet) +{ + addressRet.clear(); + typeRet = TX_NONSTANDARD; + vector vSolutions; + if (!Solver(scriptPubKey, typeRet, vSolutions)) + return false; + if (typeRet == TX_NULL_DATA){ + // This is data, not addresses + return false; + } + + if (typeRet == TX_MULTISIG) + { + nRequiredRet = vSolutions.front()[0]; + for (unsigned int i = 1; i < vSolutions.size()-1; i++) + { + CTxDestination address = CPubKey(vSolutions[i]).GetID(); + addressRet.push_back(address); + } + } + else + { + nRequiredRet = 1; + CTxDestination address; + if (!ExtractDestination(scriptPubKey, address)) + return false; + addressRet.push_back(address); + } + + return true; +} + +bool VerifyScript(const CScript& scriptSig, const CScript& scriptPubKey, const CTransaction& txTo, unsigned int nIn, + int nHashType) +{ + vector > stack, stackCopy; + if (!EvalScript(stack, scriptSig, txTo, nIn, nHashType)) + return false; + + stackCopy = stack; + + if (!EvalScript(stack, scriptPubKey, txTo, nIn, nHashType)) + return false; + if (stack.empty()) + return false; + + if (CastToBool(stack.back()) == false) + return false; + + // Additional validation for spend-to-script-hash transactions: + if (scriptPubKey.IsPayToScriptHash()) + { + if (!scriptSig.IsPushOnly()) // scriptSig must be literals-only + return false; // or validation fails + + const valtype& pubKeySerialized = stackCopy.back(); + CScript pubKey2(pubKeySerialized.begin(), pubKeySerialized.end()); + popstack(stackCopy); + + if (!EvalScript(stackCopy, pubKey2, txTo, nIn, nHashType)) + return false; + if (stackCopy.empty()) + return false; + return CastToBool(stackCopy.back()); + } + + return true; +} + + +bool SignSignature(const CKeyStore &keystore, const CScript& fromPubKey, CTransaction& txTo, unsigned int nIn, int nHashType) +{ + assert(nIn < txTo.vin.size()); + CTxIn& txin = txTo.vin[nIn]; + + // Leave out the signature from the hash, since a signature can't sign itself. + // The checksig op will also drop the signatures from its hash. + uint256 hash = SignatureHash(fromPubKey, txTo, nIn, nHashType); + + txnouttype whichType; + if (!Solver(keystore, fromPubKey, hash, nHashType, txin.scriptSig, whichType)) + return false; + + if (whichType == TX_SCRIPTHASH) + { + // Solver returns the subscript that need to be evaluated; + // the final scriptSig is the signatures from that + // and then the serialized subscript: + CScript subscript = txin.scriptSig; + + // Recompute txn hash using subscript in place of scriptPubKey: + uint256 hash2 = SignatureHash(subscript, txTo, nIn, nHashType); + + txnouttype subType; + bool fSolved = + Solver(keystore, subscript, hash2, nHashType, txin.scriptSig, subType) && subType != TX_SCRIPTHASH; + // Append serialized subscript whether or not it is completely signed: + txin.scriptSig << static_cast(subscript); + if (!fSolved) return false; + } + + // Test solution + return VerifyScript(txin.scriptSig, fromPubKey, txTo, nIn, 0); +} + +bool SignSignature(const CKeyStore &keystore, const CTransaction& txFrom, CTransaction& txTo, unsigned int nIn, int nHashType) +{ + assert(nIn < txTo.vin.size()); + CTxIn& txin = txTo.vin[nIn]; + assert(txin.prevout.n < txFrom.vout.size()); + assert(txin.prevout.hash == txFrom.GetHash()); + const CTxOut& txout = txFrom.vout[txin.prevout.n]; + + return SignSignature(keystore, txout.scriptPubKey, txTo, nIn, nHashType); +} + +bool VerifySignature(const CTransaction& txFrom, const CTransaction& txTo, unsigned int nIn, int nHashType) +{ + assert(nIn < txTo.vin.size()); + const CTxIn& txin = txTo.vin[nIn]; + if (txin.prevout.n >= txFrom.vout.size()) + return false; + const CTxOut& txout = txFrom.vout[txin.prevout.n]; + + if (txin.prevout.hash != txFrom.GetHash()) + return false; + + return VerifyScript(txin.scriptSig, txout.scriptPubKey, txTo, nIn, nHashType); +} + +static CScript PushAll(const vector& values) +{ + CScript result; + BOOST_FOREACH(const valtype& v, values) + result << v; + return result; +} + +static CScript CombineMultisig(CScript scriptPubKey, const CTransaction& txTo, unsigned int nIn, + const vector& vSolutions, + vector& sigs1, vector& sigs2) +{ + // Combine all the signatures we've got: + set allsigs; + BOOST_FOREACH(const valtype& v, sigs1) + { + if (!v.empty()) + allsigs.insert(v); + } + BOOST_FOREACH(const valtype& v, sigs2) + { + if (!v.empty()) + allsigs.insert(v); + } + + // Build a map of pubkey -> signature by matching sigs to pubkeys: + assert(vSolutions.size() > 1); + unsigned int nSigsRequired = vSolutions.front()[0]; + unsigned int nPubKeys = vSolutions.size()-2; + map sigs; + BOOST_FOREACH(const valtype& sig, allsigs) + { + for (unsigned int i = 0; i < nPubKeys; i++) + { + const valtype& pubkey = vSolutions[i+1]; + if (sigs.count(pubkey)) + continue; // Already got a sig for this pubkey + + if (CheckSig(sig, pubkey, scriptPubKey, txTo, nIn, 0)) + { + sigs[pubkey] = sig; + break; + } + } + } + // Now build a merged CScript: + unsigned int nSigsHave = 0; + CScript result; result << OP_0; // pop-one-too-many workaround + for (unsigned int i = 0; i < nPubKeys && nSigsHave < nSigsRequired; i++) + { + if (sigs.count(vSolutions[i+1])) + { + result << sigs[vSolutions[i+1]]; + ++nSigsHave; + } + } + // Fill any missing with OP_0: + for (unsigned int i = nSigsHave; i < nSigsRequired; i++) + result << OP_0; + + return result; +} + +static CScript CombineSignatures(CScript scriptPubKey, const CTransaction& txTo, unsigned int nIn, + const txnouttype txType, const vector& vSolutions, + vector& sigs1, vector& sigs2) +{ + switch (txType) + { + case TX_NONSTANDARD: + case TX_NULL_DATA: + // Don't know anything about this, assume bigger one is correct: + if (sigs1.size() >= sigs2.size()) + return PushAll(sigs1); + return PushAll(sigs2); + case TX_PUBKEY: + case TX_PUBKEYHASH: + // Signatures are bigger than placeholders or empty scripts: + if (sigs1.empty() || sigs1[0].empty()) + return PushAll(sigs2); + return PushAll(sigs1); + case TX_SCRIPTHASH: + if (sigs1.empty() || sigs1.back().empty()) + return PushAll(sigs2); + else if (sigs2.empty() || sigs2.back().empty()) + return PushAll(sigs1); + else + { + // Recur to combine: + valtype spk = sigs1.back(); + CScript pubKey2(spk.begin(), spk.end()); + + txnouttype txType2; + vector > vSolutions2; + Solver(pubKey2, txType2, vSolutions2); + sigs1.pop_back(); + sigs2.pop_back(); + CScript result = CombineSignatures(pubKey2, txTo, nIn, txType2, vSolutions2, sigs1, sigs2); + result << spk; + return result; + } + case TX_MULTISIG: + return CombineMultisig(scriptPubKey, txTo, nIn, vSolutions, sigs1, sigs2); + } + + return CScript(); +} + +CScript CombineSignatures(CScript scriptPubKey, const CTransaction& txTo, unsigned int nIn, + const CScript& scriptSig1, const CScript& scriptSig2) +{ + txnouttype txType; + vector > vSolutions; + Solver(scriptPubKey, txType, vSolutions); + + vector stack1; + EvalScript(stack1, scriptSig1, CTransaction(), 0, 0); + vector stack2; + EvalScript(stack2, scriptSig2, CTransaction(), 0, 0); + + return CombineSignatures(scriptPubKey, txTo, nIn, txType, vSolutions, stack1, stack2); +} + +unsigned int CScript::GetSigOpCount(bool fAccurate) const +{ + unsigned int n = 0; + const_iterator pc = begin(); + opcodetype lastOpcode = OP_INVALIDOPCODE; + while (pc < end()) + { + opcodetype opcode; + if (!GetOp(pc, opcode)) + break; + if (opcode == OP_CHECKSIG || opcode == OP_CHECKSIGVERIFY) + n++; + else if (opcode == OP_CHECKMULTISIG || opcode == OP_CHECKMULTISIGVERIFY) + { + if (fAccurate && lastOpcode >= OP_1 && lastOpcode <= OP_16) + n += DecodeOP_N(lastOpcode); + else + n += 20; + } + lastOpcode = opcode; + } + return n; +} + +unsigned int CScript::GetSigOpCount(const CScript& scriptSig) const +{ + if (!IsPayToScriptHash()) + return GetSigOpCount(true); + + // This is a pay-to-script-hash scriptPubKey; + // get the last item that the scriptSig + // pushes onto the stack: + const_iterator pc = scriptSig.begin(); + vector data; + while (pc < scriptSig.end()) + { + opcodetype opcode; + if (!scriptSig.GetOp(pc, opcode, data)) + return 0; + if (opcode > OP_16) + return 0; + } + + /// ... and return its opcount: + CScript subscript(data.begin(), data.end()); + return subscript.GetSigOpCount(true); +} + +bool CScript::IsPayToScriptHash() const +{ + // Extra-fast test for pay-to-script-hash CScripts: + return (this->size() == 23 && + this->at(0) == OP_HASH160 && + this->at(1) == 0x14 && + this->at(22) == OP_EQUAL); +} + +bool CScript::HasCanonicalPushes() const +{ + const_iterator pc = begin(); + while (pc < end()) + { + opcodetype opcode; + std::vector data; + if (!GetOp(pc, opcode, data)) + return false; + if (opcode > OP_16) + continue; + if (opcode < OP_PUSHDATA1 && opcode > OP_0 && (data.size() == 1 && data[0] <= 16)) + // Could have used an OP_n code, rather than a 1-byte push. + return false; + if (opcode == OP_PUSHDATA1 && data.size() < OP_PUSHDATA1) + // Could have used a normal n-byte push, rather than OP_PUSHDATA1. + return false; + if (opcode == OP_PUSHDATA2 && data.size() <= 0xFF) + // Could have used an OP_PUSHDATA1. + return false; + if (opcode == OP_PUSHDATA4 && data.size() <= 0xFFFF) + // Could have used an OP_PUSHDATA2. + return false; + } + return true; +} + +class CScriptVisitor : public boost::static_visitor +{ +private: + CScript *script; +public: + CScriptVisitor(CScript *scriptin) { script = scriptin; } + + bool operator()(const CNoDestination &dest) const { + script->clear(); + return false; + } + + bool operator()(const CKeyID &keyID) const { + script->clear(); + *script << OP_DUP << OP_HASH160 << keyID << OP_EQUALVERIFY << OP_CHECKSIG; + return true; + } + + bool operator()(const CScriptID &scriptID) const { + script->clear(); + *script << OP_HASH160 << scriptID << OP_EQUAL; + return true; + } +}; + +void CScript::SetDestination(const CTxDestination& dest) +{ + boost::apply_visitor(CScriptVisitor(this), dest); +} + +void CScript::SetMultisig(int nRequired, const std::vector& keys) +{ + this->clear(); + + *this << EncodeOP_N(nRequired); + BOOST_FOREACH(const CKey& key, keys) + *this << key.GetPubKey(); + *this << EncodeOP_N(keys.size()) << OP_CHECKMULTISIG; +} diff --git a/src/script.h b/src/script.h new file mode 100644 index 0000000..290664c --- /dev/null +++ b/src/script.h @@ -0,0 +1,604 @@ +// Copyright (c) 2009-2010 Satoshi Nakamoto +// Copyright (c) 2009-2012 The Bitcoin developers +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifndef H_BITCOIN_SCRIPT +#define H_BITCOIN_SCRIPT + +#include +#include + +#include + +#include +#include + +#include "keystore.h" +#include "bignum.h" + +typedef std::vector valtype; + +class CTransaction; + +static const unsigned int MAX_SCRIPT_ELEMENT_SIZE = 520; // bytes + +/** Signature hash types/flags */ +enum +{ + SIGHASH_ALL = 1, + SIGHASH_NONE = 2, + SIGHASH_SINGLE = 3, + SIGHASH_ANYONECANPAY = 0x80, +}; + + +enum txnouttype +{ + TX_NONSTANDARD, + // 'standard' transaction types: + TX_PUBKEY, + TX_PUBKEYHASH, + TX_SCRIPTHASH, + TX_MULTISIG, + TX_NULL_DATA, +}; + +class CNoDestination { +public: + friend bool operator==(const CNoDestination &a, const CNoDestination &b) { return true; } + friend bool operator<(const CNoDestination &a, const CNoDestination &b) { return true; } +}; + +/** A txout script template with a specific destination. It is either: + * * CNoDestination: no destination set + * * CKeyID: TX_PUBKEYHASH destination + * * CScriptID: TX_SCRIPTHASH destination + * A CTxDestination is the internal data type encoded in a CBitcoinAddress + */ +typedef boost::variant CTxDestination; + +const char* GetTxnOutputType(txnouttype t); + +/** Script opcodes */ +enum opcodetype +{ + // push value + OP_0 = 0x00, + OP_FALSE = OP_0, + OP_PUSHDATA1 = 0x4c, + OP_PUSHDATA2 = 0x4d, + OP_PUSHDATA4 = 0x4e, + OP_1NEGATE = 0x4f, + OP_RESERVED = 0x50, + OP_1 = 0x51, + OP_TRUE=OP_1, + OP_2 = 0x52, + OP_3 = 0x53, + OP_4 = 0x54, + OP_5 = 0x55, + OP_6 = 0x56, + OP_7 = 0x57, + OP_8 = 0x58, + OP_9 = 0x59, + OP_10 = 0x5a, + OP_11 = 0x5b, + OP_12 = 0x5c, + OP_13 = 0x5d, + OP_14 = 0x5e, + OP_15 = 0x5f, + OP_16 = 0x60, + + // control + OP_NOP = 0x61, + OP_VER = 0x62, + OP_IF = 0x63, + OP_NOTIF = 0x64, + OP_VERIF = 0x65, + OP_VERNOTIF = 0x66, + OP_ELSE = 0x67, + OP_ENDIF = 0x68, + OP_VERIFY = 0x69, + OP_RETURN = 0x6a, + + // stack ops + OP_TOALTSTACK = 0x6b, + OP_FROMALTSTACK = 0x6c, + OP_2DROP = 0x6d, + OP_2DUP = 0x6e, + OP_3DUP = 0x6f, + OP_2OVER = 0x70, + OP_2ROT = 0x71, + OP_2SWAP = 0x72, + OP_IFDUP = 0x73, + OP_DEPTH = 0x74, + OP_DROP = 0x75, + OP_DUP = 0x76, + OP_NIP = 0x77, + OP_OVER = 0x78, + OP_PICK = 0x79, + OP_ROLL = 0x7a, + OP_ROT = 0x7b, + OP_SWAP = 0x7c, + OP_TUCK = 0x7d, + + // splice ops + OP_CAT = 0x7e, + OP_SUBSTR = 0x7f, + OP_LEFT = 0x80, + OP_RIGHT = 0x81, + OP_SIZE = 0x82, + + // bit logic + OP_INVERT = 0x83, + OP_AND = 0x84, + OP_OR = 0x85, + OP_XOR = 0x86, + OP_EQUAL = 0x87, + OP_EQUALVERIFY = 0x88, + OP_RESERVED1 = 0x89, + OP_RESERVED2 = 0x8a, + + // numeric + OP_1ADD = 0x8b, + OP_1SUB = 0x8c, + OP_2MUL = 0x8d, + OP_2DIV = 0x8e, + OP_NEGATE = 0x8f, + OP_ABS = 0x90, + OP_NOT = 0x91, + OP_0NOTEQUAL = 0x92, + + OP_ADD = 0x93, + OP_SUB = 0x94, + OP_MUL = 0x95, + OP_DIV = 0x96, + OP_MOD = 0x97, + OP_LSHIFT = 0x98, + OP_RSHIFT = 0x99, + + OP_BOOLAND = 0x9a, + OP_BOOLOR = 0x9b, + OP_NUMEQUAL = 0x9c, + OP_NUMEQUALVERIFY = 0x9d, + OP_NUMNOTEQUAL = 0x9e, + OP_LESSTHAN = 0x9f, + OP_GREATERTHAN = 0xa0, + OP_LESSTHANOREQUAL = 0xa1, + OP_GREATERTHANOREQUAL = 0xa2, + OP_MIN = 0xa3, + OP_MAX = 0xa4, + + OP_WITHIN = 0xa5, + + // crypto + OP_RIPEMD160 = 0xa6, + OP_SHA1 = 0xa7, + OP_SHA256 = 0xa8, + OP_HASH160 = 0xa9, + OP_HASH256 = 0xaa, + OP_CODESEPARATOR = 0xab, + OP_CHECKSIG = 0xac, + OP_CHECKSIGVERIFY = 0xad, + OP_CHECKMULTISIG = 0xae, + OP_CHECKMULTISIGVERIFY = 0xaf, + + // expansion + OP_NOP1 = 0xb0, + OP_NOP2 = 0xb1, + OP_NOP3 = 0xb2, + OP_NOP4 = 0xb3, + OP_NOP5 = 0xb4, + OP_NOP6 = 0xb5, + OP_NOP7 = 0xb6, + OP_NOP8 = 0xb7, + OP_NOP9 = 0xb8, + OP_NOP10 = 0xb9, + + + + // template matching params + OP_SMALLINTEGER = 0xfa, + OP_PUBKEYS = 0xfb, + OP_PUBKEYHASH = 0xfd, + OP_PUBKEY = 0xfe, + + OP_INVALIDOPCODE = 0xff, +}; + +const char* GetOpName(opcodetype opcode); + + + +inline std::string ValueString(const std::vector& vch) +{ + if (vch.size() <= 4) + return strprintf("%d", CBigNum(vch).getint()); + else + return HexStr(vch); +} + +inline std::string StackString(const std::vector >& vStack) +{ + std::string str; + BOOST_FOREACH(const std::vector& vch, vStack) + { + if (!str.empty()) + str += " "; + str += ValueString(vch); + } + return str; +} + + + + + + + + +/** Serialized script, used inside transaction inputs and outputs */ +class CScript : public std::vector +{ +protected: + CScript& push_int64(int64_t n) + { + if (n == -1 || (n >= 1 && n <= 16)) + { + push_back(n + (OP_1 - 1)); + } + else + { + CBigNum bn(n); + *this << bn.getvch(); + } + return *this; + } + + CScript& push_uint64(uint64_t n) + { + if (n >= 1 && n <= 16) + { + push_back(n + (OP_1 - 1)); + } + else + { + CBigNum bn(n); + *this << bn.getvch(); + } + return *this; + } + +public: + CScript() { } + CScript(const CScript& b) : std::vector(b.begin(), b.end()) { } + CScript(const_iterator pbegin, const_iterator pend) : std::vector(pbegin, pend) { } +#ifndef _MSC_VER + CScript(const unsigned char* pbegin, const unsigned char* pend) : std::vector(pbegin, pend) { } +#endif + + CScript& operator+=(const CScript& b) + { + insert(end(), b.begin(), b.end()); + return *this; + } + + friend CScript operator+(const CScript& a, const CScript& b) + { + CScript ret = a; + ret += b; + return ret; + } + + + //explicit CScript(char b) is not portable. Use 'signed char' or 'unsigned char'. + explicit CScript(signed char b) { operator<<(b); } + explicit CScript(short b) { operator<<(b); } + explicit CScript(int b) { operator<<(b); } + explicit CScript(long b) { operator<<(b); } + explicit CScript(long long b) { operator<<(b); } + explicit CScript(unsigned char b) { operator<<(b); } + explicit CScript(unsigned int b) { operator<<(b); } + explicit CScript(unsigned short b) { operator<<(b); } + explicit CScript(unsigned long b) { operator<<(b); } + explicit CScript(unsigned long long b) { operator<<(b); } + + explicit CScript(opcodetype b) { operator<<(b); } + explicit CScript(const uint256& b) { operator<<(b); } + explicit CScript(const CBigNum& b) { operator<<(b); } + explicit CScript(const std::vector& b) { operator<<(b); } + + + //CScript& operator<<(char b) is not portable. Use 'signed char' or 'unsigned char'. + CScript& operator<<(signed char b) { return push_int64(b); } + CScript& operator<<(short b) { return push_int64(b); } + CScript& operator<<(int b) { return push_int64(b); } + CScript& operator<<(long b) { return push_int64(b); } + CScript& operator<<(long long b) { return push_int64(b); } + CScript& operator<<(unsigned char b) { return push_uint64(b); } + CScript& operator<<(unsigned int b) { return push_uint64(b); } + CScript& operator<<(unsigned short b) { return push_uint64(b); } + CScript& operator<<(unsigned long b) { return push_uint64(b); } + CScript& operator<<(unsigned long long b) { return push_uint64(b); } + + CScript& operator<<(opcodetype opcode) + { + if (opcode < 0 || opcode > 0xff) + throw std::runtime_error("CScript::operator<<() : invalid opcode"); + insert(end(), (unsigned char)opcode); + return *this; + } + + CScript& operator<<(const uint160& b) + { + insert(end(), sizeof(b)); + insert(end(), (unsigned char*)&b, (unsigned char*)&b + sizeof(b)); + return *this; + } + + CScript& operator<<(const uint256& b) + { + insert(end(), sizeof(b)); + insert(end(), (unsigned char*)&b, (unsigned char*)&b + sizeof(b)); + return *this; + } + + CScript& operator<<(const CPubKey& key) + { + std::vector vchKey = key.Raw(); + return (*this) << vchKey; + } + + CScript& operator<<(const CBigNum& b) + { + *this << b.getvch(); + return *this; + } + + CScript& operator<<(const std::vector& b) + { + if (b.size() < OP_PUSHDATA1) + { + insert(end(), (unsigned char)b.size()); + } + else if (b.size() <= 0xff) + { + insert(end(), OP_PUSHDATA1); + insert(end(), (unsigned char)b.size()); + } + else if (b.size() <= 0xffff) + { + insert(end(), OP_PUSHDATA2); + unsigned short nSize = b.size(); + insert(end(), (unsigned char*)&nSize, (unsigned char*)&nSize + sizeof(nSize)); + } + else + { + insert(end(), OP_PUSHDATA4); + unsigned int nSize = b.size(); + insert(end(), (unsigned char*)&nSize, (unsigned char*)&nSize + sizeof(nSize)); + } + insert(end(), b.begin(), b.end()); + return *this; + } + + CScript& operator<<(const CScript& b) + { + // I'm not sure if this should push the script or concatenate scripts. + // If there's ever a use for pushing a script onto a script, delete this member fn + assert(!"Warning: Pushing a CScript onto a CScript with << is probably not intended, use + to concatenate!"); + return *this; + } + + + bool GetOp(iterator& pc, opcodetype& opcodeRet, std::vector& vchRet) + { + // Wrapper so it can be called with either iterator or const_iterator + const_iterator pc2 = pc; + bool fRet = GetOp2(pc2, opcodeRet, &vchRet); + pc = begin() + (pc2 - begin()); + return fRet; + } + + bool GetOp(iterator& pc, opcodetype& opcodeRet) + { + const_iterator pc2 = pc; + bool fRet = GetOp2(pc2, opcodeRet, NULL); + pc = begin() + (pc2 - begin()); + return fRet; + } + + bool GetOp(const_iterator& pc, opcodetype& opcodeRet, std::vector& vchRet) const + { + return GetOp2(pc, opcodeRet, &vchRet); + } + + bool GetOp(const_iterator& pc, opcodetype& opcodeRet) const + { + return GetOp2(pc, opcodeRet, NULL); + } + + bool GetOp2(const_iterator& pc, opcodetype& opcodeRet, std::vector* pvchRet) const + { + opcodeRet = OP_INVALIDOPCODE; + if (pvchRet) + pvchRet->clear(); + if (pc >= end()) + return false; + + // Read instruction + if (end() - pc < 1) + return false; + unsigned int opcode = *pc++; + + // Immediate operand + if (opcode <= OP_PUSHDATA4) + { + unsigned int nSize; + if (opcode < OP_PUSHDATA1) + { + nSize = opcode; + } + else if (opcode == OP_PUSHDATA1) + { + if (end() - pc < 1) + return false; + nSize = *pc++; + } + else if (opcode == OP_PUSHDATA2) + { + if (end() - pc < 2) + return false; + nSize = 0; + memcpy(&nSize, &pc[0], 2); + pc += 2; + } + else if (opcode == OP_PUSHDATA4) + { + if (end() - pc < 4) + return false; + memcpy(&nSize, &pc[0], 4); + pc += 4; + } + if (end() - pc < 0 || (unsigned int)(end() - pc) < nSize) + return false; + if (pvchRet) + pvchRet->assign(pc, pc + nSize); + pc += nSize; + } + + opcodeRet = (opcodetype)opcode; + return true; + } + + // Encode/decode small integers: + static int DecodeOP_N(opcodetype opcode) + { + if (opcode == OP_0) + return 0; + assert(opcode >= OP_1 && opcode <= OP_16); + return (int)opcode - (int)(OP_1 - 1); + } + static opcodetype EncodeOP_N(int n) + { + assert(n >= 0 && n <= 16); + if (n == 0) + return OP_0; + return (opcodetype)(OP_1+n-1); + } + + int FindAndDelete(const CScript& b) + { + int nFound = 0; + if (b.empty()) + return nFound; + iterator pc = begin(); + opcodetype opcode; + do + { + while (end() - pc >= (long)b.size() && memcmp(&pc[0], &b[0], b.size()) == 0) + { + erase(pc, pc + b.size()); + ++nFound; + } + } + while (GetOp(pc, opcode)); + return nFound; + } + int Find(opcodetype op) const + { + int nFound = 0; + opcodetype opcode; + for (const_iterator pc = begin(); pc != end() && GetOp(pc, opcode);) + if (opcode == op) + ++nFound; + return nFound; + } + + // Pre-version-0.6, Bitcoin always counted CHECKMULTISIGs + // as 20 sigops. With pay-to-script-hash, that changed: + // CHECKMULTISIGs serialized in scriptSigs are + // counted more accurately, assuming they are of the form + // ... OP_N CHECKMULTISIG ... + unsigned int GetSigOpCount(bool fAccurate) const; + + // Accurately count sigOps, including sigOps in + // pay-to-script-hash transactions: + unsigned int GetSigOpCount(const CScript& scriptSig) const; + + bool IsPayToScriptHash() const; + + // Called by IsStandardTx and P2SH VerifyScript (which makes it consensus-critical). + bool IsPushOnly() const + { + const_iterator pc = begin(); + while (pc < end()) + { + opcodetype opcode; + if (!GetOp(pc, opcode)) + return false; + if (opcode > OP_16) + return false; + } + return true; + } + + // Called by IsStandardTx. + bool HasCanonicalPushes() const; + + void SetDestination(const CTxDestination& address); + void SetMultisig(int nRequired, const std::vector& keys); + + std::string ToString(bool fShort=false) const + { + std::string str; + opcodetype opcode; + std::vector vch; + const_iterator pc = begin(); + while (pc < end()) + { + if (!str.empty()) + str += " "; + if (!GetOp(pc, opcode, vch)) + { + str += "[error]"; + return str; + } + if (0 <= opcode && opcode <= OP_PUSHDATA4) + str += fShort? ValueString(vch).substr(0, 10) : ValueString(vch); + else + str += GetOpName(opcode); + } + return str; + } + + CScriptID GetID() const + { + return CScriptID(Hash160(*this)); + } +}; + + + + + +bool EvalScript(std::vector >& stack, const CScript& script, const CTransaction& txTo, unsigned int nIn, int nHashType); +bool Solver(const CScript& scriptPubKey, txnouttype& typeRet, std::vector >& vSolutionsRet); +int ScriptSigArgsExpected(txnouttype t, const std::vector >& vSolutions); +bool IsStandard(const CScript& scriptPubKey, txnouttype& whichType); +bool IsMine(const CKeyStore& keystore, const CScript& scriptPubKey); +bool IsMine(const CKeyStore& keystore, const CTxDestination &dest); +void ExtractAffectedKeys(const CKeyStore &keystore, const CScript& scriptPubKey, std::vector &vKeys); +bool ExtractDestination(const CScript& scriptPubKey, CTxDestination& addressRet); +bool ExtractDestinations(const CScript& scriptPubKey, txnouttype& typeRet, std::vector& addressRet, int& nRequiredRet); +bool SignSignature(const CKeyStore& keystore, const CScript& fromPubKey, CTransaction& txTo, unsigned int nIn, int nHashType=SIGHASH_ALL); +bool SignSignature(const CKeyStore& keystore, const CTransaction& txFrom, CTransaction& txTo, unsigned int nIn, int nHashType=SIGHASH_ALL); +bool VerifyScript(const CScript& scriptSig, const CScript& scriptPubKey, const CTransaction& txTo, unsigned int nIn, + int nHashType); +bool VerifySignature(const CTransaction& txFrom, const CTransaction& txTo, unsigned int nIn, int nHashType); + +// Given two sets of signatures for scriptPubKey, possibly with OP_0 placeholders, +// combine them intelligently and return the result. +CScript CombineSignatures(CScript scriptPubKey, const CTransaction& txTo, unsigned int nIn, const CScript& scriptSig1, const CScript& scriptSig2); + +#endif diff --git a/src/scrypt-arm.S b/src/scrypt-arm.S new file mode 100644 index 0000000..143eb3a --- /dev/null +++ b/src/scrypt-arm.S @@ -0,0 +1,555 @@ +/* + * Copyright 2012 pooler@litecoinpool.org + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. See COPYING for more details. + */ + + +#if defined(OPTIMIZED_SALSA) && defined(__arm__) && defined(__APCS_32__) + +#if defined(__linux__) && defined(__ELF__) +.section .note.GNU-stack,"",%progbits +#endif + +#if defined(__ARM_ARCH_5E__) || defined(__ARM_ARCH_5TE__) || \ + defined(__ARM_ARCH_5TEJ__) || defined(__ARM_ARCH_6__) || \ + defined(__ARM_ARCH_6J__) || defined(__ARM_ARCH_6K__) || \ + defined(__ARM_ARCH_6M__) || defined(__ARM_ARCH_6T2__) || \ + defined(__ARM_ARCH_6Z__) || defined(__ARM_ARCH_6ZK__) +#define __ARM_ARCH_5E_OR_6__ +#endif + +#if defined(__ARM_ARCH_5E_OR_6__) || defined(__ARM_ARCH_7__) || \ + defined(__ARM_ARCH_7A__) || defined(__ARM_ARCH_7R__) || \ + defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__) +#define __ARM_ARCH_5E_OR_6_OR_7__ +#endif + +#ifdef __ARM_ARCH_5E_OR_6__ + +#define scrypt_shuffle() \ + add lr, r0, #9*4; \ + ldmia r0, {r2-r7}; \ + ldmia lr, {r2, r8-r12, lr}; \ + str r3, [r0, #5*4]; \ + str r5, [r0, #15*4]; \ + str r6, [r0, #12*4]; \ + str r7, [r0, #1*4]; \ + ldr r5, [r0, #7*4]; \ + str r2, [r0, #13*4]; \ + str r8, [r0, #2*4]; \ + strd r4, [r0, #10*4]; \ + str r9, [r0, #7*4]; \ + str r10, [r0, #4*4]; \ + str r11, [r0, #9*4]; \ + str lr, [r0, #3*4]; \ + add r2, r0, #64+0*4; \ + add lr, r0, #64+9*4; \ + ldmia r2, {r2-r7}; \ + ldmia lr, {r2, r8-r12, lr}; \ + str r3, [r0, #64+5*4]; \ + str r5, [r0, #64+15*4]; \ + str r6, [r0, #64+12*4]; \ + str r7, [r0, #64+1*4]; \ + ldr r5, [r0, #64+7*4]; \ + str r2, [r0, #64+13*4]; \ + str r8, [r0, #64+2*4]; \ + strd r4, [r0, #64+10*4]; \ + str r9, [r0, #64+7*4]; \ + str r10, [r0, #64+4*4]; \ + str r11, [r0, #64+9*4]; \ + str lr, [r0, #64+3*4]; \ + + +#define salsa8_core_doubleround_body() \ + add r6, r2, r6; \ + add r7, r3, r7; \ + eor r10, r10, r6, ror #25; \ + add r6, r0, r4; \ + eor r11, r11, r7, ror #25; \ + add r7, r1, r5; \ + strd r10, [sp, #14*4]; \ + eor r12, r12, r6, ror #25; \ + eor lr, lr, r7, ror #25; \ + ldrd r6, [sp, #10*4]; \ + add r2, r10, r2; \ + add r3, r11, r3; \ + eor r6, r6, r2, ror #23; \ + add r2, r12, r0; \ + eor r7, r7, r3, ror #23; \ + add r3, lr, r1; \ + strd r6, [sp, #10*4]; \ + eor r8, r8, r2, ror #23; \ + eor r9, r9, r3, ror #23; \ + ldrd r2, [sp, #6*4]; \ + add r10, r6, r10; \ + add r11, r7, r11; \ + eor r2, r2, r10, ror #19; \ + add r10, r8, r12; \ + eor r3, r3, r11, ror #19; \ + add r11, r9, lr; \ + eor r4, r4, r10, ror #19; \ + eor r5, r5, r11, ror #19; \ + ldrd r10, [sp, #2*4]; \ + add r6, r2, r6; \ + add r7, r3, r7; \ + eor r10, r10, r6, ror #14; \ + add r6, r4, r8; \ + eor r11, r11, r7, ror #14; \ + add r7, r5, r9; \ + eor r0, r0, r6, ror #14; \ + eor r1, r1, r7, ror #14; \ + ldrd r6, [sp, #14*4]; \ + strd r2, [sp, #6*4]; \ + strd r10, [sp, #2*4]; \ + add r6, r11, r6; \ + add r7, r0, r7; \ + eor r4, r4, r6, ror #25; \ + add r6, r1, r12; \ + eor r5, r5, r7, ror #25; \ + add r7, r10, lr; \ + eor r2, r2, r6, ror #25; \ + eor r3, r3, r7, ror #25; \ + strd r2, [sp, #6*4]; \ + add r10, r3, r10; \ + ldrd r6, [sp, #10*4]; \ + add r11, r4, r11; \ + eor r8, r8, r10, ror #23; \ + add r10, r5, r0; \ + eor r9, r9, r11, ror #23; \ + add r11, r2, r1; \ + eor r6, r6, r10, ror #23; \ + eor r7, r7, r11, ror #23; \ + strd r6, [sp, #10*4]; \ + add r2, r7, r2; \ + ldrd r10, [sp, #14*4]; \ + add r3, r8, r3; \ + eor r12, r12, r2, ror #19; \ + add r2, r9, r4; \ + eor lr, lr, r3, ror #19; \ + add r3, r6, r5; \ + eor r10, r10, r2, ror #19; \ + eor r11, r11, r3, ror #19; \ + ldrd r2, [sp, #2*4]; \ + add r6, r11, r6; \ + add r7, r12, r7; \ + eor r0, r0, r6, ror #14; \ + add r6, lr, r8; \ + eor r1, r1, r7, ror #14; \ + add r7, r10, r9; \ + eor r2, r2, r6, ror #14; \ + eor r3, r3, r7, ror #14; \ + + +#define salsa8_core() \ + ldmia sp, {r0-r12, lr}; \ + ldrd r10, [sp, #14*4]; \ + salsa8_core_doubleround_body(); \ + ldrd r6, [sp, #6*4]; \ + strd r2, [sp, #2*4]; \ + strd r10, [sp, #14*4]; \ + salsa8_core_doubleround_body(); \ + ldrd r6, [sp, #6*4]; \ + strd r2, [sp, #2*4]; \ + strd r10, [sp, #14*4]; \ + salsa8_core_doubleround_body(); \ + ldrd r6, [sp, #6*4]; \ + strd r2, [sp, #2*4]; \ + strd r10, [sp, #14*4]; \ + salsa8_core_doubleround_body(); \ + stmia sp, {r0-r5}; \ + strd r8, [sp, #8*4]; \ + str r12, [sp, #12*4]; \ + str lr, [sp, #13*4]; \ + strd r10, [sp, #14*4]; \ + + +#else + +#define scrypt_shuffle() \ + + +#define salsa8_core_doubleround_body() \ + ldr r8, [sp, #8*4]; \ + add r11, r11, r10; \ + ldr lr, [sp, #13*4]; \ + add r12, r12, r3; \ + eor r2, r2, r11, ror #23; \ + add r11, r4, r0; \ + eor r7, r7, r12, ror #23; \ + add r12, r9, r5; \ + str r9, [sp, #9*4]; \ + eor r8, r8, r11, ror #23; \ + str r10, [sp, #14*4]; \ + eor lr, lr, r12, ror #23; \ + ldr r11, [sp, #11*4]; \ + add r9, lr, r9; \ + ldr r12, [sp, #12*4]; \ + add r10, r2, r10; \ + eor r1, r1, r9, ror #19; \ + add r9, r7, r3; \ + eor r6, r6, r10, ror #19; \ + add r10, r8, r4; \ + str r8, [sp, #8*4]; \ + eor r11, r11, r9, ror #19; \ + str lr, [sp, #13*4]; \ + eor r12, r12, r10, ror #19; \ + ldr r9, [sp, #10*4]; \ + add r8, r12, r8; \ + ldr r10, [sp, #15*4]; \ + add lr, r1, lr; \ + eor r0, r0, r8, ror #14; \ + add r8, r6, r2; \ + eor r5, r5, lr, ror #14; \ + add lr, r11, r7; \ + eor r9, r9, r8, ror #14; \ + ldr r8, [sp, #9*4]; \ + eor r10, r10, lr, ror #14; \ + ldr lr, [sp, #14*4]; \ + add r8, r9, r8; \ + str r9, [sp, #10*4]; \ + add lr, r10, lr; \ + str r10, [sp, #15*4]; \ + eor r11, r11, r8, ror #25; \ + add r8, r0, r3; \ + eor r12, r12, lr, ror #25; \ + add lr, r5, r4; \ + eor r1, r1, r8, ror #25; \ + ldr r8, [sp, #8*4]; \ + eor r6, r6, lr, ror #25; \ + add r9, r11, r9; \ + ldr lr, [sp, #13*4]; \ + add r10, r12, r10; \ + eor r8, r8, r9, ror #23; \ + add r9, r1, r0; \ + eor lr, lr, r10, ror #23; \ + add r10, r6, r5; \ + str r11, [sp, #11*4]; \ + eor r2, r2, r9, ror #23; \ + str r12, [sp, #12*4]; \ + eor r7, r7, r10, ror #23; \ + ldr r9, [sp, #9*4]; \ + add r11, r8, r11; \ + ldr r10, [sp, #14*4]; \ + add r12, lr, r12; \ + eor r9, r9, r11, ror #19; \ + add r11, r2, r1; \ + eor r10, r10, r12, ror #19; \ + add r12, r7, r6; \ + str r8, [sp, #8*4]; \ + eor r3, r3, r11, ror #19; \ + str lr, [sp, #13*4]; \ + eor r4, r4, r12, ror #19; \ + + +#define salsa8_core() \ + ldmia sp, {r0-r7}; \ + ldr r12, [sp, #15*4]; \ + ldr r8, [sp, #11*4]; \ + ldr lr, [sp, #12*4]; \ + ldr r9, [sp, #9*4]; \ + add r8, r8, r12; \ + ldr r11, [sp, #10*4]; \ + add lr, lr, r0; \ + eor r3, r3, r8, ror #25; \ + add r8, r5, r1; \ + ldr r10, [sp, #14*4]; \ + eor r4, r4, lr, ror #25; \ + add lr, r11, r6; \ + eor r9, r9, r8, ror #25; \ + eor r10, r10, lr, ror #25; \ + salsa8_core_doubleround_body(); \ + ldr r11, [sp, #10*4]; \ + add r8, r9, r8; \ + ldr r12, [sp, #15*4]; \ + add lr, r10, lr; \ + eor r11, r11, r8, ror #14; \ + add r8, r3, r2; \ + eor r12, r12, lr, ror #14; \ + add lr, r4, r7; \ + eor r0, r0, r8, ror #14; \ + ldr r8, [sp, #11*4]; \ + eor r5, r5, lr, ror #14; \ + ldr lr, [sp, #12*4]; \ + add r8, r8, r12; \ + str r11, [sp, #10*4]; \ + add lr, lr, r0; \ + str r12, [sp, #15*4]; \ + eor r3, r3, r8, ror #25; \ + add r8, r5, r1; \ + eor r4, r4, lr, ror #25; \ + add lr, r11, r6; \ + str r9, [sp, #9*4]; \ + eor r9, r9, r8, ror #25; \ + str r10, [sp, #14*4]; \ + eor r10, r10, lr, ror #25; \ + salsa8_core_doubleround_body(); \ + ldr r11, [sp, #10*4]; \ + add r8, r9, r8; \ + ldr r12, [sp, #15*4]; \ + add lr, r10, lr; \ + eor r11, r11, r8, ror #14; \ + add r8, r3, r2; \ + eor r12, r12, lr, ror #14; \ + add lr, r4, r7; \ + eor r0, r0, r8, ror #14; \ + ldr r8, [sp, #11*4]; \ + eor r5, r5, lr, ror #14; \ + ldr lr, [sp, #12*4]; \ + add r8, r8, r12; \ + str r11, [sp, #10*4]; \ + add lr, lr, r0; \ + str r12, [sp, #15*4]; \ + eor r3, r3, r8, ror #25; \ + add r8, r5, r1; \ + eor r4, r4, lr, ror #25; \ + add lr, r11, r6; \ + str r9, [sp, #9*4]; \ + eor r9, r9, r8, ror #25; \ + str r10, [sp, #14*4]; \ + eor r10, r10, lr, ror #25; \ + salsa8_core_doubleround_body(); \ + ldr r11, [sp, #10*4]; \ + add r8, r9, r8; \ + ldr r12, [sp, #15*4]; \ + add lr, r10, lr; \ + eor r11, r11, r8, ror #14; \ + add r8, r3, r2; \ + eor r12, r12, lr, ror #14; \ + add lr, r4, r7; \ + eor r0, r0, r8, ror #14; \ + ldr r8, [sp, #11*4]; \ + eor r5, r5, lr, ror #14; \ + ldr lr, [sp, #12*4]; \ + add r8, r8, r12; \ + str r11, [sp, #10*4]; \ + add lr, lr, r0; \ + str r12, [sp, #15*4]; \ + eor r3, r3, r8, ror #25; \ + add r8, r5, r1; \ + eor r4, r4, lr, ror #25; \ + add lr, r11, r6; \ + str r9, [sp, #9*4]; \ + eor r9, r9, r8, ror #25; \ + str r10, [sp, #14*4]; \ + eor r10, r10, lr, ror #25; \ + salsa8_core_doubleround_body(); \ + ldr r11, [sp, #10*4]; \ + add r8, r9, r8; \ + ldr r12, [sp, #15*4]; \ + add lr, r10, lr; \ + str r9, [sp, #9*4]; \ + eor r11, r11, r8, ror #14; \ + eor r12, r12, lr, ror #14; \ + add r8, r3, r2; \ + str r10, [sp, #14*4]; \ + add lr, r4, r7; \ + str r11, [sp, #10*4]; \ + eor r0, r0, r8, ror #14; \ + str r12, [sp, #15*4]; \ + eor r5, r5, lr, ror #14; \ + stmia sp, {r0-r7}; \ + + +#endif + + +#define scrypt_core_macro1a_x4() \ + ldmia r0, {r4-r7}; \ + ldmia lr!, {r8-r11}; \ + stmia r1!, {r4-r7}; \ + stmia r3!, {r8-r11}; \ + eor r4, r4, r8; \ + eor r5, r5, r9; \ + eor r6, r6, r10; \ + eor r7, r7, r11; \ + stmia r0!, {r4-r7}; \ + stmia r12!, {r4-r7}; \ + + +#define scrypt_core_macro1b_x4() \ + ldmia r3!, {r8-r11}; \ + ldmia r2, {r4-r7}; \ + eor r8, r8, r4; \ + eor r9, r9, r5; \ + eor r10, r10, r6; \ + eor r11, r11, r7; \ + ldmia r0, {r4-r7}; \ + stmia r2!, {r8-r11}; \ + eor r4, r4, r8; \ + eor r5, r5, r9; \ + eor r6, r6, r10; \ + eor r7, r7, r11; \ + ldmia r1!, {r8-r11}; \ + eor r4, r4, r8; \ + eor r5, r5, r9; \ + eor r6, r6, r10; \ + eor r7, r7, r11; \ + stmia r0!, {r4-r7}; \ + stmia r12!, {r4-r7}; \ + + +#define scrypt_core_macro2_x4() \ + ldmia r12, {r4-r7}; \ + ldmia r0, {r8-r11}; \ + add r4, r4, r8; \ + add r5, r5, r9; \ + add r6, r6, r10; \ + add r7, r7, r11; \ + stmia r0!, {r4-r7}; \ + ldmia r2, {r8-r11}; \ + eor r4, r4, r8; \ + eor r5, r5, r9; \ + eor r6, r6, r10; \ + eor r7, r7, r11; \ + stmia r2!, {r4-r7}; \ + stmia r12!, {r4-r7}; \ + + +#define scrypt_core_macro3_x4() \ + ldmia r1!, {r4-r7}; \ + ldmia r0, {r8-r11}; \ + add r4, r4, r8; \ + add r5, r5, r9; \ + add r6, r6, r10; \ + add r7, r7, r11; \ + stmia r0!, {r4-r7}; \ + + +#define scrypt_core_macro3_x6() \ + ldmia r1!, {r2-r7}; \ + ldmia r0, {r8-r12, lr}; \ + add r2, r2, r8; \ + add r3, r3, r9; \ + add r4, r4, r10; \ + add r5, r5, r11; \ + add r6, r6, r12; \ + add r7, r7, lr; \ + stmia r0!, {r2-r7}; \ + + + + .text + .code 32 + .align 2 + .globl scrypt_core + .globl _scrypt_core +#ifdef __ELF__ + .type scrypt_core, %function +#endif +scrypt_core: +_scrypt_core: + stmfd sp!, {r4-r11, lr} + mov r12, sp + sub sp, sp, #21*4 + bic sp, sp, #63 + str r12, [sp, #20*4] + + scrypt_shuffle() + + str r0, [sp, #16*4] + add r12, r1, #1024*32*4 + str r12, [sp, #18*4] +scrypt_core_loop1: + add lr, r0, #16*4 + add r3, r1, #16*4 + mov r12, sp + scrypt_core_macro1a_x4() + scrypt_core_macro1a_x4() + scrypt_core_macro1a_x4() + scrypt_core_macro1a_x4() + str r1, [sp, #17*4] + + salsa8_core() + + ldr r0, [sp, #16*4] + mov r12, sp + add r2, r0, #16*4 + scrypt_core_macro2_x4() + scrypt_core_macro2_x4() + scrypt_core_macro2_x4() + scrypt_core_macro2_x4() + + salsa8_core() + + ldr r0, [sp, #16*4] + mov r1, sp + add r0, r0, #16*4 + scrypt_core_macro3_x6() + scrypt_core_macro3_x6() + ldr r3, [sp, #17*4] + ldr r12, [sp, #18*4] + scrypt_core_macro3_x4() + + add r1, r3, #16*4 + sub r0, r0, #32*4 + cmp r1, r12 + bne scrypt_core_loop1 + + ldr r4, [r0, #16*4] + sub r1, r1, #1024*32*4 + str r1, [sp, #17*4] + mov r4, r4, lsl #32-10 + mov r12, #1024 + add r1, r1, r4, lsr #32-10-7 +scrypt_core_loop2: + add r2, r0, #16*4 + add r3, r1, #16*4 + str r12, [sp, #18*4] + mov r12, sp +#ifdef __ARM_ARCH_5E_OR_6_OR_7__ + pld [r1, #24*4] + pld [r1, #8*4] +#endif + scrypt_core_macro1b_x4() + scrypt_core_macro1b_x4() + scrypt_core_macro1b_x4() + scrypt_core_macro1b_x4() + + salsa8_core() + + ldr r0, [sp, #16*4] + mov r12, sp + add r2, r0, #16*4 + scrypt_core_macro2_x4() + scrypt_core_macro2_x4() + scrypt_core_macro2_x4() + scrypt_core_macro2_x4() + + salsa8_core() + + ldr r0, [sp, #16*4] + mov r1, sp + ldr r3, [sp, #17*4] + add r0, r0, #16*4 + scrypt_core_macro3_x4() + mov r4, r4, lsl #32-10 + add r3, r3, r4, lsr #32-10-7 + str r3, [sp, #19*4] +#ifdef __ARM_ARCH_5E_OR_6_OR_7__ + pld [r3, #16*4] + pld [r3] +#endif + scrypt_core_macro3_x6() + scrypt_core_macro3_x6() + + ldr r12, [sp, #18*4] + sub r0, r0, #32*4 + ldr r1, [sp, #19*4] + subs r12, r12, #1 + bne scrypt_core_loop2 + + scrypt_shuffle() + + ldr sp, [sp, #20*4] +#ifdef __thumb__ + ldmfd sp!, {r4-r11, lr} + bx lr +#else + ldmfd sp!, {r4-r11, pc} +#endif + +#endif diff --git a/src/scrypt-x86.S b/src/scrypt-x86.S new file mode 100644 index 0000000..c1d2cef --- /dev/null +++ b/src/scrypt-x86.S @@ -0,0 +1,912 @@ +# Copyright 2011 pooler@litecoinpool.org +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. + +#if defined(OPTIMIZED_SALSA) && defined(__i386__) + +#if defined(__linux__) && defined(__ELF__) +.section .note.GNU-stack,"",%progbits +#endif + +#define gen_salsa8_core_quadround() \ + movl 52(%esp), %ecx; \ + movl 4(%esp), %edx; \ + movl 20(%esp), %ebx; \ + movl 8(%esp), %esi; \ + leal (%ecx, %edx), %edi; \ + roll $7, %edi; \ + xorl %edi, %ebx; \ + movl %ebx, 4(%esp); \ + movl 36(%esp), %edi; \ + leal (%edx, %ebx), %ebp; \ + roll $9, %ebp; \ + xorl %ebp, %edi; \ + movl 24(%esp), %ebp; \ + movl %edi, 8(%esp); \ + addl %edi, %ebx; \ + roll $13, %ebx; \ + xorl %ebx, %ecx; \ + movl 40(%esp), %ebx; \ + movl %ecx, 20(%esp); \ + addl %edi, %ecx; \ + roll $18, %ecx; \ + leal (%esi, %ebp), %edi; \ + roll $7, %edi; \ + xorl %edi, %ebx; \ + movl %ebx, 24(%esp); \ + movl 56(%esp), %edi; \ + xorl %ecx, %edx; \ + leal (%ebp, %ebx), %ecx; \ + roll $9, %ecx; \ + xorl %ecx, %edi; \ + movl %edi, 36(%esp); \ + movl 28(%esp), %ecx; \ + movl %edx, 28(%esp); \ + movl 44(%esp), %edx; \ + addl %edi, %ebx; \ + roll $13, %ebx; \ + xorl %ebx, %esi; \ + movl 60(%esp), %ebx; \ + movl %esi, 40(%esp); \ + addl %edi, %esi; \ + roll $18, %esi; \ + leal (%ecx, %edx), %edi; \ + roll $7, %edi; \ + xorl %edi, %ebx; \ + movl %ebx, 44(%esp); \ + movl 12(%esp), %edi; \ + xorl %esi, %ebp; \ + leal (%edx, %ebx), %esi; \ + roll $9, %esi; \ + xorl %esi, %edi; \ + movl %edi, 12(%esp); \ + movl 48(%esp), %esi; \ + movl %ebp, 48(%esp); \ + movl 64(%esp), %ebp; \ + addl %edi, %ebx; \ + roll $13, %ebx; \ + xorl %ebx, %ecx; \ + movl 16(%esp), %ebx; \ + movl %ecx, 16(%esp); \ + addl %edi, %ecx; \ + roll $18, %ecx; \ + leal (%esi, %ebp), %edi; \ + roll $7, %edi; \ + xorl %edi, %ebx; \ + movl 32(%esp), %edi; \ + xorl %ecx, %edx; \ + leal (%ebp, %ebx), %ecx; \ + roll $9, %ecx; \ + xorl %ecx, %edi; \ + movl %edi, 32(%esp); \ + movl %ebx, %ecx; \ + movl %edx, 52(%esp); \ + movl 28(%esp), %edx; \ + addl %edi, %ebx; \ + roll $13, %ebx; \ + xorl %ebx, %esi; \ + movl 40(%esp), %ebx; \ + movl %esi, 28(%esp); \ + addl %edi, %esi; \ + roll $18, %esi; \ + leal (%ecx, %edx), %edi; \ + roll $7, %edi; \ + xorl %edi, %ebx; \ + movl %ebx, 40(%esp); \ + movl 12(%esp), %edi; \ + xorl %esi, %ebp; \ + leal (%edx, %ebx), %esi; \ + roll $9, %esi; \ + xorl %esi, %edi; \ + movl %edi, 12(%esp); \ + movl 4(%esp), %esi; \ + movl %ebp, 4(%esp); \ + movl 48(%esp), %ebp; \ + addl %edi, %ebx; \ + roll $13, %ebx; \ + xorl %ebx, %ecx; \ + movl 16(%esp), %ebx; \ + movl %ecx, 16(%esp); \ + addl %edi, %ecx; \ + roll $18, %ecx; \ + leal (%esi, %ebp), %edi; \ + roll $7, %edi; \ + xorl %edi, %ebx; \ + movl %ebx, 48(%esp); \ + movl 32(%esp), %edi; \ + xorl %ecx, %edx; \ + leal (%ebp, %ebx), %ecx; \ + roll $9, %ecx; \ + xorl %ecx, %edi; \ + movl %edi, 32(%esp); \ + movl 24(%esp), %ecx; \ + movl %edx, 24(%esp); \ + movl 52(%esp), %edx; \ + addl %edi, %ebx; \ + roll $13, %ebx; \ + xorl %ebx, %esi; \ + movl 28(%esp), %ebx; \ + movl %esi, 28(%esp); \ + addl %edi, %esi; \ + roll $18, %esi; \ + leal (%ecx, %edx), %edi; \ + roll $7, %edi; \ + xorl %edi, %ebx; \ + movl %ebx, 52(%esp); \ + movl 8(%esp), %edi; \ + xorl %esi, %ebp; \ + leal (%edx, %ebx), %esi; \ + roll $9, %esi; \ + xorl %esi, %edi; \ + movl %edi, 8(%esp); \ + movl 44(%esp), %esi; \ + movl %ebp, 44(%esp); \ + movl 4(%esp), %ebp; \ + addl %edi, %ebx; \ + roll $13, %ebx; \ + xorl %ebx, %ecx; \ + movl 20(%esp), %ebx; \ + movl %ecx, 4(%esp); \ + addl %edi, %ecx; \ + roll $18, %ecx; \ + leal (%esi, %ebp), %edi; \ + roll $7, %edi; \ + xorl %edi, %ebx; \ + movl 36(%esp), %edi; \ + xorl %ecx, %edx; \ + leal (%ebp, %ebx), %ecx; \ + roll $9, %ecx; \ + xorl %ecx, %edi; \ + movl %edi, 20(%esp); \ + movl %ebx, %ecx; \ + movl %edx, 36(%esp); \ + movl 24(%esp), %edx; \ + addl %edi, %ebx; \ + roll $13, %ebx; \ + xorl %ebx, %esi; \ + movl 28(%esp), %ebx; \ + movl %esi, 24(%esp); \ + addl %edi, %esi; \ + roll $18, %esi; \ + leal (%ecx, %edx), %edi; \ + roll $7, %edi; \ + xorl %edi, %ebx; \ + movl %ebx, 28(%esp); \ + xorl %esi, %ebp; \ + movl 8(%esp), %esi; \ + leal (%edx, %ebx), %edi; \ + roll $9, %edi; \ + xorl %edi, %esi; \ + movl 40(%esp), %edi; \ + movl %ebp, 8(%esp); \ + movl 44(%esp), %ebp; \ + movl %esi, 40(%esp); \ + addl %esi, %ebx; \ + roll $13, %ebx; \ + xorl %ebx, %ecx; \ + movl 4(%esp), %ebx; \ + movl %ecx, 44(%esp); \ + addl %esi, %ecx; \ + roll $18, %ecx; \ + leal (%edi, %ebp), %esi; \ + roll $7, %esi; \ + xorl %esi, %ebx; \ + movl %ebx, 4(%esp); \ + movl 20(%esp), %esi; \ + xorl %ecx, %edx; \ + leal (%ebp, %ebx), %ecx; \ + roll $9, %ecx; \ + xorl %ecx, %esi; \ + movl %esi, 56(%esp); \ + movl 48(%esp), %ecx; \ + movl %edx, 20(%esp); \ + movl 36(%esp), %edx; \ + addl %esi, %ebx; \ + roll $13, %ebx; \ + xorl %ebx, %edi; \ + movl 24(%esp), %ebx; \ + movl %edi, 24(%esp); \ + addl %esi, %edi; \ + roll $18, %edi; \ + leal (%ecx, %edx), %esi; \ + roll $7, %esi; \ + xorl %esi, %ebx; \ + movl %ebx, 60(%esp); \ + movl 12(%esp), %esi; \ + xorl %edi, %ebp; \ + leal (%edx, %ebx), %edi; \ + roll $9, %edi; \ + xorl %edi, %esi; \ + movl %esi, 12(%esp); \ + movl 52(%esp), %edi; \ + movl %ebp, 36(%esp); \ + movl 8(%esp), %ebp; \ + addl %esi, %ebx; \ + roll $13, %ebx; \ + xorl %ebx, %ecx; \ + movl 16(%esp), %ebx; \ + movl %ecx, 16(%esp); \ + addl %esi, %ecx; \ + roll $18, %ecx; \ + leal (%edi, %ebp), %esi; \ + roll $7, %esi; \ + xorl %esi, %ebx; \ + movl 32(%esp), %esi; \ + xorl %ecx, %edx; \ + leal (%ebp, %ebx), %ecx; \ + roll $9, %ecx; \ + xorl %ecx, %esi; \ + movl %esi, 32(%esp); \ + movl %ebx, %ecx; \ + movl %edx, 48(%esp); \ + movl 20(%esp), %edx; \ + addl %esi, %ebx; \ + roll $13, %ebx; \ + xorl %ebx, %edi; \ + movl 24(%esp), %ebx; \ + movl %edi, 20(%esp); \ + addl %esi, %edi; \ + roll $18, %edi; \ + leal (%ecx, %edx), %esi; \ + roll $7, %esi; \ + xorl %esi, %ebx; \ + movl %ebx, 8(%esp); \ + movl 12(%esp), %esi; \ + xorl %edi, %ebp; \ + leal (%edx, %ebx), %edi; \ + roll $9, %edi; \ + xorl %edi, %esi; \ + movl %esi, 12(%esp); \ + movl 28(%esp), %edi; \ + movl %ebp, 52(%esp); \ + movl 36(%esp), %ebp; \ + addl %esi, %ebx; \ + roll $13, %ebx; \ + xorl %ebx, %ecx; \ + movl 16(%esp), %ebx; \ + movl %ecx, 16(%esp); \ + addl %esi, %ecx; \ + roll $18, %ecx; \ + leal (%edi, %ebp), %esi; \ + roll $7, %esi; \ + xorl %esi, %ebx; \ + movl %ebx, 28(%esp); \ + movl 32(%esp), %esi; \ + xorl %ecx, %edx; \ + leal (%ebp, %ebx), %ecx; \ + roll $9, %ecx; \ + xorl %ecx, %esi; \ + movl %esi, 32(%esp); \ + movl 4(%esp), %ecx; \ + movl %edx, 4(%esp); \ + movl 48(%esp), %edx; \ + addl %esi, %ebx; \ + roll $13, %ebx; \ + xorl %ebx, %edi; \ + movl 20(%esp), %ebx; \ + movl %edi, 20(%esp); \ + addl %esi, %edi; \ + roll $18, %edi; \ + leal (%ecx, %edx), %esi; \ + roll $7, %esi; \ + xorl %esi, %ebx; \ + movl %ebx, 48(%esp); \ + movl 40(%esp), %esi; \ + xorl %edi, %ebp; \ + leal (%edx, %ebx), %edi; \ + roll $9, %edi; \ + xorl %edi, %esi; \ + movl %esi, 36(%esp); \ + movl 60(%esp), %edi; \ + movl %ebp, 24(%esp); \ + movl 52(%esp), %ebp; \ + addl %esi, %ebx; \ + roll $13, %ebx; \ + xorl %ebx, %ecx; \ + movl 44(%esp), %ebx; \ + movl %ecx, 40(%esp); \ + addl %esi, %ecx; \ + roll $18, %ecx; \ + leal (%edi, %ebp), %esi; \ + roll $7, %esi; \ + xorl %esi, %ebx; \ + movl %ebx, 52(%esp); \ + movl 56(%esp), %esi; \ + xorl %ecx, %edx; \ + leal (%ebp, %ebx), %ecx; \ + roll $9, %ecx; \ + xorl %ecx, %esi; \ + movl %esi, 56(%esp); \ + addl %esi, %ebx; \ + movl %edx, 44(%esp); \ + roll $13, %ebx; \ + xorl %ebx, %edi; \ + movl %edi, 60(%esp); \ + addl %esi, %edi; \ + roll $18, %edi; \ + xorl %edi, %ebp; \ + movl %ebp, 64(%esp); \ + + + .text + .align 32 +gen_salsa8_core: + gen_salsa8_core_quadround() + gen_salsa8_core_quadround() + ret + + + .text + .align 32 + .globl scrypt_core + .globl _scrypt_core +scrypt_core: +_scrypt_core: + pushl %ebx + pushl %ebp + pushl %edi + pushl %esi + + # Check for SSE2 availability + movl $1, %eax + cpuid + andl $0x04000000, %edx + jnz xmm_scrypt_core + +gen_scrypt_core: + movl 20(%esp), %edi + movl 24(%esp), %esi + subl $72, %esp + +#define scrypt_core_macro1a(p, q) \ + movl p(%edi), %eax; \ + movl q(%edi), %edx; \ + movl %eax, p(%esi); \ + movl %edx, q(%esi); \ + xorl %edx, %eax; \ + movl %eax, p(%edi); \ + movl %eax, p(%esp); \ + + +#define scrypt_core_macro1b(p, q) \ + movl p(%edi), %eax; \ + xorl p(%esi, %edx), %eax; \ + movl q(%edi), %ebx; \ + xorl q(%esi, %edx), %ebx; \ + movl %ebx, q(%edi); \ + xorl %ebx, %eax; \ + movl %eax, p(%edi); \ + movl %eax, p(%esp); \ + + +#define scrypt_core_macro2(p, q) \ + movl p(%esp), %eax; \ + addl p(%edi), %eax; \ + movl %eax, p(%edi); \ + xorl q(%edi), %eax; \ + movl %eax, q(%edi); \ + movl %eax, p(%esp); \ + + +#define scrypt_core_macro3(p, q) \ + movl p(%esp), %eax; \ + addl q(%edi), %eax; \ + movl %eax, q(%edi); \ + + + leal 131072(%esi), %ecx +gen_scrypt_core_loop1: + movl %esi, 64(%esp) + movl %ecx, 68(%esp) + + scrypt_core_macro1a(0, 64) + scrypt_core_macro1a(4, 68) + scrypt_core_macro1a(8, 72) + scrypt_core_macro1a(12, 76) + scrypt_core_macro1a(16, 80) + scrypt_core_macro1a(20, 84) + scrypt_core_macro1a(24, 88) + scrypt_core_macro1a(28, 92) + scrypt_core_macro1a(32, 96) + scrypt_core_macro1a(36, 100) + scrypt_core_macro1a(40, 104) + scrypt_core_macro1a(44, 108) + scrypt_core_macro1a(48, 112) + scrypt_core_macro1a(52, 116) + scrypt_core_macro1a(56, 120) + scrypt_core_macro1a(60, 124) + + call gen_salsa8_core + + movl 92(%esp), %edi + scrypt_core_macro2(0, 64) + scrypt_core_macro2(4, 68) + scrypt_core_macro2(8, 72) + scrypt_core_macro2(12, 76) + scrypt_core_macro2(16, 80) + scrypt_core_macro2(20, 84) + scrypt_core_macro2(24, 88) + scrypt_core_macro2(28, 92) + scrypt_core_macro2(32, 96) + scrypt_core_macro2(36, 100) + scrypt_core_macro2(40, 104) + scrypt_core_macro2(44, 108) + scrypt_core_macro2(48, 112) + scrypt_core_macro2(52, 116) + scrypt_core_macro2(56, 120) + scrypt_core_macro2(60, 124) + + call gen_salsa8_core + + movl 92(%esp), %edi + scrypt_core_macro3(0, 64) + scrypt_core_macro3(4, 68) + scrypt_core_macro3(8, 72) + scrypt_core_macro3(12, 76) + scrypt_core_macro3(16, 80) + scrypt_core_macro3(20, 84) + scrypt_core_macro3(24, 88) + scrypt_core_macro3(28, 92) + scrypt_core_macro3(32, 96) + scrypt_core_macro3(36, 100) + scrypt_core_macro3(40, 104) + scrypt_core_macro3(44, 108) + scrypt_core_macro3(48, 112) + scrypt_core_macro3(52, 116) + scrypt_core_macro3(56, 120) + scrypt_core_macro3(60, 124) + + movl 64(%esp), %esi + movl 68(%esp), %ecx + addl $128, %esi + cmpl %ecx, %esi + jne gen_scrypt_core_loop1 + + movl 96(%esp), %esi + movl $1024, %ecx +gen_scrypt_core_loop2: + movl %ecx, 68(%esp) + + movl 64(%edi), %edx + andl $1023, %edx + shll $7, %edx + + scrypt_core_macro1b(0, 64) + scrypt_core_macro1b(4, 68) + scrypt_core_macro1b(8, 72) + scrypt_core_macro1b(12, 76) + scrypt_core_macro1b(16, 80) + scrypt_core_macro1b(20, 84) + scrypt_core_macro1b(24, 88) + scrypt_core_macro1b(28, 92) + scrypt_core_macro1b(32, 96) + scrypt_core_macro1b(36, 100) + scrypt_core_macro1b(40, 104) + scrypt_core_macro1b(44, 108) + scrypt_core_macro1b(48, 112) + scrypt_core_macro1b(52, 116) + scrypt_core_macro1b(56, 120) + scrypt_core_macro1b(60, 124) + + call gen_salsa8_core + + movl 92(%esp), %edi + scrypt_core_macro2(0, 64) + scrypt_core_macro2(4, 68) + scrypt_core_macro2(8, 72) + scrypt_core_macro2(12, 76) + scrypt_core_macro2(16, 80) + scrypt_core_macro2(20, 84) + scrypt_core_macro2(24, 88) + scrypt_core_macro2(28, 92) + scrypt_core_macro2(32, 96) + scrypt_core_macro2(36, 100) + scrypt_core_macro2(40, 104) + scrypt_core_macro2(44, 108) + scrypt_core_macro2(48, 112) + scrypt_core_macro2(52, 116) + scrypt_core_macro2(56, 120) + scrypt_core_macro2(60, 124) + + call gen_salsa8_core + + movl 92(%esp), %edi + movl 96(%esp), %esi + scrypt_core_macro3(0, 64) + scrypt_core_macro3(4, 68) + scrypt_core_macro3(8, 72) + scrypt_core_macro3(12, 76) + scrypt_core_macro3(16, 80) + scrypt_core_macro3(20, 84) + scrypt_core_macro3(24, 88) + scrypt_core_macro3(28, 92) + scrypt_core_macro3(32, 96) + scrypt_core_macro3(36, 100) + scrypt_core_macro3(40, 104) + scrypt_core_macro3(44, 108) + scrypt_core_macro3(48, 112) + scrypt_core_macro3(52, 116) + scrypt_core_macro3(56, 120) + scrypt_core_macro3(60, 124) + + movl 68(%esp), %ecx + subl $1, %ecx + ja gen_scrypt_core_loop2 + + addl $72, %esp + popl %esi + popl %edi + popl %ebp + popl %ebx + ret + + +#define xmm_salsa8_core_doubleround() \ + movdqa %xmm1, %xmm4; \ + paddd %xmm0, %xmm4; \ + movdqa %xmm4, %xmm5; \ + pslld $7, %xmm4; \ + psrld $25, %xmm5; \ + pxor %xmm4, %xmm3; \ + pxor %xmm5, %xmm3; \ + movdqa %xmm0, %xmm4; \ + paddd %xmm3, %xmm4; \ + movdqa %xmm4, %xmm5; \ + pslld $9, %xmm4; \ + psrld $23, %xmm5; \ + pxor %xmm4, %xmm2; \ + movdqa %xmm3, %xmm4; \ + pshufd $0x93, %xmm3, %xmm3; \ + pxor %xmm5, %xmm2; \ + paddd %xmm2, %xmm4; \ + movdqa %xmm4, %xmm5; \ + pslld $13, %xmm4; \ + psrld $19, %xmm5; \ + pxor %xmm4, %xmm1; \ + movdqa %xmm2, %xmm4; \ + pshufd $0x4e, %xmm2, %xmm2; \ + pxor %xmm5, %xmm1; \ + paddd %xmm1, %xmm4; \ + movdqa %xmm4, %xmm5; \ + pslld $18, %xmm4; \ + psrld $14, %xmm5; \ + pxor %xmm4, %xmm0; \ + pshufd $0x39, %xmm1, %xmm1; \ + pxor %xmm5, %xmm0; \ + movdqa %xmm3, %xmm4; \ + paddd %xmm0, %xmm4; \ + movdqa %xmm4, %xmm5; \ + pslld $7, %xmm4; \ + psrld $25, %xmm5; \ + pxor %xmm4, %xmm1; \ + pxor %xmm5, %xmm1; \ + movdqa %xmm0, %xmm4; \ + paddd %xmm1, %xmm4; \ + movdqa %xmm4, %xmm5; \ + pslld $9, %xmm4; \ + psrld $23, %xmm5; \ + pxor %xmm4, %xmm2; \ + movdqa %xmm1, %xmm4; \ + pshufd $0x93, %xmm1, %xmm1; \ + pxor %xmm5, %xmm2; \ + paddd %xmm2, %xmm4; \ + movdqa %xmm4, %xmm5; \ + pslld $13, %xmm4; \ + psrld $19, %xmm5; \ + pxor %xmm4, %xmm3; \ + movdqa %xmm2, %xmm4; \ + pshufd $0x4e, %xmm2, %xmm2; \ + pxor %xmm5, %xmm3; \ + paddd %xmm3, %xmm4; \ + movdqa %xmm4, %xmm5; \ + pslld $18, %xmm4; \ + psrld $14, %xmm5; \ + pxor %xmm4, %xmm0; \ + pshufd $0x39, %xmm3, %xmm3; \ + pxor %xmm5, %xmm0; \ + + +#define xmm_salsa8_core() \ + xmm_salsa8_core_doubleround(); \ + xmm_salsa8_core_doubleround(); \ + xmm_salsa8_core_doubleround(); \ + xmm_salsa8_core_doubleround(); \ + + + .align 32 +xmm_scrypt_core: + movl 20(%esp), %edi + movl 24(%esp), %esi + movl %esp, %ebp + subl $128, %esp + andl $-16, %esp + + # shuffle 1st block to (%esp) + movl 60(%edi), %edx + movl 44(%edi), %ecx + movl 28(%edi), %ebx + movl 12(%edi), %eax + movl %edx, 12(%esp) + movl %ecx, 28(%esp) + movl %ebx, 44(%esp) + movl %eax, 60(%esp) + movl 40(%edi), %ecx + movl 24(%edi), %ebx + movl 8(%edi), %eax + movl 56(%edi), %edx + movl %ecx, 8(%esp) + movl %ebx, 24(%esp) + movl %eax, 40(%esp) + movl %edx, 56(%esp) + movl 20(%edi), %ebx + movl 4(%edi), %eax + movl 52(%edi), %edx + movl 36(%edi), %ecx + movl %ebx, 4(%esp) + movl %eax, 20(%esp) + movl %edx, 36(%esp) + movl %ecx, 52(%esp) + movl 0(%edi), %eax + movl 48(%edi), %edx + movl 32(%edi), %ecx + movl 16(%edi), %ebx + movl %eax, 0(%esp) + movl %edx, 16(%esp) + movl %ecx, 32(%esp) + movl %ebx, 48(%esp) + + # shuffle 2nd block to 64(%esp) + movl 124(%edi), %edx + movl 108(%edi), %ecx + movl 92(%edi), %ebx + movl 76(%edi), %eax + movl %edx, 76(%esp) + movl %ecx, 92(%esp) + movl %ebx, 108(%esp) + movl %eax, 124(%esp) + movl 104(%edi), %ecx + movl 88(%edi), %ebx + movl 72(%edi), %eax + movl 120(%edi), %edx + movl %ecx, 72(%esp) + movl %ebx, 88(%esp) + movl %eax, 104(%esp) + movl %edx, 120(%esp) + movl 84(%edi), %ebx + movl 68(%edi), %eax + movl 116(%edi), %edx + movl 100(%edi), %ecx + movl %ebx, 68(%esp) + movl %eax, 84(%esp) + movl %edx, 100(%esp) + movl %ecx, 116(%esp) + movl 64(%edi), %eax + movl 112(%edi), %edx + movl 96(%edi), %ecx + movl 80(%edi), %ebx + movl %eax, 64(%esp) + movl %edx, 80(%esp) + movl %ecx, 96(%esp) + movl %ebx, 112(%esp) + + movl %esi, %edx + leal 131072(%esi), %ecx +xmm_scrypt_core_loop1: + movdqa 0(%esp), %xmm0 + movdqa 16(%esp), %xmm1 + movdqa 32(%esp), %xmm2 + movdqa 48(%esp), %xmm3 + movdqa 64(%esp), %xmm4 + movdqa 80(%esp), %xmm5 + movdqa 96(%esp), %xmm6 + movdqa 112(%esp), %xmm7 + movdqa %xmm0, 0(%edx) + movdqa %xmm1, 16(%edx) + movdqa %xmm2, 32(%edx) + movdqa %xmm3, 48(%edx) + movdqa %xmm4, 64(%edx) + movdqa %xmm5, 80(%edx) + movdqa %xmm6, 96(%edx) + movdqa %xmm7, 112(%edx) + + pxor %xmm4, %xmm0 + pxor %xmm5, %xmm1 + pxor %xmm6, %xmm2 + pxor %xmm7, %xmm3 + movdqa %xmm0, 0(%esp) + movdqa %xmm1, 16(%esp) + movdqa %xmm2, 32(%esp) + movdqa %xmm3, 48(%esp) + xmm_salsa8_core() + paddd 0(%esp), %xmm0 + paddd 16(%esp), %xmm1 + paddd 32(%esp), %xmm2 + paddd 48(%esp), %xmm3 + movdqa %xmm0, 0(%esp) + movdqa %xmm1, 16(%esp) + movdqa %xmm2, 32(%esp) + movdqa %xmm3, 48(%esp) + + pxor 64(%esp), %xmm0 + pxor 80(%esp), %xmm1 + pxor 96(%esp), %xmm2 + pxor 112(%esp), %xmm3 + movdqa %xmm0, 64(%esp) + movdqa %xmm1, 80(%esp) + movdqa %xmm2, 96(%esp) + movdqa %xmm3, 112(%esp) + xmm_salsa8_core() + paddd 64(%esp), %xmm0 + paddd 80(%esp), %xmm1 + paddd 96(%esp), %xmm2 + paddd 112(%esp), %xmm3 + movdqa %xmm0, 64(%esp) + movdqa %xmm1, 80(%esp) + movdqa %xmm2, 96(%esp) + movdqa %xmm3, 112(%esp) + + addl $128, %edx + cmpl %ecx, %edx + jne xmm_scrypt_core_loop1 + + movl $1024, %ecx +xmm_scrypt_core_loop2: + movdqa 0(%esp), %xmm0 + movdqa 16(%esp), %xmm1 + movdqa 32(%esp), %xmm2 + movdqa 48(%esp), %xmm3 + movdqa 64(%esp), %xmm4 + movdqa 80(%esp), %xmm5 + movdqa 96(%esp), %xmm6 + movdqa 112(%esp), %xmm7 + movd %xmm4, %edx + andl $1023, %edx + shll $7, %edx + pxor 0(%esi, %edx), %xmm0 + pxor 16(%esi, %edx), %xmm1 + pxor 32(%esi, %edx), %xmm2 + pxor 48(%esi, %edx), %xmm3 + pxor 64(%esi, %edx), %xmm4 + pxor 80(%esi, %edx), %xmm5 + pxor 96(%esi, %edx), %xmm6 + pxor 112(%esi, %edx), %xmm7 + movdqa %xmm4, 64(%esp) + movdqa %xmm5, 80(%esp) + movdqa %xmm6, 96(%esp) + movdqa %xmm7, 112(%esp) + + pxor %xmm4, %xmm0 + pxor %xmm5, %xmm1 + pxor %xmm6, %xmm2 + pxor %xmm7, %xmm3 + movdqa %xmm0, 0(%esp) + movdqa %xmm1, 16(%esp) + movdqa %xmm2, 32(%esp) + movdqa %xmm3, 48(%esp) + xmm_salsa8_core() + paddd 0(%esp), %xmm0 + paddd 16(%esp), %xmm1 + paddd 32(%esp), %xmm2 + paddd 48(%esp), %xmm3 + movdqa %xmm0, 0(%esp) + movdqa %xmm1, 16(%esp) + movdqa %xmm2, 32(%esp) + movdqa %xmm3, 48(%esp) + + pxor 64(%esp), %xmm0 + pxor 80(%esp), %xmm1 + pxor 96(%esp), %xmm2 + pxor 112(%esp), %xmm3 + movdqa %xmm0, 64(%esp) + movdqa %xmm1, 80(%esp) + movdqa %xmm2, 96(%esp) + movdqa %xmm3, 112(%esp) + xmm_salsa8_core() + paddd 64(%esp), %xmm0 + paddd 80(%esp), %xmm1 + paddd 96(%esp), %xmm2 + paddd 112(%esp), %xmm3 + movdqa %xmm0, 64(%esp) + movdqa %xmm1, 80(%esp) + movdqa %xmm2, 96(%esp) + movdqa %xmm3, 112(%esp) + + subl $1, %ecx + ja xmm_scrypt_core_loop2 + + # re-shuffle 1st block back + movl 60(%esp), %edx + movl 44(%esp), %ecx + movl 28(%esp), %ebx + movl 12(%esp), %eax + movl %edx, 12(%edi) + movl %ecx, 28(%edi) + movl %ebx, 44(%edi) + movl %eax, 60(%edi) + movl 40(%esp), %ecx + movl 24(%esp), %ebx + movl 8(%esp), %eax + movl 56(%esp), %edx + movl %ecx, 8(%edi) + movl %ebx, 24(%edi) + movl %eax, 40(%edi) + movl %edx, 56(%edi) + movl 20(%esp), %ebx + movl 4(%esp), %eax + movl 52(%esp), %edx + movl 36(%esp), %ecx + movl %ebx, 4(%edi) + movl %eax, 20(%edi) + movl %edx, 36(%edi) + movl %ecx, 52(%edi) + movl 0(%esp), %eax + movl 48(%esp), %edx + movl 32(%esp), %ecx + movl 16(%esp), %ebx + movl %eax, 0(%edi) + movl %edx, 16(%edi) + movl %ecx, 32(%edi) + movl %ebx, 48(%edi) + + # re-shuffle 2nd block back + movl 124(%esp), %edx + movl 108(%esp), %ecx + movl 92(%esp), %ebx + movl 76(%esp), %eax + movl %edx, 76(%edi) + movl %ecx, 92(%edi) + movl %ebx, 108(%edi) + movl %eax, 124(%edi) + movl 104(%esp), %ecx + movl 88(%esp), %ebx + movl 72(%esp), %eax + movl 120(%esp), %edx + movl %ecx, 72(%edi) + movl %ebx, 88(%edi) + movl %eax, 104(%edi) + movl %edx, 120(%edi) + movl 84(%esp), %ebx + movl 68(%esp), %eax + movl 116(%esp), %edx + movl 100(%esp), %ecx + movl %ebx, 68(%edi) + movl %eax, 84(%edi) + movl %edx, 100(%edi) + movl %ecx, 116(%edi) + movl 64(%esp), %eax + movl 112(%esp), %edx + movl 96(%esp), %ecx + movl 80(%esp), %ebx + movl %eax, 64(%edi) + movl %edx, 80(%edi) + movl %ecx, 96(%edi) + movl %ebx, 112(%edi) + + movl %ebp, %esp + popl %esi + popl %edi + popl %ebp + popl %ebx + ret + +#endif diff --git a/src/scrypt-x86_64.S b/src/scrypt-x86_64.S new file mode 100644 index 0000000..3036d03 --- /dev/null +++ b/src/scrypt-x86_64.S @@ -0,0 +1,859 @@ +# Copyright 2011-2012 pooler@litecoinpool.org +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. + + +#if defined(OPTIMIZED_SALSA) && defined(__x86_64__) + +#if defined(__linux__) && defined(__ELF__) + .section .note.GNU-stack,"",%progbits +#endif + +#define scrypt_shuffle(src, so, dest, do) \ + movl so+60(src), %r8d; \ + movl so+44(src), %r9d; \ + movl so+28(src), %r10d; \ + movl so+12(src), %r11d; \ + movl %r8d, do+12(dest); \ + movl %r9d, do+28(dest); \ + movl %r10d, do+44(dest); \ + movl %r11d, do+60(dest); \ + movl so+40(src), %r8d; \ + movl so+8(src), %r9d; \ + movl so+48(src), %r10d; \ + movl so+16(src), %r11d; \ + movl %r8d, do+8(dest); \ + movl %r9d, do+40(dest); \ + movl %r10d, do+16(dest); \ + movl %r11d, do+48(dest); \ + movl so+20(src), %r8d; \ + movl so+4(src), %r9d; \ + movl so+52(src), %r10d; \ + movl so+36(src), %r11d; \ + movl %r8d, do+4(dest); \ + movl %r9d, do+20(dest); \ + movl %r10d, do+36(dest); \ + movl %r11d, do+52(dest); \ + movl so+0(src), %r8d; \ + movl so+24(src), %r9d; \ + movl so+32(src), %r10d; \ + movl so+56(src), %r11d; \ + movl %r8d, do+0(dest); \ + movl %r9d, do+24(dest); \ + movl %r10d, do+32(dest); \ + movl %r11d, do+56(dest); \ + + +#define gen_salsa8_core_doubleround() \ + movq 72(%rsp), %r15; \ + leaq (%r14, %rdx), %rbp; \ + roll $7, %ebp; \ + xorq %rbp, %r9; \ + leaq (%rdi, %r15), %rbp; \ + roll $7, %ebp; \ + xorq %rbp, %r10; \ + leaq (%rdx, %r9), %rbp; \ + roll $9, %ebp; \ + xorq %rbp, %r11; \ + leaq (%r15, %r10), %rbp; \ + roll $9, %ebp; \ + xorq %rbp, %r13; \ + leaq (%r9, %r11), %rbp; \ + roll $13, %ebp; \ + xorq %rbp, %r14; \ + leaq (%r10, %r13), %rbp; \ + roll $13, %ebp; \ + xorq %rbp, %rdi; \ + leaq (%r11, %r14), %rbp; \ + roll $18, %ebp; \ + xorq %rbp, %rdx; \ + leaq (%r13, %rdi), %rbp; \ + roll $18, %ebp; \ + xorq %rbp, %r15; \ + movq 48(%rsp), %rbp; \ + movq %r15, 72(%rsp); \ + leaq (%rax, %rbp), %r15; \ + roll $7, %r15d; \ + xorq %r15, %rbx; \ + leaq (%rbp, %rbx), %r15; \ + roll $9, %r15d; \ + xorq %r15, %rcx; \ + leaq (%rbx, %rcx), %r15; \ + roll $13, %r15d; \ + xorq %r15, %rax; \ + leaq (%rcx, %rax), %r15; \ + roll $18, %r15d; \ + xorq %r15, %rbp; \ + movq 88(%rsp), %r15; \ + movq %rbp, 48(%rsp); \ + leaq (%r12, %r15), %rbp; \ + roll $7, %ebp; \ + xorq %rbp, %rsi; \ + leaq (%r15, %rsi), %rbp; \ + roll $9, %ebp; \ + xorq %rbp, %r8; \ + leaq (%rsi, %r8), %rbp; \ + roll $13, %ebp; \ + xorq %rbp, %r12; \ + leaq (%r8, %r12), %rbp; \ + roll $18, %ebp; \ + xorq %rbp, %r15; \ + movq %r15, 88(%rsp); \ + movq 72(%rsp), %r15; \ + leaq (%rsi, %rdx), %rbp; \ + roll $7, %ebp; \ + xorq %rbp, %rdi; \ + leaq (%r9, %r15), %rbp; \ + roll $7, %ebp; \ + xorq %rbp, %rax; \ + leaq (%rdx, %rdi), %rbp; \ + roll $9, %ebp; \ + xorq %rbp, %rcx; \ + leaq (%r15, %rax), %rbp; \ + roll $9, %ebp; \ + xorq %rbp, %r8; \ + leaq (%rdi, %rcx), %rbp; \ + roll $13, %ebp; \ + xorq %rbp, %rsi; \ + leaq (%rax, %r8), %rbp; \ + roll $13, %ebp; \ + xorq %rbp, %r9; \ + leaq (%rcx, %rsi), %rbp; \ + roll $18, %ebp; \ + xorq %rbp, %rdx; \ + leaq (%r8, %r9), %rbp; \ + roll $18, %ebp; \ + xorq %rbp, %r15; \ + movq 48(%rsp), %rbp; \ + movq %r15, 72(%rsp); \ + leaq (%r10, %rbp), %r15; \ + roll $7, %r15d; \ + xorq %r15, %r12; \ + leaq (%rbp, %r12), %r15; \ + roll $9, %r15d; \ + xorq %r15, %r11; \ + leaq (%r12, %r11), %r15; \ + roll $13, %r15d; \ + xorq %r15, %r10; \ + leaq (%r11, %r10), %r15; \ + roll $18, %r15d; \ + xorq %r15, %rbp; \ + movq 88(%rsp), %r15; \ + movq %rbp, 48(%rsp); \ + leaq (%rbx, %r15), %rbp; \ + roll $7, %ebp; \ + xorq %rbp, %r14; \ + leaq (%r15, %r14), %rbp; \ + roll $9, %ebp; \ + xorq %rbp, %r13; \ + leaq (%r14, %r13), %rbp; \ + roll $13, %ebp; \ + xorq %rbp, %rbx; \ + leaq (%r13, %rbx), %rbp; \ + roll $18, %ebp; \ + xorq %rbp, %r15; \ + movq %r15, 88(%rsp); \ + + + .text + .align 32 +gen_salsa8_core: + # 0: %rdx, %rdi, %rcx, %rsi + movq 8(%rsp), %rdi + movq %rdi, %rdx + shrq $32, %rdi + movq 16(%rsp), %rsi + movq %rsi, %rcx + shrq $32, %rsi + # 1: %r9, 72(%rsp), %rax, %r8 + movq 24(%rsp), %r8 + movq %r8, %r9 + shrq $32, %r8 + movq %r8, 72(%rsp) + movq 32(%rsp), %r8 + movq %r8, %rax + shrq $32, %r8 + # 2: %r11, %r10, 48(%rsp), %r12 + movq 40(%rsp), %r10 + movq %r10, %r11 + shrq $32, %r10 + movq 48(%rsp), %r12 + #movq %r12, %r13 + #movq %r13, 48(%rsp) + shrq $32, %r12 + # 3: %r14, %r13, %rbx, 88(%rsp) + movq 56(%rsp), %r13 + movq %r13, %r14 + shrq $32, %r13 + movq 64(%rsp), %r15 + movq %r15, %rbx + shrq $32, %r15 + movq %r15, 88(%rsp) + + gen_salsa8_core_doubleround() + gen_salsa8_core_doubleround() + gen_salsa8_core_doubleround() + gen_salsa8_core_doubleround() + + movl %edx, %edx + shlq $32, %rdi + addq %rdi, %rdx + movd %rdx, %xmm0 + + movl %ecx, %ecx + shlq $32, %rsi + addq %rsi, %rcx + movd %rcx, %xmm4 + + movq 72(%rsp), %rdi + movl %r9d, %r9d + shlq $32, %rdi + addq %rdi, %r9 + movd %r9, %xmm1 + + movl %eax, %eax + shlq $32, %r8 + addq %r8, %rax + movd %rax, %xmm5 + + movl %r11d, %r11d + shlq $32, %r10 + addq %r10, %r11 + movd %r11, %xmm2 + + movl 48(%rsp), %r8d + shlq $32, %r12 + addq %r12, %r8 + movd %r8, %xmm6 + + movl %r14d, %r14d + shlq $32, %r13 + addq %r13, %r14 + movd %r14, %xmm3 + + movq 88(%rsp), %rdi + movl %ebx, %ebx + shlq $32, %rdi + addq %rdi, %rbx + movd %rbx, %xmm7 + + punpcklqdq %xmm4, %xmm0 + punpcklqdq %xmm5, %xmm1 + punpcklqdq %xmm6, %xmm2 + punpcklqdq %xmm7, %xmm3 + + #movq %rdx, 8(%rsp) + #movq %rcx, 16(%rsp) + #movq %r9, 24(%rsp) + #movq %rax, 32(%rsp) + #movq %r11, 40(%rsp) + #movq %r8, 48(%rsp) + #movq %r14, 56(%rsp) + #movq %rbx, 64(%rsp) + + ret + + + .text + .align 32 + .globl scrypt_core + .globl _scrypt_core +scrypt_core: +_scrypt_core: + pushq %rbx + pushq %rbp + pushq %r12 + pushq %r13 + pushq %r14 + pushq %r15 +#if defined(WIN64) + subq $176, %rsp + movdqa %xmm6, 8(%rsp) + movdqa %xmm7, 24(%rsp) + movdqa %xmm8, 40(%rsp) + movdqa %xmm9, 56(%rsp) + movdqa %xmm10, 72(%rsp) + movdqa %xmm11, 88(%rsp) + movdqa %xmm12, 104(%rsp) + movdqa %xmm13, 120(%rsp) + movdqa %xmm14, 136(%rsp) + movdqa %xmm15, 152(%rsp) + pushq %rdi + pushq %rsi + movq %rcx, %rdi + movq %rdx, %rsi +#endif + +#define scrypt_core_cleanup() \ + popq %r15; \ + popq %r14; \ + popq %r13; \ + popq %r12; \ + popq %rbp; \ + popq %rbx; \ + + + # GenuineIntel processors have fast SIMD + xorl %eax, %eax + cpuid + cmpl $0x6c65746e, %ecx + jne gen_scrypt_core + cmpl $0x49656e69, %edx + jne gen_scrypt_core + cmpl $0x756e6547, %ebx + je xmm_scrypt_core + +gen_scrypt_core: + subq $136, %rsp + movdqa 0(%rdi), %xmm8 + movdqa 16(%rdi), %xmm9 + movdqa 32(%rdi), %xmm10 + movdqa 48(%rdi), %xmm11 + movdqa 64(%rdi), %xmm12 + movdqa 80(%rdi), %xmm13 + movdqa 96(%rdi), %xmm14 + movdqa 112(%rdi), %xmm15 + + leaq 131072(%rsi), %rcx + movq %rdi, 104(%rsp) + movq %rsi, 112(%rsp) + movq %rcx, 120(%rsp) +gen_scrypt_core_loop1: + movdqa %xmm8, 0(%rsi) + movdqa %xmm9, 16(%rsi) + movdqa %xmm10, 32(%rsi) + movdqa %xmm11, 48(%rsi) + movdqa %xmm12, 64(%rsi) + movdqa %xmm13, 80(%rsi) + movdqa %xmm14, 96(%rsi) + movdqa %xmm15, 112(%rsi) + + pxor %xmm12, %xmm8 + pxor %xmm13, %xmm9 + pxor %xmm14, %xmm10 + pxor %xmm15, %xmm11 + movdqa %xmm8, 0(%rsp) + movdqa %xmm9, 16(%rsp) + movdqa %xmm10, 32(%rsp) + movdqa %xmm11, 48(%rsp) + movq %rsi, 128(%rsp) + call gen_salsa8_core + paddd %xmm0, %xmm8 + paddd %xmm1, %xmm9 + paddd %xmm2, %xmm10 + paddd %xmm3, %xmm11 + + pxor %xmm8, %xmm12 + pxor %xmm9, %xmm13 + pxor %xmm10, %xmm14 + pxor %xmm11, %xmm15 + movdqa %xmm12, 0(%rsp) + movdqa %xmm13, 16(%rsp) + movdqa %xmm14, 32(%rsp) + movdqa %xmm15, 48(%rsp) + call gen_salsa8_core + movq 128(%rsp), %rsi + paddd %xmm0, %xmm12 + paddd %xmm1, %xmm13 + paddd %xmm2, %xmm14 + paddd %xmm3, %xmm15 + + addq $128, %rsi + movq 120(%rsp), %rcx + cmpq %rcx, %rsi + jne gen_scrypt_core_loop1 + + movq $1024, %rcx +gen_scrypt_core_loop2: + movq 112(%rsp), %rsi + movd %xmm12, %edx + andl $1023, %edx + shll $7, %edx + movdqa 0(%rsi, %rdx), %xmm0 + movdqa 16(%rsi, %rdx), %xmm1 + movdqa 32(%rsi, %rdx), %xmm2 + movdqa 48(%rsi, %rdx), %xmm3 + movdqa 64(%rsi, %rdx), %xmm4 + movdqa 80(%rsi, %rdx), %xmm5 + movdqa 96(%rsi, %rdx), %xmm6 + movdqa 112(%rsi, %rdx), %xmm7 + pxor %xmm0, %xmm8 + pxor %xmm1, %xmm9 + pxor %xmm2, %xmm10 + pxor %xmm3, %xmm11 + pxor %xmm4, %xmm12 + pxor %xmm5, %xmm13 + pxor %xmm6, %xmm14 + pxor %xmm7, %xmm15 + + pxor %xmm12, %xmm8 + pxor %xmm13, %xmm9 + pxor %xmm14, %xmm10 + pxor %xmm15, %xmm11 + movdqa %xmm8, 0(%rsp) + movdqa %xmm9, 16(%rsp) + movdqa %xmm10, 32(%rsp) + movdqa %xmm11, 48(%rsp) + movq %rcx, 128(%rsp) + call gen_salsa8_core + paddd %xmm0, %xmm8 + paddd %xmm1, %xmm9 + paddd %xmm2, %xmm10 + paddd %xmm3, %xmm11 + + pxor %xmm8, %xmm12 + pxor %xmm9, %xmm13 + pxor %xmm10, %xmm14 + pxor %xmm11, %xmm15 + movdqa %xmm12, 0(%rsp) + movdqa %xmm13, 16(%rsp) + movdqa %xmm14, 32(%rsp) + movdqa %xmm15, 48(%rsp) + call gen_salsa8_core + movq 128(%rsp), %rcx + paddd %xmm0, %xmm12 + paddd %xmm1, %xmm13 + paddd %xmm2, %xmm14 + paddd %xmm3, %xmm15 + + subq $1, %rcx + ja gen_scrypt_core_loop2 + + movq 104(%rsp), %rdi + movdqa %xmm8, 0(%rdi) + movdqa %xmm9, 16(%rdi) + movdqa %xmm10, 32(%rdi) + movdqa %xmm11, 48(%rdi) + movdqa %xmm12, 64(%rdi) + movdqa %xmm13, 80(%rdi) + movdqa %xmm14, 96(%rdi) + movdqa %xmm15, 112(%rdi) + + addq $136, %rsp + scrypt_core_cleanup() + ret + + +#define xmm_salsa8_core_doubleround() \ + movdqa %xmm1, %xmm4; \ + paddd %xmm0, %xmm4; \ + movdqa %xmm4, %xmm5; \ + pslld $7, %xmm4; \ + psrld $25, %xmm5; \ + pxor %xmm4, %xmm3; \ + pxor %xmm5, %xmm3; \ + movdqa %xmm0, %xmm4; \ + paddd %xmm3, %xmm4; \ + movdqa %xmm4, %xmm5; \ + pslld $9, %xmm4; \ + psrld $23, %xmm5; \ + pxor %xmm4, %xmm2; \ + movdqa %xmm3, %xmm4; \ + pshufd $0x93, %xmm3, %xmm3; \ + pxor %xmm5, %xmm2; \ + paddd %xmm2, %xmm4; \ + movdqa %xmm4, %xmm5; \ + pslld $13, %xmm4; \ + psrld $19, %xmm5; \ + pxor %xmm4, %xmm1; \ + movdqa %xmm2, %xmm4; \ + pshufd $0x4e, %xmm2, %xmm2; \ + pxor %xmm5, %xmm1; \ + paddd %xmm1, %xmm4; \ + movdqa %xmm4, %xmm5; \ + pslld $18, %xmm4; \ + psrld $14, %xmm5; \ + pxor %xmm4, %xmm0; \ + pshufd $0x39, %xmm1, %xmm1; \ + pxor %xmm5, %xmm0; \ + movdqa %xmm3, %xmm4; \ + paddd %xmm0, %xmm4; \ + movdqa %xmm4, %xmm5; \ + pslld $7, %xmm4; \ + psrld $25, %xmm5; \ + pxor %xmm4, %xmm1; \ + pxor %xmm5, %xmm1; \ + movdqa %xmm0, %xmm4; \ + paddd %xmm1, %xmm4; \ + movdqa %xmm4, %xmm5; \ + pslld $9, %xmm4; \ + psrld $23, %xmm5; \ + pxor %xmm4, %xmm2; \ + movdqa %xmm1, %xmm4; \ + pshufd $0x93, %xmm1, %xmm1; \ + pxor %xmm5, %xmm2; \ + paddd %xmm2, %xmm4; \ + movdqa %xmm4, %xmm5; \ + pslld $13, %xmm4; \ + psrld $19, %xmm5; \ + pxor %xmm4, %xmm3; \ + movdqa %xmm2, %xmm4; \ + pshufd $0x4e, %xmm2, %xmm2; \ + pxor %xmm5, %xmm3; \ + paddd %xmm3, %xmm4; \ + movdqa %xmm4, %xmm5; \ + pslld $18, %xmm4; \ + psrld $14, %xmm5; \ + pxor %xmm4, %xmm0; \ + pshufd $0x39, %xmm3, %xmm3; \ + pxor %xmm5, %xmm0; \ + + +#define xmm_salsa8_core() \ + xmm_salsa8_core_doubleround(); \ + xmm_salsa8_core_doubleround(); \ + xmm_salsa8_core_doubleround(); \ + xmm_salsa8_core_doubleround(); \ + + + .align 32 +xmm_scrypt_core: + # shuffle 1st block into %xmm8-%xmm11 + movl 60(%rdi), %edx + movl 44(%rdi), %ecx + movl 28(%rdi), %ebx + movl 12(%rdi), %eax + movd %edx, %xmm0 + movd %ecx, %xmm1 + movd %ebx, %xmm2 + movd %eax, %xmm3 + movl 40(%rdi), %ecx + movl 24(%rdi), %ebx + movl 8(%rdi), %eax + movl 56(%rdi), %edx + pshufd $0x93, %xmm0, %xmm0 + pshufd $0x93, %xmm1, %xmm1 + pshufd $0x93, %xmm2, %xmm2 + pshufd $0x93, %xmm3, %xmm3 + movd %ecx, %xmm4 + movd %ebx, %xmm5 + movd %eax, %xmm6 + movd %edx, %xmm7 + paddd %xmm4, %xmm0 + paddd %xmm5, %xmm1 + paddd %xmm6, %xmm2 + paddd %xmm7, %xmm3 + movl 20(%rdi), %ebx + movl 4(%rdi), %eax + movl 52(%rdi), %edx + movl 36(%rdi), %ecx + pshufd $0x93, %xmm0, %xmm0 + pshufd $0x93, %xmm1, %xmm1 + pshufd $0x93, %xmm2, %xmm2 + pshufd $0x93, %xmm3, %xmm3 + movd %ebx, %xmm4 + movd %eax, %xmm5 + movd %edx, %xmm6 + movd %ecx, %xmm7 + paddd %xmm4, %xmm0 + paddd %xmm5, %xmm1 + paddd %xmm6, %xmm2 + paddd %xmm7, %xmm3 + movl 0(%rdi), %eax + movl 48(%rdi), %edx + movl 32(%rdi), %ecx + movl 16(%rdi), %ebx + pshufd $0x93, %xmm0, %xmm0 + pshufd $0x93, %xmm1, %xmm1 + pshufd $0x93, %xmm2, %xmm2 + pshufd $0x93, %xmm3, %xmm3 + movd %eax, %xmm8 + movd %edx, %xmm9 + movd %ecx, %xmm10 + movd %ebx, %xmm11 + paddd %xmm0, %xmm8 + paddd %xmm1, %xmm9 + paddd %xmm2, %xmm10 + paddd %xmm3, %xmm11 + + # shuffle 2nd block into %xmm12-%xmm15 + movl 124(%rdi), %edx + movl 108(%rdi), %ecx + movl 92(%rdi), %ebx + movl 76(%rdi), %eax + movd %edx, %xmm0 + movd %ecx, %xmm1 + movd %ebx, %xmm2 + movd %eax, %xmm3 + movl 104(%rdi), %ecx + movl 88(%rdi), %ebx + movl 72(%rdi), %eax + movl 120(%rdi), %edx + pshufd $0x93, %xmm0, %xmm0 + pshufd $0x93, %xmm1, %xmm1 + pshufd $0x93, %xmm2, %xmm2 + pshufd $0x93, %xmm3, %xmm3 + movd %ecx, %xmm4 + movd %ebx, %xmm5 + movd %eax, %xmm6 + movd %edx, %xmm7 + paddd %xmm4, %xmm0 + paddd %xmm5, %xmm1 + paddd %xmm6, %xmm2 + paddd %xmm7, %xmm3 + movl 84(%rdi), %ebx + movl 68(%rdi), %eax + movl 116(%rdi), %edx + movl 100(%rdi), %ecx + pshufd $0x93, %xmm0, %xmm0 + pshufd $0x93, %xmm1, %xmm1 + pshufd $0x93, %xmm2, %xmm2 + pshufd $0x93, %xmm3, %xmm3 + movd %ebx, %xmm4 + movd %eax, %xmm5 + movd %edx, %xmm6 + movd %ecx, %xmm7 + paddd %xmm4, %xmm0 + paddd %xmm5, %xmm1 + paddd %xmm6, %xmm2 + paddd %xmm7, %xmm3 + movl 64(%rdi), %eax + movl 112(%rdi), %edx + movl 96(%rdi), %ecx + movl 80(%rdi), %ebx + pshufd $0x93, %xmm0, %xmm0 + pshufd $0x93, %xmm1, %xmm1 + pshufd $0x93, %xmm2, %xmm2 + pshufd $0x93, %xmm3, %xmm3 + movd %eax, %xmm12 + movd %edx, %xmm13 + movd %ecx, %xmm14 + movd %ebx, %xmm15 + paddd %xmm0, %xmm12 + paddd %xmm1, %xmm13 + paddd %xmm2, %xmm14 + paddd %xmm3, %xmm15 + + movq %rsi, %rdx + leaq 131072(%rsi), %rcx +xmm_scrypt_core_loop1: + movdqa %xmm8, 0(%rdx) + movdqa %xmm9, 16(%rdx) + movdqa %xmm10, 32(%rdx) + movdqa %xmm11, 48(%rdx) + movdqa %xmm12, 64(%rdx) + movdqa %xmm13, 80(%rdx) + movdqa %xmm14, 96(%rdx) + movdqa %xmm15, 112(%rdx) + + pxor %xmm12, %xmm8 + pxor %xmm13, %xmm9 + pxor %xmm14, %xmm10 + pxor %xmm15, %xmm11 + movdqa %xmm8, %xmm0 + movdqa %xmm9, %xmm1 + movdqa %xmm10, %xmm2 + movdqa %xmm11, %xmm3 + xmm_salsa8_core() + paddd %xmm0, %xmm8 + paddd %xmm1, %xmm9 + paddd %xmm2, %xmm10 + paddd %xmm3, %xmm11 + + pxor %xmm8, %xmm12 + pxor %xmm9, %xmm13 + pxor %xmm10, %xmm14 + pxor %xmm11, %xmm15 + movdqa %xmm12, %xmm0 + movdqa %xmm13, %xmm1 + movdqa %xmm14, %xmm2 + movdqa %xmm15, %xmm3 + xmm_salsa8_core() + paddd %xmm0, %xmm12 + paddd %xmm1, %xmm13 + paddd %xmm2, %xmm14 + paddd %xmm3, %xmm15 + + addq $128, %rdx + cmpq %rcx, %rdx + jne xmm_scrypt_core_loop1 + + movq $1024, %rcx +xmm_scrypt_core_loop2: + movd %xmm12, %edx + andl $1023, %edx + shll $7, %edx + movdqa 0(%rsi, %rdx), %xmm0 + movdqa 16(%rsi, %rdx), %xmm1 + movdqa 32(%rsi, %rdx), %xmm2 + movdqa 48(%rsi, %rdx), %xmm3 + movdqa 64(%rsi, %rdx), %xmm4 + movdqa 80(%rsi, %rdx), %xmm5 + movdqa 96(%rsi, %rdx), %xmm6 + movdqa 112(%rsi, %rdx), %xmm7 + pxor %xmm0, %xmm8 + pxor %xmm1, %xmm9 + pxor %xmm2, %xmm10 + pxor %xmm3, %xmm11 + pxor %xmm4, %xmm12 + pxor %xmm5, %xmm13 + pxor %xmm6, %xmm14 + pxor %xmm7, %xmm15 + + pxor %xmm12, %xmm8 + pxor %xmm13, %xmm9 + pxor %xmm14, %xmm10 + pxor %xmm15, %xmm11 + movdqa %xmm8, %xmm0 + movdqa %xmm9, %xmm1 + movdqa %xmm10, %xmm2 + movdqa %xmm11, %xmm3 + xmm_salsa8_core() + paddd %xmm0, %xmm8 + paddd %xmm1, %xmm9 + paddd %xmm2, %xmm10 + paddd %xmm3, %xmm11 + + pxor %xmm8, %xmm12 + pxor %xmm9, %xmm13 + pxor %xmm10, %xmm14 + pxor %xmm11, %xmm15 + movdqa %xmm12, %xmm0 + movdqa %xmm13, %xmm1 + movdqa %xmm14, %xmm2 + movdqa %xmm15, %xmm3 + xmm_salsa8_core() + paddd %xmm0, %xmm12 + paddd %xmm1, %xmm13 + paddd %xmm2, %xmm14 + paddd %xmm3, %xmm15 + + subq $1, %rcx + ja xmm_scrypt_core_loop2 + + # re-shuffle 1st block back + movd %xmm8, %eax + movd %xmm9, %edx + movd %xmm10, %ecx + movd %xmm11, %ebx + pshufd $0x39, %xmm8, %xmm8 + pshufd $0x39, %xmm9, %xmm9 + pshufd $0x39, %xmm10, %xmm10 + pshufd $0x39, %xmm11, %xmm11 + movl %eax, 0(%rdi) + movl %edx, 48(%rdi) + movl %ecx, 32(%rdi) + movl %ebx, 16(%rdi) + movd %xmm8, %ebx + movd %xmm9, %eax + movd %xmm10, %edx + movd %xmm11, %ecx + pshufd $0x39, %xmm8, %xmm8 + pshufd $0x39, %xmm9, %xmm9 + pshufd $0x39, %xmm10, %xmm10 + pshufd $0x39, %xmm11, %xmm11 + movl %ebx, 20(%rdi) + movl %eax, 4(%rdi) + movl %edx, 52(%rdi) + movl %ecx, 36(%rdi) + movd %xmm8, %ecx + movd %xmm9, %ebx + movd %xmm10, %eax + movd %xmm11, %edx + pshufd $0x39, %xmm8, %xmm8 + pshufd $0x39, %xmm9, %xmm9 + pshufd $0x39, %xmm10, %xmm10 + pshufd $0x39, %xmm11, %xmm11 + movl %ecx, 40(%rdi) + movl %ebx, 24(%rdi) + movl %eax, 8(%rdi) + movl %edx, 56(%rdi) + movd %xmm8, %edx + movd %xmm9, %ecx + movd %xmm10, %ebx + movd %xmm11, %eax + movl %edx, 60(%rdi) + movl %ecx, 44(%rdi) + movl %ebx, 28(%rdi) + movl %eax, 12(%rdi) + + # re-shuffle 2nd block back + movd %xmm12, %eax + movd %xmm13, %edx + movd %xmm14, %ecx + movd %xmm15, %ebx + pshufd $0x39, %xmm12, %xmm12 + pshufd $0x39, %xmm13, %xmm13 + pshufd $0x39, %xmm14, %xmm14 + pshufd $0x39, %xmm15, %xmm15 + movl %eax, 64(%rdi) + movl %edx, 112(%rdi) + movl %ecx, 96(%rdi) + movl %ebx, 80(%rdi) + movd %xmm12, %ebx + movd %xmm13, %eax + movd %xmm14, %edx + movd %xmm15, %ecx + pshufd $0x39, %xmm12, %xmm12 + pshufd $0x39, %xmm13, %xmm13 + pshufd $0x39, %xmm14, %xmm14 + pshufd $0x39, %xmm15, %xmm15 + movl %ebx, 84(%rdi) + movl %eax, 68(%rdi) + movl %edx, 116(%rdi) + movl %ecx, 100(%rdi) + movd %xmm12, %ecx + movd %xmm13, %ebx + movd %xmm14, %eax + movd %xmm15, %edx + pshufd $0x39, %xmm12, %xmm12 + pshufd $0x39, %xmm13, %xmm13 + pshufd $0x39, %xmm14, %xmm14 + pshufd $0x39, %xmm15, %xmm15 + movl %ecx, 104(%rdi) + movl %ebx, 88(%rdi) + movl %eax, 72(%rdi) + movl %edx, 120(%rdi) + movd %xmm12, %edx + movd %xmm13, %ecx + movd %xmm14, %ebx + movd %xmm15, %eax + movl %edx, 124(%rdi) + movl %ecx, 108(%rdi) + movl %ebx, 92(%rdi) + movl %eax, 76(%rdi) + + scrypt_core_cleanup() + ret + + addq $392, %rsp +#if defined(WIN64) + popq %rsi + popq %rdi + movdqa 8(%rsp), %xmm6 + movdqa 24(%rsp), %xmm7 + movdqa 40(%rsp), %xmm8 + movdqa 56(%rsp), %xmm9 + movdqa 72(%rsp), %xmm10 + movdqa 88(%rsp), %xmm11 + movdqa 104(%rsp), %xmm12 + movdqa 120(%rsp), %xmm13 + movdqa 136(%rsp), %xmm14 + movdqa 152(%rsp), %xmm15 + addq $176, %rsp +#endif + popq %rbp + popq %rbx + ret + +#endif \ No newline at end of file diff --git a/src/scrypt.cpp b/src/scrypt.cpp new file mode 100644 index 0000000..06ef53c --- /dev/null +++ b/src/scrypt.cpp @@ -0,0 +1,198 @@ +/*- + * Copyright 2009 Colin Percival, 2011 ArtForz, 2011 pooler, 2013 Balthazar + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file was originally written by Colin Percival as part of the Tarsnap + * online backup system. + */ + +#include +#include + +#include "scrypt.h" +#include "pbkdf2.h" + +#include "util.h" +#include "net.h" + +#define SCRYPT_BUFFER_SIZE (131072 + 63) + +#if defined (OPTIMIZED_SALSA) && ( defined (__x86_64__) || defined (__i386__) || defined(__arm__) ) +extern "C" void scrypt_core(unsigned int *X, unsigned int *V); +#else +// Generic scrypt_core implementation + +static inline void xor_salsa8(unsigned int B[16], const unsigned int Bx[16]) +{ + unsigned int x00,x01,x02,x03,x04,x05,x06,x07,x08,x09,x10,x11,x12,x13,x14,x15; + int i; + + x00 = (B[0] ^= Bx[0]); + x01 = (B[1] ^= Bx[1]); + x02 = (B[2] ^= Bx[2]); + x03 = (B[3] ^= Bx[3]); + x04 = (B[4] ^= Bx[4]); + x05 = (B[5] ^= Bx[5]); + x06 = (B[6] ^= Bx[6]); + x07 = (B[7] ^= Bx[7]); + x08 = (B[8] ^= Bx[8]); + x09 = (B[9] ^= Bx[9]); + x10 = (B[10] ^= Bx[10]); + x11 = (B[11] ^= Bx[11]); + x12 = (B[12] ^= Bx[12]); + x13 = (B[13] ^= Bx[13]); + x14 = (B[14] ^= Bx[14]); + x15 = (B[15] ^= Bx[15]); + for (i = 0; i < 8; i += 2) { +#define R(a, b) (((a) << (b)) | ((a) >> (32 - (b)))) + /* Operate on columns. */ + x04 ^= R(x00+x12, 7); x09 ^= R(x05+x01, 7); + x14 ^= R(x10+x06, 7); x03 ^= R(x15+x11, 7); + + x08 ^= R(x04+x00, 9); x13 ^= R(x09+x05, 9); + x02 ^= R(x14+x10, 9); x07 ^= R(x03+x15, 9); + + x12 ^= R(x08+x04,13); x01 ^= R(x13+x09,13); + x06 ^= R(x02+x14,13); x11 ^= R(x07+x03,13); + + x00 ^= R(x12+x08,18); x05 ^= R(x01+x13,18); + x10 ^= R(x06+x02,18); x15 ^= R(x11+x07,18); + + /* Operate on rows. */ + x01 ^= R(x00+x03, 7); x06 ^= R(x05+x04, 7); + x11 ^= R(x10+x09, 7); x12 ^= R(x15+x14, 7); + + x02 ^= R(x01+x00, 9); x07 ^= R(x06+x05, 9); + x08 ^= R(x11+x10, 9); x13 ^= R(x12+x15, 9); + + x03 ^= R(x02+x01,13); x04 ^= R(x07+x06,13); + x09 ^= R(x08+x11,13); x14 ^= R(x13+x12,13); + + x00 ^= R(x03+x02,18); x05 ^= R(x04+x07,18); + x10 ^= R(x09+x08,18); x15 ^= R(x14+x13,18); +#undef R + } + B[0] += x00; + B[1] += x01; + B[2] += x02; + B[3] += x03; + B[4] += x04; + B[5] += x05; + B[6] += x06; + B[7] += x07; + B[8] += x08; + B[9] += x09; + B[10] += x10; + B[11] += x11; + B[12] += x12; + B[13] += x13; + B[14] += x14; + B[15] += x15; +} + +static inline void scrypt_core(unsigned int *X, unsigned int *V) +{ + unsigned int i, j, k; + + for (i = 0; i < 1024; i++) { + memcpy(&V[i * 32], X, 128); + xor_salsa8(&X[0], &X[16]); + xor_salsa8(&X[16], &X[0]); + } + for (i = 0; i < 1024; i++) { + j = 32 * (X[16] & 1023); + for (k = 0; k < 32; k++) + X[k] ^= V[j + k]; + xor_salsa8(&X[0], &X[16]); + xor_salsa8(&X[16], &X[0]); + } +} + +#endif + +/* cpu and memory intensive function to transform a 80 byte buffer into a 32 byte output + scratchpad size needs to be at least 63 + (128 * r * p) + (256 * r + 64) + (128 * r * N) bytes + r = 1, p = 1, N = 1024 + */ + +uint256 scrypt_nosalt(const void* input, size_t inputlen, void *scratchpad) +{ + unsigned int *V; + unsigned int X[32]; + uint256 result = 0; + V = (unsigned int *)(((uintptr_t)(scratchpad) + 63) & ~ (uintptr_t)(63)); + + PBKDF2_SHA256((const uint8_t*)input, inputlen, (const uint8_t*)input, inputlen, 1, (uint8_t *)X, 128); + scrypt_core(X, V); + PBKDF2_SHA256((const uint8_t*)input, inputlen, (uint8_t *)X, 128, 1, (uint8_t*)&result, 32); + + return result; +} + +uint256 scrypt(const void* data, size_t datalen, const void* salt, size_t saltlen, void *scratchpad) +{ + unsigned int *V; + unsigned int X[32]; + uint256 result = 0; + V = (unsigned int *)(((uintptr_t)(scratchpad) + 63) & ~ (uintptr_t)(63)); + + PBKDF2_SHA256((const uint8_t*)data, datalen, (const uint8_t*)salt, saltlen, 1, (uint8_t *)X, 128); + scrypt_core(X, V); + PBKDF2_SHA256((const uint8_t*)data, datalen, (uint8_t *)X, 128, 1, (uint8_t*)&result, 32); + + return result; +} + +uint256 scrypt_hash(const void* input, size_t inputlen) +{ + unsigned char scratchpad[SCRYPT_BUFFER_SIZE]; + return scrypt_nosalt(input, inputlen, scratchpad); +} + +uint256 scrypt_salted_hash(const void* input, size_t inputlen, const void* salt, size_t saltlen) +{ + unsigned char scratchpad[SCRYPT_BUFFER_SIZE]; + return scrypt(input, inputlen, salt, saltlen, scratchpad); +} + +uint256 scrypt_salted_multiround_hash(const void* input, size_t inputlen, const void* salt, size_t saltlen, const unsigned int nRounds) +{ + uint256 resultHash = scrypt_salted_hash(input, inputlen, salt, saltlen); + uint256 transitionalHash = resultHash; + + for(unsigned int i = 1; i < nRounds; i++) + { + resultHash = scrypt_salted_hash(input, inputlen, (const void*)&transitionalHash, 32); + transitionalHash = resultHash; + } + + return resultHash; +} + +uint256 scrypt_blockhash(const void* input) +{ + unsigned char scratchpad[SCRYPT_BUFFER_SIZE]; + return scrypt_nosalt(input, 80, scratchpad); +} + diff --git a/src/scrypt.h b/src/scrypt.h new file mode 100644 index 0000000..17afd85 --- /dev/null +++ b/src/scrypt.h @@ -0,0 +1,15 @@ +#ifndef SCRYPT_MINE_H +#define SCRYPT_MINE_H + +#include +#include + +#include "util.h" +#include "net.h" + +uint256 scrypt_salted_multiround_hash(const void* input, size_t inputlen, const void* salt, size_t saltlen, const unsigned int nRounds); +uint256 scrypt_salted_hash(const void* input, size_t inputlen, const void* salt, size_t saltlen); +uint256 scrypt_hash(const void* input, size_t inputlen); +uint256 scrypt_blockhash(const void* input); + +#endif // SCRYPT_MINE_H diff --git a/src/serialize.h b/src/serialize.h new file mode 100644 index 0000000..6a53138 --- /dev/null +++ b/src/serialize.h @@ -0,0 +1,1130 @@ +// Copyright (c) 2009-2010 Satoshi Nakamoto +// Copyright (c) 2009-2012 The Bitcoin developers +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifndef BITCOIN_SERIALIZE_H +#define BITCOIN_SERIALIZE_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "allocators.h" +#include "version.h" + +class CAutoFile; +class CDataStream; +class CScript; + +static const unsigned int MAX_SIZE = 0x02000000; + +// Used to bypass the rule against non-const reference to temporary +// where it makes sense with wrappers such as CFlatData or CTxDB +template +inline T& REF(const T& val) +{ + return const_cast(val); +} + +///////////////////////////////////////////////////////////////// +// +// Templates for serializing to anything that looks like a stream, +// i.e. anything that supports .read(char*, int) and .write(char*, int) +// + +enum +{ + // primary actions + SER_NETWORK = (1 << 0), + SER_DISK = (1 << 1), + SER_GETHASH = (1 << 2), + + // modifiers + SER_SKIPSIG = (1 << 16), + SER_BLOCKHEADERONLY = (1 << 17), +}; + +#define IMPLEMENT_SERIALIZE(statements) \ + unsigned int GetSerializeSize(int nType, int nVersion) const \ + { \ + CSerActionGetSerializeSize ser_action; \ + const bool fGetSize = true; \ + const bool fWrite = false; \ + const bool fRead = false; \ + unsigned int nSerSize = 0; \ + ser_streamplaceholder s; \ + assert(fGetSize||fWrite||fRead); /* suppress warning */ \ + s.nType = nType; \ + s.nVersion = nVersion; \ + {statements} \ + return nSerSize; \ + } \ + template \ + void Serialize(Stream& s, int nType, int nVersion) const \ + { \ + CSerActionSerialize ser_action; \ + const bool fGetSize = false; \ + const bool fWrite = true; \ + const bool fRead = false; \ + unsigned int nSerSize = 0; \ + assert(fGetSize||fWrite||fRead); /* suppress warning */ \ + {statements} \ + } \ + template \ + void Unserialize(Stream& s, int nType, int nVersion) \ + { \ + CSerActionUnserialize ser_action; \ + const bool fGetSize = false; \ + const bool fWrite = false; \ + const bool fRead = true; \ + unsigned int nSerSize = 0; \ + assert(fGetSize||fWrite||fRead); /* suppress warning */ \ + {statements} \ + } + +#define READWRITE(obj) (nSerSize += ::SerReadWrite(s, (obj), nType, nVersion, ser_action)) + + + + + + +// +// Basic types +// +#define WRITEDATA(s, obj) s.write((char*)&(obj), sizeof(obj)) +#define READDATA(s, obj) s.read((char*)&(obj), sizeof(obj)) + +inline unsigned int GetSerializeSize(char a, int, int=0) { return sizeof(a); } +inline unsigned int GetSerializeSize(signed char a, int, int=0) { return sizeof(a); } +inline unsigned int GetSerializeSize(unsigned char a, int, int=0) { return sizeof(a); } +inline unsigned int GetSerializeSize(signed short a, int, int=0) { return sizeof(a); } +inline unsigned int GetSerializeSize(unsigned short a, int, int=0) { return sizeof(a); } +inline unsigned int GetSerializeSize(signed int a, int, int=0) { return sizeof(a); } +inline unsigned int GetSerializeSize(unsigned int a, int, int=0) { return sizeof(a); } +inline unsigned int GetSerializeSize(signed long a, int, int=0) { return sizeof(a); } +inline unsigned int GetSerializeSize(unsigned long a, int, int=0) { return sizeof(a); } +inline unsigned int GetSerializeSize(signed long long a, int, int=0) { return sizeof(a); } +inline unsigned int GetSerializeSize(unsigned long long a, int, int=0) { return sizeof(a); } +inline unsigned int GetSerializeSize(float a, int, int=0) { return sizeof(a); } +inline unsigned int GetSerializeSize(double a, int, int=0) { return sizeof(a); } + +template inline void Serialize(Stream& s, char a, int, int=0) { WRITEDATA(s, a); } +template inline void Serialize(Stream& s, signed char a, int, int=0) { WRITEDATA(s, a); } +template inline void Serialize(Stream& s, unsigned char a, int, int=0) { WRITEDATA(s, a); } +template inline void Serialize(Stream& s, signed short a, int, int=0) { WRITEDATA(s, a); } +template inline void Serialize(Stream& s, unsigned short a, int, int=0) { WRITEDATA(s, a); } +template inline void Serialize(Stream& s, signed int a, int, int=0) { WRITEDATA(s, a); } +template inline void Serialize(Stream& s, unsigned int a, int, int=0) { WRITEDATA(s, a); } +template inline void Serialize(Stream& s, signed long a, int, int=0) { WRITEDATA(s, a); } +template inline void Serialize(Stream& s, unsigned long a, int, int=0) { WRITEDATA(s, a); } +template inline void Serialize(Stream& s, signed long long a, int, int=0) { WRITEDATA(s, a); } +template inline void Serialize(Stream& s, unsigned long long a, int, int=0) { WRITEDATA(s, a); } +template inline void Serialize(Stream& s, float a, int, int=0) { WRITEDATA(s, a); } +template inline void Serialize(Stream& s, double a, int, int=0) { WRITEDATA(s, a); } + +template inline void Unserialize(Stream& s, char& a, int, int=0) { READDATA(s, a); } +template inline void Unserialize(Stream& s, signed char& a, int, int=0) { READDATA(s, a); } +template inline void Unserialize(Stream& s, unsigned char& a, int, int=0) { READDATA(s, a); } +template inline void Unserialize(Stream& s, signed short& a, int, int=0) { READDATA(s, a); } +template inline void Unserialize(Stream& s, unsigned short& a, int, int=0) { READDATA(s, a); } +template inline void Unserialize(Stream& s, signed int& a, int, int=0) { READDATA(s, a); } +template inline void Unserialize(Stream& s, unsigned int& a, int, int=0) { READDATA(s, a); } +template inline void Unserialize(Stream& s, signed long& a, int, int=0) { READDATA(s, a); } +template inline void Unserialize(Stream& s, unsigned long& a, int, int=0) { READDATA(s, a); } +template inline void Unserialize(Stream& s, signed long long& a, int, int=0) { READDATA(s, a); } +template inline void Unserialize(Stream& s, unsigned long long& a, int, int=0) { READDATA(s, a); } +template inline void Unserialize(Stream& s, float& a, int, int=0) { READDATA(s, a); } +template inline void Unserialize(Stream& s, double& a, int, int=0) { READDATA(s, a); } + +inline unsigned int GetSerializeSize(bool a, int, int=0) { return sizeof(char); } +template inline void Serialize(Stream& s, bool a, int, int=0) { char f=a; WRITEDATA(s, f); } +template inline void Unserialize(Stream& s, bool& a, int, int=0) { char f; READDATA(s, f); a=f; } + + + + + + +// +// Compact size +// size < 253 -- 1 byte +// size <= USHRT_MAX -- 3 bytes (253 + 2 bytes) +// size <= UINT_MAX -- 5 bytes (254 + 4 bytes) +// size > UINT_MAX -- 9 bytes (255 + 8 bytes) +// +inline unsigned int GetSizeOfCompactSize(uint64_t nSize) +{ + if (nSize < 253) return sizeof(unsigned char); + else if (nSize <= std::numeric_limits::max()) return sizeof(unsigned char) + sizeof(unsigned short); + else if (nSize <= std::numeric_limits::max()) return sizeof(unsigned char) + sizeof(unsigned int); + else return sizeof(unsigned char) + sizeof(uint64_t); +} + +template +void WriteCompactSize(Stream& os, uint64_t nSize) +{ + if (nSize < 253) + { + unsigned char chSize = nSize; + WRITEDATA(os, chSize); + } + else if (nSize <= std::numeric_limits::max()) + { + unsigned char chSize = 253; + unsigned short xSize = nSize; + WRITEDATA(os, chSize); + WRITEDATA(os, xSize); + } + else if (nSize <= std::numeric_limits::max()) + { + unsigned char chSize = 254; + unsigned int xSize = nSize; + WRITEDATA(os, chSize); + WRITEDATA(os, xSize); + } + else + { + unsigned char chSize = 255; + uint64_t xSize = nSize; + WRITEDATA(os, chSize); + WRITEDATA(os, xSize); + } + return; +} + +template +uint64_t ReadCompactSize(Stream& is) +{ + unsigned char chSize; + READDATA(is, chSize); + uint64_t nSizeRet = 0; + if (chSize < 253) + { + nSizeRet = chSize; + } + else if (chSize == 253) + { + unsigned short xSize; + READDATA(is, xSize); + nSizeRet = xSize; + if (nSizeRet < 253) + throw std::ios_base::failure("non-canonical ReadCompactSize()"); + } + else if (chSize == 254) + { + unsigned int xSize; + READDATA(is, xSize); + nSizeRet = xSize; + if (nSizeRet < 0x10000u) + throw std::ios_base::failure("non-canonical ReadCompactSize()"); + } + else + { + uint64_t xSize; + READDATA(is, xSize); + nSizeRet = xSize; + if (nSizeRet < 0x100000000LLu) + throw std::ios_base::failure("non-canonical ReadCompactSize()"); + } + if (nSizeRet > (uint64_t)MAX_SIZE) + throw std::ios_base::failure("ReadCompactSize() : size too large"); + return nSizeRet; +} + + + +#define FLATDATA(obj) REF(CFlatData((char*)&(obj), (char*)&(obj) + sizeof(obj))) + +/** Wrapper for serializing arrays and POD. + */ +class CFlatData +{ +protected: + char* pbegin; + char* pend; +public: + CFlatData(void* pbeginIn, void* pendIn) : pbegin((char*)pbeginIn), pend((char*)pendIn) { } + char* begin() { return pbegin; } + const char* begin() const { return pbegin; } + char* end() { return pend; } + const char* end() const { return pend; } + + unsigned int GetSerializeSize(int, int=0) const + { + return pend - pbegin; + } + + template + void Serialize(Stream& s, int, int=0) const + { + s.write(pbegin, pend - pbegin); + } + + template + void Unserialize(Stream& s, int, int=0) + { + s.read(pbegin, pend - pbegin); + } +}; + +// +// Forward declarations +// + +// string +template unsigned int GetSerializeSize(const std::basic_string& str, int, int=0); +template void Serialize(Stream& os, const std::basic_string& str, int, int=0); +template void Unserialize(Stream& is, std::basic_string& str, int, int=0); + +// vector +template unsigned int GetSerializeSize_impl(const std::vector& v, int nType, int nVersion, const boost::true_type&); +template unsigned int GetSerializeSize_impl(const std::vector& v, int nType, int nVersion, const boost::false_type&); +template inline unsigned int GetSerializeSize(const std::vector& v, int nType, int nVersion); +template void Serialize_impl(Stream& os, const std::vector& v, int nType, int nVersion, const boost::true_type&); +template void Serialize_impl(Stream& os, const std::vector& v, int nType, int nVersion, const boost::false_type&); +template inline void Serialize(Stream& os, const std::vector& v, int nType, int nVersion); +template void Unserialize_impl(Stream& is, std::vector& v, int nType, int nVersion, const boost::true_type&); +template void Unserialize_impl(Stream& is, std::vector& v, int nType, int nVersion, const boost::false_type&); +template inline void Unserialize(Stream& is, std::vector& v, int nType, int nVersion); + +// others derived from vector +extern inline unsigned int GetSerializeSize(const CScript& v, int nType, int nVersion); +template void Serialize(Stream& os, const CScript& v, int nType, int nVersion); +template void Unserialize(Stream& is, CScript& v, int nType, int nVersion); + +// pair +template unsigned int GetSerializeSize(const std::pair& item, int nType, int nVersion); +template void Serialize(Stream& os, const std::pair& item, int nType, int nVersion); +template void Unserialize(Stream& is, std::pair& item, int nType, int nVersion); + +// 3 tuple +template unsigned int GetSerializeSize(const boost::tuple& item, int nType, int nVersion); +template void Serialize(Stream& os, const boost::tuple& item, int nType, int nVersion); +template void Unserialize(Stream& is, boost::tuple& item, int nType, int nVersion); + +// 4 tuple +template unsigned int GetSerializeSize(const boost::tuple& item, int nType, int nVersion); +template void Serialize(Stream& os, const boost::tuple& item, int nType, int nVersion); +template void Unserialize(Stream& is, boost::tuple& item, int nType, int nVersion); + +// map +template unsigned int GetSerializeSize(const std::map& m, int nType, int nVersion); +template void Serialize(Stream& os, const std::map& m, int nType, int nVersion); +template void Unserialize(Stream& is, std::map& m, int nType, int nVersion); + +// set +template unsigned int GetSerializeSize(const std::set& m, int nType, int nVersion); +template void Serialize(Stream& os, const std::set& m, int nType, int nVersion); +template void Unserialize(Stream& is, std::set& m, int nType, int nVersion); + + + + + +// +// If none of the specialized versions above matched, default to calling member function. +// "int nType" is changed to "long nType" to keep from getting an ambiguous overload error. +// The compiler will only cast int to long if none of the other templates matched. +// Thanks to Boost serialization for this idea. +// +template +inline unsigned int GetSerializeSize(const T& a, long nType, int nVersion) +{ + return a.GetSerializeSize((int)nType, nVersion); +} + +template +inline void Serialize(Stream& os, const T& a, long nType, int nVersion) +{ + a.Serialize(os, (int)nType, nVersion); +} + +template +inline void Unserialize(Stream& is, T& a, long nType, int nVersion) +{ + a.Unserialize(is, (int)nType, nVersion); +} + + + + + +// +// string +// +template +unsigned int GetSerializeSize(const std::basic_string& str, int, int) +{ + return GetSizeOfCompactSize(str.size()) + str.size() * sizeof(str[0]); +} + +template +void Serialize(Stream& os, const std::basic_string& str, int, int) +{ + WriteCompactSize(os, str.size()); + if (!str.empty()) + os.write((char*)&str[0], str.size() * sizeof(str[0])); +} + +template +void Unserialize(Stream& is, std::basic_string& str, int, int) +{ + unsigned int nSize = ReadCompactSize(is); + str.resize(nSize); + if (nSize != 0) + is.read((char*)&str[0], nSize * sizeof(str[0])); +} + + + +// +// vector +// +template +unsigned int GetSerializeSize_impl(const std::vector& v, int nType, int nVersion, const boost::true_type&) +{ + return (GetSizeOfCompactSize(v.size()) + v.size() * sizeof(T)); +} + +template +unsigned int GetSerializeSize_impl(const std::vector& v, int nType, int nVersion, const boost::false_type&) +{ + unsigned int nSize = GetSizeOfCompactSize(v.size()); + for (typename std::vector::const_iterator vi = v.begin(); vi != v.end(); ++vi) + nSize += GetSerializeSize((*vi), nType, nVersion); + return nSize; +} + +template +inline unsigned int GetSerializeSize(const std::vector& v, int nType, int nVersion) +{ + return GetSerializeSize_impl(v, nType, nVersion, boost::is_fundamental()); +} + + +template +void Serialize_impl(Stream& os, const std::vector& v, int nType, int nVersion, const boost::true_type&) +{ + WriteCompactSize(os, v.size()); + if (!v.empty()) + os.write((char*)&v[0], v.size() * sizeof(T)); +} + +template +void Serialize_impl(Stream& os, const std::vector& v, int nType, int nVersion, const boost::false_type&) +{ + WriteCompactSize(os, v.size()); + for (typename std::vector::const_iterator vi = v.begin(); vi != v.end(); ++vi) + ::Serialize(os, (*vi), nType, nVersion); +} + +template +inline void Serialize(Stream& os, const std::vector& v, int nType, int nVersion) +{ + Serialize_impl(os, v, nType, nVersion, boost::is_fundamental()); +} + + +template +void Unserialize_impl(Stream& is, std::vector& v, int nType, int nVersion, const boost::true_type&) +{ + // Limit size per read so bogus size value won't cause out of memory + v.clear(); + unsigned int nSize = ReadCompactSize(is); + unsigned int i = 0; + while (i < nSize) + { + unsigned int blk = std::min(nSize - i, (unsigned int)(1 + 4999999 / sizeof(T))); + v.resize(i + blk); + is.read((char*)&v[i], blk * sizeof(T)); + i += blk; + } +} + +template +void Unserialize_impl(Stream& is, std::vector& v, int nType, int nVersion, const boost::false_type&) +{ + v.clear(); + unsigned int nSize = ReadCompactSize(is); + unsigned int i = 0; + unsigned int nMid = 0; + while (nMid < nSize) + { + nMid += 5000000 / sizeof(T); + if (nMid > nSize) + nMid = nSize; + v.resize(nMid); + for (; i < nMid; i++) + Unserialize(is, v[i], nType, nVersion); + } +} + +template +inline void Unserialize(Stream& is, std::vector& v, int nType, int nVersion) +{ + Unserialize_impl(is, v, nType, nVersion, boost::is_fundamental()); +} + + + +// +// others derived from vector +// +inline unsigned int GetSerializeSize(const CScript& v, int nType, int nVersion) +{ + return GetSerializeSize((const std::vector&)v, nType, nVersion); +} + +template +void Serialize(Stream& os, const CScript& v, int nType, int nVersion) +{ + Serialize(os, (const std::vector&)v, nType, nVersion); +} + +template +void Unserialize(Stream& is, CScript& v, int nType, int nVersion) +{ + Unserialize(is, (std::vector&)v, nType, nVersion); +} + + + +// +// pair +// +template +unsigned int GetSerializeSize(const std::pair& item, int nType, int nVersion) +{ + return GetSerializeSize(item.first, nType, nVersion) + GetSerializeSize(item.second, nType, nVersion); +} + +template +void Serialize(Stream& os, const std::pair& item, int nType, int nVersion) +{ + Serialize(os, item.first, nType, nVersion); + Serialize(os, item.second, nType, nVersion); +} + +template +void Unserialize(Stream& is, std::pair& item, int nType, int nVersion) +{ + Unserialize(is, item.first, nType, nVersion); + Unserialize(is, item.second, nType, nVersion); +} + + + +// +// 3 tuple +// +template +unsigned int GetSerializeSize(const boost::tuple& item, int nType, int nVersion) +{ + unsigned int nSize = 0; + nSize += GetSerializeSize(boost::get<0>(item), nType, nVersion); + nSize += GetSerializeSize(boost::get<1>(item), nType, nVersion); + nSize += GetSerializeSize(boost::get<2>(item), nType, nVersion); + return nSize; +} + +template +void Serialize(Stream& os, const boost::tuple& item, int nType, int nVersion) +{ + Serialize(os, boost::get<0>(item), nType, nVersion); + Serialize(os, boost::get<1>(item), nType, nVersion); + Serialize(os, boost::get<2>(item), nType, nVersion); +} + +template +void Unserialize(Stream& is, boost::tuple& item, int nType, int nVersion) +{ + Unserialize(is, boost::get<0>(item), nType, nVersion); + Unserialize(is, boost::get<1>(item), nType, nVersion); + Unserialize(is, boost::get<2>(item), nType, nVersion); +} + + + +// +// 4 tuple +// +template +unsigned int GetSerializeSize(const boost::tuple& item, int nType, int nVersion) +{ + unsigned int nSize = 0; + nSize += GetSerializeSize(boost::get<0>(item), nType, nVersion); + nSize += GetSerializeSize(boost::get<1>(item), nType, nVersion); + nSize += GetSerializeSize(boost::get<2>(item), nType, nVersion); + nSize += GetSerializeSize(boost::get<3>(item), nType, nVersion); + return nSize; +} + +template +void Serialize(Stream& os, const boost::tuple& item, int nType, int nVersion) +{ + Serialize(os, boost::get<0>(item), nType, nVersion); + Serialize(os, boost::get<1>(item), nType, nVersion); + Serialize(os, boost::get<2>(item), nType, nVersion); + Serialize(os, boost::get<3>(item), nType, nVersion); +} + +template +void Unserialize(Stream& is, boost::tuple& item, int nType, int nVersion) +{ + Unserialize(is, boost::get<0>(item), nType, nVersion); + Unserialize(is, boost::get<1>(item), nType, nVersion); + Unserialize(is, boost::get<2>(item), nType, nVersion); + Unserialize(is, boost::get<3>(item), nType, nVersion); +} + + + +// +// map +// +template +unsigned int GetSerializeSize(const std::map& m, int nType, int nVersion) +{ + unsigned int nSize = GetSizeOfCompactSize(m.size()); + for (typename std::map::const_iterator mi = m.begin(); mi != m.end(); ++mi) + nSize += GetSerializeSize((*mi), nType, nVersion); + return nSize; +} + +template +void Serialize(Stream& os, const std::map& m, int nType, int nVersion) +{ + WriteCompactSize(os, m.size()); + for (typename std::map::const_iterator mi = m.begin(); mi != m.end(); ++mi) + Serialize(os, (*mi), nType, nVersion); +} + +template +void Unserialize(Stream& is, std::map& m, int nType, int nVersion) +{ + m.clear(); + unsigned int nSize = ReadCompactSize(is); + typename std::map::iterator mi = m.begin(); + for (unsigned int i = 0; i < nSize; i++) + { + std::pair item; + Unserialize(is, item, nType, nVersion); + mi = m.insert(mi, item); + } +} + + + +// +// set +// +template +unsigned int GetSerializeSize(const std::set& m, int nType, int nVersion) +{ + unsigned int nSize = GetSizeOfCompactSize(m.size()); + for (typename std::set::const_iterator it = m.begin(); it != m.end(); ++it) + nSize += GetSerializeSize((*it), nType, nVersion); + return nSize; +} + +template +void Serialize(Stream& os, const std::set& m, int nType, int nVersion) +{ + WriteCompactSize(os, m.size()); + for (typename std::set::const_iterator it = m.begin(); it != m.end(); ++it) + Serialize(os, (*it), nType, nVersion); +} + +template +void Unserialize(Stream& is, std::set& m, int nType, int nVersion) +{ + m.clear(); + unsigned int nSize = ReadCompactSize(is); + typename std::set::iterator it = m.begin(); + for (unsigned int i = 0; i < nSize; i++) + { + K key; + Unserialize(is, key, nType, nVersion); + it = m.insert(it, key); + } +} + + + +// +// Support for IMPLEMENT_SERIALIZE and READWRITE macro +// +class CSerActionGetSerializeSize { }; +class CSerActionSerialize { }; +class CSerActionUnserialize { }; + +template +inline unsigned int SerReadWrite(Stream& s, const T& obj, int nType, int nVersion, CSerActionGetSerializeSize ser_action) +{ + return ::GetSerializeSize(obj, nType, nVersion); +} + +template +inline unsigned int SerReadWrite(Stream& s, const T& obj, int nType, int nVersion, CSerActionSerialize ser_action) +{ + ::Serialize(s, obj, nType, nVersion); + return 0; +} + +template +inline unsigned int SerReadWrite(Stream& s, T& obj, int nType, int nVersion, CSerActionUnserialize ser_action) +{ + ::Unserialize(s, obj, nType, nVersion); + return 0; +} + +struct ser_streamplaceholder +{ + int nType; + int nVersion; +}; + + + + + + + + + + + +typedef std::vector > CSerializeData; + +/** Double ended buffer combining vector and stream-like interfaces. + * + * >> and << read and write unformatted data using the above serialization templates. + * Fills with data in linear time; some stringstream implementations take N^2 time. + */ +class CDataStream +{ +protected: + typedef CSerializeData vector_type; + vector_type vch; + unsigned int nReadPos; + short state; + short exceptmask; +public: + int nType; + int nVersion; + + typedef vector_type::allocator_type allocator_type; + typedef vector_type::size_type size_type; + typedef vector_type::difference_type difference_type; + typedef vector_type::reference reference; + typedef vector_type::const_reference const_reference; + typedef vector_type::value_type value_type; + typedef vector_type::iterator iterator; + typedef vector_type::const_iterator const_iterator; + typedef vector_type::reverse_iterator reverse_iterator; + + explicit CDataStream(int nTypeIn, int nVersionIn) + { + Init(nTypeIn, nVersionIn); + } + + CDataStream(const_iterator pbegin, const_iterator pend, int nTypeIn, int nVersionIn) : vch(pbegin, pend) + { + Init(nTypeIn, nVersionIn); + } + +#if !defined(_MSC_VER) || _MSC_VER >= 1300 + CDataStream(const char* pbegin, const char* pend, int nTypeIn, int nVersionIn) : vch(pbegin, pend) + { + Init(nTypeIn, nVersionIn); + } +#endif + + CDataStream(const vector_type& vchIn, int nTypeIn, int nVersionIn) : vch(vchIn.begin(), vchIn.end()) + { + Init(nTypeIn, nVersionIn); + } + + CDataStream(const std::vector& vchIn, int nTypeIn, int nVersionIn) : vch(vchIn.begin(), vchIn.end()) + { + Init(nTypeIn, nVersionIn); + } + + CDataStream(const std::vector& vchIn, int nTypeIn, int nVersionIn) : vch((char*)&vchIn.begin()[0], (char*)&vchIn.end()[0]) + { + Init(nTypeIn, nVersionIn); + } + + void Init(int nTypeIn, int nVersionIn) + { + nReadPos = 0; + nType = nTypeIn; + nVersion = nVersionIn; + state = 0; + exceptmask = std::ios::badbit | std::ios::failbit; + } + + CDataStream& operator+=(const CDataStream& b) + { + vch.insert(vch.end(), b.begin(), b.end()); + return *this; + } + + friend CDataStream operator+(const CDataStream& a, const CDataStream& b) + { + CDataStream ret = a; + ret += b; + return (ret); + } + + std::string str() const + { + return (std::string(begin(), end())); + } + + + // + // Vector subset + // + const_iterator begin() const { return vch.begin() + nReadPos; } + iterator begin() { return vch.begin() + nReadPos; } + const_iterator end() const { return vch.end(); } + iterator end() { return vch.end(); } + size_type size() const { return vch.size() - nReadPos; } + bool empty() const { return vch.size() == nReadPos; } + void resize(size_type n, value_type c=0) { vch.resize(n + nReadPos, c); } + void reserve(size_type n) { vch.reserve(n + nReadPos); } + const_reference operator[](size_type pos) const { return vch[pos + nReadPos]; } + reference operator[](size_type pos) { return vch[pos + nReadPos]; } + void clear() { vch.clear(); nReadPos = 0; } + iterator insert(iterator it, const char& x=char()) { return vch.insert(it, x); } + void insert(iterator it, size_type n, const char& x) { vch.insert(it, n, x); } + + void insert(iterator it, std::vector::const_iterator first, std::vector::const_iterator last) + { + assert(last - first >= 0); + if (it == vch.begin() + nReadPos && (unsigned int)(last - first) <= nReadPos) + { + // special case for inserting at the front when there's room + nReadPos -= (last - first); + memcpy(&vch[nReadPos], &first[0], last - first); + } + else + vch.insert(it, first, last); + } + +#if !defined(_MSC_VER) || _MSC_VER >= 1300 + void insert(iterator it, const char* first, const char* last) + { + assert(last - first >= 0); + if (it == vch.begin() + nReadPos && (unsigned int)(last - first) <= nReadPos) + { + // special case for inserting at the front when there's room + nReadPos -= (last - first); + memcpy(&vch[nReadPos], &first[0], last - first); + } + else + vch.insert(it, first, last); + } +#endif + + iterator erase(iterator it) + { + if (it == vch.begin() + nReadPos) + { + // special case for erasing from the front + if (++nReadPos >= vch.size()) + { + // whenever we reach the end, we take the opportunity to clear the buffer + nReadPos = 0; + return vch.erase(vch.begin(), vch.end()); + } + return vch.begin() + nReadPos; + } + else + return vch.erase(it); + } + + iterator erase(iterator first, iterator last) + { + if (first == vch.begin() + nReadPos) + { + // special case for erasing from the front + if (last == vch.end()) + { + nReadPos = 0; + return vch.erase(vch.begin(), vch.end()); + } + else + { + nReadPos = (last - vch.begin()); + return last; + } + } + else + return vch.erase(first, last); + } + + inline void Compact() + { + vch.erase(vch.begin(), vch.begin() + nReadPos); + nReadPos = 0; + } + + bool Rewind(size_type n) + { + // Rewind by n characters if the buffer hasn't been compacted yet + if (n > nReadPos) + return false; + nReadPos -= n; + return true; + } + + + // + // Stream subset + // + void setstate(short bits, const char* psz) + { + state |= bits; + if (state & exceptmask) + throw std::ios_base::failure(psz); + } + + bool eof() const { return size() == 0; } + bool fail() const { return state & (std::ios::badbit | std::ios::failbit); } + bool good() const { return !eof() && (state == 0); } + void clear(short n) { state = n; } // name conflict with vector clear() + short exceptions() { return exceptmask; } + short exceptions(short mask) { short prev = exceptmask; exceptmask = mask; setstate(0, "CDataStream"); return prev; } + CDataStream* rdbuf() { return this; } + int in_avail() { return size(); } + + void SetType(int n) { nType = n; } + int GetType() { return nType; } + void SetVersion(int n) { nVersion = n; } + int GetVersion() { return nVersion; } + void ReadVersion() { *this >> nVersion; } + void WriteVersion() { *this << nVersion; } + + CDataStream& read(char* pch, int nSize) + { + // Read from the beginning of the buffer + assert(nSize >= 0); + unsigned int nReadPosNext = nReadPos + nSize; + if (nReadPosNext >= vch.size()) + { + if (nReadPosNext > vch.size()) + { + setstate(std::ios::failbit, "CDataStream::read() : end of data"); + memset(pch, 0, nSize); + nSize = vch.size() - nReadPos; + } + memcpy(pch, &vch[nReadPos], nSize); + nReadPos = 0; + vch.clear(); + return (*this); + } + memcpy(pch, &vch[nReadPos], nSize); + nReadPos = nReadPosNext; + return (*this); + } + + CDataStream& ignore(int nSize) + { + // Ignore from the beginning of the buffer + assert(nSize >= 0); + unsigned int nReadPosNext = nReadPos + nSize; + if (nReadPosNext >= vch.size()) + { + if (nReadPosNext > vch.size()) + setstate(std::ios::failbit, "CDataStream::ignore() : end of data"); + nReadPos = 0; + vch.clear(); + return (*this); + } + nReadPos = nReadPosNext; + return (*this); + } + + CDataStream& write(const char* pch, int nSize) + { + // Write to the end of the buffer + assert(nSize >= 0); + vch.insert(vch.end(), pch, pch + nSize); + return (*this); + } + + template + void Serialize(Stream& s, int nType, int nVersion) const + { + // Special case: stream << stream concatenates like stream += stream + if (!vch.empty()) + s.write((char*)&vch[0], vch.size() * sizeof(vch[0])); + } + + template + unsigned int GetSerializeSize(const T& obj) + { + // Tells the size of the object if serialized to this stream + return ::GetSerializeSize(obj, nType, nVersion); + } + + template + CDataStream& operator<<(const T& obj) + { + // Serialize to this stream + ::Serialize(*this, obj, nType, nVersion); + return (*this); + } + + template + CDataStream& operator>>(T& obj) + { + // Unserialize from this stream + ::Unserialize(*this, obj, nType, nVersion); + return (*this); + } + + void GetAndClear(CSerializeData &data) { + data.insert(data.end(), begin(), end()); + clear(); + } +}; + + + + + + + + + + +/** RAII wrapper for FILE*. + * + * Will automatically close the file when it goes out of scope if not null. + * If you're returning the file pointer, return file.release(). + * If you need to close the file early, use file.fclose() instead of fclose(file). + */ +class CAutoFile +{ +protected: + FILE* file; + short state; + short exceptmask; +public: + int nType; + int nVersion; + + CAutoFile(FILE* filenew, int nTypeIn, int nVersionIn) + { + file = filenew; + nType = nTypeIn; + nVersion = nVersionIn; + state = 0; + exceptmask = std::ios::badbit | std::ios::failbit; + } + + ~CAutoFile() + { + fclose(); + } + + void fclose() + { + if (file != NULL && file != stdin && file != stdout && file != stderr) + ::fclose(file); + file = NULL; + } + + FILE* release() { FILE* ret = file; file = NULL; return ret; } + operator FILE*() { return file; } + FILE* operator->() { return file; } + FILE& operator*() { return *file; } + FILE** operator&() { return &file; } + FILE* operator=(FILE* pnew) { return file = pnew; } + bool operator!() { return (file == NULL); } + + + // + // Stream subset + // + void setstate(short bits, const char* psz) + { + state |= bits; + if (state & exceptmask) + throw std::ios_base::failure(psz); + } + + bool fail() const { return state & (std::ios::badbit | std::ios::failbit); } + bool good() const { return state == 0; } + void clear(short n = 0) { state = n; } + short exceptions() { return exceptmask; } + short exceptions(short mask) { short prev = exceptmask; exceptmask = mask; setstate(0, "CAutoFile"); return prev; } + + void SetType(int n) { nType = n; } + int GetType() { return nType; } + void SetVersion(int n) { nVersion = n; } + int GetVersion() { return nVersion; } + void ReadVersion() { *this >> nVersion; } + void WriteVersion() { *this << nVersion; } + + CAutoFile& read(char* pch, size_t nSize) + { + if (!file) + throw std::ios_base::failure("CAutoFile::read : file handle is NULL"); + if (fread(pch, 1, nSize, file) != nSize) + setstate(std::ios::failbit, feof(file) ? "CAutoFile::read : end of file" : "CAutoFile::read : fread failed"); + return (*this); + } + + CAutoFile& write(const char* pch, size_t nSize) + { + if (!file) + throw std::ios_base::failure("CAutoFile::write : file handle is NULL"); + if (fwrite(pch, 1, nSize, file) != nSize) + setstate(std::ios::failbit, "CAutoFile::write : write failed"); + return (*this); + } + + template + unsigned int GetSerializeSize(const T& obj) + { + // Tells the size of the object if serialized to this stream + return ::GetSerializeSize(obj, nType, nVersion); + } + + template + CAutoFile& operator<<(const T& obj) + { + // Serialize to this stream + if (!file) + throw std::ios_base::failure("CAutoFile::operator<< : file handle is NULL"); + ::Serialize(*this, obj, nType, nVersion); + return (*this); + } + + template + CAutoFile& operator>>(T& obj) + { + // Unserialize from this stream + if (!file) + throw std::ios_base::failure("CAutoFile::operator>> : file handle is NULL"); + ::Unserialize(*this, obj, nType, nVersion); + return (*this); + } +}; + +#endif diff --git a/src/strlcpy.h b/src/strlcpy.h new file mode 100644 index 0000000..2cc786e --- /dev/null +++ b/src/strlcpy.h @@ -0,0 +1,90 @@ +/* + * Copyright (c) 1998 Todd C. Miller + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +#ifndef BITCOIN_STRLCPY_H +#define BITCOIN_STRLCPY_H + +#include +#include + +/* + * Copy src to string dst of size siz. At most siz-1 characters + * will be copied. Always NUL terminates (unless siz == 0). + * Returns strlen(src); if retval >= siz, truncation occurred. + */ +inline size_t strlcpy(char *dst, const char *src, size_t siz) +{ + char *d = dst; + const char *s = src; + size_t n = siz; + + /* Copy as many bytes as will fit */ + if (n != 0) + { + while (--n != 0) + { + if ((*d++ = *s++) == '\0') + break; + } + } + + /* Not enough room in dst, add NUL and traverse rest of src */ + if (n == 0) + { + if (siz != 0) + *d = '\0'; /* NUL-terminate dst */ + while (*s++) + ; + } + + return(s - src - 1); /* count does not include NUL */ +} + +/* + * Appends src to string dst of size siz (unlike strncat, siz is the + * full size of dst, not space left). At most siz-1 characters + * will be copied. Always NUL terminates (unless siz <= strlen(dst)). + * Returns strlen(src) + MIN(siz, strlen(initial dst)). + * If retval >= siz, truncation occurred. + */ +inline size_t strlcat(char *dst, const char *src, size_t siz) +{ + char *d = dst; + const char *s = src; + size_t n = siz; + size_t dlen; + + /* Find the end of dst and adjust bytes left but don't go past end */ + while (n-- != 0 && *d != '\0') + d++; + dlen = d - dst; + n = siz - dlen; + + if (n == 0) + return(dlen + strlen(s)); + while (*s != '\0') + { + if (n != 1) + { + *d++ = *s; + n--; + } + s++; + } + *d = '\0'; + + return(dlen + (s - src)); /* count does not include NUL */ +} +#endif diff --git a/src/sync.cpp b/src/sync.cpp new file mode 100644 index 0000000..1dfed40 --- /dev/null +++ b/src/sync.cpp @@ -0,0 +1,148 @@ +// Copyright (c) 2011-2012 The Bitcoin developers +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include "sync.h" + +#include "util.h" + +#include + +#ifdef DEBUG_LOCKCONTENTION +void PrintLockContention(const char* pszName, const char* pszFile, int nLine) +{ + printf("LOCKCONTENTION: %s\n", pszName); + printf("Locker: %s:%d\n", pszFile, nLine); +} +#endif /* DEBUG_LOCKCONTENTION */ + +#ifdef DEBUG_LOCKORDER +// +// Early deadlock detection. +// Problem being solved: +// Thread 1 locks A, then B, then C +// Thread 2 locks D, then C, then A +// --> may result in deadlock between the two threads, depending on when they run. +// Solution implemented here: +// Keep track of pairs of locks: (A before B), (A before C), etc. +// Complain if any thread tries to lock in a different order. +// + +struct CLockLocation +{ + CLockLocation(const char* pszName, const char* pszFile, int nLine) + { + mutexName = pszName; + sourceFile = pszFile; + sourceLine = nLine; + } + + std::string ToString() const + { + return mutexName+" "+sourceFile+":"+itostr(sourceLine); + } + + std::string MutexName() const { return mutexName; } + +private: + std::string mutexName; + std::string sourceFile; + int sourceLine; +}; + +typedef std::vector< std::pair > LockStack; + +static boost::mutex dd_mutex; +static std::map, LockStack> lockorders; +static boost::thread_specific_ptr lockstack; + + +static void potential_deadlock_detected(const std::pair& mismatch, const LockStack& s1, const LockStack& s2) +{ + printf("POTENTIAL DEADLOCK DETECTED\n"); + printf("Previous lock order was:\n"); + BOOST_FOREACH(const PAIRTYPE(void*, CLockLocation)& i, s2) + { + if (i.first == mismatch.first) printf(" (1)"); + if (i.first == mismatch.second) printf(" (2)"); + printf(" %s\n", i.second.ToString().c_str()); + } + printf("Current lock order is:\n"); + BOOST_FOREACH(const PAIRTYPE(void*, CLockLocation)& i, s1) + { + if (i.first == mismatch.first) printf(" (1)"); + if (i.first == mismatch.second) printf(" (2)"); + printf(" %s\n", i.second.ToString().c_str()); + } +} + +static void push_lock(void* c, const CLockLocation& locklocation, bool fTry) +{ + if (lockstack.get() == NULL) + lockstack.reset(new LockStack); + + if (fDebug) printf("Locking: %s\n", locklocation.ToString().c_str()); + dd_mutex.lock(); + + (*lockstack).push_back(std::make_pair(c, locklocation)); + + if (!fTry) { + BOOST_FOREACH(const PAIRTYPE(void*, CLockLocation)& i, (*lockstack)) { + if (i.first == c) break; + + std::pair p1 = std::make_pair(i.first, c); + if (lockorders.count(p1)) + continue; + lockorders[p1] = (*lockstack); + + std::pair p2 = std::make_pair(c, i.first); + if (lockorders.count(p2)) + { + potential_deadlock_detected(p1, lockorders[p2], lockorders[p1]); + break; + } + } + } + dd_mutex.unlock(); +} + +static void pop_lock() +{ + if (fDebug) + { + const CLockLocation& locklocation = (*lockstack).rbegin()->second; + printf("Unlocked: %s\n", locklocation.ToString().c_str()); + } + dd_mutex.lock(); + (*lockstack).pop_back(); + dd_mutex.unlock(); +} + +void EnterCritical(const char* pszName, const char* pszFile, int nLine, void* cs, bool fTry) +{ + push_lock(cs, CLockLocation(pszName, pszFile, nLine), fTry); +} + +void LeaveCritical() +{ + pop_lock(); +} + +std::string LocksHeld() +{ + std::string result; + BOOST_FOREACH(const PAIRTYPE(void*, CLockLocation)&i, *lockstack) + result += i.second.ToString() + std::string("\n"); + return result; +} + +void AssertLockHeldInternal(const char *pszName, const char* pszFile, int nLine, void *cs) +{ + BOOST_FOREACH(const PAIRTYPE(void*, CLockLocation)&i, *lockstack) + if (i.first == cs) return; + fprintf(stderr, "Assertion failed: lock %s not held in %s:%i; locks held:\n%s", + pszName, pszFile, nLine, LocksHeld().c_str()); + abort(); +} + +#endif /* DEBUG_LOCKORDER */ diff --git a/src/sync.h b/src/sync.h new file mode 100644 index 0000000..928b12c --- /dev/null +++ b/src/sync.h @@ -0,0 +1,261 @@ +// Copyright (c) 2009-2010 Satoshi Nakamoto +// Copyright (c) 2009-2012 The Bitcoin developers +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifndef BITCOIN_SYNC_H +#define BITCOIN_SYNC_H + +#include "threadsafety.h" + +#include +#include +#include +#include + + +//////////////////////////////////////////////// +// // +// THE SIMPLE DEFINITON, EXCLUDING DEBUG CODE // +// // +//////////////////////////////////////////////// + +/* + + + +CCriticalSection mutex; + boost::recursive_mutex mutex; + +LOCK(mutex); + boost::unique_lock criticalblock(mutex); + +LOCK2(mutex1, mutex2); + boost::unique_lock criticalblock1(mutex1); + boost::unique_lock criticalblock2(mutex2); + +TRY_LOCK(mutex, name); + boost::unique_lock name(mutex, boost::try_to_lock_t); + +ENTER_CRITICAL_SECTION(mutex); // no RAII + mutex.lock(); + +LEAVE_CRITICAL_SECTION(mutex); // no RAII + mutex.unlock(); + + + + */ + + + +/////////////////////////////// +// // +// THE ACTUAL IMPLEMENTATION // +// // +/////////////////////////////// + +// Template mixin that adds -Wthread-safety locking annotations to a +// subset of the mutex API. +template +class LOCKABLE AnnotatedMixin : public PARENT +{ +public: + void lock() EXCLUSIVE_LOCK_FUNCTION() + { + PARENT::lock(); + } + + void unlock() UNLOCK_FUNCTION() + { + PARENT::unlock(); + } + + bool try_lock() EXCLUSIVE_TRYLOCK_FUNCTION(true) + { + return PARENT::try_lock(); + } +}; + +/** Wrapped boost mutex: supports recursive locking, but no waiting */ +// TODO: We should move away from using the recursive lock by default. +typedef AnnotatedMixin CCriticalSection; + +/** Wrapped boost mutex: supports waiting but not recursive locking */ +typedef AnnotatedMixin CWaitableCriticalSection; + +#ifdef DEBUG_LOCKORDER +void EnterCritical(const char* pszName, const char* pszFile, int nLine, void* cs, bool fTry = false); +void LeaveCritical(); +std::string LocksHeld(); +void AssertLockHeldInternal(const char* pszName, const char* pszFile, int nLine, void *cs); +#else +void static inline EnterCritical(const char* pszName, const char* pszFile, int nLine, void* cs, bool fTry = false) {} +void static inline LeaveCritical() {} +void static inline AssertLockHeldInternal(const char* pszName, const char* pszFile, int nLine, void *cs) {} +#endif +#define AssertLockHeld(cs) AssertLockHeldInternal(#cs, __FILE__, __LINE__, &cs) + +#ifdef DEBUG_LOCKCONTENTION +void PrintLockContention(const char* pszName, const char* pszFile, int nLine); +#endif + +/** Wrapper around boost::unique_lock */ +template +class CMutexLock +{ +private: + boost::unique_lock lock; + + void Enter(const char* pszName, const char* pszFile, int nLine) + { + EnterCritical(pszName, pszFile, nLine, (void*)(lock.mutex())); +#ifdef DEBUG_LOCKCONTENTION + if (!lock.try_lock()) + { + PrintLockContention(pszName, pszFile, nLine); +#endif + lock.lock(); +#ifdef DEBUG_LOCKCONTENTION + } +#endif + } + + bool TryEnter(const char* pszName, const char* pszFile, int nLine) + { + EnterCritical(pszName, pszFile, nLine, (void*)(lock.mutex()), true); + lock.try_lock(); + if (!lock.owns_lock()) + LeaveCritical(); + return lock.owns_lock(); + } + +public: + CMutexLock(Mutex& mutexIn, const char* pszName, const char* pszFile, int nLine, bool fTry = false) : lock(mutexIn, boost::defer_lock) + { + if (fTry) + TryEnter(pszName, pszFile, nLine); + else + Enter(pszName, pszFile, nLine); + } + + ~CMutexLock() + { + if (lock.owns_lock()) + LeaveCritical(); + } + + operator bool() + { + return lock.owns_lock(); + } +}; + +typedef CMutexLock CCriticalBlock; + +#define LOCK(cs) CCriticalBlock criticalblock(cs, #cs, __FILE__, __LINE__) +#define LOCK2(cs1,cs2) CCriticalBlock criticalblock1(cs1, #cs1, __FILE__, __LINE__),criticalblock2(cs2, #cs2, __FILE__, __LINE__) +#define TRY_LOCK(cs,name) CCriticalBlock name(cs, #cs, __FILE__, __LINE__, true) + +#define ENTER_CRITICAL_SECTION(cs) \ + { \ + EnterCritical(#cs, __FILE__, __LINE__, (void*)(&cs)); \ + (cs).lock(); \ + } + +#define LEAVE_CRITICAL_SECTION(cs) \ + { \ + (cs).unlock(); \ + LeaveCritical(); \ + } + +class CSemaphore +{ +private: + boost::condition_variable condition; + boost::mutex mutex; + int value; + +public: + CSemaphore(int init) : value(init) {} + + void wait() { + boost::unique_lock lock(mutex); + while (value < 1) { + condition.wait(lock); + } + value--; + } + + bool try_wait() { + boost::unique_lock lock(mutex); + if (value < 1) + return false; + value--; + return true; + } + + void post() { + { + boost::unique_lock lock(mutex); + value++; + } + condition.notify_one(); + } +}; + +/** RAII-style semaphore lock */ +class CSemaphoreGrant +{ +private: + CSemaphore *sem; + bool fHaveGrant; + +public: + void Acquire() { + if (fHaveGrant) + return; + sem->wait(); + fHaveGrant = true; + } + + void Release() { + if (!fHaveGrant) + return; + sem->post(); + fHaveGrant = false; + } + + bool TryAcquire() { + if (!fHaveGrant && sem->try_wait()) + fHaveGrant = true; + return fHaveGrant; + } + + void MoveTo(CSemaphoreGrant &grant) { + grant.Release(); + grant.sem = sem; + grant.fHaveGrant = fHaveGrant; + sem = NULL; + fHaveGrant = false; + } + + CSemaphoreGrant() : sem(NULL), fHaveGrant(false) {} + + CSemaphoreGrant(CSemaphore &sema, bool fTry = false) : sem(&sema), fHaveGrant(false) { + if (fTry) + TryAcquire(); + else + Acquire(); + } + + ~CSemaphoreGrant() { + Release(); + } + + operator bool() { + return fHaveGrant; + } +}; +#endif + diff --git a/src/test/Checkpoints_tests.cpp b/src/test/Checkpoints_tests.cpp new file mode 100644 index 0000000..b14e9f7 --- /dev/null +++ b/src/test/Checkpoints_tests.cpp @@ -0,0 +1,34 @@ +// +// Unit tests for block-chain checkpoints +// +#include // for 'map_list_of()' +#include +#include + +#include "../checkpoints.h" +#include "../util.h" + +using namespace std; + +BOOST_AUTO_TEST_SUITE(Checkpoints_tests) + +BOOST_AUTO_TEST_CASE(sanity) +{ + uint256 p11111 = uint256("0x0000000069e244f73d78e8fd29ba2fd2ed618bd6fa2ee92559f542fdb26e7c1d"); + uint256 p134444 = uint256("0x00000000000005b12ffd4cd315cd34ffd4a594f430ac814c91184a0d42d2b0fe"); + BOOST_CHECK(Checkpoints::CheckBlock(11111, p11111)); + BOOST_CHECK(Checkpoints::CheckBlock(134444, p134444)); + + + // Wrong hashes at checkpoints should fail: + BOOST_CHECK(!Checkpoints::CheckBlock(11111, p134444)); + BOOST_CHECK(!Checkpoints::CheckBlock(134444, p11111)); + + // ... but any hash not at a checkpoint should succeed: + BOOST_CHECK(Checkpoints::CheckBlock(11111+1, p134444)); + BOOST_CHECK(Checkpoints::CheckBlock(134444+1, p11111)); + + BOOST_CHECK(Checkpoints::GetTotalBlocksEstimate() >= 134444); +} + +BOOST_AUTO_TEST_SUITE_END() diff --git a/src/test/DoS_tests.cpp b/src/test/DoS_tests.cpp new file mode 100644 index 0000000..7f08dd5 --- /dev/null +++ b/src/test/DoS_tests.cpp @@ -0,0 +1,314 @@ +// +// Unit tests for denial-of-service detection/prevention code +// +#include + +#include // for 'map_list_of()' +#include +#include +#include + +#include "main.h" +#include "wallet.h" +#include "net.h" +#include "util.h" + +#include + +// Tests this internal-to-main.cpp method: +extern bool AddOrphanTx(const CDataStream& vMsg); +extern unsigned int LimitOrphanTxSize(unsigned int nMaxOrphans); +extern std::map mapOrphanTransactions; +extern std::map > mapOrphanTransactionsByPrev; + +CService ip(uint32_t i) +{ + struct in_addr s; + s.s_addr = i; + return CService(CNetAddr(s), GetDefaultPort()); +} + +BOOST_AUTO_TEST_SUITE(DoS_tests) + +BOOST_AUTO_TEST_CASE(DoS_banning) +{ + CNode::ClearBanned(); + CAddress addr1(ip(0xa0b0c001)); + CNode dummyNode1(INVALID_SOCKET, addr1, "", true); + dummyNode1.Misbehaving(100); // Should get banned + BOOST_CHECK(CNode::IsBanned(addr1)); + BOOST_CHECK(!CNode::IsBanned(ip(0xa0b0c001|0x0000ff00))); // Different IP, not banned + + CAddress addr2(ip(0xa0b0c002)); + CNode dummyNode2(INVALID_SOCKET, addr2, "", true); + dummyNode2.Misbehaving(50); + BOOST_CHECK(!CNode::IsBanned(addr2)); // 2 not banned yet... + BOOST_CHECK(CNode::IsBanned(addr1)); // ... but 1 still should be + dummyNode2.Misbehaving(50); + BOOST_CHECK(CNode::IsBanned(addr2)); +} + +BOOST_AUTO_TEST_CASE(DoS_banscore) +{ + CNode::ClearBanned(); + mapArgs["-banscore"] = "111"; // because 11 is my favorite number + CAddress addr1(ip(0xa0b0c001)); + CNode dummyNode1(INVALID_SOCKET, addr1, "", true); + dummyNode1.Misbehaving(100); + BOOST_CHECK(!CNode::IsBanned(addr1)); + dummyNode1.Misbehaving(10); + BOOST_CHECK(!CNode::IsBanned(addr1)); + dummyNode1.Misbehaving(1); + BOOST_CHECK(CNode::IsBanned(addr1)); + mapArgs.erase("-banscore"); +} + +BOOST_AUTO_TEST_CASE(DoS_bantime) +{ + CNode::ClearBanned(); + int64 nStartTime = GetTime(); + SetMockTime(nStartTime); // Overrides future calls to GetTime() + + CAddress addr(ip(0xa0b0c001)); + CNode dummyNode(INVALID_SOCKET, addr, "", true); + + dummyNode.Misbehaving(100); + BOOST_CHECK(CNode::IsBanned(addr)); + + SetMockTime(nStartTime+60*60); + BOOST_CHECK(CNode::IsBanned(addr)); + + SetMockTime(nStartTime+60*60*24+1); + BOOST_CHECK(!CNode::IsBanned(addr)); +} + +static bool CheckNBits(unsigned int nbits1, int64 time1, unsigned int nbits2, int64 time2)\ +{ + if (time1 > time2) + return CheckNBits(nbits2, time2, nbits1, time1); + int64 deltaTime = time2-time1; + + CBigNum required; + required.SetCompact(ComputeMinWork(nbits1, deltaTime)); + CBigNum have; + have.SetCompact(nbits2); + return (have <= required); +} + +BOOST_AUTO_TEST_CASE(DoS_checknbits) +{ + using namespace boost::assign; // for 'map_list_of()' + + // Timestamps,nBits from the bitcoin blockchain. + // These are the block-chain checkpoint blocks + typedef std::map BlockData; + BlockData chainData = + map_list_of(1239852051,486604799)(1262749024,486594666) + (1279305360,469854461)(1280200847,469830746)(1281678674,469809688) + (1296207707,453179945)(1302624061,453036989)(1309640330,437004818) + (1313172719,436789733); + + // Make sure CheckNBits considers every combination of block-chain-lock-in-points + // "sane": + BOOST_FOREACH(const BlockData::value_type& i, chainData) + { + BOOST_FOREACH(const BlockData::value_type& j, chainData) + { + BOOST_CHECK(CheckNBits(i.second, i.first, j.second, j.first)); + } + } + + // Test a couple of insane combinations: + BlockData::value_type firstcheck = *(chainData.begin()); + BlockData::value_type lastcheck = *(chainData.rbegin()); + + // First checkpoint difficulty at or a while after the last checkpoint time should fail when + // compared to last checkpoint + BOOST_CHECK(!CheckNBits(firstcheck.second, lastcheck.first+60*10, lastcheck.second, lastcheck.first)); + BOOST_CHECK(!CheckNBits(firstcheck.second, lastcheck.first+60*60*24*14, lastcheck.second, lastcheck.first)); + + // ... but OK if enough time passed for difficulty to adjust downward: + BOOST_CHECK(CheckNBits(firstcheck.second, lastcheck.first+60*60*24*365*4, lastcheck.second, lastcheck.first)); + +} + +CTransaction RandomOrphan() +{ + std::map::iterator it; + it = mapOrphanTransactions.lower_bound(GetRandHash()); + if (it == mapOrphanTransactions.end()) + it = mapOrphanTransactions.begin(); + const CDataStream* pvMsg = it->second; + CTransaction tx; + CDataStream(*pvMsg) >> tx; + return tx; +} + +BOOST_AUTO_TEST_CASE(DoS_mapOrphans) +{ + CKey key; + key.MakeNewKey(true); + CBasicKeyStore keystore; + keystore.AddKey(key); + + // 50 orphan transactions: + for (int i = 0; i < 50; i++) + { + CTransaction tx; + tx.vin.resize(1); + tx.vin[0].prevout.n = 0; + tx.vin[0].prevout.hash = GetRandHash(); + tx.vin[0].scriptSig << OP_1; + tx.vout.resize(1); + tx.vout[0].nValue = 1*CENT; + tx.vout[0].scriptPubKey.SetDestination(key.GetPubKey().GetID()); + + CDataStream ds(SER_DISK, CLIENT_VERSION); + ds << tx; + AddOrphanTx(ds); + } + + // ... and 50 that depend on other orphans: + for (int i = 0; i < 50; i++) + { + CTransaction txPrev = RandomOrphan(); + + CTransaction tx; + tx.vin.resize(1); + tx.vin[0].prevout.n = 0; + tx.vin[0].prevout.hash = txPrev.GetHash(); + tx.vout.resize(1); + tx.vout[0].nValue = 1*CENT; + tx.vout[0].scriptPubKey.SetDestination(key.GetPubKey().GetID()); + SignSignature(keystore, txPrev, tx, 0); + + CDataStream ds(SER_DISK, CLIENT_VERSION); + ds << tx; + AddOrphanTx(ds); + } + + // This really-big orphan should be ignored: + for (int i = 0; i < 10; i++) + { + CTransaction txPrev = RandomOrphan(); + + CTransaction tx; + tx.vout.resize(1); + tx.vout[0].nValue = 1*CENT; + tx.vout[0].scriptPubKey.SetDestination(key.GetPubKey().GetID()); + tx.vin.resize(500); + for (unsigned int j = 0; j < tx.vin.size(); j++) + { + tx.vin[j].prevout.n = j; + tx.vin[j].prevout.hash = txPrev.GetHash(); + } + SignSignature(keystore, txPrev, tx, 0); + // Re-use same signature for other inputs + // (they don't have to be valid for this test) + for (unsigned int j = 1; j < tx.vin.size(); j++) + tx.vin[j].scriptSig = tx.vin[0].scriptSig; + + CDataStream ds(SER_DISK, CLIENT_VERSION); + ds << tx; + BOOST_CHECK(!AddOrphanTx(ds)); + } + + // Test LimitOrphanTxSize() function: + LimitOrphanTxSize(40); + BOOST_CHECK(mapOrphanTransactions.size() <= 40); + LimitOrphanTxSize(10); + BOOST_CHECK(mapOrphanTransactions.size() <= 10); + LimitOrphanTxSize(0); + BOOST_CHECK(mapOrphanTransactions.empty()); + BOOST_CHECK(mapOrphanTransactionsByPrev.empty()); +} + +BOOST_AUTO_TEST_CASE(DoS_checkSig) +{ + // Test signature caching code (see key.cpp Verify() methods) + + CKey key; + key.MakeNewKey(true); + CBasicKeyStore keystore; + keystore.AddKey(key); + + // 100 orphan transactions: + static const int NPREV=100; + CTransaction orphans[NPREV]; + for (int i = 0; i < NPREV; i++) + { + CTransaction& tx = orphans[i]; + tx.vin.resize(1); + tx.vin[0].prevout.n = 0; + tx.vin[0].prevout.hash = GetRandHash(); + tx.vin[0].scriptSig << OP_1; + tx.vout.resize(1); + tx.vout[0].nValue = 1*CENT; + tx.vout[0].scriptPubKey.SetDestination(key.GetPubKey().GetID()); + + CDataStream ds(SER_DISK, CLIENT_VERSION); + ds << tx; + AddOrphanTx(ds); + } + + // Create a transaction that depends on orphans: + CTransaction tx; + tx.vout.resize(1); + tx.vout[0].nValue = 1*CENT; + tx.vout[0].scriptPubKey.SetDestination(key.GetPubKey().GetID()); + tx.vin.resize(NPREV); + for (unsigned int j = 0; j < tx.vin.size(); j++) + { + tx.vin[j].prevout.n = 0; + tx.vin[j].prevout.hash = orphans[j].GetHash(); + } + // Creating signatures primes the cache: + boost::posix_time::ptime mst1 = boost::posix_time::microsec_clock::local_time(); + for (unsigned int j = 0; j < tx.vin.size(); j++) + BOOST_CHECK(SignSignature(keystore, orphans[j], tx, j)); + boost::posix_time::ptime mst2 = boost::posix_time::microsec_clock::local_time(); + boost::posix_time::time_duration msdiff = mst2 - mst1; + long nOneValidate = msdiff.total_milliseconds(); + if (fDebug) printf("DoS_Checksig sign: %ld\n", nOneValidate); + + // ... now validating repeatedly should be quick: + // 2.8GHz machine, -g build: Sign takes ~760ms, + // uncached Verify takes ~250ms, cached Verify takes ~50ms + // (for 100 single-signature inputs) + mst1 = boost::posix_time::microsec_clock::local_time(); + for (unsigned int i = 0; i < 5; i++) + for (unsigned int j = 0; j < tx.vin.size(); j++) + BOOST_CHECK(VerifySignature(orphans[j], tx, j, true, SIGHASH_ALL)); + mst2 = boost::posix_time::microsec_clock::local_time(); + msdiff = mst2 - mst1; + long nManyValidate = msdiff.total_milliseconds(); + if (fDebug) printf("DoS_Checksig five: %ld\n", nManyValidate); + + BOOST_CHECK_MESSAGE(nManyValidate < nOneValidate, "Signature cache timing failed"); + + // Empty a signature, validation should fail: + CScript save = tx.vin[0].scriptSig; + tx.vin[0].scriptSig = CScript(); + BOOST_CHECK(!VerifySignature(orphans[0], tx, 0, true, SIGHASH_ALL)); + tx.vin[0].scriptSig = save; + + // Swap signatures, validation should fail: + std::swap(tx.vin[0].scriptSig, tx.vin[1].scriptSig); + BOOST_CHECK(!VerifySignature(orphans[0], tx, 0, true, SIGHASH_ALL)); + BOOST_CHECK(!VerifySignature(orphans[1], tx, 1, true, SIGHASH_ALL)); + std::swap(tx.vin[0].scriptSig, tx.vin[1].scriptSig); + + // Exercise -maxsigcachesize code: + mapArgs["-maxsigcachesize"] = "10"; + // Generate a new, different signature for vin[0] to trigger cache clear: + CScript oldSig = tx.vin[0].scriptSig; + BOOST_CHECK(SignSignature(keystore, orphans[0], tx, 0)); + BOOST_CHECK(tx.vin[0].scriptSig != oldSig); + for (unsigned int j = 0; j < tx.vin.size(); j++) + BOOST_CHECK(VerifySignature(orphans[j], tx, j, true, SIGHASH_ALL)); + mapArgs.erase("-maxsigcachesize"); + + LimitOrphanTxSize(0); +} + +BOOST_AUTO_TEST_SUITE_END() diff --git a/src/test/README b/src/test/README new file mode 100644 index 0000000..77f7faa --- /dev/null +++ b/src/test/README @@ -0,0 +1,21 @@ +The sources in this directory are unit test cases. Boost includes a +unit testing framework, and since bitcoin already uses boost, it makes +sense to simply use this framework rather than require developers to +configure some other framework (we want as few impediments to creating +unit tests as possible). + +The build system is setup to compile an executable called "test_bitcoin" +that runs all of the unit tests. The main source file is called +test_bitcoin.cpp, which simply includes other files that contain the +actual unit tests (outside of a couple required preprocessor +directives). The pattern is to create one test file for each class or +source file for which you want to create unit tests. The file naming +convention is "_tests.cpp" and such files should wrap +their tests in a test suite called "_tests". For an +examples of this pattern, examine uint160_tests.cpp and +uint256_tests.cpp. + +For further reading, I found the following website to be helpful in +explaining how the boost unit test framework works: + +http://www.alittlemadness.com/2009/03/31/c-unit-testing-with-boosttest/ diff --git a/src/test/accounting_tests.cpp b/src/test/accounting_tests.cpp new file mode 100644 index 0000000..8ac6572 --- /dev/null +++ b/src/test/accounting_tests.cpp @@ -0,0 +1,123 @@ +#include + +#include + +#include "init.h" +#include "wallet.h" +#include "walletdb.h" + +BOOST_AUTO_TEST_SUITE(accounting_tests) + +static void +GetResults(CWalletDB& walletdb, std::map& results) +{ + std::list aes; + + results.clear(); + BOOST_CHECK(walletdb.ReorderTransactions(pwalletMain) == DB_LOAD_OK); + walletdb.ListAccountCreditDebit("", aes); + BOOST_FOREACH(CAccountingEntry& ae, aes) + { + results[ae.nOrderPos] = ae; + } +} + +BOOST_AUTO_TEST_CASE(acc_orderupgrade) +{ + CWalletDB walletdb(pwalletMain->strWalletFile); + std::vector vpwtx; + CWalletTx wtx; + CAccountingEntry ae; + std::map results; + + ae.strAccount = ""; + ae.nCreditDebit = 1; + ae.nTime = 1333333333; + ae.strOtherAccount = "b"; + ae.strComment = ""; + walletdb.WriteAccountingEntry(ae); + + wtx.mapValue["comment"] = "z"; + pwalletMain->AddToWallet(wtx); + vpwtx.push_back(&pwalletMain->mapWallet[wtx.GetHash()]); + vpwtx[0]->nTimeReceived = (unsigned int)1333333335; + vpwtx[0]->nOrderPos = -1; + + ae.nTime = 1333333336; + ae.strOtherAccount = "c"; + walletdb.WriteAccountingEntry(ae); + + GetResults(walletdb, results); + + BOOST_CHECK(pwalletMain->nOrderPosNext == 3); + BOOST_CHECK(2 == results.size()); + BOOST_CHECK(results[0].nTime == 1333333333); + BOOST_CHECK(results[0].strComment.empty()); + BOOST_CHECK(1 == vpwtx[0]->nOrderPos); + BOOST_CHECK(results[2].nTime == 1333333336); + BOOST_CHECK(results[2].strOtherAccount == "c"); + + + ae.nTime = 1333333330; + ae.strOtherAccount = "d"; + ae.nOrderPos = pwalletMain->IncOrderPosNext(); + walletdb.WriteAccountingEntry(ae); + + GetResults(walletdb, results); + + BOOST_CHECK(results.size() == 3); + BOOST_CHECK(pwalletMain->nOrderPosNext == 4); + BOOST_CHECK(results[0].nTime == 1333333333); + BOOST_CHECK(1 == vpwtx[0]->nOrderPos); + BOOST_CHECK(results[2].nTime == 1333333336); + BOOST_CHECK(results[3].nTime == 1333333330); + BOOST_CHECK(results[3].strComment.empty()); + + + wtx.mapValue["comment"] = "y"; + --wtx.nLockTime; // Just to change the hash :) + pwalletMain->AddToWallet(wtx); + vpwtx.push_back(&pwalletMain->mapWallet[wtx.GetHash()]); + vpwtx[1]->nTimeReceived = (unsigned int)1333333336; + + wtx.mapValue["comment"] = "x"; + --wtx.nLockTime; // Just to change the hash :) + pwalletMain->AddToWallet(wtx); + vpwtx.push_back(&pwalletMain->mapWallet[wtx.GetHash()]); + vpwtx[2]->nTimeReceived = (unsigned int)1333333329; + vpwtx[2]->nOrderPos = -1; + + GetResults(walletdb, results); + + BOOST_CHECK(results.size() == 3); + BOOST_CHECK(pwalletMain->nOrderPosNext == 6); + BOOST_CHECK(0 == vpwtx[2]->nOrderPos); + BOOST_CHECK(results[1].nTime == 1333333333); + BOOST_CHECK(2 == vpwtx[0]->nOrderPos); + BOOST_CHECK(results[3].nTime == 1333333336); + BOOST_CHECK(results[4].nTime == 1333333330); + BOOST_CHECK(results[4].strComment.empty()); + BOOST_CHECK(5 == vpwtx[1]->nOrderPos); + + + ae.nTime = 1333333334; + ae.strOtherAccount = "e"; + ae.nOrderPos = -1; + walletdb.WriteAccountingEntry(ae); + + GetResults(walletdb, results); + + BOOST_CHECK(results.size() == 4); + BOOST_CHECK(pwalletMain->nOrderPosNext == 7); + BOOST_CHECK(0 == vpwtx[2]->nOrderPos); + BOOST_CHECK(results[1].nTime == 1333333333); + BOOST_CHECK(2 == vpwtx[0]->nOrderPos); + BOOST_CHECK(results[3].nTime == 1333333336); + BOOST_CHECK(results[3].strComment.empty()); + BOOST_CHECK(results[4].nTime == 1333333330); + BOOST_CHECK(results[4].strComment.empty()); + BOOST_CHECK(results[5].nTime == 1333333334); + BOOST_CHECK(6 == vpwtx[1]->nOrderPos); +} + +BOOST_AUTO_TEST_SUITE_END() diff --git a/src/test/allocator_tests.cpp b/src/test/allocator_tests.cpp new file mode 100644 index 0000000..d5cb8e8 --- /dev/null +++ b/src/test/allocator_tests.cpp @@ -0,0 +1,115 @@ +#include + +#include "init.h" +#include "main.h" +#include "util.h" + +BOOST_AUTO_TEST_SUITE(allocator_tests) + +// Dummy memory page locker for platform independent tests +static const void *last_lock_addr, *last_unlock_addr; +static size_t last_lock_len, last_unlock_len; +class TestLocker +{ +public: + bool Lock(const void *addr, size_t len) + { + last_lock_addr = addr; + last_lock_len = len; + return true; + } + bool Unlock(const void *addr, size_t len) + { + last_unlock_addr = addr; + last_unlock_len = len; + return true; + } +}; + +BOOST_AUTO_TEST_CASE(test_LockedPageManagerBase) +{ + const size_t test_page_size = 4096; + LockedPageManagerBase lpm(test_page_size); + size_t addr; + last_lock_addr = last_unlock_addr = 0; + last_lock_len = last_unlock_len = 0; + + /* Try large number of small objects */ + addr = 0; + for(int i=0; i<1000; ++i) + { + lpm.LockRange(reinterpret_cast(addr), 33); + addr += 33; + } + /* Try small number of page-sized objects, straddling two pages */ + addr = test_page_size*100 + 53; + for(int i=0; i<100; ++i) + { + lpm.LockRange(reinterpret_cast(addr), test_page_size); + addr += test_page_size; + } + /* Try small number of page-sized objects aligned to exactly one page */ + addr = test_page_size*300; + for(int i=0; i<100; ++i) + { + lpm.LockRange(reinterpret_cast(addr), test_page_size); + addr += test_page_size; + } + /* one very large object, straddling pages */ + lpm.LockRange(reinterpret_cast(test_page_size*600+1), test_page_size*500); + BOOST_CHECK(last_lock_addr == reinterpret_cast(test_page_size*(600+500))); + /* one very large object, page aligned */ + lpm.LockRange(reinterpret_cast(test_page_size*1200), test_page_size*500-1); + BOOST_CHECK(last_lock_addr == reinterpret_cast(test_page_size*(1200+500-1))); + + BOOST_CHECK(lpm.GetLockedPageCount() == ( + (1000*33+test_page_size-1)/test_page_size + // small objects + 101 + 100 + // page-sized objects + 501 + 500)); // large objects + BOOST_CHECK((last_lock_len & (test_page_size-1)) == 0); // always lock entire pages + BOOST_CHECK(last_unlock_len == 0); // nothing unlocked yet + + /* And unlock again */ + addr = 0; + for(int i=0; i<1000; ++i) + { + lpm.UnlockRange(reinterpret_cast(addr), 33); + addr += 33; + } + addr = test_page_size*100 + 53; + for(int i=0; i<100; ++i) + { + lpm.UnlockRange(reinterpret_cast(addr), test_page_size); + addr += test_page_size; + } + addr = test_page_size*300; + for(int i=0; i<100; ++i) + { + lpm.UnlockRange(reinterpret_cast(addr), test_page_size); + addr += test_page_size; + } + lpm.UnlockRange(reinterpret_cast(test_page_size*600+1), test_page_size*500); + lpm.UnlockRange(reinterpret_cast(test_page_size*1200), test_page_size*500-1); + + /* Check that everything is released */ + BOOST_CHECK(lpm.GetLockedPageCount() == 0); + + /* A few and unlocks of size zero (should have no effect) */ + addr = 0; + for(int i=0; i<1000; ++i) + { + lpm.LockRange(reinterpret_cast(addr), 0); + addr += 1; + } + BOOST_CHECK(lpm.GetLockedPageCount() == 0); + addr = 0; + for(int i=0; i<1000; ++i) + { + lpm.UnlockRange(reinterpret_cast(addr), 0); + addr += 1; + } + BOOST_CHECK(lpm.GetLockedPageCount() == 0); + BOOST_CHECK((last_unlock_len & (test_page_size-1)) == 0); // always unlock entire pages +} + +BOOST_AUTO_TEST_SUITE_END() diff --git a/src/test/base32_tests.cpp b/src/test/base32_tests.cpp new file mode 100644 index 0000000..fdf3285 --- /dev/null +++ b/src/test/base32_tests.cpp @@ -0,0 +1,20 @@ +#include + +#include "util.h" + +BOOST_AUTO_TEST_SUITE(base32_tests) + +BOOST_AUTO_TEST_CASE(base32_testvectors) +{ + static const std::string vstrIn[] = {"","f","fo","foo","foob","fooba","foobar"}; + static const std::string vstrOut[] = {"","my======","mzxq====","mzxw6===","mzxw6yq=","mzxw6ytb","mzxw6ytboi======"}; + for (unsigned int i=0; i +#include "json/json_spirit_reader_template.h" +#include "json/json_spirit_writer_template.h" +#include "json/json_spirit_utils.h" + +#include "base58.h" +#include "util.h" + +using namespace json_spirit; +extern Array read_json(const std::string& filename); + +BOOST_AUTO_TEST_SUITE(base58_tests) + +// Goal: test low-level base58 encoding functionality +BOOST_AUTO_TEST_CASE(base58_EncodeBase58) +{ + Array tests = read_json("base58_encode_decode.json"); + + BOOST_FOREACH(Value& tv, tests) + { + Array test = tv.get_array(); + std::string strTest = write_string(tv, false); + if (test.size() < 2) // Allow for extra stuff (useful for comments) + { + BOOST_ERROR("Bad test: " << strTest); + continue; + } + std::vector sourcedata = ParseHex(test[0].get_str()); + std::string base58string = test[1].get_str(); + BOOST_CHECK_MESSAGE( + EncodeBase58(&sourcedata[0], &sourcedata[sourcedata.size()]) == base58string, + strTest); + } +} + +// Goal: test low-level base58 decoding functionality +BOOST_AUTO_TEST_CASE(base58_DecodeBase58) +{ + Array tests = read_json("base58_encode_decode.json"); + std::vector result; + + BOOST_FOREACH(Value& tv, tests) + { + Array test = tv.get_array(); + std::string strTest = write_string(tv, false); + if (test.size() < 2) // Allow for extra stuff (useful for comments) + { + BOOST_ERROR("Bad test: " << strTest); + continue; + } + std::vector expected = ParseHex(test[0].get_str()); + std::string base58string = test[1].get_str(); + BOOST_CHECK_MESSAGE(DecodeBase58(base58string, result), strTest); + BOOST_CHECK_MESSAGE(result.size() == expected.size() && std::equal(result.begin(), result.end(), expected.begin()), strTest); + } + + BOOST_CHECK(!DecodeBase58("invalid", result)); +} + +// Visitor to check address type +class TestAddrTypeVisitor : public boost::static_visitor +{ +private: + std::string exp_addrType; +public: + TestAddrTypeVisitor(const std::string &exp_addrType) : exp_addrType(exp_addrType) { } + bool operator()(const CKeyID &id) const + { + return (exp_addrType == "pubkey"); + } + bool operator()(const CScriptID &id) const + { + return (exp_addrType == "script"); + } + bool operator()(const CNoDestination &no) const + { + return (exp_addrType == "none"); + } +}; + +// Visitor to check address payload +class TestPayloadVisitor : public boost::static_visitor +{ +private: + std::vector exp_payload; +public: + TestPayloadVisitor(std::vector &exp_payload) : exp_payload(exp_payload) { } + bool operator()(const CKeyID &id) const + { + uint160 exp_key(exp_payload); + return exp_key == id; + } + bool operator()(const CScriptID &id) const + { + uint160 exp_key(exp_payload); + return exp_key == id; + } + bool operator()(const CNoDestination &no) const + { + return exp_payload.size() == 0; + } +}; + +// Goal: check that parsed keys match test payload +BOOST_AUTO_TEST_CASE(base58_keys_valid_parse) +{ + Array tests = read_json("base58_keys_valid.json"); + std::vector result; + CBitcoinSecret secret; + CBitcoinAddress addr; + // Save global state + bool fTestNet_stored = fTestNet; + + BOOST_FOREACH(Value& tv, tests) + { + Array test = tv.get_array(); + std::string strTest = write_string(tv, false); + if (test.size() < 3) // Allow for extra stuff (useful for comments) + { + BOOST_ERROR("Bad test: " << strTest); + continue; + } + std::string exp_base58string = test[0].get_str(); + std::vector exp_payload = ParseHex(test[1].get_str()); + const Object &metadata = test[2].get_obj(); + bool isPrivkey = find_value(metadata, "isPrivkey").get_bool(); + bool isTestnet = find_value(metadata, "isTestnet").get_bool(); + fTestNet = isTestnet; // Override testnet flag + if(isPrivkey) + { + bool isCompressed = find_value(metadata, "isCompressed").get_bool(); + // Must be valid private key + // Note: CBitcoinSecret::SetString tests isValid, whereas CBitcoinAddress does not! + BOOST_CHECK_MESSAGE(secret.SetString(exp_base58string), "!SetString:"+ strTest); + BOOST_CHECK_MESSAGE(secret.IsValid(), "!IsValid:" + strTest); + bool fCompressedOut = false; + CSecret privkey = secret.GetSecret(fCompressedOut); + BOOST_CHECK_MESSAGE(fCompressedOut == isCompressed, "compressed mismatch:" + strTest); + BOOST_CHECK_MESSAGE(privkey.size() == exp_payload.size() && std::equal(privkey.begin(), privkey.end(), exp_payload.begin()), "key mismatch:" + strTest); + + // Private key must be invalid public key + addr.SetString(exp_base58string); + BOOST_CHECK_MESSAGE(!addr.IsValid(), "IsValid privkey as pubkey:" + strTest); + } + else + { + std::string exp_addrType = find_value(metadata, "addrType").get_str(); // "script" or "pubkey" + // Must be valid public key + BOOST_CHECK_MESSAGE(addr.SetString(exp_base58string), "SetString:" + strTest); + BOOST_CHECK_MESSAGE(addr.IsValid(), "!IsValid:" + strTest); + BOOST_CHECK_MESSAGE(addr.IsScript() == (exp_addrType == "script"), "isScript mismatch" + strTest); + CTxDestination dest = addr.Get(); + BOOST_CHECK_MESSAGE(boost::apply_visitor(TestAddrTypeVisitor(exp_addrType), dest), "addrType mismatch" + strTest); + + // Public key must be invalid private key + secret.SetString(exp_base58string); + BOOST_CHECK_MESSAGE(!secret.IsValid(), "IsValid pubkey as privkey:" + strTest); + } + } + // Restore global state + fTestNet = fTestNet_stored; +} + +// Goal: check that generated keys match test vectors +BOOST_AUTO_TEST_CASE(base58_keys_valid_gen) +{ + Array tests = read_json("base58_keys_valid.json"); + std::vector result; + // Save global state + bool fTestNet_stored = fTestNet; + + BOOST_FOREACH(Value& tv, tests) + { + Array test = tv.get_array(); + std::string strTest = write_string(tv, false); + if (test.size() < 3) // Allow for extra stuff (useful for comments) + { + BOOST_ERROR("Bad test: " << strTest); + continue; + } + std::string exp_base58string = test[0].get_str(); + std::vector exp_payload = ParseHex(test[1].get_str()); + const Object &metadata = test[2].get_obj(); + bool isPrivkey = find_value(metadata, "isPrivkey").get_bool(); + bool isTestnet = find_value(metadata, "isTestnet").get_bool(); + fTestNet = isTestnet; // Override testnet flag + if(isPrivkey) + { + bool isCompressed = find_value(metadata, "isCompressed").get_bool(); + CBitcoinSecret secret; + secret.SetSecret(CSecret(exp_payload.begin(), exp_payload.end()), isCompressed); + BOOST_CHECK_MESSAGE(secret.ToString() == exp_base58string, "result mismatch: " + strTest); + } + else + { + std::string exp_addrType = find_value(metadata, "addrType").get_str(); + CTxDestination dest; + if(exp_addrType == "pubkey") + { + dest = CKeyID(uint160(exp_payload)); + } + else if(exp_addrType == "script") + { + dest = CScriptID(uint160(exp_payload)); + } + else if(exp_addrType == "none") + { + dest = CNoDestination(); + } + else + { + BOOST_ERROR("Bad addrtype: " << strTest); + continue; + } + CBitcoinAddress addrOut; + BOOST_CHECK_MESSAGE(boost::apply_visitor(CBitcoinAddressVisitor(&addrOut), dest), "encode dest: " + strTest); + BOOST_CHECK_MESSAGE(addrOut.ToString() == exp_base58string, "mismatch: " + strTest); + } + } + + // Visiting a CNoDestination must fail + CBitcoinAddress dummyAddr; + CTxDestination nodest = CNoDestination(); + BOOST_CHECK(!boost::apply_visitor(CBitcoinAddressVisitor(&dummyAddr), nodest)); + + // Restore global state + fTestNet = fTestNet_stored; +} + +// Goal: check that base58 parsing code is robust against a variety of corrupted data +BOOST_AUTO_TEST_CASE(base58_keys_invalid) +{ + Array tests = read_json("base58_keys_invalid.json"); // Negative testcases + std::vector result; + CBitcoinSecret secret; + CBitcoinAddress addr; + + BOOST_FOREACH(Value& tv, tests) + { + Array test = tv.get_array(); + std::string strTest = write_string(tv, false); + if (test.size() < 1) // Allow for extra stuff (useful for comments) + { + BOOST_ERROR("Bad test: " << strTest); + continue; + } + std::string exp_base58string = test[0].get_str(); + + // must be invalid as public and as private key + addr.SetString(exp_base58string); + BOOST_CHECK_MESSAGE(!addr.IsValid(), "IsValid pubkey:" + strTest); + secret.SetString(exp_base58string); + BOOST_CHECK_MESSAGE(!secret.IsValid(), "IsValid privkey:" + strTest); + } +} + + +BOOST_AUTO_TEST_SUITE_END() + diff --git a/src/test/base64_tests.cpp b/src/test/base64_tests.cpp new file mode 100644 index 0000000..c5a053e --- /dev/null +++ b/src/test/base64_tests.cpp @@ -0,0 +1,22 @@ +#include + +#include "main.h" +#include "wallet.h" +#include "util.h" + +BOOST_AUTO_TEST_SUITE(base64_tests) + +BOOST_AUTO_TEST_CASE(base64_testvectors) +{ + static const std::string vstrIn[] = {"","f","fo","foo","foob","fooba","foobar"}; + static const std::string vstrOut[] = {"","Zg==","Zm8=","Zm9v","Zm9vYg==","Zm9vYmE=","Zm9vYmFy"}; + for (unsigned int i=0; i +#include + +#include "bignum.h" +#include "util.h" + +BOOST_AUTO_TEST_SUITE(bignum_tests) + +// Unfortunately there's no standard way of preventing a function from being +// inlined, so we define a macro for it. +// +// You should use it like this: +// NOINLINE void function() {...} +#if defined(__GNUC__) +// This also works and will be defined for any compiler implementing GCC +// extensions, such as Clang and ICC. +#define NOINLINE __attribute__((noinline)) +#elif defined(_MSC_VER) +#define NOINLINE __declspec(noinline) +#else +// We give out a warning because it impacts the correctness of one bignum test. +#warning You should define NOINLINE for your compiler. +#define NOINLINE +#endif + +// For the following test case, it is useful to use additional tools. +// +// The simplest one to use is the compiler flag -ftrapv, which detects integer +// overflows and similar errors. However, due to optimizations and compilers +// taking advantage of undefined behavior sometimes it may not actually detect +// anything. +// +// You can also use compiler-based stack protection to possibly detect possible +// stack buffer overruns. +// +// For more accurate diagnostics, you can use an undefined arithmetic operation +// detector such as the clang-based tool: +// +// "IOC: An Integer Overflow Checker for C/C++" +// +// Available at: http://embed.cs.utah.edu/ioc/ +// +// It might also be useful to use Google's AddressSanitizer to detect +// stack buffer overruns, which valgrind can't currently detect. + +// Let's force this code not to be inlined, in order to actually +// test a generic version of the function. This increases the chance +// that -ftrapv will detect overflows. +NOINLINE void mysetint64(CBigNum& num, int64 n) +{ + num.setint64(n); +} + +// For each number, we do 2 tests: one with inline code, then we reset the +// value to 0, then the second one with a non-inlined function. +BOOST_AUTO_TEST_CASE(bignum_setint64) +{ + int64 n; + + { + n = 0; + CBigNum num(n); + BOOST_CHECK(num.ToString() == "0"); + num.setulong(0); + BOOST_CHECK(num.ToString() == "0"); + mysetint64(num, n); + BOOST_CHECK(num.ToString() == "0"); + } + { + n = 1; + CBigNum num(n); + BOOST_CHECK(num.ToString() == "1"); + num.setulong(0); + BOOST_CHECK(num.ToString() == "0"); + mysetint64(num, n); + BOOST_CHECK(num.ToString() == "1"); + } + { + n = -1; + CBigNum num(n); + BOOST_CHECK(num.ToString() == "-1"); + num.setulong(0); + BOOST_CHECK(num.ToString() == "0"); + mysetint64(num, n); + BOOST_CHECK(num.ToString() == "-1"); + } + { + n = 5; + CBigNum num(n); + BOOST_CHECK(num.ToString() == "5"); + num.setulong(0); + BOOST_CHECK(num.ToString() == "0"); + mysetint64(num, n); + BOOST_CHECK(num.ToString() == "5"); + } + { + n = -5; + CBigNum num(n); + BOOST_CHECK(num.ToString() == "-5"); + num.setulong(0); + BOOST_CHECK(num.ToString() == "0"); + mysetint64(num, n); + BOOST_CHECK(num.ToString() == "-5"); + } + { + n = std::numeric_limits::min(); + CBigNum num(n); + BOOST_CHECK(num.ToString() == "-9223372036854775808"); + num.setulong(0); + BOOST_CHECK(num.ToString() == "0"); + mysetint64(num, n); + BOOST_CHECK(num.ToString() == "-9223372036854775808"); + } + { + n = std::numeric_limits::max(); + CBigNum num(n); + BOOST_CHECK(num.ToString() == "9223372036854775807"); + num.setulong(0); + BOOST_CHECK(num.ToString() == "0"); + mysetint64(num, n); + BOOST_CHECK(num.ToString() == "9223372036854775807"); + } +} + +BOOST_AUTO_TEST_SUITE_END() diff --git a/src/test/data/base58_encode_decode.json b/src/test/data/base58_encode_decode.json new file mode 100644 index 0000000..9448f25 --- /dev/null +++ b/src/test/data/base58_encode_decode.json @@ -0,0 +1,14 @@ +[ +["", ""], +["61", "2g"], +["626262", "a3gV"], +["636363", "aPEr"], +["73696d706c792061206c6f6e6720737472696e67", "2cFupjhnEsSn59qHXstmK2ffpLv2"], +["00eb15231dfceb60925886b67d065299925915aeb172c06647", "1NS17iag9jJgTHD1VXjvLCEnZuQ3rJDE9L"], +["516b6fcd0f", "ABnLTmg"], +["bf4f89001e670274dd", "3SEo3LWLoPntC"], +["572e4794", "3EFU7m"], +["ecac89cad93923c02321", "EJDM8drfXA6uyA"], +["10c8511e", "Rt5zm"], +["00000000000000000000", "1111111111"] +] diff --git a/src/test/data/base58_keys_invalid.json b/src/test/data/base58_keys_invalid.json new file mode 100644 index 0000000..a088620 --- /dev/null +++ b/src/test/data/base58_keys_invalid.json @@ -0,0 +1,152 @@ +[ + [ + "" + ], + [ + "x" + ], + [ + "37qgekLpCCHrQuSjvX3fs496FWTGsHFHizjJAs6NPcR47aefnnCWECAhHV6E3g4YN7u7Yuwod5Y" + ], + [ + "dzb7VV1Ui55BARxv7ATxAtCUeJsANKovDGWFVgpTbhq9gvPqP3yv" + ], + [ + "MuNu7ZAEDFiHthiunm7dPjwKqrVNCM3mAz6rP9zFveQu14YA8CxExSJTHcVP9DErn6u84E6Ej7S" + ], + [ + "rPpQpYknyNQ5AEHuY6H8ijJJrYc2nDKKk9jjmKEXsWzyAQcFGpDLU2Zvsmoi8JLR7hAwoy3RQWf" + ], + [ + "4Uc3FmN6NQ6zLBK5QQBXRBUREaaHwCZYsGCueHauuDmJpZKn6jkEskMB2Zi2CNgtb5r6epWEFfUJq" + ], + [ + "7aQgR5DFQ25vyXmqZAWmnVCjL3PkBcdVkBUpjrjMTcghHx3E8wb" + ], + [ + "17QpPprjeg69fW1DV8DcYYCKvWjYhXvWkov6MJ1iTTvMFj6weAqW7wybZeH57WTNxXVCRH4veVs" + ], + [ + "KxuACDviz8Xvpn1xAh9MfopySZNuyajYMZWz16Dv2mHHryznWUp3" + ], + [ + "7nK3GSmqdXJQtdohvGfJ7KsSmn3TmGqExug49583bDAL91pVSGq5xS9SHoAYL3Wv3ijKTit65th" + ], + [ + "cTivdBmq7bay3RFGEBBuNfMh2P1pDCgRYN2Wbxmgwr4ki3jNUL2va" + ], + [ + "gjMV4vjNjyMrna4fsAr8bWxAbwtmMUBXJS3zL4NJt5qjozpbQLmAfK1uA3CquSqsZQMpoD1g2nk" + ], + [ + "emXm1naBMoVzPjbk7xpeTVMFy4oDEe25UmoyGgKEB1gGWsK8kRGs" + ], + [ + "7VThQnNRj1o3Zyvc7XHPRrjDf8j2oivPTeDXnRPYWeYGE4pXeRJDZgf28ppti5hsHWXS2GSobdqyo" + ], + [ + "1G9u6oCVCPh2o8m3t55ACiYvG1y5BHewUkDSdiQarDcYXXhFHYdzMdYfUAhfxn5vNZBwpgUNpso" + ], + [ + "31QQ7ZMLkScDiB4VyZjuptr7AEc9j1SjstF7pRoLhHTGkW4Q2y9XELobQmhhWxeRvqcukGd1XCq" + ], + [ + "DHqKSnpxa8ZdQyH8keAhvLTrfkyBMQxqngcQA5N8LQ9KVt25kmGN" + ], + [ + "2LUHcJPbwLCy9GLH1qXmfmAwvadWw4bp4PCpDfduLqV17s6iDcy1imUwhQJhAoNoN1XNmweiJP4i" + ], + [ + "7USRzBXAnmck8fX9HmW7RAb4qt92VFX6soCnts9s74wxm4gguVhtG5of8fZGbNPJA83irHVY6bCos" + ], + [ + "1DGezo7BfVebZxAbNT3XGujdeHyNNBF3vnficYoTSp4PfK2QaML9bHzAMxke3wdKdHYWmsMTJVu" + ], + [ + "2D12DqDZKwCxxkzs1ZATJWvgJGhQ4cFi3WrizQ5zLAyhN5HxuAJ1yMYaJp8GuYsTLLxTAz6otCfb" + ], + [ + "8AFJzuTujXjw1Z6M3fWhQ1ujDW7zsV4ePeVjVo7D1egERqSW9nZ" + ], + [ + "163Q17qLbTCue8YY3AvjpUhotuaodLm2uqMhpYirsKjVqnxJRWTEoywMVY3NbBAHuhAJ2cF9GAZ" + ], + [ + "2MnmgiRH4eGLyLc9eAqStzk7dFgBjFtUCtu" + ], + [ + "461QQ2sYWxU7H2PV4oBwJGNch8XVTYYbZxU" + ], + [ + "2UCtv53VttmQYkVU4VMtXB31REvQg4ABzs41AEKZ8UcB7DAfVzdkV9JDErwGwyj5AUHLkmgZeobs" + ], + [ + "cSNjAsnhgtiFMi6MtfvgscMB2Cbhn2v1FUYfviJ1CdjfidvmeW6mn" + ], + [ + "gmsow2Y6EWAFDFE1CE4Hd3Tpu2BvfmBfG1SXsuRARbnt1WjkZnFh1qGTiptWWbjsq2Q6qvpgJVj" + ], + [ + "nksUKSkzS76v8EsSgozXGMoQFiCoCHzCVajFKAXqzK5on9ZJYVHMD5CKwgmX3S3c7M1U3xabUny" + ], + [ + "L3favK1UzFGgdzYBF2oBT5tbayCo4vtVBLJhg2iYuMeePxWG8SQc" + ], + [ + "7VxLxGGtYT6N99GdEfi6xz56xdQ8nP2dG1CavuXx7Rf2PrvNMTBNevjkfgs9JmkcGm6EXpj8ipyPZ" + ], + [ + "2mbZwFXF6cxShaCo2czTRB62WTx9LxhTtpP" + ], + [ + "dB7cwYdcPSgiyAwKWL3JwCVwSk6epU2txw" + ], + [ + "HPhFUhUAh8ZQQisH8QQWafAxtQYju3SFTX" + ], + [ + "4ctAH6AkHzq5ioiM1m9T3E2hiYEev5mTsB" + ], + [ + "Hn1uFi4dNexWrqARpjMqgT6cX1UsNPuV3cHdGg9ExyXw8HTKadbktRDtdeVmY3M1BxJStiL4vjJ" + ], + [ + "Sq3fDbvutABmnAHHExJDgPLQn44KnNC7UsXuT7KZecpaYDMU9Txs" + ], + [ + "6TqWyrqdgUEYDQU1aChMuFMMEimHX44qHFzCUgGfqxGgZNMUVWJ" + ], + [ + "giqJo7oWqFxNKWyrgcBxAVHXnjJ1t6cGoEffce5Y1y7u649Noj5wJ4mmiUAKEVVrYAGg2KPB3Y4" + ], + [ + "cNzHY5e8vcmM3QVJUcjCyiKMYfeYvyueq5qCMV3kqcySoLyGLYUK" + ], + [ + "37uTe568EYc9WLoHEd9jXEvUiWbq5LFLscNyqvAzLU5vBArUJA6eydkLmnMwJDjkL5kXc2VK7ig" + ], + [ + "EsYbG4tWWWY45G31nox838qNdzksbPySWc" + ], + [ + "nbuzhfwMoNzA3PaFnyLcRxE9bTJPDkjZ6Rf6Y6o2ckXZfzZzXBT" + ], + [ + "cQN9PoxZeCWK1x56xnz6QYAsvR11XAce3Ehp3gMUdfSQ53Y2mPzx" + ], + [ + "1Gm3N3rkef6iMbx4voBzaxtXcmmiMTqZPhcuAepRzYUJQW4qRpEnHvMojzof42hjFRf8PE2jPde" + ], + [ + "2TAq2tuN6x6m233bpT7yqdYQPELdTDJn1eU" + ], + [ + "ntEtnnGhqPii4joABvBtSEJG6BxjT2tUZqE8PcVYgk3RHpgxgHDCQxNbLJf7ardf1dDk2oCQ7Cf" + ], + [ + "Ky1YjoZNgQ196HJV3HpdkecfhRBmRZdMJk89Hi5KGfpfPwS2bUbfd" + ], + [ + "2A1q1YsMZowabbvta7kTy2Fd6qN4r5ZCeG3qLpvZBMzCixMUdkN2Y4dHB1wPsZAeVXUGD83MfRED" + ] +] diff --git a/src/test/data/base58_keys_valid.json b/src/test/data/base58_keys_valid.json new file mode 100644 index 0000000..e1e252e --- /dev/null +++ b/src/test/data/base58_keys_valid.json @@ -0,0 +1,452 @@ +[ + [ + "1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62i", + "65a16059864a2fdbc7c99a4723a8395bc6f188eb", + { + "addrType": "pubkey", + "isPrivkey": false, + "isTestnet": false + } + ], + [ + "3CMNFxN1oHBc4R1EpboAL5yzHGgE611Xou", + "74f209f6ea907e2ea48f74fae05782ae8a665257", + { + "addrType": "script", + "isPrivkey": false, + "isTestnet": false + } + ], + [ + "mo9ncXisMeAoXwqcV5EWuyncbmCcQN4rVs", + "53c0307d6851aa0ce7825ba883c6bd9ad242b486", + { + "addrType": "pubkey", + "isPrivkey": false, + "isTestnet": true + } + ], + [ + "2N2JD6wb56AfK4tfmM6PwdVmoYk2dCKf4Br", + "6349a418fc4578d10a372b54b45c280cc8c4382f", + { + "addrType": "script", + "isPrivkey": false, + "isTestnet": true + } + ], + [ + "5Kd3NBUAdUnhyzenEwVLy9pBKxSwXvE9FMPyR4UKZvpe6E3AgLr", + "eddbdc1168f1daeadbd3e44c1e3f8f5a284c2029f78ad26af98583a499de5b19", + { + "isCompressed": false, + "isPrivkey": true, + "isTestnet": false + } + ], + [ + "Kz6UJmQACJmLtaQj5A3JAge4kVTNQ8gbvXuwbmCj7bsaabudb3RD", + "55c9bccb9ed68446d1b75273bbce89d7fe013a8acd1625514420fb2aca1a21c4", + { + "isCompressed": true, + "isPrivkey": true, + "isTestnet": false + } + ], + [ + "9213qJab2HNEpMpYNBa7wHGFKKbkDn24jpANDs2huN3yi4J11ko", + "36cb93b9ab1bdabf7fb9f2c04f1b9cc879933530ae7842398eef5a63a56800c2", + { + "isCompressed": false, + "isPrivkey": true, + "isTestnet": true + } + ], + [ + "cTpB4YiyKiBcPxnefsDpbnDxFDffjqJob8wGCEDXxgQ7zQoMXJdH", + "b9f4892c9e8282028fea1d2667c4dc5213564d41fc5783896a0d843fc15089f3", + { + "isCompressed": true, + "isPrivkey": true, + "isTestnet": true + } + ], + [ + "1Ax4gZtb7gAit2TivwejZHYtNNLT18PUXJ", + "6d23156cbbdcc82a5a47eee4c2c7c583c18b6bf4", + { + "addrType": "pubkey", + "isPrivkey": false, + "isTestnet": false + } + ], + [ + "3QjYXhTkvuj8qPaXHTTWb5wjXhdsLAAWVy", + "fcc5460dd6e2487c7d75b1963625da0e8f4c5975", + { + "addrType": "script", + "isPrivkey": false, + "isTestnet": false + } + ], + [ + "n3ZddxzLvAY9o7184TB4c6FJasAybsw4HZ", + "f1d470f9b02370fdec2e6b708b08ac431bf7a5f7", + { + "addrType": "pubkey", + "isPrivkey": false, + "isTestnet": true + } + ], + [ + "2NBFNJTktNa7GZusGbDbGKRZTxdK9VVez3n", + "c579342c2c4c9220205e2cdc285617040c924a0a", + { + "addrType": "script", + "isPrivkey": false, + "isTestnet": true + } + ], + [ + "5K494XZwps2bGyeL71pWid4noiSNA2cfCibrvRWqcHSptoFn7rc", + "a326b95ebae30164217d7a7f57d72ab2b54e3be64928a19da0210b9568d4015e", + { + "isCompressed": false, + "isPrivkey": true, + "isTestnet": false + } + ], + [ + "L1RrrnXkcKut5DEMwtDthjwRcTTwED36thyL1DebVrKuwvohjMNi", + "7d998b45c219a1e38e99e7cbd312ef67f77a455a9b50c730c27f02c6f730dfb4", + { + "isCompressed": true, + "isPrivkey": true, + "isTestnet": false + } + ], + [ + "93DVKyFYwSN6wEo3E2fCrFPUp17FtrtNi2Lf7n4G3garFb16CRj", + "d6bca256b5abc5602ec2e1c121a08b0da2556587430bcf7e1898af2224885203", + { + "isCompressed": false, + "isPrivkey": true, + "isTestnet": true + } + ], + [ + "cTDVKtMGVYWTHCb1AFjmVbEbWjvKpKqKgMaR3QJxToMSQAhmCeTN", + "a81ca4e8f90181ec4b61b6a7eb998af17b2cb04de8a03b504b9e34c4c61db7d9", + { + "isCompressed": true, + "isPrivkey": true, + "isTestnet": true + } + ], + [ + "1C5bSj1iEGUgSTbziymG7Cn18ENQuT36vv", + "7987ccaa53d02c8873487ef919677cd3db7a6912", + { + "addrType": "pubkey", + "isPrivkey": false, + "isTestnet": false + } + ], + [ + "3AnNxabYGoTxYiTEZwFEnerUoeFXK2Zoks", + "63bcc565f9e68ee0189dd5cc67f1b0e5f02f45cb", + { + "addrType": "script", + "isPrivkey": false, + "isTestnet": false + } + ], + [ + "n3LnJXCqbPjghuVs8ph9CYsAe4Sh4j97wk", + "ef66444b5b17f14e8fae6e7e19b045a78c54fd79", + { + "addrType": "pubkey", + "isPrivkey": false, + "isTestnet": true + } + ], + [ + "2NB72XtkjpnATMggui83aEtPawyyKvnbX2o", + "c3e55fceceaa4391ed2a9677f4a4d34eacd021a0", + { + "addrType": "script", + "isPrivkey": false, + "isTestnet": true + } + ], + [ + "5KaBW9vNtWNhc3ZEDyNCiXLPdVPHCikRxSBWwV9NrpLLa4LsXi9", + "e75d936d56377f432f404aabb406601f892fd49da90eb6ac558a733c93b47252", + { + "isCompressed": false, + "isPrivkey": true, + "isTestnet": false + } + ], + [ + "L1axzbSyynNYA8mCAhzxkipKkfHtAXYF4YQnhSKcLV8YXA874fgT", + "8248bd0375f2f75d7e274ae544fb920f51784480866b102384190b1addfbaa5c", + { + "isCompressed": true, + "isPrivkey": true, + "isTestnet": false + } + ], + [ + "927CnUkUbasYtDwYwVn2j8GdTuACNnKkjZ1rpZd2yBB1CLcnXpo", + "44c4f6a096eac5238291a94cc24c01e3b19b8d8cef72874a079e00a242237a52", + { + "isCompressed": false, + "isPrivkey": true, + "isTestnet": true + } + ], + [ + "cUcfCMRjiQf85YMzzQEk9d1s5A4K7xL5SmBCLrezqXFuTVefyhY7", + "d1de707020a9059d6d3abaf85e17967c6555151143db13dbb06db78df0f15c69", + { + "isCompressed": true, + "isPrivkey": true, + "isTestnet": true + } + ], + [ + "1Gqk4Tv79P91Cc1STQtU3s1W6277M2CVWu", + "adc1cc2081a27206fae25792f28bbc55b831549d", + { + "addrType": "pubkey", + "isPrivkey": false, + "isTestnet": false + } + ], + [ + "33vt8ViH5jsr115AGkW6cEmEz9MpvJSwDk", + "188f91a931947eddd7432d6e614387e32b244709", + { + "addrType": "script", + "isPrivkey": false, + "isTestnet": false + } + ], + [ + "mhaMcBxNh5cqXm4aTQ6EcVbKtfL6LGyK2H", + "1694f5bc1a7295b600f40018a618a6ea48eeb498", + { + "addrType": "pubkey", + "isPrivkey": false, + "isTestnet": true + } + ], + [ + "2MxgPqX1iThW3oZVk9KoFcE5M4JpiETssVN", + "3b9b3fd7a50d4f08d1a5b0f62f644fa7115ae2f3", + { + "addrType": "script", + "isPrivkey": false, + "isTestnet": true + } + ], + [ + "5HtH6GdcwCJA4ggWEL1B3jzBBUB8HPiBi9SBc5h9i4Wk4PSeApR", + "091035445ef105fa1bb125eccfb1882f3fe69592265956ade751fd095033d8d0", + { + "isCompressed": false, + "isPrivkey": true, + "isTestnet": false + } + ], + [ + "L2xSYmMeVo3Zek3ZTsv9xUrXVAmrWxJ8Ua4cw8pkfbQhcEFhkXT8", + "ab2b4bcdfc91d34dee0ae2a8c6b6668dadaeb3a88b9859743156f462325187af", + { + "isCompressed": true, + "isPrivkey": true, + "isTestnet": false + } + ], + [ + "92xFEve1Z9N8Z641KQQS7ByCSb8kGjsDzw6fAmjHN1LZGKQXyMq", + "b4204389cef18bbe2b353623cbf93e8678fbc92a475b664ae98ed594e6cf0856", + { + "isCompressed": false, + "isPrivkey": true, + "isTestnet": true + } + ], + [ + "cVM65tdYu1YK37tNoAyGoJTR13VBYFva1vg9FLuPAsJijGvG6NEA", + "e7b230133f1b5489843260236b06edca25f66adb1be455fbd38d4010d48faeef", + { + "isCompressed": true, + "isPrivkey": true, + "isTestnet": true + } + ], + [ + "1JwMWBVLtiqtscbaRHai4pqHokhFCbtoB4", + "c4c1b72491ede1eedaca00618407ee0b772cad0d", + { + "addrType": "pubkey", + "isPrivkey": false, + "isTestnet": false + } + ], + [ + "3QCzvfL4ZRvmJFiWWBVwxfdaNBT8EtxB5y", + "f6fe69bcb548a829cce4c57bf6fff8af3a5981f9", + { + "addrType": "script", + "isPrivkey": false, + "isTestnet": false + } + ], + [ + "mizXiucXRCsEriQCHUkCqef9ph9qtPbZZ6", + "261f83568a098a8638844bd7aeca039d5f2352c0", + { + "addrType": "pubkey", + "isPrivkey": false, + "isTestnet": true + } + ], + [ + "2NEWDzHWwY5ZZp8CQWbB7ouNMLqCia6YRda", + "e930e1834a4d234702773951d627cce82fbb5d2e", + { + "addrType": "script", + "isPrivkey": false, + "isTestnet": true + } + ], + [ + "5KQmDryMNDcisTzRp3zEq9e4awRmJrEVU1j5vFRTKpRNYPqYrMg", + "d1fab7ab7385ad26872237f1eb9789aa25cc986bacc695e07ac571d6cdac8bc0", + { + "isCompressed": false, + "isPrivkey": true, + "isTestnet": false + } + ], + [ + "L39Fy7AC2Hhj95gh3Yb2AU5YHh1mQSAHgpNixvm27poizcJyLtUi", + "b0bbede33ef254e8376aceb1510253fc3550efd0fcf84dcd0c9998b288f166b3", + { + "isCompressed": true, + "isPrivkey": true, + "isTestnet": false + } + ], + [ + "91cTVUcgydqyZLgaANpf1fvL55FH53QMm4BsnCADVNYuWuqdVys", + "037f4192c630f399d9271e26c575269b1d15be553ea1a7217f0cb8513cef41cb", + { + "isCompressed": false, + "isPrivkey": true, + "isTestnet": true + } + ], + [ + "cQspfSzsgLeiJGB2u8vrAiWpCU4MxUT6JseWo2SjXy4Qbzn2fwDw", + "6251e205e8ad508bab5596bee086ef16cd4b239e0cc0c5d7c4e6035441e7d5de", + { + "isCompressed": true, + "isPrivkey": true, + "isTestnet": true + } + ], + [ + "19dcawoKcZdQz365WpXWMhX6QCUpR9SY4r", + "5eadaf9bb7121f0f192561a5a62f5e5f54210292", + { + "addrType": "pubkey", + "isPrivkey": false, + "isTestnet": false + } + ], + [ + "37Sp6Rv3y4kVd1nQ1JV5pfqXccHNyZm1x3", + "3f210e7277c899c3a155cc1c90f4106cbddeec6e", + { + "addrType": "script", + "isPrivkey": false, + "isTestnet": false + } + ], + [ + "myoqcgYiehufrsnnkqdqbp69dddVDMopJu", + "c8a3c2a09a298592c3e180f02487cd91ba3400b5", + { + "addrType": "pubkey", + "isPrivkey": false, + "isTestnet": true + } + ], + [ + "2N7FuwuUuoTBrDFdrAZ9KxBmtqMLxce9i1C", + "99b31df7c9068d1481b596578ddbb4d3bd90baeb", + { + "addrType": "script", + "isPrivkey": false, + "isTestnet": true + } + ], + [ + "5KL6zEaMtPRXZKo1bbMq7JDjjo1bJuQcsgL33je3oY8uSJCR5b4", + "c7666842503db6dc6ea061f092cfb9c388448629a6fe868d068c42a488b478ae", + { + "isCompressed": false, + "isPrivkey": true, + "isTestnet": false + } + ], + [ + "KwV9KAfwbwt51veZWNscRTeZs9CKpojyu1MsPnaKTF5kz69H1UN2", + "07f0803fc5399e773555ab1e8939907e9badacc17ca129e67a2f5f2ff84351dd", + { + "isCompressed": true, + "isPrivkey": true, + "isTestnet": false + } + ], + [ + "93N87D6uxSBzwXvpokpzg8FFmfQPmvX4xHoWQe3pLdYpbiwT5YV", + "ea577acfb5d1d14d3b7b195c321566f12f87d2b77ea3a53f68df7ebf8604a801", + { + "isCompressed": false, + "isPrivkey": true, + "isTestnet": true + } + ], + [ + "cMxXusSihaX58wpJ3tNuuUcZEQGt6DKJ1wEpxys88FFaQCYjku9h", + "0b3b34f0958d8a268193a9814da92c3e8b58b4a4378a542863e34ac289cd830c", + { + "isCompressed": true, + "isPrivkey": true, + "isTestnet": true + } + ], + [ + "13p1ijLwsnrcuyqcTvJXkq2ASdXqcnEBLE", + "1ed467017f043e91ed4c44b4e8dd674db211c4e6", + { + "addrType": "pubkey", + "isPrivkey": false, + "isTestnet": false + } + ], + [ + "3ALJH9Y951VCGcVZYAdpA3KchoP9McEj1G", + "5ece0cadddc415b1980f001785947120acdb36fc", + { + "addrType": "script", + "isPrivkey": false, + "isTestnet": false + } + ] +] diff --git a/src/test/data/script_invalid.json b/src/test/data/script_invalid.json new file mode 100644 index 0000000..d413eae --- /dev/null +++ b/src/test/data/script_invalid.json @@ -0,0 +1,245 @@ +[ +["", ""], +["", "NOP"], +["NOP", ""], +["NOP","NOP"], + +["0x4c01","0x01 NOP", "PUSHDATA1 with not enough bytes"], +["0x4d0200ff","0x01 NOP", "PUSHDATA2 with not enough bytes"], +["0x4e03000000ffff","0x01 NOP", "PUSHDATA4 with not enough bytes"], + +["1", "IF 0x50 ENDIF 1", "0x50 is reserved"], +["0x52", "0x5f ADD 0x60 EQUAL", "0x51 through 0x60 push 1 through 16 onto stack"], +["0","NOP"], +["1", "IF VER ELSE 1 ENDIF", "VER non-functional"], +["0", "IF VERIF ELSE 1 ENDIF", "VERIF illegal everywhere"], +["0", "IF VERNOTIF ELSE 1 ENDIF", "VERNOT illegal everywhere"], + +["1 IF", "1 ENDIF", "IF/ENDIF can't span scriptSig/scriptPubKey"], +["1 IF 0 ENDIF", "1 ENDIF"], +["1 ELSE 0 ENDIF", "1"], +["0 NOTIF", "123"], + +["0", "DUP IF ENDIF"], +["0", "IF 1 ENDIF"], +["0", "DUP IF ELSE ENDIF"], +["0", "IF 1 ELSE ENDIF"], +["0", "NOTIF ELSE 1 ENDIF"], + +["0 1", "IF IF 1 ELSE 0 ENDIF ENDIF"], +["0 0", "IF IF 1 ELSE 0 ENDIF ENDIF"], +["1 0", "IF IF 1 ELSE 0 ENDIF ELSE IF 0 ELSE 1 ENDIF ENDIF"], +["0 1", "IF IF 1 ELSE 0 ENDIF ELSE IF 0 ELSE 1 ENDIF ENDIF"], + +["0 0", "NOTIF IF 1 ELSE 0 ENDIF ENDIF"], +["0 1", "NOTIF IF 1 ELSE 0 ENDIF ENDIF"], +["1 1", "NOTIF IF 1 ELSE 0 ENDIF ELSE IF 0 ELSE 1 ENDIF ENDIF"], +["0 0", "NOTIF IF 1 ELSE 0 ENDIF ELSE IF 0 ELSE 1 ENDIF ENDIF"], + +["1", "RETURN"], +["1", "DUP IF RETURN ENDIF"], + +["0", "VERIFY 1"], +["1", "VERIFY"], +["1", "VERIFY 0"], + +["1 TOALTSTACK", "FROMALTSTACK 1", "alt stack not shared between sig/pubkey"], + +["IFDUP", "DEPTH 0 EQUAL"], +["DROP", "DEPTH 0 EQUAL"], +["DUP", "DEPTH 0 EQUAL"], +["1", "DUP 1 ADD 2 EQUALVERIFY 0 EQUAL"], +["NOP", "NIP"], +["NOP", "1 NIP"], +["NOP", "1 0 NIP"], +["NOP", "OVER 1"], +["1", "OVER"], +["0 1", "OVER DEPTH 3 EQUALVERIFY"], +["19 20 21", "PICK 19 EQUALVERIFY DEPTH 2 EQUAL"], +["NOP", "0 PICK"], +["1", "-1 PICK"], +["19 20 21", "0 PICK 20 EQUALVERIFY DEPTH 3 EQUAL"], +["19 20 21", "1 PICK 21 EQUALVERIFY DEPTH 3 EQUAL"], +["19 20 21", "2 PICK 22 EQUALVERIFY DEPTH 3 EQUAL"], +["NOP", "0 ROLL"], +["1", "-1 ROLL"], +["19 20 21", "0 ROLL 20 EQUALVERIFY DEPTH 2 EQUAL"], +["19 20 21", "1 ROLL 21 EQUALVERIFY DEPTH 2 EQUAL"], +["19 20 21", "2 ROLL 22 EQUALVERIFY DEPTH 2 EQUAL"], +["NOP", "ROT 1"], +["NOP", "1 ROT 1"], +["NOP", "1 2 ROT 1"], +["NOP", "0 1 2 ROT"], +["NOP", "SWAP 1"], +["1", "SWAP 1"], +["0 1", "SWAP 1 EQUALVERIFY"], +["NOP", "TUCK 1"], +["1", "TUCK 1"], +["1 0", "TUCK DEPTH 3 EQUALVERIFY SWAP 2DROP"], +["NOP", "2DUP 1"], +["1", "2DUP 1"], +["NOP", "3DUP 1"], +["1", "3DUP 1"], +["1 2", "3DUP 1"], +["NOP", "2OVER 1"], +["1", "2 3 2OVER 1"], +["NOP", "2SWAP 1"], +["1", "2 3 2SWAP 1"], + +["'a' 'b'", "CAT", "CAT disabled"], +["'a' 'b' 0", "IF CAT ELSE 1 ENDIF", "CAT disabled"], +["'abc' 1 1", "SUBSTR", "SUBSTR disabled"], +["'abc' 1 1 0", "IF SUBSTR ELSE 1 ENDIF", "SUBSTR disabled"], +["'abc' 2 0", "IF LEFT ELSE 1 ENDIF", "LEFT disabled"], +["'abc' 2 0", "IF RIGHT ELSE 1 ENDIF", "RIGHT disabled"], + +["NOP", "SIZE 1"], + +["'abc'", "IF INVERT ELSE 1 ENDIF", "INVERT disabled"], +["1 2 0 IF AND ELSE 1 ENDIF", "NOP", "AND disabled"], +["1 2 0 IF OR ELSE 1 ENDIF", "NOP", "OR disabled"], +["1 2 0 IF XOR ELSE 1 ENDIF", "NOP", "XOR disabled"], +["2 0 IF 2MUL ELSE 1 ENDIF", "NOP", "2MUL disabled"], +["2 0 IF 2DIV ELSE 1 ENDIF", "NOP", "2DIV disabled"], +["2 2 0 IF MUL ELSE 1 ENDIF", "NOP", "MUL disabled"], +["2 2 0 IF DIV ELSE 1 ENDIF", "NOP", "DIV disabled"], +["2 2 0 IF MOD ELSE 1 ENDIF", "NOP", "MOD disabled"], +["2 2 0 IF LSHIFT ELSE 1 ENDIF", "NOP", "LSHIFT disabled"], +["2 2 0 IF RSHIFT ELSE 1 ENDIF", "NOP", "RSHIFT disabled"], + +["0 1","EQUAL"], +["1 1 ADD", "0 EQUAL"], +["11 1 ADD 12 SUB", "11 EQUAL"], + +["2147483648 0 ADD", "NOP", "arithmetic operands must be in range [-2^31...2^31] "], +["-2147483648 0 ADD", "NOP", "arithmetic operands must be in range [-2^31...2^31] "], +["2147483647 DUP ADD", "4294967294 NUMEQUAL", "NUMEQUAL must be in numeric range"], +["'abcdef' NOT", "0 EQUAL", "NOT is an arithmetic operand"], + +["2 DUP MUL", "4 EQUAL", "disabled"], +["2 DUP DIV", "1 EQUAL", "disabled"], +["2 2MUL", "4 EQUAL", "disabled"], +["2 2DIV", "1 EQUAL", "disabled"], +["7 3 MOD", "1 EQUAL", "disabled"], +["2 2 LSHIFT", "8 EQUAL", "disabled"], +["2 1 RSHIFT", "1 EQUAL", "disabled"], + +["1","NOP1 NOP2 NOP3 NOP4 NOP5 NOP6 NOP7 NOP8 NOP9 NOP10 2 EQUAL"], +["'NOP_1_to_10' NOP1 NOP2 NOP3 NOP4 NOP5 NOP6 NOP7 NOP8 NOP9 NOP10","'NOP_1_to_11' EQUAL"], + +["0x50","1", "opcode 0x50 is reserved"], +["1", "IF 0xba ELSE 1 ENDIF", "opcodes above NOP10 invalid"], +["1", "IF 0xc0 ELSE 1 ENDIF"], +["1", "IF 0xd1 ELSE 1 ENDIF"], +["1", "IF 0xee ELSE 1 ENDIF"], +["1", "IF 0xfd ELSE 1 ENDIF"], +["1", "IF 0xff ELSE 1 ENDIF"], + +["NOP", "RIPEMD160"], +["NOP", "SHA1"], +["NOP", "SHA256"], +["NOP", "HASH160"], +["NOP", "HASH256"], + +["NOP", +"'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb'", +">520 byte push"], +["0", +"IF 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' ENDIF 1", +">520 byte push in non-executed IF branch"], +["1", +"0x61616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", +">201 opcodes executed. 0x61 is NOP"], +["0", +"IF 0x6161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161 ENDIF 1", +">201 opcodes including non-executed IF branch. 0x61 is NOP"], +["1 2 3 4 5 0x6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f", +"1 2 3 4 5 6 0x6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f", +">1,000 stack size (0x6f is 3DUP)"], +["1 2 3 4 5 0x6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f", +"1 TOALTSTACK 2 TOALTSTACK 3 4 5 6 0x6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f", +">1,000 stack+altstack size"], +["NOP", +"0 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 0x6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f 2DUP 0x616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", +"10,001-byte scriptPubKey"], + +["NOP1","NOP10"], + +["1","VER", "OP_VER is reserved"], +["1","VERIF", "OP_VERIF is reserved"], +["1","VERNOTIF", "OP_VERNOTIF is reserved"], +["1","RESERVED1", "OP_RESERVED1 is reserved"], +["1","RESERVED2", "OP_RESERVED2 is reserved"], +["1","0xba", "0xba == OP_NOP10 + 1"], + +["2147483648", "1ADD 1", "We cannot do math on 5-byte integers"], +["-2147483648", "1ADD 1", "Because we use a sign bit, -2147483648 is also 5 bytes"], + +["1", "1 ENDIF", "ENDIF without IF"], +["1", "IF 1", "IF without ENDIF"], +["1 IF 1", "ENDIF", "IFs don't carry over"], + +["NOP", "IF 1 ENDIF", "The following tests check the if(stack.size() < N) tests in each opcode"], +["NOP", "NOTIF 1 ENDIF", "They are here to catch copy-and-paste errors"], +["NOP", "VERIFY 1", "Most of them are duplicated elsewhere,"], + +["NOP", "TOALTSTACK 1", "but, hey, more is always better, right?"], +["1", "FROMALTSTACK"], +["1", "2DROP 1"], +["1", "2DUP"], +["1 1", "3DUP"], +["1 1 1", "2OVER"], +["1 1 1 1 1", "2ROT"], +["1 1 1", "2SWAP"], +["NOP", "IFDUP 1"], +["NOP", "DROP 1"], +["NOP", "DUP 1"], +["1", "NIP"], +["1", "OVER"], +["1 1 1 3", "PICK"], +["0", "PICK 1"], +["1 1 1 3", "ROLL"], +["0", "ROLL 1"], +["1 1", "ROT"], +["1", "SWAP"], +["1", "TUCK"], + +["NOP", "SIZE 1"], + +["1", "EQUAL 1"], +["1", "EQUALVERIFY 1"], + +["NOP", "1ADD 1"], +["NOP", "1SUB 1"], +["NOP", "NEGATE 1"], +["NOP", "ABS 1"], +["NOP", "NOT 1"], +["NOP", "0NOTEQUAL 1"], + +["1", "ADD"], +["1", "SUB"], +["1", "BOOLAND"], +["1", "BOOLOR"], +["1", "NUMEQUAL"], +["1", "NUMEQUALVERIFY 1"], +["1", "NUMNOTEQUAL"], +["1", "LESSTHAN"], +["1", "GREATERTHAN"], +["1", "LESSTHANOREQUAL"], +["1", "GREATERTHANOREQUAL"], +["1", "MIN"], +["1", "MAX"], +["1 1", "WITHIN"], + +["NOP", "RIPEMD160 1"], +["NOP", "SHA1 1"], +["NOP", "SHA256 1"], +["NOP", "HASH160 1"], +["NOP", "HASH256 1"], + +["NOP 0x01 1", "HASH160 0x14 0xda1745e9b549bd0bfa1a569971c77eba30cd5a4b EQUAL", "Tests for Script.IsPushOnly()"], +["NOP1 0x01 1", "HASH160 0x14 0xda1745e9b549bd0bfa1a569971c77eba30cd5a4b EQUAL"], + +["0 0x01 0x50", "HASH160 0x14 0xece424a6bb6ddf4db592c0faed60685047a361b1 EQUAL", "OP_RESERVED in P2SH should fail"], +["0 0x01 VER", "HASH160 0x14 0x0f4d7845db968f2a81b530b6f3c1d6246d4c7e01 EQUAL", "OP_VER in P2SH should fail"] +] diff --git a/src/test/data/script_valid.json b/src/test/data/script_valid.json new file mode 100644 index 0000000..c33a3c7 --- /dev/null +++ b/src/test/data/script_valid.json @@ -0,0 +1,313 @@ +[ +["0x01 0x0b", "11 EQUAL", "push 1 byte"], +["0x02 0x417a", "'Az' EQUAL"], +["0x4b 0x417a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a", + "'Azzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz' EQUAL", "push 75 bytes"], + +["0x4c 0x01 0x07","7 EQUAL", "0x4c is OP_PUSHDATA1"], +["0x4d 0x0100 0x08","8 EQUAL", "0x4d is OP_PUSHDATA2"], +["0x4e 0x01000000 0x09","9 EQUAL", "0x4e is OP_PUSHDATA4"], + +["0x4c 0x00","0 EQUAL"], +["0x4d 0x0000","0 EQUAL"], +["0x4e 0x00000000","0 EQUAL"], +["0x4f 1000 ADD","999 EQUAL"], +["0", "IF 0x50 ENDIF 1", "0x50 is reserved (ok if not executed)"], +["0x51", "0x5f ADD 0x60 EQUAL", "0x51 through 0x60 push 1 through 16 onto stack"], +["1","NOP"], +["0", "IF VER ELSE 1 ENDIF", "VER non-functional (ok if not executed)"], +["0", "IF RESERVED1 RESERVED2 ELSE 1 ENDIF", "RESERVED ok in un-executed IF"], + +["1", "DUP IF ENDIF"], +["1", "IF 1 ENDIF"], +["1", "DUP IF ELSE ENDIF"], +["1", "IF 1 ELSE ENDIF"], +["0", "IF ELSE 1 ENDIF"], + +["1 1", "IF IF 1 ELSE 0 ENDIF ENDIF"], +["1 0", "IF IF 1 ELSE 0 ENDIF ENDIF"], +["1 1", "IF IF 1 ELSE 0 ENDIF ELSE IF 0 ELSE 1 ENDIF ENDIF"], +["0 0", "IF IF 1 ELSE 0 ENDIF ELSE IF 0 ELSE 1 ENDIF ENDIF"], + +["1 0", "NOTIF IF 1 ELSE 0 ENDIF ENDIF"], +["1 1", "NOTIF IF 1 ELSE 0 ENDIF ENDIF"], +["1 0", "NOTIF IF 1 ELSE 0 ENDIF ELSE IF 0 ELSE 1 ENDIF ENDIF"], +["0 1", "NOTIF IF 1 ELSE 0 ENDIF ELSE IF 0 ELSE 1 ENDIF ENDIF"], + +["1 1", "VERIFY"], + +["10 0 11 TOALTSTACK DROP FROMALTSTACK", "ADD 21 EQUAL"], +["'gavin_was_here' TOALTSTACK 11 FROMALTSTACK", "'gavin_was_here' EQUALVERIFY 11 EQUAL"], + +["0 IFDUP", "DEPTH 1 EQUALVERIFY 0 EQUAL"], +["1 IFDUP", "DEPTH 2 EQUALVERIFY 1 EQUALVERIFY 1 EQUAL"], +["0 DROP", "DEPTH 0 EQUAL"], +["0", "DUP 1 ADD 1 EQUALVERIFY 0 EQUAL"], +["0 1", "NIP"], +["1 0", "OVER DEPTH 3 EQUALVERIFY"], +["22 21 20", "0 PICK 20 EQUALVERIFY DEPTH 3 EQUAL"], +["22 21 20", "1 PICK 21 EQUALVERIFY DEPTH 3 EQUAL"], +["22 21 20", "2 PICK 22 EQUALVERIFY DEPTH 3 EQUAL"], +["22 21 20", "0 ROLL 20 EQUALVERIFY DEPTH 2 EQUAL"], +["22 21 20", "1 ROLL 21 EQUALVERIFY DEPTH 2 EQUAL"], +["22 21 20", "2 ROLL 22 EQUALVERIFY DEPTH 2 EQUAL"], +["22 21 20", "ROT 22 EQUAL"], +["22 21 20", "ROT DROP 20 EQUAL"], +["22 21 20", "ROT DROP DROP 21 EQUAL"], +["22 21 20", "ROT ROT 21 EQUAL"], +["22 21 20", "ROT ROT ROT 20 EQUAL"], +["25 24 23 22 21 20", "2ROT 24 EQUAL"], +["25 24 23 22 21 20", "2ROT DROP 25 EQUAL"], +["25 24 23 22 21 20", "2ROT 2DROP 20 EQUAL"], +["25 24 23 22 21 20", "2ROT 2DROP DROP 21 EQUAL"], +["25 24 23 22 21 20", "2ROT 2DROP 2DROP 22 EQUAL"], +["25 24 23 22 21 20", "2ROT 2DROP 2DROP DROP 23 EQUAL"], +["25 24 23 22 21 20", "2ROT 2ROT 22 EQUAL"], +["25 24 23 22 21 20", "2ROT 2ROT 2ROT 20 EQUAL"], +["1 0", "SWAP 1 EQUALVERIFY 0 EQUAL"], +["0 1", "TUCK DEPTH 3 EQUALVERIFY SWAP 2DROP"], +["13 14", "2DUP ROT EQUALVERIFY EQUAL"], +["-1 0 1 2", "3DUP DEPTH 7 EQUALVERIFY ADD ADD 3 EQUALVERIFY 2DROP 0 EQUALVERIFY"], +["1 2 3 5", "2OVER ADD ADD 8 EQUALVERIFY ADD ADD 6 EQUAL"], +["1 3 5 7", "2SWAP ADD 4 EQUALVERIFY ADD 12 EQUAL"], +["0", "SIZE 0 EQUAL"], +["1", "SIZE 1 EQUAL"], +["127", "SIZE 1 EQUAL"], +["128", "SIZE 2 EQUAL"], +["32767", "SIZE 2 EQUAL"], +["32768", "SIZE 3 EQUAL"], +["8388607", "SIZE 3 EQUAL"], +["8388608", "SIZE 4 EQUAL"], +["2147483647", "SIZE 4 EQUAL"], +["2147483648", "SIZE 5 EQUAL"], +["-1", "SIZE 1 EQUAL"], +["-127", "SIZE 1 EQUAL"], +["-128", "SIZE 2 EQUAL"], +["-32767", "SIZE 2 EQUAL"], +["-32768", "SIZE 3 EQUAL"], +["-8388607", "SIZE 3 EQUAL"], +["-8388608", "SIZE 4 EQUAL"], +["-2147483647", "SIZE 4 EQUAL"], +["-2147483648", "SIZE 5 EQUAL"], +["'abcdefghijklmnopqrstuvwxyz'", "SIZE 26 EQUAL"], + + +["2 -2 ADD", "0 EQUAL"], +["2147483647 -2147483647 ADD", "0 EQUAL"], +["-1 -1 ADD", "-2 EQUAL"], + +["0 0","EQUAL"], +["1 1 ADD", "2 EQUAL"], +["1 1ADD", "2 EQUAL"], +["111 1SUB", "110 EQUAL"], +["111 1 ADD 12 SUB", "100 EQUAL"], +["0 ABS", "0 EQUAL"], +["16 ABS", "16 EQUAL"], +["-16 ABS", "-16 NEGATE EQUAL"], +["0 NOT", "NOP"], +["1 NOT", "0 EQUAL"], +["11 NOT", "0 EQUAL"], +["0 0NOTEQUAL", "0 EQUAL"], +["1 0NOTEQUAL", "1 EQUAL"], +["111 0NOTEQUAL", "1 EQUAL"], +["-111 0NOTEQUAL", "1 EQUAL"], +["1 1 BOOLAND", "NOP"], +["1 0 BOOLAND", "NOT"], +["0 1 BOOLAND", "NOT"], +["0 0 BOOLAND", "NOT"], +["16 17 BOOLAND", "NOP"], +["1 1 BOOLOR", "NOP"], +["1 0 BOOLOR", "NOP"], +["0 1 BOOLOR", "NOP"], +["0 0 BOOLOR", "NOT"], +["16 17 BOOLOR", "NOP"], +["11 10 1 ADD", "NUMEQUAL"], +["11 10 1 ADD", "NUMEQUALVERIFY 1"], +["11 10 1 ADD", "NUMNOTEQUAL NOT"], +["111 10 1 ADD", "NUMNOTEQUAL"], +["11 10", "LESSTHAN NOT"], +["4 4", "LESSTHAN NOT"], +["10 11", "LESSTHAN"], +["-11 11", "LESSTHAN"], +["-11 -10", "LESSTHAN"], +["11 10", "GREATERTHAN"], +["4 4", "GREATERTHAN NOT"], +["10 11", "GREATERTHAN NOT"], +["-11 11", "GREATERTHAN NOT"], +["-11 -10", "GREATERTHAN NOT"], +["11 10", "LESSTHANOREQUAL NOT"], +["4 4", "LESSTHANOREQUAL"], +["10 11", "LESSTHANOREQUAL"], +["-11 11", "LESSTHANOREQUAL"], +["-11 -10", "LESSTHANOREQUAL"], +["11 10", "GREATERTHANOREQUAL"], +["4 4", "GREATERTHANOREQUAL"], +["10 11", "GREATERTHANOREQUAL NOT"], +["-11 11", "GREATERTHANOREQUAL NOT"], +["-11 -10", "GREATERTHANOREQUAL NOT"], +["1 0 MIN", "0 NUMEQUAL"], +["0 1 MIN", "0 NUMEQUAL"], +["-1 0 MIN", "-1 NUMEQUAL"], +["0 -2147483647 MIN", "-2147483647 NUMEQUAL"], +["2147483647 0 MAX", "2147483647 NUMEQUAL"], +["0 100 MAX", "100 NUMEQUAL"], +["-100 0 MAX", "0 NUMEQUAL"], +["0 -2147483647 MAX", "0 NUMEQUAL"], +["0 0 1", "WITHIN"], +["1 0 1", "WITHIN NOT"], +["0 -2147483647 2147483647", "WITHIN"], +["-1 -100 100", "WITHIN"], +["11 -100 100", "WITHIN"], +["-2147483647 -100 100", "WITHIN NOT"], +["2147483647 -100 100", "WITHIN NOT"], + +["2147483647 2147483647 SUB", "0 EQUAL"], +["2147483647 DUP ADD", "4294967294 EQUAL", ">32 bit EQUAL is valid"], +["2147483647 NEGATE DUP ADD", "-4294967294 EQUAL"], + +["''", "RIPEMD160 0x14 0x9c1185a5c5e9fc54612808977ee8f548b2258d31 EQUAL"], +["'a'", "RIPEMD160 0x14 0x0bdc9d2d256b3ee9daae347be6f4dc835a467ffe EQUAL"], +["'abcdefghijklmnopqrstuvwxyz'", "RIPEMD160 0x14 0xf71c27109c692c1b56bbdceb5b9d2865b3708dbc EQUAL"], +["''", "SHA1 0x14 0xda39a3ee5e6b4b0d3255bfef95601890afd80709 EQUAL"], +["'a'", "SHA1 0x14 0x86f7e437faa5a7fce15d1ddcb9eaeaea377667b8 EQUAL"], +["'abcdefghijklmnopqrstuvwxyz'", "SHA1 0x14 0x32d10c7b8cf96570ca04ce37f2a19d84240d3a89 EQUAL"], +["''", "SHA256 0x20 0xe3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 EQUAL"], +["'a'", "SHA256 0x20 0xca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb EQUAL"], +["'abcdefghijklmnopqrstuvwxyz'", "SHA256 0x20 0x71c480df93d6ae2f1efad1447c66c9525e316218cf51fc8d9ed832f2daf18b73 EQUAL"], +["''", "DUP HASH160 SWAP SHA256 RIPEMD160 EQUAL"], +["''", "DUP HASH256 SWAP SHA256 SHA256 EQUAL"], +["''", "NOP HASH160 0x14 0xb472a266d0bd89c13706a4132ccfb16f7c3b9fcb EQUAL"], +["'a'", "HASH160 NOP 0x14 0x994355199e516ff76c4fa4aab39337b9d84cf12b EQUAL"], +["'abcdefghijklmnopqrstuvwxyz'", "HASH160 0x4c 0x14 0xc286a1af0947f58d1ad787385b1c2c4a976f9e71 EQUAL"], +["''", "HASH256 0x20 0x5df6e0e2761359d30a8275058e299fcc0381534545f55cf43e41983f5d4c9456 EQUAL"], +["'a'", "HASH256 0x20 0xbf5d3affb73efd2ec6c36ad3112dd933efed63c4e1cbffcfa88e2759c144f2d8 EQUAL"], +["'abcdefghijklmnopqrstuvwxyz'", "HASH256 0x4c 0x20 0xca139bc10c2f660da42666f72e89a225936fc60f193c161124a672050c434671 EQUAL"], + + +["1","NOP1 NOP2 NOP3 NOP4 NOP5 NOP6 NOP7 NOP8 NOP9 NOP10 1 EQUAL"], +["'NOP_1_to_10' NOP1 NOP2 NOP3 NOP4 NOP5 NOP6 NOP7 NOP8 NOP9 NOP10","'NOP_1_to_10' EQUAL"], + +["0", "IF 0xba ELSE 1 ENDIF", "opcodes above NOP10 invalid if executed"], +["0", "IF 0xc0 ELSE 1 ENDIF"], +["0", "IF 0xd1 ELSE 1 ENDIF"], +["0", "IF 0xee ELSE 1 ENDIF"], +["0", "IF 0xfd ELSE 1 ENDIF"], +["0", "IF 0xff ELSE 1 ENDIF"], + +["NOP", +"'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb'", +"520 byte push"], +["1", +"0x616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", +"201 opcodes executed. 0x61 is NOP"], +["1 2 3 4 5 0x6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f", +"1 2 3 4 5 0x6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f", +"1,000 stack size (0x6f is 3DUP)"], +["1 TOALTSTACK 2 TOALTSTACK 3 4 5 0x6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f", +"1 2 3 4 5 6 7 0x6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f", +"1,000 stack size (altstack cleared between scriptSig/scriptPubKey)"], +["'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 0x6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f", +"'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 0x6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f 2DUP 0x616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", +"Max-size (10,000-byte), max-push(520 bytes), max-opcodes(201), max stack size(1,000 items). 0x6f is 3DUP, 0x61 is NOP"], + +["NOP","1"], + +["1", "0x01 0x01 EQUAL", "The following is useful for checking implementations of BN_bn2mpi"], +["127", "0x01 0x7F EQUAL"], +["128", "0x02 0x8000 EQUAL", "Leave room for the sign bit"], +["32767", "0x02 0xFF7F EQUAL"], +["32768", "0x03 0x008000 EQUAL"], +["8388607", "0x03 0xFFFF7F EQUAL"], +["8388608", "0x04 0x00008000 EQUAL"], +["2147483647", "0x04 0xFFFFFF7F EQUAL"], +["2147483648", "0x05 0x0000008000 EQUAL"], +["-1", "0x01 0x81 EQUAL", "Numbers are little-endian with the MSB being a sign bit"], +["-127", "0x01 0xFF EQUAL"], +["-128", "0x02 0x8080 EQUAL"], +["-32767", "0x02 0xFFFF EQUAL"], +["-32768", "0x03 0x008080 EQUAL"], +["-8388607", "0x03 0xFFFFFF EQUAL"], +["-8388608", "0x04 0x00008080 EQUAL"], +["-2147483647", "0x04 0xFFFFFFFF EQUAL"], +["-2147483648", "0x05 0x0000008080 EQUAL"], + +["2147483647", "1ADD 2147483648 EQUAL", "We can do math on 4-byte integers, and compare 5-byte ones"], +["2147483647", "1ADD 1"], +["-2147483647", "1ADD 1"], + + +["NOP", "NOP 1", "The following tests check the if(stack.size() < N) tests in each opcode"], +["1", "IF 1 ENDIF", "They are here to catch copy-and-paste errors"], +["0", "NOTIF 1 ENDIF", "Most of them are duplicated elsewhere,"], +["1", "VERIFY 1", "but, hey, more is always better, right?"], + +["0", "TOALTSTACK 1"], +["1", "TOALTSTACK FROMALTSTACK"], +["0 0", "2DROP 1"], +["0 1", "2DUP"], +["0 0 1", "3DUP"], +["0 1 0 0", "2OVER"], +["0 1 0 0 0 0", "2ROT"], +["0 1 0 0", "2SWAP"], +["1", "IFDUP"], +["NOP", "DEPTH 1"], +["0", "DROP 1"], +["1", "DUP"], +["0 1", "NIP"], +["1 0", "OVER"], +["1 0 0 0 3", "PICK"], +["1 0", "PICK"], +["1 0 0 0 3", "ROLL"], +["1 0", "ROLL"], +["1 0 0", "ROT"], +["1 0", "SWAP"], +["0 1", "TUCK"], + +["1", "SIZE"], + +["0 0", "EQUAL"], +["0 0", "EQUALVERIFY 1"], + +["0", "1ADD"], +["2", "1SUB"], +["-1", "NEGATE"], +["-1", "ABS"], +["0", "NOT"], +["-1", "0NOTEQUAL"], + +["1 0", "ADD"], +["1 0", "SUB"], +["-1 -1", "BOOLAND"], +["-1 0", "BOOLOR"], +["0 0", "NUMEQUAL"], +["0 0", "NUMEQUALVERIFY 1"], +["-1 0", "NUMNOTEQUAL"], +["-1 0", "LESSTHAN"], +["1 0", "GREATERTHAN"], +["0 0", "LESSTHANOREQUAL"], +["0 0", "GREATERTHANOREQUAL"], +["-1 0", "MIN"], +["1 0", "MAX"], +["-1 -1 0", "WITHIN"], + +["0", "RIPEMD160"], +["0", "SHA1"], +["0", "SHA256"], +["0", "HASH160"], +["0", "HASH256"], +["NOP", "CODESEPARATOR 1"], + +["NOP", "NOP1 1"], +["NOP", "NOP2 1"], +["NOP", "NOP3 1"], +["NOP", "NOP4 1"], +["NOP", "NOP5 1"], +["NOP", "NOP6 1"], +["NOP", "NOP7 1"], +["NOP", "NOP8 1"], +["NOP", "NOP9 1"], +["NOP", "NOP10 1"], + +["0 0x01 1", "HASH160 0x14 0xda1745e9b549bd0bfa1a569971c77eba30cd5a4b EQUAL", "Very basic P2SH"], +["0x4c 0 0x01 1", "HASH160 0x14 0xda1745e9b549bd0bfa1a569971c77eba30cd5a4b EQUAL"] +] diff --git a/src/test/data/tx_invalid.json b/src/test/data/tx_invalid.json new file mode 100644 index 0000000..f01ee06 --- /dev/null +++ b/src/test/data/tx_invalid.json @@ -0,0 +1,64 @@ +[ +["The following are deserialized transactions which are invalid."], +["They are in the form"], +["[[[prevout hash, prevout index, prevout scriptPubKey], [input 2], ...],"], +["serializedTransaction, enforceP2SH]"], +["Objects that are only a single string (like this one) are ignored"], + +["0e1b5688cf179cd9f7cbda1fac0090f6e684bbf8cd946660120197c3f3681809 but with extra junk appended to the end of the scriptPubKey"], +[[["6ca7ec7b1847f6bdbd737176050e6a08d66ccd55bb94ad24f4018024107a5827", 0, "0x41 0x043b640e983c9690a14c039a2037ecc3467b27a0dcd58f19d76c7bc118d09fec45adc5370a1c5bf8067ca9f5557a4cf885fdb0fe0dcc9c3a7137226106fbc779a5 CHECKSIG VERIFY 1"]], +"010000000127587a10248001f424ad94bb55cd6cd6086a0e05767173bdbdf647187beca76c000000004948304502201b822ad10d6adc1a341ae8835be3f70a25201bbff31f59cbb9c5353a5f0eca18022100ea7b2f7074e9aa9cf70aa8d0ffee13e6b45dddabf1ab961bda378bcdb778fa4701ffffffff0100f2052a010000001976a914fc50c5907d86fed474ba5ce8b12a66e0a4c139d888ac00000000", true], + +["This is the nearly-standard transaction with CHECKSIGVERIFY 1 instead of CHECKSIG from tx_valid.json"], +["but with the signature duplicated in the scriptPubKey with a non-standard pushdata prefix"], +["See FindAndDelete, which will only remove if it uses the same pushdata prefix as is standard"], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "DUP HASH160 0x14 0x5b6462475454710f3c22f5fdf0b40704c92f25c3 EQUALVERIFY CHECKSIGVERIFY 1 0x4c 0x47 0x3044022067288ea50aa799543a536ff9306f8e1cba05b9c6b10951175b924f96732555ed022026d7b5265f38d21541519e4a1e55044d5b9e17e15cdbaf29ae3792e99e883e7a01"]], +"01000000010001000000000000000000000000000000000000000000000000000000000000000000006a473044022067288ea50aa799543a536ff9306f8e1cba05b9c6b10951175b924f96732555ed022026d7b5265f38d21541519e4a1e55044d5b9e17e15cdbaf29ae3792e99e883e7a012103ba8c8b86dea131c22ab967e6dd99bdae8eff7a1f75a2c35f1f944109e3fe5e22ffffffff010000000000000000015100000000", true], + +["Same as above, but with the sig in the scriptSig also pushed with the same non-standard OP_PUSHDATA"], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "DUP HASH160 0x14 0x5b6462475454710f3c22f5fdf0b40704c92f25c3 EQUALVERIFY CHECKSIGVERIFY 1 0x4c 0x47 0x3044022067288ea50aa799543a536ff9306f8e1cba05b9c6b10951175b924f96732555ed022026d7b5265f38d21541519e4a1e55044d5b9e17e15cdbaf29ae3792e99e883e7a01"]], +"01000000010001000000000000000000000000000000000000000000000000000000000000000000006b4c473044022067288ea50aa799543a536ff9306f8e1cba05b9c6b10951175b924f96732555ed022026d7b5265f38d21541519e4a1e55044d5b9e17e15cdbaf29ae3792e99e883e7a012103ba8c8b86dea131c22ab967e6dd99bdae8eff7a1f75a2c35f1f944109e3fe5e22ffffffff010000000000000000015100000000", true], + +["An invalid P2SH Transaction"], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "HASH160 0x14 0x7a052c840ba73af26755de42cf01cc9e0a49fef0 EQUAL"]], +"010000000100010000000000000000000000000000000000000000000000000000000000000000000009085768617420697320ffffffff010000000000000000015100000000", true], + +["Tests for CTransaction::CheckTransaction()"], +["No inputs"], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "HASH160 0x14 0x7a052c840ba73af26755de42cf01cc9e0a49fef0 EQUAL"]], +"0100000000010000000000000000015100000000", true], + +["No outputs"], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "HASH160 0x14 0x05ab9e14d983742513f0f451e105ffb4198d1dd4 EQUAL"]], +"01000000010001000000000000000000000000000000000000000000000000000000000000000000006d483045022100f16703104aab4e4088317c862daec83440242411b039d14280e03dd33b487ab802201318a7be236672c5c56083eb7a5a195bc57a40af7923ff8545016cd3b571e2a601232103c40e5d339df3f30bf753e7e04450ae4ef76c9e45587d1d993bdc4cd06f0651c7acffffffff0000000000", true], + +["Negative output"], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "HASH160 0x14 0xae609aca8061d77c5e111f6bb62501a6bbe2bfdb EQUAL"]], +"01000000010001000000000000000000000000000000000000000000000000000000000000000000006d4830450220063222cbb128731fc09de0d7323746539166544d6c1df84d867ccea84bcc8903022100bf568e8552844de664cd41648a031554327aa8844af34b4f27397c65b92c04de0123210243ec37dee0e2e053a9c976f43147e79bc7d9dc606ea51010af1ac80db6b069e1acffffffff01ffffffffffffffff015100000000", true], + +["MAX_MONEY + 1 output"], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "HASH160 0x14 0x32afac281462b822adbec5094b8d4d337dd5bd6a EQUAL"]], +"01000000010001000000000000000000000000000000000000000000000000000000000000000000006e493046022100e1eadba00d9296c743cb6ecc703fd9ddc9b3cd12906176a226ae4c18d6b00796022100a71aef7d2874deff681ba6080f1b278bac7bb99c61b08a85f4311970ffe7f63f012321030c0588dc44d92bdcbf8e72093466766fdc265ead8db64517b0c542275b70fffbacffffffff010140075af0750700015100000000", true], + +["MAX_MONEY output + 1 output"], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "HASH160 0x14 0xb558cbf4930954aa6a344363a15668d7477ae716 EQUAL"]], +"01000000010001000000000000000000000000000000000000000000000000000000000000000000006d483045022027deccc14aa6668e78a8c9da3484fbcd4f9dcc9bb7d1b85146314b21b9ae4d86022100d0b43dece8cfb07348de0ca8bc5b86276fa88f7f2138381128b7c36ab2e42264012321029bb13463ddd5d2cc05da6e84e37536cb9525703cfd8f43afdb414988987a92f6acffffffff020040075af075070001510001000000000000015100000000", true], + +["Duplicate inputs"], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "HASH160 0x14 0x236d0639db62b0773fd8ac34dc85ae19e9aba80a EQUAL"]], +"01000000020001000000000000000000000000000000000000000000000000000000000000000000006c47304402204bb1197053d0d7799bf1b30cd503c44b58d6240cccbdc85b6fe76d087980208f02204beeed78200178ffc6c74237bb74b3f276bbb4098b5605d814304fe128bf1431012321039e8815e15952a7c3fada1905f8cf55419837133bd7756c0ef14fc8dfe50c0deaacffffffff0001000000000000000000000000000000000000000000000000000000000000000000006c47304402202306489afef52a6f62e90bf750bbcdf40c06f5c6b138286e6b6b86176bb9341802200dba98486ea68380f47ebb19a7df173b99e6bc9c681d6ccf3bde31465d1f16b3012321039e8815e15952a7c3fada1905f8cf55419837133bd7756c0ef14fc8dfe50c0deaacffffffff010000000000000000015100000000", true], + +["Coinbase of size 1"], +["Note the input is just required to make the tester happy"], +[[["0000000000000000000000000000000000000000000000000000000000000000", -1, "1"]], +"01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0151ffffffff010000000000000000015100000000", true], + +["Coinbase of size 101"], +["Note the input is just required to make the tester happy"], +[[["0000000000000000000000000000000000000000000000000000000000000000", -1, "1"]], +"01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff655151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151ffffffff010000000000000000015100000000", true], + +["Null txin"], +[[["0000000000000000000000000000000000000000000000000000000000000000", -1, "HASH160 0x14 0x02dae7dbbda56097959cba59b1989dd3e47937bf EQUAL"]], +"01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff6e49304602210086f39e028e46dafa8e1e3be63906465f4cf038fbe5ed6403dc3e74ae876e6431022100c4625c675cfc5c7e3a0e0d7eaec92ac24da20c73a88eb40d09253e51ac6def5201232103a183ddc41e84753aca47723c965d1b5c8b0e2b537963518355e6dd6cf8415e50acffffffff010000000000000000015100000000", true] +] diff --git a/src/test/data/tx_valid.json b/src/test/data/tx_valid.json new file mode 100644 index 0000000..5528ae7 --- /dev/null +++ b/src/test/data/tx_valid.json @@ -0,0 +1,71 @@ +[ +["The following are deserialized transactions which are valid."], +["They are in the form"], +["[[[prevout hash, prevout index, prevout scriptPubKey], [input 2], ...],"], +["serializedTransaction, enforceP2SH]"], +["Objects that are only a single string (like this one) are ignored"], + +["The following is 23b397edccd3740a74adb603c9756370fafcde9bcc4483eb271ecad09a94dd63"], +["It is of particular interest because it contains an invalidly-encoded signature which OpenSSL accepts"], +["See http://r6.ca/blog/20111119T211504Z.html"], +["It is also the first OP_CHECKMULTISIG transaction in standard form"], +[[["60a20bd93aa49ab4b28d514ec10b06e1829ce6818ec06cd3aabd013ebcdc4bb1", 0, "1 0x41 0x04cc71eb30d653c0c3163990c47b976f3fb3f37cccdcbedb169a1dfef58bbfbfaff7d8a473e7e2e6d317b87bafe8bde97e3cf8f065dec022b51d11fcdd0d348ac4 0x41 0x0461cbdcc5409fb4b4d42b51d33381354d80e550078cb532a34bfa2fcfdeb7d76519aecc62770f5b0e4ef8551946d8a540911abe3e7854a26f39f58b25c15342af 2 OP_CHECKMULTISIG"]], +"0100000001b14bdcbc3e01bdaad36cc08e81e69c82e1060bc14e518db2b49aa43ad90ba26000000000490047304402203f16c6f40162ab686621ef3000b04e75418a0c0cb2d8aebeac894ae360ac1e780220ddc15ecdfc3507ac48e1681a33eb60996631bf6bf5bc0a0682c4db743ce7ca2b01ffffffff0140420f00000000001976a914660d4ef3a743e3e696ad990364e555c271ad504b88ac00000000", true], + +["The following is a tweaked form of 23b397edccd3740a74adb603c9756370fafcde9bcc4483eb271ecad09a94dd63"], +["It has an arbitrary extra byte stuffed into the signature at pos length - 2"], +[[["60a20bd93aa49ab4b28d514ec10b06e1829ce6818ec06cd3aabd013ebcdc4bb1", 0, "1 0x41 0x04cc71eb30d653c0c3163990c47b976f3fb3f37cccdcbedb169a1dfef58bbfbfaff7d8a473e7e2e6d317b87bafe8bde97e3cf8f065dec022b51d11fcdd0d348ac4 0x41 0x0461cbdcc5409fb4b4d42b51d33381354d80e550078cb532a34bfa2fcfdeb7d76519aecc62770f5b0e4ef8551946d8a540911abe3e7854a26f39f58b25c15342af 2 OP_CHECKMULTISIG"]], +"0100000001b14bdcbc3e01bdaad36cc08e81e69c82e1060bc14e518db2b49aa43ad90ba260000000004A0048304402203f16c6f40162ab686621ef3000b04e75418a0c0cb2d8aebeac894ae360ac1e780220ddc15ecdfc3507ac48e1681a33eb60996631bf6bf5bc0a0682c4db743ce7ca2bab01ffffffff0140420f00000000001976a914660d4ef3a743e3e696ad990364e555c271ad504b88ac00000000", true], + +["The following is c99c49da4c38af669dea436d3e73780dfdb6c1ecf9958baa52960e8baee30e73"], +["It is of interest because it contains a 0-sequence as well as a signature of SIGHASH type 0 (which is not a real type)"], +[[["406b2b06bcd34d3c8733e6b79f7a394c8a431fbf4ff5ac705c93f4076bb77602", 0, "DUP HASH160 0x14 0xdc44b1164188067c3a32d4780f5996fa14a4f2d9 EQUALVERIFY CHECKSIG"]], +"01000000010276b76b07f4935c70acf54fbf1f438a4c397a9fb7e633873c4dd3bc062b6b40000000008c493046022100d23459d03ed7e9511a47d13292d3430a04627de6235b6e51a40f9cd386f2abe3022100e7d25b080f0bb8d8d5f878bba7d54ad2fda650ea8d158a33ee3cbd11768191fd004104b0e2c879e4daf7b9ab68350228c159766676a14f5815084ba166432aab46198d4cca98fa3e9981d0a90b2effc514b76279476550ba3663fdcaff94c38420e9d5000000000100093d00000000001976a9149a7b0f3b80c6baaeedce0a0842553800f832ba1f88ac00000000", true], + +["A nearly-standard transaction with CHECKSIGVERIFY 1 instead of CHECKSIG"], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "DUP HASH160 0x14 0x5b6462475454710f3c22f5fdf0b40704c92f25c3 EQUALVERIFY CHECKSIGVERIFY 1"]], +"01000000010001000000000000000000000000000000000000000000000000000000000000000000006a473044022067288ea50aa799543a536ff9306f8e1cba05b9c6b10951175b924f96732555ed022026d7b5265f38d21541519e4a1e55044d5b9e17e15cdbaf29ae3792e99e883e7a012103ba8c8b86dea131c22ab967e6dd99bdae8eff7a1f75a2c35f1f944109e3fe5e22ffffffff010000000000000000015100000000", true], + +["Same as above, but with the signature duplicated in the scriptPubKey with the proper pushdata prefix"], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "DUP HASH160 0x14 0x5b6462475454710f3c22f5fdf0b40704c92f25c3 EQUALVERIFY CHECKSIGVERIFY 1 0x47 0x3044022067288ea50aa799543a536ff9306f8e1cba05b9c6b10951175b924f96732555ed022026d7b5265f38d21541519e4a1e55044d5b9e17e15cdbaf29ae3792e99e883e7a01"]], +"01000000010001000000000000000000000000000000000000000000000000000000000000000000006a473044022067288ea50aa799543a536ff9306f8e1cba05b9c6b10951175b924f96732555ed022026d7b5265f38d21541519e4a1e55044d5b9e17e15cdbaf29ae3792e99e883e7a012103ba8c8b86dea131c22ab967e6dd99bdae8eff7a1f75a2c35f1f944109e3fe5e22ffffffff010000000000000000015100000000", true], + +["The following is f7fdd091fa6d8f5e7a8c2458f5c38faffff2d3f1406b6e4fe2c99dcc0d2d1cbb"], +["It caught a bug in the workaround for 23b397edccd3740a74adb603c9756370fafcde9bcc4483eb271ecad09a94dd63 in an overly simple implementation"], +[[["b464e85df2a238416f8bdae11d120add610380ea07f4ef19c5f9dfd472f96c3d", 0, "DUP HASH160 0x14 0xbef80ecf3a44500fda1bc92176e442891662aed2 EQUALVERIFY CHECKSIG"], +["b7978cc96e59a8b13e0865d3f95657561a7f725be952438637475920bac9eb21", 1, "DUP HASH160 0x14 0xbef80ecf3a44500fda1bc92176e442891662aed2 EQUALVERIFY CHECKSIG"]], +"01000000023d6cf972d4dff9c519eff407ea800361dd0a121de1da8b6f4138a2f25de864b4000000008a4730440220ffda47bfc776bcd269da4832626ac332adfca6dd835e8ecd83cd1ebe7d709b0e022049cffa1cdc102a0b56e0e04913606c70af702a1149dc3b305ab9439288fee090014104266abb36d66eb4218a6dd31f09bb92cf3cfa803c7ea72c1fc80a50f919273e613f895b855fb7465ccbc8919ad1bd4a306c783f22cd3227327694c4fa4c1c439affffffff21ebc9ba20594737864352e95b727f1a565756f9d365083eb1a8596ec98c97b7010000008a4730440220503ff10e9f1e0de731407a4a245531c9ff17676eda461f8ceeb8c06049fa2c810220c008ac34694510298fa60b3f000df01caa244f165b727d4896eb84f81e46bcc4014104266abb36d66eb4218a6dd31f09bb92cf3cfa803c7ea72c1fc80a50f919273e613f895b855fb7465ccbc8919ad1bd4a306c783f22cd3227327694c4fa4c1c439affffffff01f0da5200000000001976a914857ccd42dded6df32949d4646dfa10a92458cfaa88ac00000000", true], + +["The following tests for the presence of a bug in the handling of SIGHASH_SINGLE"], +["It results in signing the constant 1, instead of something generated based on the transaction,"], +["when the input doing the signing has an index greater than the maximum output index"], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "DUP HASH160 0x14 0xe52b482f2faa8ecbf0db344f93c84ac908557f33 EQUALVERIFY CHECKSIG"], ["0000000000000000000000000000000000000000000000000000000000000200", 0, "1"]], +"01000000020002000000000000000000000000000000000000000000000000000000000000000000000151ffffffff0001000000000000000000000000000000000000000000000000000000000000000000006b483045022100c9cdd08798a28af9d1baf44a6c77bcc7e279f47dc487c8c899911bc48feaffcc0220503c5c50ae3998a733263c5c0f7061b483e2b56c4c41b456e7d2f5a78a74c077032102d5c25adb51b61339d2b05315791e21bbe80ea470a49db0135720983c905aace0ffffffff010000000000000000015100000000", true], + +["An invalid P2SH Transaction"], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "HASH160 0x14 0x7a052c840ba73af26755de42cf01cc9e0a49fef0 EQUAL"]], +"010000000100010000000000000000000000000000000000000000000000000000000000000000000009085768617420697320ffffffff010000000000000000015100000000", false], + +["A valid P2SH Transaction using the standard transaction type put forth in BIP 16"], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "HASH160 0x14 0x8febbed40483661de6958d957412f82deed8e2f7 EQUAL"]], +"01000000010001000000000000000000000000000000000000000000000000000000000000000000006e493046022100c66c9cdf4c43609586d15424c54707156e316d88b0a1534c9e6b0d4f311406310221009c0fe51dbc9c4ab7cc25d3fdbeccf6679fe6827f08edf2b4a9f16ee3eb0e438a0123210338e8034509af564c62644c07691942e0c056752008a173c89f60ab2a88ac2ebfacffffffff010000000000000000015100000000", true], + +["Tests for CTransaction::CheckTransaction()"], +["MAX_MONEY output"], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "HASH160 0x14 0x32afac281462b822adbec5094b8d4d337dd5bd6a EQUAL"]], +"01000000010001000000000000000000000000000000000000000000000000000000000000000000006e493046022100e1eadba00d9296c743cb6ecc703fd9ddc9b3cd12906176a226ae4c18d6b00796022100a71aef7d2874deff681ba6080f1b278bac7bb99c61b08a85f4311970ffe7f63f012321030c0588dc44d92bdcbf8e72093466766fdc265ead8db64517b0c542275b70fffbacffffffff010040075af0750700015100000000", true], + +["MAX_MONEY output + 0 output"], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "HASH160 0x14 0xb558cbf4930954aa6a344363a15668d7477ae716 EQUAL"]], +"01000000010001000000000000000000000000000000000000000000000000000000000000000000006d483045022027deccc14aa6668e78a8c9da3484fbcd4f9dcc9bb7d1b85146314b21b9ae4d86022100d0b43dece8cfb07348de0ca8bc5b86276fa88f7f2138381128b7c36ab2e42264012321029bb13463ddd5d2cc05da6e84e37536cb9525703cfd8f43afdb414988987a92f6acffffffff020040075af075070001510000000000000000015100000000", true], + +["Coinbase of size 2"], +["Note the input is just required to make the tester happy"], +[[["0000000000000000000000000000000000000000000000000000000000000000", -1, "1"]], +"01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff025151ffffffff010000000000000000015100000000", true], + +["Coinbase of size 100"], +["Note the input is just required to make the tester happy"], +[[["0000000000000000000000000000000000000000000000000000000000000000", -1, "1"]], +"01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff6451515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151ffffffff010000000000000000015100000000", true] +] diff --git a/src/test/getarg_tests.cpp b/src/test/getarg_tests.cpp new file mode 100644 index 0000000..78953d2 --- /dev/null +++ b/src/test/getarg_tests.cpp @@ -0,0 +1,167 @@ +#include +#include +#include + +#include "util.h" + +BOOST_AUTO_TEST_SUITE(getarg_tests) + +static void +ResetArgs(const std::string& strArg) +{ + std::vector vecArg; + boost::split(vecArg, strArg, boost::is_space(), boost::token_compress_on); + + // Insert dummy executable name: + vecArg.insert(vecArg.begin(), "testbitcoin"); + + // Convert to char*: + std::vector vecChar; + BOOST_FOREACH(std::string& s, vecArg) + vecChar.push_back(s.c_str()); + + ParseParameters(vecChar.size(), &vecChar[0]); +} + +BOOST_AUTO_TEST_CASE(boolarg) +{ + ResetArgs("-foo"); + BOOST_CHECK(GetBoolArg("-foo")); + BOOST_CHECK(GetBoolArg("-foo", false)); + BOOST_CHECK(GetBoolArg("-foo", true)); + + BOOST_CHECK(!GetBoolArg("-fo")); + BOOST_CHECK(!GetBoolArg("-fo", false)); + BOOST_CHECK(GetBoolArg("-fo", true)); + + BOOST_CHECK(!GetBoolArg("-fooo")); + BOOST_CHECK(!GetBoolArg("-fooo", false)); + BOOST_CHECK(GetBoolArg("-fooo", true)); + + ResetArgs("-foo=0"); + BOOST_CHECK(!GetBoolArg("-foo")); + BOOST_CHECK(!GetBoolArg("-foo", false)); + BOOST_CHECK(!GetBoolArg("-foo", true)); + + ResetArgs("-foo=1"); + BOOST_CHECK(GetBoolArg("-foo")); + BOOST_CHECK(GetBoolArg("-foo", false)); + BOOST_CHECK(GetBoolArg("-foo", true)); + + // New 0.6 feature: auto-map -nosomething to !-something: + ResetArgs("-nofoo"); + BOOST_CHECK(!GetBoolArg("-foo")); + BOOST_CHECK(!GetBoolArg("-foo", false)); + BOOST_CHECK(!GetBoolArg("-foo", true)); + + ResetArgs("-nofoo=1"); + BOOST_CHECK(!GetBoolArg("-foo")); + BOOST_CHECK(!GetBoolArg("-foo", false)); + BOOST_CHECK(!GetBoolArg("-foo", true)); + + ResetArgs("-foo -nofoo"); // -foo should win + BOOST_CHECK(GetBoolArg("-foo")); + BOOST_CHECK(GetBoolArg("-foo", false)); + BOOST_CHECK(GetBoolArg("-foo", true)); + + ResetArgs("-foo=1 -nofoo=1"); // -foo should win + BOOST_CHECK(GetBoolArg("-foo")); + BOOST_CHECK(GetBoolArg("-foo", false)); + BOOST_CHECK(GetBoolArg("-foo", true)); + + ResetArgs("-foo=0 -nofoo=0"); // -foo should win + BOOST_CHECK(!GetBoolArg("-foo")); + BOOST_CHECK(!GetBoolArg("-foo", false)); + BOOST_CHECK(!GetBoolArg("-foo", true)); + + // New 0.6 feature: treat -- same as -: + ResetArgs("--foo=1"); + BOOST_CHECK(GetBoolArg("-foo")); + BOOST_CHECK(GetBoolArg("-foo", false)); + BOOST_CHECK(GetBoolArg("-foo", true)); + + ResetArgs("--nofoo=1"); + BOOST_CHECK(!GetBoolArg("-foo")); + BOOST_CHECK(!GetBoolArg("-foo", false)); + BOOST_CHECK(!GetBoolArg("-foo", true)); + +} + +BOOST_AUTO_TEST_CASE(stringarg) +{ + ResetArgs(""); + BOOST_CHECK_EQUAL(GetArg("-foo", ""), ""); + BOOST_CHECK_EQUAL(GetArg("-foo", "eleven"), "eleven"); + + ResetArgs("-foo -bar"); + BOOST_CHECK_EQUAL(GetArg("-foo", ""), ""); + BOOST_CHECK_EQUAL(GetArg("-foo", "eleven"), ""); + + ResetArgs("-foo="); + BOOST_CHECK_EQUAL(GetArg("-foo", ""), ""); + BOOST_CHECK_EQUAL(GetArg("-foo", "eleven"), ""); + + ResetArgs("-foo=11"); + BOOST_CHECK_EQUAL(GetArg("-foo", ""), "11"); + BOOST_CHECK_EQUAL(GetArg("-foo", "eleven"), "11"); + + ResetArgs("-foo=eleven"); + BOOST_CHECK_EQUAL(GetArg("-foo", ""), "eleven"); + BOOST_CHECK_EQUAL(GetArg("-foo", "eleven"), "eleven"); + +} + +BOOST_AUTO_TEST_CASE(intarg) +{ + ResetArgs(""); + BOOST_CHECK_EQUAL(GetArg("-foo", 11), 11); + BOOST_CHECK_EQUAL(GetArg("-foo", 0), 0); + + ResetArgs("-foo -bar"); + BOOST_CHECK_EQUAL(GetArg("-foo", 11), 0); + BOOST_CHECK_EQUAL(GetArg("-bar", 11), 0); + + ResetArgs("-foo=11 -bar=12"); + BOOST_CHECK_EQUAL(GetArg("-foo", 0), 11); + BOOST_CHECK_EQUAL(GetArg("-bar", 11), 12); + + ResetArgs("-foo=NaN -bar=NotANumber"); + BOOST_CHECK_EQUAL(GetArg("-foo", 1), 0); + BOOST_CHECK_EQUAL(GetArg("-bar", 11), 0); +} + +BOOST_AUTO_TEST_CASE(doubledash) +{ + ResetArgs("--foo"); + BOOST_CHECK_EQUAL(GetBoolArg("-foo"), true); + + ResetArgs("--foo=verbose --bar=1"); + BOOST_CHECK_EQUAL(GetArg("-foo", ""), "verbose"); + BOOST_CHECK_EQUAL(GetArg("-bar", 0), 1); +} + +BOOST_AUTO_TEST_CASE(boolargno) +{ + ResetArgs("-nofoo"); + BOOST_CHECK(!GetBoolArg("-foo")); + BOOST_CHECK(!GetBoolArg("-foo", true)); + BOOST_CHECK(!GetBoolArg("-foo", false)); + + ResetArgs("-nofoo=1"); + BOOST_CHECK(!GetBoolArg("-foo")); + BOOST_CHECK(!GetBoolArg("-foo", true)); + BOOST_CHECK(!GetBoolArg("-foo", false)); + + ResetArgs("-nofoo=0"); + BOOST_CHECK(GetBoolArg("-foo")); + BOOST_CHECK(GetBoolArg("-foo", true)); + BOOST_CHECK(GetBoolArg("-foo", false)); + + ResetArgs("-foo --nofoo"); + BOOST_CHECK(GetBoolArg("-foo")); + + ResetArgs("-nofoo -foo"); // foo always wins: + BOOST_CHECK(GetBoolArg("-foo")); +} + +BOOST_AUTO_TEST_SUITE_END() diff --git a/src/test/key_tests.cpp b/src/test/key_tests.cpp new file mode 100644 index 0000000..0a6df88 --- /dev/null +++ b/src/test/key_tests.cpp @@ -0,0 +1,147 @@ +#include + +#include +#include + +#include "key.h" +#include "base58.h" +#include "uint256.h" +#include "util.h" + +using namespace std; + +static const string strSecret1 ("5HxWvvfubhXpYYpS3tJkw6fq9jE9j18THftkZjHHfmFiWtmAbrj"); +static const string strSecret2 ("5KC4ejrDjv152FGwP386VD1i2NYc5KkfSMyv1nGy1VGDxGHqVY3"); +static const string strSecret1C ("Kwr371tjA9u2rFSMZjTNun2PXXP3WPZu2afRHTcta6KxEUdm1vEw"); +static const string strSecret2C ("L3Hq7a8FEQwJkW1M2GNKDW28546Vp5miewcCzSqUD9kCAXrJdS3g"); +static const CBitcoinAddress addr1 ("1QFqqMUD55ZV3PJEJZtaKCsQmjLT6JkjvJ"); +static const CBitcoinAddress addr2 ("1F5y5E5FMc5YzdJtB9hLaUe43GDxEKXENJ"); +static const CBitcoinAddress addr1C("1NoJrossxPBKfCHuJXT4HadJrXRE9Fxiqs"); +static const CBitcoinAddress addr2C("1CRj2HyM1CXWzHAXLQtiGLyggNT9WQqsDs"); + + +static const string strAddressBad("1HV9Lc3sNHZxwj4Zk6fB38tEmBryq2cBiF"); + + +#ifdef KEY_TESTS_DUMPINFO +void dumpKeyInfo(uint256 privkey) +{ + CSecret secret; + secret.resize(32); + memcpy(&secret[0], &privkey, 32); + vector sec; + sec.resize(32); + memcpy(&sec[0], &secret[0], 32); + printf(" * secret (hex): %s\n", HexStr(sec).c_str()); + + for (int nCompressed=0; nCompressed<2; nCompressed++) + { + bool fCompressed = nCompressed == 1; + printf(" * %s:\n", fCompressed ? "compressed" : "uncompressed"); + CBitcoinSecret bsecret; + bsecret.SetSecret(secret, fCompressed); + printf(" * secret (base58): %s\n", bsecret.ToString().c_str()); + CKey key; + key.SetSecret(secret, fCompressed); + vector vchPubKey = key.GetPubKey(); + printf(" * pubkey (hex): %s\n", HexStr(vchPubKey).c_str()); + printf(" * address (base58): %s\n", CBitcoinAddress(vchPubKey).ToString().c_str()); + } +} +#endif + + +BOOST_AUTO_TEST_SUITE(key_tests) + +BOOST_AUTO_TEST_CASE(key_test1) +{ + CBitcoinSecret bsecret1, bsecret2, bsecret1C, bsecret2C, baddress1; + BOOST_CHECK( bsecret1.SetString (strSecret1)); + BOOST_CHECK( bsecret2.SetString (strSecret2)); + BOOST_CHECK( bsecret1C.SetString(strSecret1C)); + BOOST_CHECK( bsecret2C.SetString(strSecret2C)); + BOOST_CHECK(!baddress1.SetString(strAddressBad)); + + bool fCompressed; + CSecret secret1 = bsecret1.GetSecret (fCompressed); + BOOST_CHECK(fCompressed == false); + CSecret secret2 = bsecret2.GetSecret (fCompressed); + BOOST_CHECK(fCompressed == false); + CSecret secret1C = bsecret1C.GetSecret(fCompressed); + BOOST_CHECK(fCompressed == true); + CSecret secret2C = bsecret2C.GetSecret(fCompressed); + BOOST_CHECK(fCompressed == true); + + BOOST_CHECK(secret1 == secret1C); + BOOST_CHECK(secret2 == secret2C); + + CKey key1, key2, key1C, key2C; + key1.SetSecret(secret1, false); + key2.SetSecret(secret2, false); + key1C.SetSecret(secret1, true); + key2C.SetSecret(secret2, true); + + BOOST_CHECK(addr1.Get() == CTxDestination(key1.GetPubKey().GetID())); + BOOST_CHECK(addr2.Get() == CTxDestination(key2.GetPubKey().GetID())); + BOOST_CHECK(addr1C.Get() == CTxDestination(key1C.GetPubKey().GetID())); + BOOST_CHECK(addr2C.Get() == CTxDestination(key2C.GetPubKey().GetID())); + + for (int n=0; n<16; n++) + { + string strMsg = strprintf("Very secret message %i: 11", n); + uint256 hashMsg = Hash(strMsg.begin(), strMsg.end()); + + // normal signatures + + vector sign1, sign2, sign1C, sign2C; + + BOOST_CHECK(key1.Sign (hashMsg, sign1)); + BOOST_CHECK(key2.Sign (hashMsg, sign2)); + BOOST_CHECK(key1C.Sign(hashMsg, sign1C)); + BOOST_CHECK(key2C.Sign(hashMsg, sign2C)); + + BOOST_CHECK( key1.Verify(hashMsg, sign1)); + BOOST_CHECK(!key1.Verify(hashMsg, sign2)); + BOOST_CHECK( key1.Verify(hashMsg, sign1C)); + BOOST_CHECK(!key1.Verify(hashMsg, sign2C)); + + BOOST_CHECK(!key2.Verify(hashMsg, sign1)); + BOOST_CHECK( key2.Verify(hashMsg, sign2)); + BOOST_CHECK(!key2.Verify(hashMsg, sign1C)); + BOOST_CHECK( key2.Verify(hashMsg, sign2C)); + + BOOST_CHECK( key1C.Verify(hashMsg, sign1)); + BOOST_CHECK(!key1C.Verify(hashMsg, sign2)); + BOOST_CHECK( key1C.Verify(hashMsg, sign1C)); + BOOST_CHECK(!key1C.Verify(hashMsg, sign2C)); + + BOOST_CHECK(!key2C.Verify(hashMsg, sign1)); + BOOST_CHECK( key2C.Verify(hashMsg, sign2)); + BOOST_CHECK(!key2C.Verify(hashMsg, sign1C)); + BOOST_CHECK( key2C.Verify(hashMsg, sign2C)); + + // compact signatures (with key recovery) + + vector csign1, csign2, csign1C, csign2C; + + BOOST_CHECK(key1.SignCompact (hashMsg, csign1)); + BOOST_CHECK(key2.SignCompact (hashMsg, csign2)); + BOOST_CHECK(key1C.SignCompact(hashMsg, csign1C)); + BOOST_CHECK(key2C.SignCompact(hashMsg, csign2C)); + + CKey rkey1, rkey2, rkey1C, rkey2C; + + BOOST_CHECK(rkey1.SetCompactSignature (hashMsg, csign1)); + BOOST_CHECK(rkey2.SetCompactSignature (hashMsg, csign2)); + BOOST_CHECK(rkey1C.SetCompactSignature(hashMsg, csign1C)); + BOOST_CHECK(rkey2C.SetCompactSignature(hashMsg, csign2C)); + + + BOOST_CHECK(rkey1.GetPubKey() == key1.GetPubKey()); + BOOST_CHECK(rkey2.GetPubKey() == key2.GetPubKey()); + BOOST_CHECK(rkey1C.GetPubKey() == key1C.GetPubKey()); + BOOST_CHECK(rkey2C.GetPubKey() == key2C.GetPubKey()); + } +} + +BOOST_AUTO_TEST_SUITE_END() diff --git a/src/test/mruset_tests.cpp b/src/test/mruset_tests.cpp new file mode 100644 index 0000000..64a6678 --- /dev/null +++ b/src/test/mruset_tests.cpp @@ -0,0 +1,90 @@ +#include + +using namespace std; + +#include "mruset.h" +#include "util.h" + +#define NUM_TESTS 16 +#define MAX_SIZE 100 + +class mrutester +{ +private: + mruset mru; + std::set set; + +public: + mrutester() { mru.max_size(MAX_SIZE); } + int size() const { return set.size(); } + + void insert(int n) + { + mru.insert(n); + set.insert(n); + BOOST_CHECK(mru == set); + } +}; + +BOOST_AUTO_TEST_SUITE(mruset_tests) + +// Test that an mruset behaves like a set, as long as no more than MAX_SIZE elements are in it +BOOST_AUTO_TEST_CASE(mruset_like_set) +{ + + for (int nTest=0; nTest mru(MAX_SIZE); + for (int nAction=0; nAction<3*MAX_SIZE; nAction++) + { + int n = GetRandInt(2 * MAX_SIZE); + mru.insert(n); + BOOST_CHECK(mru.size() <= MAX_SIZE); + } + } +} + +// 16-bit permutation function +int static permute(int n) +{ + // hexadecimals of pi; verified to be linearly independent + static const int table[16] = {0x243F, 0x6A88, 0x85A3, 0x08D3, 0x1319, 0x8A2E, 0x0370, 0x7344, + 0xA409, 0x3822, 0x299F, 0x31D0, 0x082E, 0xFA98, 0xEC4E, 0x6C89}; + + int ret = 0; + for (int bit=0; bit<16; bit++) + if (n & (1< mru(MAX_SIZE); + for (int n=0; n<10*MAX_SIZE; n++) + { + mru.insert(permute(n)); + + set tester; + for (int m=max(0,n-MAX_SIZE+1); m<=n; m++) + tester.insert(permute(m)); + + BOOST_CHECK(mru == tester); + } +} + +BOOST_AUTO_TEST_SUITE_END() diff --git a/src/test/multisig_tests.cpp b/src/test/multisig_tests.cpp new file mode 100644 index 0000000..6bc5e3b --- /dev/null +++ b/src/test/multisig_tests.cpp @@ -0,0 +1,296 @@ +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "keystore.h" +#include "main.h" +#include "script.h" +#include "wallet.h" + +using namespace std; +using namespace boost::assign; + +typedef vector valtype; + +extern uint256 SignatureHash(CScript scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType); +extern bool VerifyScript(const CScript& scriptSig, const CScript& scriptPubKey, const CTransaction& txTo, unsigned int nIn, + bool fValidatePayToScriptHash, int nHashType); + +BOOST_AUTO_TEST_SUITE(multisig_tests) + +CScript +sign_multisig(CScript scriptPubKey, vector keys, CTransaction transaction, int whichIn) +{ + uint256 hash = SignatureHash(scriptPubKey, transaction, whichIn, SIGHASH_ALL); + + CScript result; + result << OP_0; // CHECKMULTISIG bug workaround + BOOST_FOREACH(CKey key, keys) + { + vector vchSig; + BOOST_CHECK(key.Sign(hash, vchSig)); + vchSig.push_back((unsigned char)SIGHASH_ALL); + result << vchSig; + } + return result; +} + +BOOST_AUTO_TEST_CASE(multisig_verify) +{ + CKey key[4]; + for (int i = 0; i < 4; i++) + key[i].MakeNewKey(true); + + CScript a_and_b; + a_and_b << OP_2 << key[0].GetPubKey() << key[1].GetPubKey() << OP_2 << OP_CHECKMULTISIG; + + CScript a_or_b; + a_or_b << OP_1 << key[0].GetPubKey() << key[1].GetPubKey() << OP_2 << OP_CHECKMULTISIG; + + CScript escrow; + escrow << OP_2 << key[0].GetPubKey() << key[1].GetPubKey() << key[2].GetPubKey() << OP_3 << OP_CHECKMULTISIG; + + CTransaction txFrom; // Funding transaction + txFrom.vout.resize(3); + txFrom.vout[0].scriptPubKey = a_and_b; + txFrom.vout[1].scriptPubKey = a_or_b; + txFrom.vout[2].scriptPubKey = escrow; + + CTransaction txTo[3]; // Spending transaction + for (int i = 0; i < 3; i++) + { + txTo[i].vin.resize(1); + txTo[i].vout.resize(1); + txTo[i].vin[0].prevout.n = i; + txTo[i].vin[0].prevout.hash = txFrom.GetHash(); + txTo[i].vout[0].nValue = 1; + } + + vector keys; + CScript s; + + // Test a AND b: + keys.clear(); + keys += key[0],key[1]; // magic operator+= from boost.assign + s = sign_multisig(a_and_b, keys, txTo[0], 0); + BOOST_CHECK(VerifyScript(s, a_and_b, txTo[0], 0, true, 0)); + + for (int i = 0; i < 4; i++) + { + keys.clear(); + keys += key[i]; + s = sign_multisig(a_and_b, keys, txTo[0], 0); + BOOST_CHECK_MESSAGE(!VerifyScript(s, a_and_b, txTo[0], 0, true, 0), strprintf("a&b 1: %d", i)); + + keys.clear(); + keys += key[1],key[i]; + s = sign_multisig(a_and_b, keys, txTo[0], 0); + BOOST_CHECK_MESSAGE(!VerifyScript(s, a_and_b, txTo[0], 0, true, 0), strprintf("a&b 2: %d", i)); + } + + // Test a OR b: + for (int i = 0; i < 4; i++) + { + keys.clear(); + keys += key[i]; + s = sign_multisig(a_or_b, keys, txTo[1], 0); + if (i == 0 || i == 1) + BOOST_CHECK_MESSAGE(VerifyScript(s, a_or_b, txTo[1], 0, true, 0), strprintf("a|b: %d", i)); + else + BOOST_CHECK_MESSAGE(!VerifyScript(s, a_or_b, txTo[1], 0, true, 0), strprintf("a|b: %d", i)); + } + s.clear(); + s << OP_0 << OP_0; + BOOST_CHECK(!VerifyScript(s, a_or_b, txTo[1], 0, true, 0)); + s.clear(); + s << OP_0 << OP_1; + BOOST_CHECK(!VerifyScript(s, a_or_b, txTo[1], 0, true, 0)); + + + for (int i = 0; i < 4; i++) + for (int j = 0; j < 4; j++) + { + keys.clear(); + keys += key[i],key[j]; + s = sign_multisig(escrow, keys, txTo[2], 0); + if (i < j && i < 3 && j < 3) + BOOST_CHECK_MESSAGE(VerifyScript(s, escrow, txTo[2], 0, true, 0), strprintf("escrow 1: %d %d", i, j)); + else + BOOST_CHECK_MESSAGE(!VerifyScript(s, escrow, txTo[2], 0, true, 0), strprintf("escrow 2: %d %d", i, j)); + } +} + +BOOST_AUTO_TEST_CASE(multisig_IsStandard) +{ + CKey key[4]; + for (int i = 0; i < 4; i++) + key[i].MakeNewKey(true); + + CScript a_and_b; + a_and_b << OP_2 << key[0].GetPubKey() << key[1].GetPubKey() << OP_2 << OP_CHECKMULTISIG; + BOOST_CHECK(::IsStandard(a_and_b)); + + CScript a_or_b; + a_or_b << OP_1 << key[0].GetPubKey() << key[1].GetPubKey() << OP_2 << OP_CHECKMULTISIG; + BOOST_CHECK(::IsStandard(a_or_b)); + + CScript escrow; + escrow << OP_2 << key[0].GetPubKey() << key[1].GetPubKey() << key[2].GetPubKey() << OP_3 << OP_CHECKMULTISIG; + BOOST_CHECK(::IsStandard(escrow)); + + CScript one_of_four; + one_of_four << OP_1 << key[0].GetPubKey() << key[1].GetPubKey() << key[2].GetPubKey() << key[3].GetPubKey() << OP_4 << OP_CHECKMULTISIG; + BOOST_CHECK(!::IsStandard(one_of_four)); + + CScript malformed[6]; + malformed[0] << OP_3 << key[0].GetPubKey() << key[1].GetPubKey() << OP_2 << OP_CHECKMULTISIG; + malformed[1] << OP_2 << key[0].GetPubKey() << key[1].GetPubKey() << OP_3 << OP_CHECKMULTISIG; + malformed[2] << OP_0 << key[0].GetPubKey() << key[1].GetPubKey() << OP_2 << OP_CHECKMULTISIG; + malformed[3] << OP_1 << key[0].GetPubKey() << key[1].GetPubKey() << OP_0 << OP_CHECKMULTISIG; + malformed[4] << OP_1 << key[0].GetPubKey() << key[1].GetPubKey() << OP_CHECKMULTISIG; + malformed[5] << OP_1 << key[0].GetPubKey() << key[1].GetPubKey(); + + for (int i = 0; i < 6; i++) + BOOST_CHECK(!::IsStandard(malformed[i])); +} + +BOOST_AUTO_TEST_CASE(multisig_Solver1) +{ + // Tests Solver() that returns lists of keys that are + // required to satisfy a ScriptPubKey + // + // Also tests IsMine() and ExtractAddress() + // + // Note: ExtractAddress for the multisignature transactions + // always returns false for this release, even if you have + // one key that would satisfy an (a|b) or 2-of-3 keys needed + // to spend an escrow transaction. + // + CBasicKeyStore keystore, emptykeystore, partialkeystore; + CKey key[3]; + CTxDestination keyaddr[3]; + for (int i = 0; i < 3; i++) + { + key[i].MakeNewKey(true); + keystore.AddKey(key[i]); + keyaddr[i] = key[i].GetPubKey().GetID(); + } + partialkeystore.AddKey(key[0]); + + { + vector solutions; + txnouttype whichType; + CScript s; + s << key[0].GetPubKey() << OP_CHECKSIG; + BOOST_CHECK(Solver(s, whichType, solutions)); + BOOST_CHECK(solutions.size() == 1); + CTxDestination addr; + BOOST_CHECK(ExtractDestination(s, addr)); + BOOST_CHECK(addr == keyaddr[0]); + BOOST_CHECK(IsMine(keystore, s)); + BOOST_CHECK(!IsMine(emptykeystore, s)); + } + { + vector solutions; + txnouttype whichType; + CScript s; + s << OP_DUP << OP_HASH160 << key[0].GetPubKey().GetID() << OP_EQUALVERIFY << OP_CHECKSIG; + BOOST_CHECK(Solver(s, whichType, solutions)); + BOOST_CHECK(solutions.size() == 1); + CTxDestination addr; + BOOST_CHECK(ExtractDestination(s, addr)); + BOOST_CHECK(addr == keyaddr[0]); + BOOST_CHECK(IsMine(keystore, s)); + BOOST_CHECK(!IsMine(emptykeystore, s)); + } + { + vector solutions; + txnouttype whichType; + CScript s; + s << OP_2 << key[0].GetPubKey() << key[1].GetPubKey() << OP_2 << OP_CHECKMULTISIG; + BOOST_CHECK(Solver(s, whichType, solutions)); + BOOST_CHECK_EQUAL(solutions.size(), 4); + CTxDestination addr; + BOOST_CHECK(!ExtractDestination(s, addr)); + BOOST_CHECK(IsMine(keystore, s)); + BOOST_CHECK(!IsMine(emptykeystore, s)); + BOOST_CHECK(!IsMine(partialkeystore, s)); + } + { + vector solutions; + txnouttype whichType; + CScript s; + s << OP_1 << key[0].GetPubKey() << key[1].GetPubKey() << OP_2 << OP_CHECKMULTISIG; + BOOST_CHECK(Solver(s, whichType, solutions)); + BOOST_CHECK_EQUAL(solutions.size(), 4); + vector addrs; + int nRequired; + BOOST_CHECK(ExtractDestinations(s, whichType, addrs, nRequired)); + BOOST_CHECK(addrs[0] == keyaddr[0]); + BOOST_CHECK(addrs[1] == keyaddr[1]); + BOOST_CHECK(nRequired == 1); + BOOST_CHECK(IsMine(keystore, s)); + BOOST_CHECK(!IsMine(emptykeystore, s)); + BOOST_CHECK(!IsMine(partialkeystore, s)); + } + { + vector solutions; + txnouttype whichType; + CScript s; + s << OP_2 << key[0].GetPubKey() << key[1].GetPubKey() << key[2].GetPubKey() << OP_3 << OP_CHECKMULTISIG; + BOOST_CHECK(Solver(s, whichType, solutions)); + BOOST_CHECK(solutions.size() == 5); + } +} + +BOOST_AUTO_TEST_CASE(multisig_Sign) +{ + // Test SignSignature() (and therefore the version of Solver() that signs transactions) + CBasicKeyStore keystore; + CKey key[4]; + for (int i = 0; i < 4; i++) + { + key[i].MakeNewKey(true); + keystore.AddKey(key[i]); + } + + CScript a_and_b; + a_and_b << OP_2 << key[0].GetPubKey() << key[1].GetPubKey() << OP_2 << OP_CHECKMULTISIG; + + CScript a_or_b; + a_or_b << OP_1 << key[0].GetPubKey() << key[1].GetPubKey() << OP_2 << OP_CHECKMULTISIG; + + CScript escrow; + escrow << OP_2 << key[0].GetPubKey() << key[1].GetPubKey() << key[2].GetPubKey() << OP_3 << OP_CHECKMULTISIG; + + CTransaction txFrom; // Funding transaction + txFrom.vout.resize(3); + txFrom.vout[0].scriptPubKey = a_and_b; + txFrom.vout[1].scriptPubKey = a_or_b; + txFrom.vout[2].scriptPubKey = escrow; + + CTransaction txTo[3]; // Spending transaction + for (int i = 0; i < 3; i++) + { + txTo[i].vin.resize(1); + txTo[i].vout.resize(1); + txTo[i].vin[0].prevout.n = i; + txTo[i].vin[0].prevout.hash = txFrom.GetHash(); + txTo[i].vout[0].nValue = 1; + } + + for (int i = 0; i < 3; i++) + { + BOOST_CHECK_MESSAGE(SignSignature(keystore, txFrom, txTo[i], 0), strprintf("SignSignature %d", i)); + } +} + + +BOOST_AUTO_TEST_SUITE_END() diff --git a/src/test/netbase_tests.cpp b/src/test/netbase_tests.cpp new file mode 100644 index 0000000..e5a7562 --- /dev/null +++ b/src/test/netbase_tests.cpp @@ -0,0 +1,102 @@ +#include + +#include +#include + +#include "netbase.h" + +using namespace std; + +BOOST_AUTO_TEST_SUITE(netbase_tests) + +BOOST_AUTO_TEST_CASE(netbase_networks) +{ + BOOST_CHECK(CNetAddr("127.0.0.1").GetNetwork() == NET_UNROUTABLE); + BOOST_CHECK(CNetAddr("::1").GetNetwork() == NET_UNROUTABLE); + BOOST_CHECK(CNetAddr("8.8.8.8").GetNetwork() == NET_IPV4); + BOOST_CHECK(CNetAddr("2001::8888").GetNetwork() == NET_IPV6); + BOOST_CHECK(CNetAddr("FD87:D87E:EB43:edb1:8e4:3588:e546:35ca").GetNetwork() == NET_TOR); +} + +BOOST_AUTO_TEST_CASE(netbase_properties) +{ + BOOST_CHECK(CNetAddr("127.0.0.1").IsIPv4()); + BOOST_CHECK(CNetAddr("::FFFF:192.168.1.1").IsIPv4()); + BOOST_CHECK(CNetAddr("::1").IsIPv6()); + BOOST_CHECK(CNetAddr("10.0.0.1").IsRFC1918()); + BOOST_CHECK(CNetAddr("192.168.1.1").IsRFC1918()); + BOOST_CHECK(CNetAddr("172.31.255.255").IsRFC1918()); + BOOST_CHECK(CNetAddr("2001:0DB8::").IsRFC3849()); + BOOST_CHECK(CNetAddr("169.254.1.1").IsRFC3927()); + BOOST_CHECK(CNetAddr("2002::1").IsRFC3964()); + BOOST_CHECK(CNetAddr("FC00::").IsRFC4193()); + BOOST_CHECK(CNetAddr("2001::2").IsRFC4380()); + BOOST_CHECK(CNetAddr("2001:10::").IsRFC4843()); + BOOST_CHECK(CNetAddr("FE80::").IsRFC4862()); + BOOST_CHECK(CNetAddr("64:FF9B::").IsRFC6052()); + BOOST_CHECK(CNetAddr("FD87:D87E:EB43:edb1:8e4:3588:e546:35ca").IsTor()); + BOOST_CHECK(CNetAddr("127.0.0.1").IsLocal()); + BOOST_CHECK(CNetAddr("::1").IsLocal()); + BOOST_CHECK(CNetAddr("8.8.8.8").IsRoutable()); + BOOST_CHECK(CNetAddr("2001::1").IsRoutable()); + BOOST_CHECK(CNetAddr("127.0.0.1").IsValid()); +} + +bool static TestSplitHost(string test, string host, int port) +{ + string hostOut; + int portOut = -1; + SplitHostPort(test, portOut, hostOut); + return hostOut == host && port == portOut; +} + +BOOST_AUTO_TEST_CASE(netbase_splithost) +{ + BOOST_CHECK(TestSplitHost("www.bitcoin.org", "www.bitcoin.org", -1)); + BOOST_CHECK(TestSplitHost("[www.bitcoin.org]", "www.bitcoin.org", -1)); + BOOST_CHECK(TestSplitHost("www.bitcoin.org:80", "www.bitcoin.org", 80)); + BOOST_CHECK(TestSplitHost("[www.bitcoin.org]:80", "www.bitcoin.org", 80)); + BOOST_CHECK(TestSplitHost("127.0.0.1", "127.0.0.1", -1)); + BOOST_CHECK(TestSplitHost("127.0.0.1:8333", "127.0.0.1", 8333)); + BOOST_CHECK(TestSplitHost("[127.0.0.1]", "127.0.0.1", -1)); + BOOST_CHECK(TestSplitHost("[127.0.0.1]:8333", "127.0.0.1", 8333)); + BOOST_CHECK(TestSplitHost("::ffff:127.0.0.1", "::ffff:127.0.0.1", -1)); + BOOST_CHECK(TestSplitHost("[::ffff:127.0.0.1]:8333", "::ffff:127.0.0.1", 8333)); + BOOST_CHECK(TestSplitHost("[::]:8333", "::", 8333)); + BOOST_CHECK(TestSplitHost("::8333", "::8333", -1)); + BOOST_CHECK(TestSplitHost(":8333", "", 8333)); + BOOST_CHECK(TestSplitHost("[]:8333", "", 8333)); + BOOST_CHECK(TestSplitHost("", "", -1)); +} + +bool static TestParse(string src, string canon) +{ + CService addr; + if (!LookupNumeric(src.c_str(), addr, 65535)) + return canon == ""; + return canon == addr.ToString(); +} + +BOOST_AUTO_TEST_CASE(netbase_lookupnumeric) +{ + BOOST_CHECK(TestParse("127.0.0.1", "127.0.0.1:65535")); + BOOST_CHECK(TestParse("127.0.0.1:8333", "127.0.0.1:8333")); + BOOST_CHECK(TestParse("::ffff:127.0.0.1", "127.0.0.1:65535")); + BOOST_CHECK(TestParse("::", "[::]:65535")); + BOOST_CHECK(TestParse("[::]:8333", "[::]:8333")); + BOOST_CHECK(TestParse("[127.0.0.1]", "127.0.0.1:65535")); + BOOST_CHECK(TestParse(":::", "")); +} + +BOOST_AUTO_TEST_CASE(onioncat_test) +{ + // values from http://www.cypherpunk.at/onioncat/wiki/OnionCat + CNetAddr addr1("5wyqrzbvrdsumnok.onion"); + CNetAddr addr2("FD87:D87E:EB43:edb1:8e4:3588:e546:35ca"); + BOOST_CHECK(addr1 == addr2); + BOOST_CHECK(addr1.IsTor()); + BOOST_CHECK(addr1.ToStringIP() == "5wyqrzbvrdsumnok.onion"); + BOOST_CHECK(addr1.IsRoutable()); +} + +BOOST_AUTO_TEST_SUITE_END() diff --git a/src/test/rpc_tests.cpp b/src/test/rpc_tests.cpp new file mode 100644 index 0000000..505ec8f --- /dev/null +++ b/src/test/rpc_tests.cpp @@ -0,0 +1,62 @@ +#include +#include + +#include "base58.h" +#include "util.h" +#include "bitcoinrpc.h" + +using namespace std; +using namespace json_spirit; + +BOOST_AUTO_TEST_SUITE(rpc_tests) + +static Array +createArgs(int nRequired, const char* address1=NULL, const char* address2=NULL) +{ + Array result; + result.push_back(nRequired); + Array addresses; + if (address1) addresses.push_back(address1); + if (address2) addresses.push_back(address2); + result.push_back(addresses); + return result; +} + +BOOST_AUTO_TEST_CASE(rpc_addmultisig) +{ + rpcfn_type addmultisig = tableRPC["addmultisigaddress"]->actor; + + // old, 65-byte-long: + const char address1Hex[] = "0434e3e09f49ea168c5bbf53f877ff4206923858aab7c7e1df25bc263978107c95e35065a27ef6f1b27222db0ec97e0e895eaca603d3ee0d4c060ce3d8a00286c8"; + // new, compressed: + const char address2Hex[] = "0388c2037017c62240b6b72ac1a2a5f94da790596ebd06177c8572752922165cb4"; + + Value v; + CBitcoinAddress address; + BOOST_CHECK_NO_THROW(v = addmultisig(createArgs(1, address1Hex), false)); + address.SetString(v.get_str()); + BOOST_CHECK(address.IsValid() && address.IsScript()); + + BOOST_CHECK_NO_THROW(v = addmultisig(createArgs(1, address1Hex, address2Hex), false)); + address.SetString(v.get_str()); + BOOST_CHECK(address.IsValid() && address.IsScript()); + + BOOST_CHECK_NO_THROW(v = addmultisig(createArgs(2, address1Hex, address2Hex), false)); + address.SetString(v.get_str()); + BOOST_CHECK(address.IsValid() && address.IsScript()); + + BOOST_CHECK_THROW(addmultisig(createArgs(0), false), runtime_error); + BOOST_CHECK_THROW(addmultisig(createArgs(1), false), runtime_error); + BOOST_CHECK_THROW(addmultisig(createArgs(2, address1Hex), false), runtime_error); + + BOOST_CHECK_THROW(addmultisig(createArgs(1, ""), false), runtime_error); + BOOST_CHECK_THROW(addmultisig(createArgs(1, "NotAValidPubkey"), false), runtime_error); + + string short1(address1Hex, address1Hex+sizeof(address1Hex)-2); // last byte missing + BOOST_CHECK_THROW(addmultisig(createArgs(2, short1.c_str()), false), runtime_error); + + string short2(address1Hex+1, address1Hex+sizeof(address1Hex)); // first byte missing + BOOST_CHECK_THROW(addmultisig(createArgs(2, short2.c_str()), false), runtime_error); +} + +BOOST_AUTO_TEST_SUITE_END() diff --git a/src/test/script_P2SH_tests.cpp b/src/test/script_P2SH_tests.cpp new file mode 100644 index 0000000..eabfcd0 --- /dev/null +++ b/src/test/script_P2SH_tests.cpp @@ -0,0 +1,330 @@ +#include +#include +#include +#include +#include +#include + +#include "../main.h" +#include "../script.h" +#include "../wallet.h" + +using namespace std; + +// Test routines internal to script.cpp: +extern uint256 SignatureHash(CScript scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType); +extern bool VerifyScript(const CScript& scriptSig, const CScript& scriptPubKey, const CTransaction& txTo, unsigned int nIn, + bool fValidatePayToScriptHash, int nHashType); + +// Helpers: +static std::vector +Serialize(const CScript& s) +{ + std::vector sSerialized(s); + return sSerialized; +} + +static bool +Verify(const CScript& scriptSig, const CScript& scriptPubKey, bool fStrict) +{ + // Create dummy to/from transactions: + CTransaction txFrom; + txFrom.vout.resize(1); + txFrom.vout[0].scriptPubKey = scriptPubKey; + + CTransaction txTo; + txTo.vin.resize(1); + txTo.vout.resize(1); + txTo.vin[0].prevout.n = 0; + txTo.vin[0].prevout.hash = txFrom.GetHash(); + txTo.vin[0].scriptSig = scriptSig; + txTo.vout[0].nValue = 1; + + return VerifyScript(scriptSig, scriptPubKey, txTo, 0, fStrict, 0); +} + + +BOOST_AUTO_TEST_SUITE(script_P2SH_tests) + +BOOST_AUTO_TEST_CASE(sign) +{ + // Pay-to-script-hash looks like this: + // scriptSig: + // scriptPubKey: HASH160 EQUAL + + // Test SignSignature() (and therefore the version of Solver() that signs transactions) + CBasicKeyStore keystore; + CKey key[4]; + for (int i = 0; i < 4; i++) + { + key[i].MakeNewKey(true); + keystore.AddKey(key[i]); + } + + // 8 Scripts: checking all combinations of + // different keys, straight/P2SH, pubkey/pubkeyhash + CScript standardScripts[4]; + standardScripts[0] << key[0].GetPubKey() << OP_CHECKSIG; + standardScripts[1].SetDestination(key[1].GetPubKey().GetID()); + standardScripts[2] << key[1].GetPubKey() << OP_CHECKSIG; + standardScripts[3].SetDestination(key[2].GetPubKey().GetID()); + CScript evalScripts[4]; + for (int i = 0; i < 4; i++) + { + keystore.AddCScript(standardScripts[i]); + evalScripts[i].SetDestination(standardScripts[i].GetID()); + } + + CTransaction txFrom; // Funding transaction: + txFrom.vout.resize(8); + for (int i = 0; i < 4; i++) + { + txFrom.vout[i].scriptPubKey = evalScripts[i]; + txFrom.vout[i+4].scriptPubKey = standardScripts[i]; + } + BOOST_CHECK(txFrom.IsStandard()); + + CTransaction txTo[8]; // Spending transactions + for (int i = 0; i < 8; i++) + { + txTo[i].vin.resize(1); + txTo[i].vout.resize(1); + txTo[i].vin[0].prevout.n = i; + txTo[i].vin[0].prevout.hash = txFrom.GetHash(); + txTo[i].vout[0].nValue = 1; + BOOST_CHECK_MESSAGE(IsMine(keystore, txFrom.vout[i].scriptPubKey), strprintf("IsMine %d", i)); + } + for (int i = 0; i < 8; i++) + { + BOOST_CHECK_MESSAGE(SignSignature(keystore, txFrom, txTo[i], 0), strprintf("SignSignature %d", i)); + } + // All of the above should be OK, and the txTos have valid signatures + // Check to make sure signature verification fails if we use the wrong ScriptSig: + for (int i = 0; i < 8; i++) + for (int j = 0; j < 8; j++) + { + CScript sigSave = txTo[i].vin[0].scriptSig; + txTo[i].vin[0].scriptSig = txTo[j].vin[0].scriptSig; + bool sigOK = VerifySignature(txFrom, txTo[i], 0, true, 0); + if (i == j) + BOOST_CHECK_MESSAGE(sigOK, strprintf("VerifySignature %d %d", i, j)); + else + BOOST_CHECK_MESSAGE(!sigOK, strprintf("VerifySignature %d %d", i, j)); + txTo[i].vin[0].scriptSig = sigSave; + } +} + +BOOST_AUTO_TEST_CASE(norecurse) +{ + // Make sure only the outer pay-to-script-hash does the + // extra-validation thing: + CScript invalidAsScript; + invalidAsScript << OP_INVALIDOPCODE << OP_INVALIDOPCODE; + + CScript p2sh; + p2sh.SetDestination(invalidAsScript.GetID()); + + CScript scriptSig; + scriptSig << Serialize(invalidAsScript); + + // Should not verify, because it will try to execute OP_INVALIDOPCODE + BOOST_CHECK(!Verify(scriptSig, p2sh, true)); + + // Try to recur, and verification should succeed because + // the inner HASH160 <> EQUAL should only check the hash: + CScript p2sh2; + p2sh2.SetDestination(p2sh.GetID()); + CScript scriptSig2; + scriptSig2 << Serialize(invalidAsScript) << Serialize(p2sh); + + BOOST_CHECK(Verify(scriptSig2, p2sh2, true)); +} + +BOOST_AUTO_TEST_CASE(set) +{ + // Test the CScript::Set* methods + CBasicKeyStore keystore; + CKey key[4]; + std::vector keys; + for (int i = 0; i < 4; i++) + { + key[i].MakeNewKey(true); + keystore.AddKey(key[i]); + keys.push_back(key[i]); + } + + CScript inner[4]; + inner[0].SetDestination(key[0].GetPubKey().GetID()); + inner[1].SetMultisig(2, std::vector(keys.begin(), keys.begin()+2)); + inner[2].SetMultisig(1, std::vector(keys.begin(), keys.begin()+2)); + inner[3].SetMultisig(2, std::vector(keys.begin(), keys.begin()+3)); + + CScript outer[4]; + for (int i = 0; i < 4; i++) + { + outer[i].SetDestination(inner[i].GetID()); + keystore.AddCScript(inner[i]); + } + + CTransaction txFrom; // Funding transaction: + txFrom.vout.resize(4); + for (int i = 0; i < 4; i++) + { + txFrom.vout[i].scriptPubKey = outer[i]; + } + BOOST_CHECK(txFrom.IsStandard()); + + CTransaction txTo[4]; // Spending transactions + for (int i = 0; i < 4; i++) + { + txTo[i].vin.resize(1); + txTo[i].vout.resize(1); + txTo[i].vin[0].prevout.n = i; + txTo[i].vin[0].prevout.hash = txFrom.GetHash(); + txTo[i].vout[0].nValue = 1; + txTo[i].vout[0].scriptPubKey = inner[i]; + BOOST_CHECK_MESSAGE(IsMine(keystore, txFrom.vout[i].scriptPubKey), strprintf("IsMine %d", i)); + } + for (int i = 0; i < 4; i++) + { + BOOST_CHECK_MESSAGE(SignSignature(keystore, txFrom, txTo[i], 0), strprintf("SignSignature %d", i)); + BOOST_CHECK_MESSAGE(txTo[i].IsStandard(), strprintf("txTo[%d].IsStandard", i)); + } +} + +BOOST_AUTO_TEST_CASE(is) +{ + // Test CScript::IsPayToScriptHash() + uint160 dummy; + CScript p2sh; + p2sh << OP_HASH160 << dummy << OP_EQUAL; + BOOST_CHECK(p2sh.IsPayToScriptHash()); + + // Not considered pay-to-script-hash if using one of the OP_PUSHDATA opcodes: + static const unsigned char direct[] = { OP_HASH160, 20, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, OP_EQUAL }; + BOOST_CHECK(CScript(direct, direct+sizeof(direct)).IsPayToScriptHash()); + static const unsigned char pushdata1[] = { OP_HASH160, OP_PUSHDATA1, 20, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, OP_EQUAL }; + BOOST_CHECK(!CScript(pushdata1, pushdata1+sizeof(pushdata1)).IsPayToScriptHash()); + static const unsigned char pushdata2[] = { OP_HASH160, OP_PUSHDATA2, 20,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, OP_EQUAL }; + BOOST_CHECK(!CScript(pushdata2, pushdata2+sizeof(pushdata2)).IsPayToScriptHash()); + static const unsigned char pushdata4[] = { OP_HASH160, OP_PUSHDATA4, 20,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, OP_EQUAL }; + BOOST_CHECK(!CScript(pushdata4, pushdata4+sizeof(pushdata4)).IsPayToScriptHash()); + + CScript not_p2sh; + BOOST_CHECK(!not_p2sh.IsPayToScriptHash()); + + not_p2sh.clear(); not_p2sh << OP_HASH160 << dummy << dummy << OP_EQUAL; + BOOST_CHECK(!not_p2sh.IsPayToScriptHash()); + + not_p2sh.clear(); not_p2sh << OP_NOP << dummy << OP_EQUAL; + BOOST_CHECK(!not_p2sh.IsPayToScriptHash()); + + not_p2sh.clear(); not_p2sh << OP_HASH160 << dummy << OP_CHECKSIG; + BOOST_CHECK(!not_p2sh.IsPayToScriptHash()); +} + +BOOST_AUTO_TEST_CASE(switchover) +{ + // Test switch over code + CScript notValid; + notValid << OP_11 << OP_12 << OP_EQUALVERIFY; + CScript scriptSig; + scriptSig << Serialize(notValid); + + CScript fund; + fund.SetDestination(notValid.GetID()); + + + // Validation should succeed under old rules (hash is correct): + BOOST_CHECK(Verify(scriptSig, fund, false)); + // Fail under new: + BOOST_CHECK(!Verify(scriptSig, fund, true)); +} + +BOOST_AUTO_TEST_CASE(AreInputsStandard) +{ + std::map > mapInputs; + CBasicKeyStore keystore; + CKey key[3]; + vector keys; + for (int i = 0; i < 3; i++) + { + key[i].MakeNewKey(true); + keystore.AddKey(key[i]); + keys.push_back(key[i]); + } + + CTransaction txFrom; + txFrom.vout.resize(6); + + // First three are standard: + CScript pay1; pay1.SetDestination(key[0].GetPubKey().GetID()); + keystore.AddCScript(pay1); + CScript payScriptHash1; payScriptHash1.SetDestination(pay1.GetID()); + CScript pay1of3; pay1of3.SetMultisig(1, keys); + + txFrom.vout[0].scriptPubKey = payScriptHash1; + txFrom.vout[1].scriptPubKey = pay1; + txFrom.vout[2].scriptPubKey = pay1of3; + + // Last three non-standard: + CScript empty; + keystore.AddCScript(empty); + txFrom.vout[3].scriptPubKey = empty; + // Can't use SetPayToScriptHash, it checks for the empty Script. So: + txFrom.vout[4].scriptPubKey << OP_HASH160 << Hash160(empty) << OP_EQUAL; + CScript oneOfEleven; + oneOfEleven << OP_1; + for (int i = 0; i < 11; i++) + oneOfEleven << key[0].GetPubKey(); + oneOfEleven << OP_11 << OP_CHECKMULTISIG; + txFrom.vout[5].scriptPubKey.SetDestination(oneOfEleven.GetID()); + + mapInputs[txFrom.GetHash()] = make_pair(CTxIndex(), txFrom); + + CTransaction txTo; + txTo.vout.resize(1); + txTo.vout[0].scriptPubKey.SetDestination(key[1].GetPubKey().GetID()); + + txTo.vin.resize(3); + txTo.vin[0].prevout.n = 0; + txTo.vin[0].prevout.hash = txFrom.GetHash(); + BOOST_CHECK(SignSignature(keystore, txFrom, txTo, 0)); + txTo.vin[1].prevout.n = 1; + txTo.vin[1].prevout.hash = txFrom.GetHash(); + BOOST_CHECK(SignSignature(keystore, txFrom, txTo, 1)); + txTo.vin[2].prevout.n = 2; + txTo.vin[2].prevout.hash = txFrom.GetHash(); + BOOST_CHECK(SignSignature(keystore, txFrom, txTo, 2)); + + BOOST_CHECK(txTo.AreInputsStandard(mapInputs)); + BOOST_CHECK_EQUAL(txTo.GetP2SHSigOpCount(mapInputs), 1); + + // Make sure adding crap to the scriptSigs makes them non-standard: + for (int i = 0; i < 3; i++) + { + CScript t = txTo.vin[i].scriptSig; + txTo.vin[i].scriptSig = (CScript() << 11) + t; + BOOST_CHECK(!txTo.AreInputsStandard(mapInputs)); + txTo.vin[i].scriptSig = t; + } + + CTransaction txToNonStd; + txToNonStd.vout.resize(1); + txToNonStd.vout[0].scriptPubKey.SetDestination(key[1].GetPubKey().GetID()); + txToNonStd.vin.resize(2); + txToNonStd.vin[0].prevout.n = 4; + txToNonStd.vin[0].prevout.hash = txFrom.GetHash(); + txToNonStd.vin[0].scriptSig << Serialize(empty); + txToNonStd.vin[1].prevout.n = 5; + txToNonStd.vin[1].prevout.hash = txFrom.GetHash(); + txToNonStd.vin[1].scriptSig << OP_0 << Serialize(oneOfEleven); + + BOOST_CHECK(!txToNonStd.AreInputsStandard(mapInputs)); + BOOST_CHECK_EQUAL(txToNonStd.GetP2SHSigOpCount(mapInputs), 11); + + txToNonStd.vin[0].scriptSig.clear(); + BOOST_CHECK(!txToNonStd.AreInputsStandard(mapInputs)); +} + +BOOST_AUTO_TEST_SUITE_END() diff --git a/src/test/script_tests.cpp b/src/test/script_tests.cpp new file mode 100644 index 0000000..61d9a64 --- /dev/null +++ b/src/test/script_tests.cpp @@ -0,0 +1,445 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "json/json_spirit_reader_template.h" +#include "json/json_spirit_writer_template.h" +#include "json/json_spirit_utils.h" + +#include "main.h" +#include "wallet.h" + +using namespace std; +using namespace json_spirit; +using namespace boost::algorithm; + +extern uint256 SignatureHash(CScript scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType); +extern bool VerifyScript(const CScript& scriptSig, const CScript& scriptPubKey, const CTransaction& txTo, unsigned int nIn, + bool fValidatePayToScriptHash, int nHashType); + +CScript +ParseScript(string s) +{ + CScript result; + + static map mapOpNames; + + if (mapOpNames.size() == 0) + { + for (int op = OP_NOP; op <= OP_NOP10; op++) + { + const char* name = GetOpName((opcodetype)op); + if (strcmp(name, "OP_UNKNOWN") == 0) + continue; + string strName(name); + mapOpNames[strName] = (opcodetype)op; + // Convenience: OP_ADD and just ADD are both recognized: + replace_first(strName, "OP_", ""); + mapOpNames[strName] = (opcodetype)op; + } + } + + vector words; + split(words, s, is_any_of(" \t\n"), token_compress_on); + + BOOST_FOREACH(string w, words) + { + if (all(w, is_digit()) || + (starts_with(w, "-") && all(string(w.begin()+1, w.end()), is_digit()))) + { + // Number + int64 n = atoi64(w); + result << n; + } + else if (starts_with(w, "0x") && IsHex(string(w.begin()+2, w.end()))) + { + // Raw hex data, inserted NOT pushed onto stack: + std::vector raw = ParseHex(string(w.begin()+2, w.end())); + result.insert(result.end(), raw.begin(), raw.end()); + } + else if (w.size() >= 2 && starts_with(w, "'") && ends_with(w, "'")) + { + // Single-quoted string, pushed as data. NOTE: this is poor-man's + // parsing, spaces/tabs/newlines in single-quoted strings won't work. + std::vector value(w.begin()+1, w.end()-1); + result << value; + } + else if (mapOpNames.count(w)) + { + // opcode, e.g. OP_ADD or OP_1: + result << mapOpNames[w]; + } + else + { + BOOST_ERROR("Parse error: " << s); + return CScript(); + } + } + + return result; +} + +Array +read_json(const std::string& filename) +{ + namespace fs = boost::filesystem; + fs::path testFile = fs::current_path() / "test" / "data" / filename; + +#ifdef TEST_DATA_DIR + if (!fs::exists(testFile)) + { + testFile = fs::path(BOOST_PP_STRINGIZE(TEST_DATA_DIR)) / filename; + } +#endif + + ifstream ifs(testFile.string().c_str(), ifstream::in); + Value v; + if (!read_stream(ifs, v)) + { + if (ifs.fail()) + BOOST_ERROR("Cound not find/open " << filename); + else + BOOST_ERROR("JSON syntax error in " << filename); + return Array(); + } + if (v.type() != array_type) + { + BOOST_ERROR(filename << " does not contain a json array"); + return Array(); + } + + return v.get_array(); +} + +BOOST_AUTO_TEST_SUITE(script_tests) + +BOOST_AUTO_TEST_CASE(script_valid) +{ + // Read tests from test/data/script_valid.json + // Format is an array of arrays + // Inner arrays are [ "scriptSig", "scriptPubKey" ] + // ... where scriptSig and scriptPubKey are stringified + // scripts. + Array tests = read_json("script_valid.json"); + + BOOST_FOREACH(Value& tv, tests) + { + Array test = tv.get_array(); + string strTest = write_string(tv, false); + if (test.size() < 2) // Allow size > 2; extra stuff ignored (useful for comments) + { + BOOST_ERROR("Bad test: " << strTest); + continue; + } + string scriptSigString = test[0].get_str(); + CScript scriptSig = ParseScript(scriptSigString); + string scriptPubKeyString = test[1].get_str(); + CScript scriptPubKey = ParseScript(scriptPubKeyString); + + CTransaction tx; + BOOST_CHECK_MESSAGE(VerifyScript(scriptSig, scriptPubKey, tx, 0, true, SIGHASH_NONE), strTest); + } +} + +BOOST_AUTO_TEST_CASE(script_invalid) +{ + // Scripts that should evaluate as invalid + Array tests = read_json("script_invalid.json"); + + BOOST_FOREACH(Value& tv, tests) + { + Array test = tv.get_array(); + string strTest = write_string(tv, false); + if (test.size() < 2) // Allow size > 2; extra stuff ignored (useful for comments) + { + BOOST_ERROR("Bad test: " << strTest); + continue; + } + string scriptSigString = test[0].get_str(); + CScript scriptSig = ParseScript(scriptSigString); + string scriptPubKeyString = test[1].get_str(); + CScript scriptPubKey = ParseScript(scriptPubKeyString); + + CTransaction tx; + BOOST_CHECK_MESSAGE(!VerifyScript(scriptSig, scriptPubKey, tx, 0, true, SIGHASH_NONE), strTest); + } +} + +BOOST_AUTO_TEST_CASE(script_PushData) +{ + // Check that PUSHDATA1, PUSHDATA2, and PUSHDATA4 create the same value on + // the stack as the 1-75 opcodes do. + static const unsigned char direct[] = { 1, 0x5a }; + static const unsigned char pushdata1[] = { OP_PUSHDATA1, 1, 0x5a }; + static const unsigned char pushdata2[] = { OP_PUSHDATA2, 1, 0, 0x5a }; + static const unsigned char pushdata4[] = { OP_PUSHDATA4, 1, 0, 0, 0, 0x5a }; + + vector > directStack; + BOOST_CHECK(EvalScript(directStack, CScript(&direct[0], &direct[sizeof(direct)]), CTransaction(), 0, 0)); + + vector > pushdata1Stack; + BOOST_CHECK(EvalScript(pushdata1Stack, CScript(&pushdata1[0], &pushdata1[sizeof(pushdata1)]), CTransaction(), 0, 0)); + BOOST_CHECK(pushdata1Stack == directStack); + + vector > pushdata2Stack; + BOOST_CHECK(EvalScript(pushdata2Stack, CScript(&pushdata2[0], &pushdata2[sizeof(pushdata2)]), CTransaction(), 0, 0)); + BOOST_CHECK(pushdata2Stack == directStack); + + vector > pushdata4Stack; + BOOST_CHECK(EvalScript(pushdata4Stack, CScript(&pushdata4[0], &pushdata4[sizeof(pushdata4)]), CTransaction(), 0, 0)); + BOOST_CHECK(pushdata4Stack == directStack); +} + +CScript +sign_multisig(CScript scriptPubKey, std::vector keys, CTransaction transaction) +{ + uint256 hash = SignatureHash(scriptPubKey, transaction, 0, SIGHASH_ALL); + + CScript result; + // + // NOTE: CHECKMULTISIG has an unfortunate bug; it requires + // one extra item on the stack, before the signatures. + // Putting OP_0 on the stack is the workaround; + // fixing the bug would mean splitting the blockchain (old + // clients would not accept new CHECKMULTISIG transactions, + // and vice-versa) + // + result << OP_0; + BOOST_FOREACH(CKey key, keys) + { + vector vchSig; + BOOST_CHECK(key.Sign(hash, vchSig)); + vchSig.push_back((unsigned char)SIGHASH_ALL); + result << vchSig; + } + return result; +} +CScript +sign_multisig(CScript scriptPubKey, CKey key, CTransaction transaction) +{ + std::vector keys; + keys.push_back(key); + return sign_multisig(scriptPubKey, keys, transaction); +} + +BOOST_AUTO_TEST_CASE(script_CHECKMULTISIG12) +{ + CKey key1, key2, key3; + key1.MakeNewKey(true); + key2.MakeNewKey(false); + key3.MakeNewKey(true); + + CScript scriptPubKey12; + scriptPubKey12 << OP_1 << key1.GetPubKey() << key2.GetPubKey() << OP_2 << OP_CHECKMULTISIG; + + CTransaction txFrom12; + txFrom12.vout.resize(1); + txFrom12.vout[0].scriptPubKey = scriptPubKey12; + + CTransaction txTo12; + txTo12.vin.resize(1); + txTo12.vout.resize(1); + txTo12.vin[0].prevout.n = 0; + txTo12.vin[0].prevout.hash = txFrom12.GetHash(); + txTo12.vout[0].nValue = 1; + + CScript goodsig1 = sign_multisig(scriptPubKey12, key1, txTo12); + BOOST_CHECK(VerifyScript(goodsig1, scriptPubKey12, txTo12, 0, true, 0)); + txTo12.vout[0].nValue = 2; + BOOST_CHECK(!VerifyScript(goodsig1, scriptPubKey12, txTo12, 0, true, 0)); + + CScript goodsig2 = sign_multisig(scriptPubKey12, key2, txTo12); + BOOST_CHECK(VerifyScript(goodsig2, scriptPubKey12, txTo12, 0, true, 0)); + + CScript badsig1 = sign_multisig(scriptPubKey12, key3, txTo12); + BOOST_CHECK(!VerifyScript(badsig1, scriptPubKey12, txTo12, 0, true, 0)); +} + +BOOST_AUTO_TEST_CASE(script_CHECKMULTISIG23) +{ + CKey key1, key2, key3, key4; + key1.MakeNewKey(true); + key2.MakeNewKey(false); + key3.MakeNewKey(true); + key4.MakeNewKey(false); + + CScript scriptPubKey23; + scriptPubKey23 << OP_2 << key1.GetPubKey() << key2.GetPubKey() << key3.GetPubKey() << OP_3 << OP_CHECKMULTISIG; + + CTransaction txFrom23; + txFrom23.vout.resize(1); + txFrom23.vout[0].scriptPubKey = scriptPubKey23; + + CTransaction txTo23; + txTo23.vin.resize(1); + txTo23.vout.resize(1); + txTo23.vin[0].prevout.n = 0; + txTo23.vin[0].prevout.hash = txFrom23.GetHash(); + txTo23.vout[0].nValue = 1; + + std::vector keys; + keys.push_back(key1); keys.push_back(key2); + CScript goodsig1 = sign_multisig(scriptPubKey23, keys, txTo23); + BOOST_CHECK(VerifyScript(goodsig1, scriptPubKey23, txTo23, 0, true, 0)); + + keys.clear(); + keys.push_back(key1); keys.push_back(key3); + CScript goodsig2 = sign_multisig(scriptPubKey23, keys, txTo23); + BOOST_CHECK(VerifyScript(goodsig2, scriptPubKey23, txTo23, 0, true, 0)); + + keys.clear(); + keys.push_back(key2); keys.push_back(key3); + CScript goodsig3 = sign_multisig(scriptPubKey23, keys, txTo23); + BOOST_CHECK(VerifyScript(goodsig3, scriptPubKey23, txTo23, 0, true, 0)); + + keys.clear(); + keys.push_back(key2); keys.push_back(key2); // Can't re-use sig + CScript badsig1 = sign_multisig(scriptPubKey23, keys, txTo23); + BOOST_CHECK(!VerifyScript(badsig1, scriptPubKey23, txTo23, 0, true, 0)); + + keys.clear(); + keys.push_back(key2); keys.push_back(key1); // sigs must be in correct order + CScript badsig2 = sign_multisig(scriptPubKey23, keys, txTo23); + BOOST_CHECK(!VerifyScript(badsig2, scriptPubKey23, txTo23, 0, true, 0)); + + keys.clear(); + keys.push_back(key3); keys.push_back(key2); // sigs must be in correct order + CScript badsig3 = sign_multisig(scriptPubKey23, keys, txTo23); + BOOST_CHECK(!VerifyScript(badsig3, scriptPubKey23, txTo23, 0, true, 0)); + + keys.clear(); + keys.push_back(key4); keys.push_back(key2); // sigs must match pubkeys + CScript badsig4 = sign_multisig(scriptPubKey23, keys, txTo23); + BOOST_CHECK(!VerifyScript(badsig4, scriptPubKey23, txTo23, 0, true, 0)); + + keys.clear(); + keys.push_back(key1); keys.push_back(key4); // sigs must match pubkeys + CScript badsig5 = sign_multisig(scriptPubKey23, keys, txTo23); + BOOST_CHECK(!VerifyScript(badsig5, scriptPubKey23, txTo23, 0, true, 0)); + + keys.clear(); // Must have signatures + CScript badsig6 = sign_multisig(scriptPubKey23, keys, txTo23); + BOOST_CHECK(!VerifyScript(badsig6, scriptPubKey23, txTo23, 0, true, 0)); +} + +BOOST_AUTO_TEST_CASE(script_combineSigs) +{ + // Test the CombineSignatures function + CBasicKeyStore keystore; + vector keys; + for (int i = 0; i < 3; i++) + { + CKey key; + key.MakeNewKey(i%2 == 1); + keys.push_back(key); + keystore.AddKey(key); + } + + CTransaction txFrom; + txFrom.vout.resize(1); + txFrom.vout[0].scriptPubKey.SetDestination(keys[0].GetPubKey().GetID()); + CScript& scriptPubKey = txFrom.vout[0].scriptPubKey; + CTransaction txTo; + txTo.vin.resize(1); + txTo.vout.resize(1); + txTo.vin[0].prevout.n = 0; + txTo.vin[0].prevout.hash = txFrom.GetHash(); + CScript& scriptSig = txTo.vin[0].scriptSig; + txTo.vout[0].nValue = 1; + + CScript empty; + CScript combined = CombineSignatures(scriptPubKey, txTo, 0, empty, empty); + BOOST_CHECK(combined.empty()); + + // Single signature case: + SignSignature(keystore, txFrom, txTo, 0); // changes scriptSig + combined = CombineSignatures(scriptPubKey, txTo, 0, scriptSig, empty); + BOOST_CHECK(combined == scriptSig); + combined = CombineSignatures(scriptPubKey, txTo, 0, empty, scriptSig); + BOOST_CHECK(combined == scriptSig); + CScript scriptSigCopy = scriptSig; + // Signing again will give a different, valid signature: + SignSignature(keystore, txFrom, txTo, 0); + combined = CombineSignatures(scriptPubKey, txTo, 0, scriptSigCopy, scriptSig); + BOOST_CHECK(combined == scriptSigCopy || combined == scriptSig); + + // P2SH, single-signature case: + CScript pkSingle; pkSingle << keys[0].GetPubKey() << OP_CHECKSIG; + keystore.AddCScript(pkSingle); + scriptPubKey.SetDestination(pkSingle.GetID()); + SignSignature(keystore, txFrom, txTo, 0); + combined = CombineSignatures(scriptPubKey, txTo, 0, scriptSig, empty); + BOOST_CHECK(combined == scriptSig); + combined = CombineSignatures(scriptPubKey, txTo, 0, empty, scriptSig); + BOOST_CHECK(combined == scriptSig); + scriptSigCopy = scriptSig; + SignSignature(keystore, txFrom, txTo, 0); + combined = CombineSignatures(scriptPubKey, txTo, 0, scriptSigCopy, scriptSig); + BOOST_CHECK(combined == scriptSigCopy || combined == scriptSig); + // dummy scriptSigCopy with placeholder, should always choose non-placeholder: + scriptSigCopy = CScript() << OP_0 << static_cast >(pkSingle); + combined = CombineSignatures(scriptPubKey, txTo, 0, scriptSigCopy, scriptSig); + BOOST_CHECK(combined == scriptSig); + combined = CombineSignatures(scriptPubKey, txTo, 0, scriptSig, scriptSigCopy); + BOOST_CHECK(combined == scriptSig); + + // Hardest case: Multisig 2-of-3 + scriptPubKey.SetMultisig(2, keys); + keystore.AddCScript(scriptPubKey); + SignSignature(keystore, txFrom, txTo, 0); + combined = CombineSignatures(scriptPubKey, txTo, 0, scriptSig, empty); + BOOST_CHECK(combined == scriptSig); + combined = CombineSignatures(scriptPubKey, txTo, 0, empty, scriptSig); + BOOST_CHECK(combined == scriptSig); + + // A couple of partially-signed versions: + vector sig1; + uint256 hash1 = SignatureHash(scriptPubKey, txTo, 0, SIGHASH_ALL); + BOOST_CHECK(keys[0].Sign(hash1, sig1)); + sig1.push_back(SIGHASH_ALL); + vector sig2; + uint256 hash2 = SignatureHash(scriptPubKey, txTo, 0, SIGHASH_NONE); + BOOST_CHECK(keys[1].Sign(hash2, sig2)); + sig2.push_back(SIGHASH_NONE); + vector sig3; + uint256 hash3 = SignatureHash(scriptPubKey, txTo, 0, SIGHASH_SINGLE); + BOOST_CHECK(keys[2].Sign(hash3, sig3)); + sig3.push_back(SIGHASH_SINGLE); + + // Not fussy about order (or even existence) of placeholders or signatures: + CScript partial1a = CScript() << OP_0 << sig1 << OP_0; + CScript partial1b = CScript() << OP_0 << OP_0 << sig1; + CScript partial2a = CScript() << OP_0 << sig2; + CScript partial2b = CScript() << sig2 << OP_0; + CScript partial3a = CScript() << sig3; + CScript partial3b = CScript() << OP_0 << OP_0 << sig3; + CScript partial3c = CScript() << OP_0 << sig3 << OP_0; + CScript complete12 = CScript() << OP_0 << sig1 << sig2; + CScript complete13 = CScript() << OP_0 << sig1 << sig3; + CScript complete23 = CScript() << OP_0 << sig2 << sig3; + + combined = CombineSignatures(scriptPubKey, txTo, 0, partial1a, partial1b); + BOOST_CHECK(combined == partial1a); + combined = CombineSignatures(scriptPubKey, txTo, 0, partial1a, partial2a); + BOOST_CHECK(combined == complete12); + combined = CombineSignatures(scriptPubKey, txTo, 0, partial2a, partial1a); + BOOST_CHECK(combined == complete12); + combined = CombineSignatures(scriptPubKey, txTo, 0, partial1b, partial2b); + BOOST_CHECK(combined == complete12); + combined = CombineSignatures(scriptPubKey, txTo, 0, partial3b, partial1b); + BOOST_CHECK(combined == complete13); + combined = CombineSignatures(scriptPubKey, txTo, 0, partial2a, partial3a); + BOOST_CHECK(combined == complete23); + combined = CombineSignatures(scriptPubKey, txTo, 0, partial3b, partial2b); + BOOST_CHECK(combined == complete23); + combined = CombineSignatures(scriptPubKey, txTo, 0, partial3b, partial3a); + BOOST_CHECK(combined == partial3c); +} + +BOOST_AUTO_TEST_SUITE_END() diff --git a/src/test/sigopcount_tests.cpp b/src/test/sigopcount_tests.cpp new file mode 100644 index 0000000..59673f9 --- /dev/null +++ b/src/test/sigopcount_tests.cpp @@ -0,0 +1,60 @@ +#include +#include +#include + +#include "script.h" +#include "key.h" + +using namespace std; + +// Helpers: +static std::vector +Serialize(const CScript& s) +{ + std::vector sSerialized(s); + return sSerialized; +} + +BOOST_AUTO_TEST_SUITE(sigopcount_tests) + +BOOST_AUTO_TEST_CASE(GetSigOpCount) +{ + // Test CScript::GetSigOpCount() + CScript s1; + BOOST_CHECK_EQUAL(s1.GetSigOpCount(false), 0); + BOOST_CHECK_EQUAL(s1.GetSigOpCount(true), 0); + + uint160 dummy; + s1 << OP_1 << dummy << dummy << OP_2 << OP_CHECKMULTISIG; + BOOST_CHECK_EQUAL(s1.GetSigOpCount(true), 2); + s1 << OP_IF << OP_CHECKSIG << OP_ENDIF; + BOOST_CHECK_EQUAL(s1.GetSigOpCount(true), 3); + BOOST_CHECK_EQUAL(s1.GetSigOpCount(false), 21); + + CScript p2sh; + p2sh.SetDestination(s1.GetID()); + CScript scriptSig; + scriptSig << OP_0 << Serialize(s1); + BOOST_CHECK_EQUAL(p2sh.GetSigOpCount(scriptSig), 3); + + std::vector keys; + for (int i = 0; i < 3; i++) + { + CKey k; + k.MakeNewKey(true); + keys.push_back(k); + } + CScript s2; + s2.SetMultisig(1, keys); + BOOST_CHECK_EQUAL(s2.GetSigOpCount(true), 3); + BOOST_CHECK_EQUAL(s2.GetSigOpCount(false), 20); + + p2sh.SetDestination(s2.GetID()); + BOOST_CHECK_EQUAL(p2sh.GetSigOpCount(true), 0); + BOOST_CHECK_EQUAL(p2sh.GetSigOpCount(false), 0); + CScript scriptSig2; + scriptSig2 << OP_1 << dummy << dummy << Serialize(s2); + BOOST_CHECK_EQUAL(p2sh.GetSigOpCount(scriptSig2), 3); +} + +BOOST_AUTO_TEST_SUITE_END() diff --git a/src/test/test_bitcoin.cpp b/src/test/test_bitcoin.cpp new file mode 100644 index 0000000..bcf0907 --- /dev/null +++ b/src/test/test_bitcoin.cpp @@ -0,0 +1,44 @@ +#define BOOST_TEST_MODULE Bitcoin Test Suite +#include + +#include "db.h" +#include "main.h" +#include "wallet.h" + +CWallet* pwalletMain; +CClientUIInterface uiInterface; + +extern bool fPrintToConsole; +extern void noui_connect(); + +struct TestingSetup { + TestingSetup() { + fPrintToDebugger = true; // don't want to write to debug.log file + noui_connect(); + bitdb.MakeMock(); + LoadBlockIndex(true); + bool fFirstRun; + pwalletMain = new CWallet("wallet.dat"); + pwalletMain->LoadWallet(fFirstRun); + RegisterWallet(pwalletMain); + } + ~TestingSetup() + { + delete pwalletMain; + pwalletMain = NULL; + bitdb.Flush(true); + } +}; + +BOOST_GLOBAL_FIXTURE(TestingSetup); + +void Shutdown(void* parg) +{ + exit(0); +} + +void StartShutdown() +{ + exit(0); +} + diff --git a/src/test/transaction_tests.cpp b/src/test/transaction_tests.cpp new file mode 100644 index 0000000..c230458 --- /dev/null +++ b/src/test/transaction_tests.cpp @@ -0,0 +1,264 @@ +#include +#include +#include +#include "json/json_spirit_writer_template.h" + +#include "main.h" +#include "wallet.h" + +using namespace std; +using namespace json_spirit; + +// In script_tests.cpp +extern Array read_json(const std::string& filename); +extern CScript ParseScript(string s); + +BOOST_AUTO_TEST_SUITE(transaction_tests) + +BOOST_AUTO_TEST_CASE(tx_valid) +{ + // Read tests from test/data/tx_valid.json + // Format is an array of arrays + // Inner arrays are either [ "comment" ] + // or [[[prevout hash, prevout index, prevout scriptPubKey], [input 2], ...],"], serializedTransaction, enforceP2SH + // ... where all scripts are stringified scripts. + Array tests = read_json("tx_valid.json"); + + BOOST_FOREACH(Value& tv, tests) + { + Array test = tv.get_array(); + string strTest = write_string(tv, false); + if (test[0].type() == array_type) + { + if (test.size() != 3 || test[1].type() != str_type || test[2].type() != bool_type) + { + BOOST_ERROR("Bad test: " << strTest); + continue; + } + + map mapprevOutScriptPubKeys; + Array inputs = test[0].get_array(); + bool fValid = true; + BOOST_FOREACH(Value& input, inputs) + { + if (input.type() != array_type) + { + fValid = false; + break; + } + Array vinput = input.get_array(); + if (vinput.size() != 3) + { + fValid = false; + break; + } + + mapprevOutScriptPubKeys[COutPoint(uint256(vinput[0].get_str()), vinput[1].get_int())] = ParseScript(vinput[2].get_str()); + } + if (!fValid) + { + BOOST_ERROR("Bad test: " << strTest); + continue; + } + + string transaction = test[1].get_str(); + CDataStream stream(ParseHex(transaction), SER_NETWORK, PROTOCOL_VERSION); + CTransaction tx; + stream >> tx; + + BOOST_CHECK_MESSAGE(tx.CheckTransaction(), strTest); + + for (unsigned int i = 0; i < tx.vin.size(); i++) + { + if (!mapprevOutScriptPubKeys.count(tx.vin[i].prevout)) + { + BOOST_ERROR("Bad test: " << strTest); + break; + } + + BOOST_CHECK_MESSAGE(VerifyScript(tx.vin[i].scriptSig, mapprevOutScriptPubKeys[tx.vin[i].prevout], tx, i, test[2].get_bool(), 0), strTest); + } + } + } +} + +BOOST_AUTO_TEST_CASE(tx_invalid) +{ + // Read tests from test/data/tx_invalid.json + // Format is an array of arrays + // Inner arrays are either [ "comment" ] + // or [[[prevout hash, prevout index, prevout scriptPubKey], [input 2], ...],"], serializedTransaction, enforceP2SH + // ... where all scripts are stringified scripts. + Array tests = read_json("tx_invalid.json"); + + BOOST_FOREACH(Value& tv, tests) + { + Array test = tv.get_array(); + string strTest = write_string(tv, false); + if (test[0].type() == array_type) + { + if (test.size() != 3 || test[1].type() != str_type || test[2].type() != bool_type) + { + BOOST_ERROR("Bad test: " << strTest); + continue; + } + + map mapprevOutScriptPubKeys; + Array inputs = test[0].get_array(); + bool fValid = true; + BOOST_FOREACH(Value& input, inputs) + { + if (input.type() != array_type) + { + fValid = false; + break; + } + Array vinput = input.get_array(); + if (vinput.size() != 3) + { + fValid = false; + break; + } + + mapprevOutScriptPubKeys[COutPoint(uint256(vinput[0].get_str()), vinput[1].get_int())] = ParseScript(vinput[2].get_str()); + } + if (!fValid) + { + BOOST_ERROR("Bad test: " << strTest); + continue; + } + + string transaction = test[1].get_str(); + CDataStream stream(ParseHex(transaction), SER_NETWORK, PROTOCOL_VERSION); + CTransaction tx; + stream >> tx; + + fValid = tx.CheckTransaction(); + + for (unsigned int i = 0; i < tx.vin.size() && fValid; i++) + { + if (!mapprevOutScriptPubKeys.count(tx.vin[i].prevout)) + { + BOOST_ERROR("Bad test: " << strTest); + break; + } + + fValid = VerifyScript(tx.vin[i].scriptSig, mapprevOutScriptPubKeys[tx.vin[i].prevout], tx, i, test[2].get_bool(), 0); + } + + BOOST_CHECK_MESSAGE(!fValid, strTest); + } + } +} + +BOOST_AUTO_TEST_CASE(basic_transaction_tests) +{ + // Random real transaction (e2769b09e784f32f62ef849763d4f45b98e07ba658647343b915ff832b110436) + unsigned char ch[] = {0x01, 0x00, 0x00, 0x00, 0x01, 0x6b, 0xff, 0x7f, 0xcd, 0x4f, 0x85, 0x65, 0xef, 0x40, 0x6d, 0xd5, 0xd6, 0x3d, 0x4f, 0xf9, 0x4f, 0x31, 0x8f, 0xe8, 0x20, 0x27, 0xfd, 0x4d, 0xc4, 0x51, 0xb0, 0x44, 0x74, 0x01, 0x9f, 0x74, 0xb4, 0x00, 0x00, 0x00, 0x00, 0x8c, 0x49, 0x30, 0x46, 0x02, 0x21, 0x00, 0xda, 0x0d, 0xc6, 0xae, 0xce, 0xfe, 0x1e, 0x06, 0xef, 0xdf, 0x05, 0x77, 0x37, 0x57, 0xde, 0xb1, 0x68, 0x82, 0x09, 0x30, 0xe3, 0xb0, 0xd0, 0x3f, 0x46, 0xf5, 0xfc, 0xf1, 0x50, 0xbf, 0x99, 0x0c, 0x02, 0x21, 0x00, 0xd2, 0x5b, 0x5c, 0x87, 0x04, 0x00, 0x76, 0xe4, 0xf2, 0x53, 0xf8, 0x26, 0x2e, 0x76, 0x3e, 0x2d, 0xd5, 0x1e, 0x7f, 0xf0, 0xbe, 0x15, 0x77, 0x27, 0xc4, 0xbc, 0x42, 0x80, 0x7f, 0x17, 0xbd, 0x39, 0x01, 0x41, 0x04, 0xe6, 0xc2, 0x6e, 0xf6, 0x7d, 0xc6, 0x10, 0xd2, 0xcd, 0x19, 0x24, 0x84, 0x78, 0x9a, 0x6c, 0xf9, 0xae, 0xa9, 0x93, 0x0b, 0x94, 0x4b, 0x7e, 0x2d, 0xb5, 0x34, 0x2b, 0x9d, 0x9e, 0x5b, 0x9f, 0xf7, 0x9a, 0xff, 0x9a, 0x2e, 0xe1, 0x97, 0x8d, 0xd7, 0xfd, 0x01, 0xdf, 0xc5, 0x22, 0xee, 0x02, 0x28, 0x3d, 0x3b, 0x06, 0xa9, 0xd0, 0x3a, 0xcf, 0x80, 0x96, 0x96, 0x8d, 0x7d, 0xbb, 0x0f, 0x91, 0x78, 0xff, 0xff, 0xff, 0xff, 0x02, 0x8b, 0xa7, 0x94, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x19, 0x76, 0xa9, 0x14, 0xba, 0xde, 0xec, 0xfd, 0xef, 0x05, 0x07, 0x24, 0x7f, 0xc8, 0xf7, 0x42, 0x41, 0xd7, 0x3b, 0xc0, 0x39, 0x97, 0x2d, 0x7b, 0x88, 0xac, 0x40, 0x94, 0xa8, 0x02, 0x00, 0x00, 0x00, 0x00, 0x19, 0x76, 0xa9, 0x14, 0xc1, 0x09, 0x32, 0x48, 0x3f, 0xec, 0x93, 0xed, 0x51, 0xf5, 0xfe, 0x95, 0xe7, 0x25, 0x59, 0xf2, 0xcc, 0x70, 0x43, 0xf9, 0x88, 0xac, 0x00, 0x00, 0x00, 0x00, 0x00}; + vector vch(ch, ch + sizeof(ch) -1); + CDataStream stream(vch, SER_DISK, CLIENT_VERSION); + CTransaction tx; + stream >> tx; + BOOST_CHECK_MESSAGE(tx.CheckTransaction(), "Simple deserialized transaction should be valid."); + + // Check that duplicate txins fail + tx.vin.push_back(tx.vin[0]); + BOOST_CHECK_MESSAGE(!tx.CheckTransaction(), "Transaction with duplicate txins should be invalid."); +} + +// +// Helper: create two dummy transactions, each with +// two outputs. The first has 11 and 50 CENT outputs +// paid to a TX_PUBKEY, the second 21 and 22 CENT outputs +// paid to a TX_PUBKEYHASH. +// +static std::vector +SetupDummyInputs(CBasicKeyStore& keystoreRet, MapPrevTx& inputsRet) +{ + std::vector dummyTransactions; + dummyTransactions.resize(2); + + // Add some keys to the keystore: + CKey key[4]; + for (int i = 0; i < 4; i++) + { + key[i].MakeNewKey(i % 2); + keystoreRet.AddKey(key[i]); + } + + // Create some dummy input transactions + dummyTransactions[0].vout.resize(2); + dummyTransactions[0].vout[0].nValue = 11*CENT; + dummyTransactions[0].vout[0].scriptPubKey << key[0].GetPubKey() << OP_CHECKSIG; + dummyTransactions[0].vout[1].nValue = 50*CENT; + dummyTransactions[0].vout[1].scriptPubKey << key[1].GetPubKey() << OP_CHECKSIG; + inputsRet[dummyTransactions[0].GetHash()] = make_pair(CTxIndex(), dummyTransactions[0]); + + dummyTransactions[1].vout.resize(2); + dummyTransactions[1].vout[0].nValue = 21*CENT; + dummyTransactions[1].vout[0].scriptPubKey.SetDestination(key[2].GetPubKey().GetID()); + dummyTransactions[1].vout[1].nValue = 22*CENT; + dummyTransactions[1].vout[1].scriptPubKey.SetDestination(key[3].GetPubKey().GetID()); + inputsRet[dummyTransactions[1].GetHash()] = make_pair(CTxIndex(), dummyTransactions[1]); + + return dummyTransactions; +} + +BOOST_AUTO_TEST_CASE(test_Get) +{ + CBasicKeyStore keystore; + MapPrevTx dummyInputs; + std::vector dummyTransactions = SetupDummyInputs(keystore, dummyInputs); + + CTransaction t1; + t1.vin.resize(3); + t1.vin[0].prevout.hash = dummyTransactions[0].GetHash(); + t1.vin[0].prevout.n = 1; + t1.vin[0].scriptSig << std::vector(65, 0); + t1.vin[1].prevout.hash = dummyTransactions[1].GetHash(); + t1.vin[1].prevout.n = 0; + t1.vin[1].scriptSig << std::vector(65, 0) << std::vector(33, 4); + t1.vin[2].prevout.hash = dummyTransactions[1].GetHash(); + t1.vin[2].prevout.n = 1; + t1.vin[2].scriptSig << std::vector(65, 0) << std::vector(33, 4); + t1.vout.resize(2); + t1.vout[0].nValue = 90*CENT; + t1.vout[0].scriptPubKey << OP_1; + + BOOST_CHECK(t1.AreInputsStandard(dummyInputs)); + BOOST_CHECK_EQUAL(t1.GetValueIn(dummyInputs), (50+21+22)*CENT); + + // Adding extra junk to the scriptSig should make it non-standard: + t1.vin[0].scriptSig << OP_11; + BOOST_CHECK(!t1.AreInputsStandard(dummyInputs)); + + // ... as should not having enough: + t1.vin[0].scriptSig = CScript(); + BOOST_CHECK(!t1.AreInputsStandard(dummyInputs)); +} + +BOOST_AUTO_TEST_CASE(test_GetThrow) +{ + CBasicKeyStore keystore; + MapPrevTx dummyInputs; + std::vector dummyTransactions = SetupDummyInputs(keystore, dummyInputs); + + MapPrevTx missingInputs; + + CTransaction t1; + t1.vin.resize(3); + t1.vin[0].prevout.hash = dummyTransactions[0].GetHash(); + t1.vin[0].prevout.n = 0; + t1.vin[1].prevout.hash = dummyTransactions[1].GetHash();; + t1.vin[1].prevout.n = 0; + t1.vin[2].prevout.hash = dummyTransactions[1].GetHash();; + t1.vin[2].prevout.n = 1; + t1.vout.resize(2); + t1.vout[0].nValue = 90*CENT; + t1.vout[0].scriptPubKey << OP_1; + + BOOST_CHECK_THROW(t1.AreInputsStandard(missingInputs), runtime_error); + BOOST_CHECK_THROW(t1.GetValueIn(missingInputs), runtime_error); +} + +BOOST_AUTO_TEST_SUITE_END() diff --git a/src/test/uint160_tests.cpp b/src/test/uint160_tests.cpp new file mode 100644 index 0000000..35cb35b --- /dev/null +++ b/src/test/uint160_tests.cpp @@ -0,0 +1,18 @@ +#include + +#include "uint256.h" + +BOOST_AUTO_TEST_SUITE(uint160_tests) + +BOOST_AUTO_TEST_CASE(uint160_equality) +{ + uint160 num1 = 10; + uint160 num2 = 11; + BOOST_CHECK(num1+1 == num2); + + uint64 num3 = 10; + BOOST_CHECK(num1 == num3); + BOOST_CHECK(num1+num2 == num3+num2); +} + +BOOST_AUTO_TEST_SUITE_END() diff --git a/src/test/uint256_tests.cpp b/src/test/uint256_tests.cpp new file mode 100644 index 0000000..efdc8a6 --- /dev/null +++ b/src/test/uint256_tests.cpp @@ -0,0 +1,18 @@ +#include + +#include "uint256.h" + +BOOST_AUTO_TEST_SUITE(uint256_tests) + +BOOST_AUTO_TEST_CASE(uint256_equality) +{ + uint256 num1 = 10; + uint256 num2 = 11; + BOOST_CHECK(num1+1 == num2); + + uint64 num3 = 10; + BOOST_CHECK(num1 == num3); + BOOST_CHECK(num1+num2 == num3+num2); +} + +BOOST_AUTO_TEST_SUITE_END() diff --git a/src/test/util_tests.cpp b/src/test/util_tests.cpp new file mode 100644 index 0000000..8b0702e --- /dev/null +++ b/src/test/util_tests.cpp @@ -0,0 +1,326 @@ +#include +#include +#include + +#include "main.h" +#include "wallet.h" +#include "util.h" + +using namespace std; + +BOOST_AUTO_TEST_SUITE(util_tests) + +BOOST_AUTO_TEST_CASE(util_criticalsection) +{ + CCriticalSection cs; + + do { + LOCK(cs); + break; + + BOOST_ERROR("break was swallowed!"); + } while(0); + + do { + TRY_LOCK(cs, lockTest); + if (lockTest) + break; + + BOOST_ERROR("break was swallowed!"); + } while(0); +} + +BOOST_AUTO_TEST_CASE(util_MedianFilter) +{ + CMedianFilter filter(5, 15); + + BOOST_CHECK_EQUAL(filter.median(), 15); + + filter.input(20); // [15 20] + BOOST_CHECK_EQUAL(filter.median(), 17); + + filter.input(30); // [15 20 30] + BOOST_CHECK_EQUAL(filter.median(), 20); + + filter.input(3); // [3 15 20 30] + BOOST_CHECK_EQUAL(filter.median(), 17); + + filter.input(7); // [3 7 15 20 30] + BOOST_CHECK_EQUAL(filter.median(), 15); + + filter.input(18); // [3 7 18 20 30] + BOOST_CHECK_EQUAL(filter.median(), 18); + + filter.input(0); // [0 3 7 18 30] + BOOST_CHECK_EQUAL(filter.median(), 7); +} + +static const unsigned char ParseHex_expected[65] = { + 0x04, 0x67, 0x8a, 0xfd, 0xb0, 0xfe, 0x55, 0x48, 0x27, 0x19, 0x67, 0xf1, 0xa6, 0x71, 0x30, 0xb7, + 0x10, 0x5c, 0xd6, 0xa8, 0x28, 0xe0, 0x39, 0x09, 0xa6, 0x79, 0x62, 0xe0, 0xea, 0x1f, 0x61, 0xde, + 0xb6, 0x49, 0xf6, 0xbc, 0x3f, 0x4c, 0xef, 0x38, 0xc4, 0xf3, 0x55, 0x04, 0xe5, 0x1e, 0xc1, 0x12, + 0xde, 0x5c, 0x38, 0x4d, 0xf7, 0xba, 0x0b, 0x8d, 0x57, 0x8a, 0x4c, 0x70, 0x2b, 0x6b, 0xf1, 0x1d, + 0x5f +}; +BOOST_AUTO_TEST_CASE(util_ParseHex) +{ + std::vector result; + std::vector expected(ParseHex_expected, ParseHex_expected + sizeof(ParseHex_expected)); + // Basic test vector + result = ParseHex("04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5f"); + BOOST_CHECK_EQUAL_COLLECTIONS(result.begin(), result.end(), expected.begin(), expected.end()); + + // Spaces between bytes must be supported + result = ParseHex("12 34 56 78"); + BOOST_CHECK(result.size() == 4 && result[0] == 0x12 && result[1] == 0x34 && result[2] == 0x56 && result[3] == 0x78); + + // Stop parsing at invalid value + result = ParseHex("1234 invalid 1234"); + BOOST_CHECK(result.size() == 2 && result[0] == 0x12 && result[1] == 0x34); +} + +BOOST_AUTO_TEST_CASE(util_HexStr) +{ + BOOST_CHECK_EQUAL( + HexStr(ParseHex_expected, ParseHex_expected + sizeof(ParseHex_expected)), + "04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5f"); + + BOOST_CHECK_EQUAL( + HexStr(ParseHex_expected, ParseHex_expected + 5, true), + "04 67 8a fd b0"); + + BOOST_CHECK_EQUAL( + HexStr(ParseHex_expected, ParseHex_expected, true), + ""); + + std::vector ParseHex_vec(ParseHex_expected, ParseHex_expected + 5); + + BOOST_CHECK_EQUAL( + HexStr(ParseHex_vec, true), + "04 67 8a fd b0"); +} + + +BOOST_AUTO_TEST_CASE(util_DateTimeStrFormat) +{ +/*These are platform-dependant and thus removed to avoid useless test failures + BOOST_CHECK_EQUAL(DateTimeStrFormat("%x %H:%M:%S", 0), "01/01/70 00:00:00"); + BOOST_CHECK_EQUAL(DateTimeStrFormat("%x %H:%M:%S", 0x7FFFFFFF), "01/19/38 03:14:07"); + // Formats used within Bitcoin + BOOST_CHECK_EQUAL(DateTimeStrFormat("%x %H:%M:%S", 1317425777), "09/30/11 23:36:17"); + BOOST_CHECK_EQUAL(DateTimeStrFormat("%x %H:%M", 1317425777), "09/30/11 23:36"); +*/ +} + +BOOST_AUTO_TEST_CASE(util_ParseParameters) +{ + const char *argv_test[] = {"-ignored", "-a", "-b", "-ccc=argument", "-ccc=multiple", "f", "-d=e"}; + + ParseParameters(0, (char**)argv_test); + BOOST_CHECK(mapArgs.empty() && mapMultiArgs.empty()); + + ParseParameters(1, (char**)argv_test); + BOOST_CHECK(mapArgs.empty() && mapMultiArgs.empty()); + + ParseParameters(5, (char**)argv_test); + // expectation: -ignored is ignored (program name argument), + // -a, -b and -ccc end up in map, -d ignored because it is after + // a non-option argument (non-GNU option parsing) + BOOST_CHECK(mapArgs.size() == 3 && mapMultiArgs.size() == 3); + BOOST_CHECK(mapArgs.count("-a") && mapArgs.count("-b") && mapArgs.count("-ccc") + && !mapArgs.count("f") && !mapArgs.count("-d")); + BOOST_CHECK(mapMultiArgs.count("-a") && mapMultiArgs.count("-b") && mapMultiArgs.count("-ccc") + && !mapMultiArgs.count("f") && !mapMultiArgs.count("-d")); + + BOOST_CHECK(mapArgs["-a"] == "" && mapArgs["-ccc"] == "multiple"); + BOOST_CHECK(mapMultiArgs["-ccc"].size() == 2); +} + +BOOST_AUTO_TEST_CASE(util_GetArg) +{ + mapArgs.clear(); + mapArgs["strtest1"] = "string..."; + // strtest2 undefined on purpose + mapArgs["inttest1"] = "12345"; + mapArgs["inttest2"] = "81985529216486895"; + // inttest3 undefined on purpose + mapArgs["booltest1"] = ""; + // booltest2 undefined on purpose + mapArgs["booltest3"] = "0"; + mapArgs["booltest4"] = "1"; + + BOOST_CHECK_EQUAL(GetArg("strtest1", "default"), "string..."); + BOOST_CHECK_EQUAL(GetArg("strtest2", "default"), "default"); + BOOST_CHECK_EQUAL(GetArg("inttest1", -1), 12345); + BOOST_CHECK_EQUAL(GetArg("inttest2", -1), 81985529216486895LL); + BOOST_CHECK_EQUAL(GetArg("inttest3", -1), -1); + BOOST_CHECK_EQUAL(GetBoolArg("booltest1"), true); + BOOST_CHECK_EQUAL(GetBoolArg("booltest2"), false); + BOOST_CHECK_EQUAL(GetBoolArg("booltest3"), false); + BOOST_CHECK_EQUAL(GetBoolArg("booltest4"), true); +} + +BOOST_AUTO_TEST_CASE(util_WildcardMatch) +{ + BOOST_CHECK(WildcardMatch("127.0.0.1", "*")); + BOOST_CHECK(WildcardMatch("127.0.0.1", "127.*")); + BOOST_CHECK(WildcardMatch("abcdef", "a?cde?")); + BOOST_CHECK(!WildcardMatch("abcdef", "a?cde??")); + BOOST_CHECK(WildcardMatch("abcdef", "a*f")); + BOOST_CHECK(!WildcardMatch("abcdef", "a*x")); + BOOST_CHECK(WildcardMatch("", "*")); +} + +BOOST_AUTO_TEST_CASE(util_FormatMoney) +{ + BOOST_CHECK_EQUAL(FormatMoney(0, false), "0.00"); + BOOST_CHECK_EQUAL(FormatMoney((COIN/10000)*123456789, false), "12345.6789"); + BOOST_CHECK_EQUAL(FormatMoney(COIN, true), "+1.00"); + BOOST_CHECK_EQUAL(FormatMoney(-COIN, false), "-1.00"); + BOOST_CHECK_EQUAL(FormatMoney(-COIN, true), "-1.00"); + + BOOST_CHECK_EQUAL(FormatMoney(COIN*100000000, false), "100000000.00"); + BOOST_CHECK_EQUAL(FormatMoney(COIN*10000000, false), "10000000.00"); + BOOST_CHECK_EQUAL(FormatMoney(COIN*1000000, false), "1000000.00"); + BOOST_CHECK_EQUAL(FormatMoney(COIN*100000, false), "100000.00"); + BOOST_CHECK_EQUAL(FormatMoney(COIN*10000, false), "10000.00"); + BOOST_CHECK_EQUAL(FormatMoney(COIN*1000, false), "1000.00"); + BOOST_CHECK_EQUAL(FormatMoney(COIN*100, false), "100.00"); + BOOST_CHECK_EQUAL(FormatMoney(COIN*10, false), "10.00"); + BOOST_CHECK_EQUAL(FormatMoney(COIN, false), "1.00"); + BOOST_CHECK_EQUAL(FormatMoney(COIN/10, false), "0.10"); + BOOST_CHECK_EQUAL(FormatMoney(COIN/100, false), "0.01"); + BOOST_CHECK_EQUAL(FormatMoney(COIN/1000, false), "0.001"); + BOOST_CHECK_EQUAL(FormatMoney(COIN/10000, false), "0.0001"); + BOOST_CHECK_EQUAL(FormatMoney(COIN/100000, false), "0.00001"); + BOOST_CHECK_EQUAL(FormatMoney(COIN/1000000, false), "0.000001"); + BOOST_CHECK_EQUAL(FormatMoney(COIN/10000000, false), "0.0000001"); + BOOST_CHECK_EQUAL(FormatMoney(COIN/100000000, false), "0.00000001"); +} + +BOOST_AUTO_TEST_CASE(util_ParseMoney) +{ + int64 ret = 0; + BOOST_CHECK(ParseMoney("0.0", ret)); + BOOST_CHECK_EQUAL(ret, 0); + + BOOST_CHECK(ParseMoney("12345.6789", ret)); + BOOST_CHECK_EQUAL(ret, (COIN/10000)*123456789); + + BOOST_CHECK(ParseMoney("100000000.00", ret)); + BOOST_CHECK_EQUAL(ret, COIN*100000000); + BOOST_CHECK(ParseMoney("10000000.00", ret)); + BOOST_CHECK_EQUAL(ret, COIN*10000000); + BOOST_CHECK(ParseMoney("1000000.00", ret)); + BOOST_CHECK_EQUAL(ret, COIN*1000000); + BOOST_CHECK(ParseMoney("100000.00", ret)); + BOOST_CHECK_EQUAL(ret, COIN*100000); + BOOST_CHECK(ParseMoney("10000.00", ret)); + BOOST_CHECK_EQUAL(ret, COIN*10000); + BOOST_CHECK(ParseMoney("1000.00", ret)); + BOOST_CHECK_EQUAL(ret, COIN*1000); + BOOST_CHECK(ParseMoney("100.00", ret)); + BOOST_CHECK_EQUAL(ret, COIN*100); + BOOST_CHECK(ParseMoney("10.00", ret)); + BOOST_CHECK_EQUAL(ret, COIN*10); + BOOST_CHECK(ParseMoney("1.00", ret)); + BOOST_CHECK_EQUAL(ret, COIN); + BOOST_CHECK(ParseMoney("0.1", ret)); + BOOST_CHECK_EQUAL(ret, COIN/10); + BOOST_CHECK(ParseMoney("0.01", ret)); + BOOST_CHECK_EQUAL(ret, COIN/100); + BOOST_CHECK(ParseMoney("0.001", ret)); + BOOST_CHECK_EQUAL(ret, COIN/1000); + BOOST_CHECK(ParseMoney("0.0001", ret)); + BOOST_CHECK_EQUAL(ret, COIN/10000); + BOOST_CHECK(ParseMoney("0.00001", ret)); + BOOST_CHECK_EQUAL(ret, COIN/100000); + BOOST_CHECK(ParseMoney("0.000001", ret)); + BOOST_CHECK_EQUAL(ret, COIN/1000000); + BOOST_CHECK(ParseMoney("0.0000001", ret)); + BOOST_CHECK_EQUAL(ret, COIN/10000000); + BOOST_CHECK(ParseMoney("0.00000001", ret)); + BOOST_CHECK_EQUAL(ret, COIN/100000000); + + // Attempted 63 bit overflow should fail + BOOST_CHECK(!ParseMoney("92233720368.54775808", ret)); +} + +BOOST_AUTO_TEST_CASE(util_IsHex) +{ + BOOST_CHECK(IsHex("00")); + BOOST_CHECK(IsHex("00112233445566778899aabbccddeeffAABBCCDDEEFF")); + BOOST_CHECK(IsHex("ff")); + BOOST_CHECK(IsHex("FF")); + + BOOST_CHECK(!IsHex("")); + BOOST_CHECK(!IsHex("0")); + BOOST_CHECK(!IsHex("a")); + BOOST_CHECK(!IsHex("eleven")); + BOOST_CHECK(!IsHex("00xx00")); + BOOST_CHECK(!IsHex("0x0000")); +} + +BOOST_AUTO_TEST_CASE(util_seed_insecure_rand) +{ + // Expected results for the determinstic seed. + const uint32_t exp_vals[11] = { 91632771U,1889679809U,3842137544U,3256031132U, + 1761911779U, 489223532U,2692793790U,2737472863U, + 2796262275U,1309899767U,840571781U}; + // Expected 0s in rand()%(idx+2) for the determinstic seed. + const int exp_count[9] = {5013,3346,2415,1972,1644,1386,1176,1096,1009}; + int i; + int count=0; + + seed_insecure_rand(); + + //Does the non-determistic rand give us results that look too like the determinstic one? + for (i=0;i<10;i++) + { + int match = 0; + uint32_t rval = insecure_rand(); + for (int j=0;j<11;j++)match |= rval==exp_vals[j]; + count += match; + } + // sum(binomial(10,i)*(11/(2^32))^i*(1-(11/(2^32)))^(10-i),i,0,4) ~= 1-1/2^134.73 + // So _very_ unlikely to throw a false failure here. + BOOST_CHECK(count<=4); + + for (int mod=2;mod<11;mod++) + { + int mask = 1; + // Really rough binomal confidence approximation. + int err = 30*10000./mod*sqrt((1./mod*(1-1./mod))/10000.); + //mask is 2^ceil(log2(mod))-1 + while(mask=(uint32_t)mod); + count += rval==0; + } + BOOST_CHECK(count<=10000/mod+err); + BOOST_CHECK(count>=10000/mod-err); + } + + seed_insecure_rand(true); + + for (i=0;i<11;i++) + { + BOOST_CHECK_EQUAL(insecure_rand(),exp_vals[i]); + } + + for (int mod=2;mod<11;mod++) + { + count = 0; + for (i=0;i<10000;i++) count += insecure_rand()%mod==0; + BOOST_CHECK_EQUAL(count,exp_count[mod-2]); + } +} + +BOOST_AUTO_TEST_SUITE_END() diff --git a/src/test/wallet_tests.cpp b/src/test/wallet_tests.cpp new file mode 100644 index 0000000..b0b3c47 --- /dev/null +++ b/src/test/wallet_tests.cpp @@ -0,0 +1,295 @@ +#include + +#include "main.h" +#include "wallet.h" + +// how many times to run all the tests to have a chance to catch errors that only show up with particular random shuffles +#define RUN_TESTS 100 + +// some tests fail 1% of the time due to bad luck. +// we repeat those tests this many times and only complain if all iterations of the test fail +#define RANDOM_REPEATS 5 + +using namespace std; + +typedef set > CoinSet; + +BOOST_AUTO_TEST_SUITE(wallet_tests) + +static CWallet wallet; +static vector vCoins; + +static void add_coin(int64 nValue, int nAge = 6*24, bool fIsFromMe = false, int nInput=0) +{ + static int i; + CTransaction* tx = new CTransaction; + tx->nLockTime = i++; // so all transactions get different hashes + tx->vout.resize(nInput+1); + tx->vout[nInput].nValue = nValue; + CWalletTx* wtx = new CWalletTx(&wallet, *tx); + delete tx; + if (fIsFromMe) + { + // IsFromMe() returns (GetDebit() > 0), and GetDebit() is 0 if vin.empty(), + // so stop vin being empty, and cache a non-zero Debit to fake out IsFromMe() + wtx->vin.resize(1); + wtx->fDebitCached = true; + wtx->nDebitCached = 1; + } + COutput output(wtx, nInput, nAge); + vCoins.push_back(output); +} + +static void empty_wallet(void) +{ + BOOST_FOREACH(COutput output, vCoins) + delete output.tx; + vCoins.clear(); +} + +static bool equal_sets(CoinSet a, CoinSet b) +{ + pair ret = mismatch(a.begin(), a.end(), b.begin()); + return ret.first == a.end() && ret.second == b.end(); +} + +BOOST_AUTO_TEST_CASE(coin_selection_tests) +{ + static CoinSet setCoinsRet, setCoinsRet2; + static int64 nValueRet; + + // test multiple times to allow for differences in the shuffle order + for (int i = 0; i < RUN_TESTS; i++) + { + empty_wallet(); + + // with an empty wallet we can't even pay one cent + BOOST_CHECK(!wallet.SelectCoinsMinConf( 1 * CENT, 1, 6, vCoins, setCoinsRet, nValueRet)); + + add_coin(1*CENT, 4); // add a new 1 cent coin + + // with a new 1 cent coin, we still can't find a mature 1 cent + BOOST_CHECK(!wallet.SelectCoinsMinConf( 1 * CENT, 1, 6, vCoins, setCoinsRet, nValueRet)); + + // but we can find a new 1 cent + BOOST_CHECK( wallet.SelectCoinsMinConf( 1 * CENT, 1, 1, vCoins, setCoinsRet, nValueRet)); + BOOST_CHECK_EQUAL(nValueRet, 1 * CENT); + + add_coin(2*CENT); // add a mature 2 cent coin + + // we can't make 3 cents of mature coins + BOOST_CHECK(!wallet.SelectCoinsMinConf( 3 * CENT, 1, 6, vCoins, setCoinsRet, nValueRet)); + + // we can make 3 cents of new coins + BOOST_CHECK( wallet.SelectCoinsMinConf( 3 * CENT, 1, 1, vCoins, setCoinsRet, nValueRet)); + BOOST_CHECK_EQUAL(nValueRet, 3 * CENT); + + add_coin(5*CENT); // add a mature 5 cent coin, + add_coin(10*CENT, 3, true); // a new 10 cent coin sent from one of our own addresses + add_coin(20*CENT); // and a mature 20 cent coin + + // now we have new: 1+10=11 (of which 10 was self-sent), and mature: 2+5+20=27. total = 38 + + // we can't make 38 cents only if we disallow new coins: + BOOST_CHECK(!wallet.SelectCoinsMinConf(38 * CENT, 1, 6, vCoins, setCoinsRet, nValueRet)); + // we can't even make 37 cents if we don't allow new coins even if they're from us + BOOST_CHECK(!wallet.SelectCoinsMinConf(38 * CENT, 6, 6, vCoins, setCoinsRet, nValueRet)); + // but we can make 37 cents if we accept new coins from ourself + BOOST_CHECK( wallet.SelectCoinsMinConf(37 * CENT, 1, 6, vCoins, setCoinsRet, nValueRet)); + BOOST_CHECK_EQUAL(nValueRet, 37 * CENT); + // and we can make 38 cents if we accept all new coins + BOOST_CHECK( wallet.SelectCoinsMinConf(38 * CENT, 1, 1, vCoins, setCoinsRet, nValueRet)); + BOOST_CHECK_EQUAL(nValueRet, 38 * CENT); + + // try making 34 cents from 1,2,5,10,20 - we can't do it exactly + BOOST_CHECK( wallet.SelectCoinsMinConf(34 * CENT, 1, 1, vCoins, setCoinsRet, nValueRet)); + BOOST_CHECK_GT(nValueRet, 34 * CENT); // but should get more than 34 cents + BOOST_CHECK_EQUAL(setCoinsRet.size(), 3); // the best should be 20+10+5. it's incredibly unlikely the 1 or 2 got included (but possible) + + // when we try making 7 cents, the smaller coins (1,2,5) are enough. We should see just 2+5 + BOOST_CHECK( wallet.SelectCoinsMinConf( 7 * CENT, 1, 1, vCoins, setCoinsRet, nValueRet)); + BOOST_CHECK_EQUAL(nValueRet, 7 * CENT); + BOOST_CHECK_EQUAL(setCoinsRet.size(), 2); + + // when we try making 8 cents, the smaller coins (1,2,5) are exactly enough. + BOOST_CHECK( wallet.SelectCoinsMinConf( 8 * CENT, 1, 1, vCoins, setCoinsRet, nValueRet)); + BOOST_CHECK(nValueRet == 8 * CENT); + BOOST_CHECK_EQUAL(setCoinsRet.size(), 3); + + // when we try making 9 cents, no subset of smaller coins is enough, and we get the next bigger coin (10) + BOOST_CHECK( wallet.SelectCoinsMinConf( 9 * CENT, 1, 1, vCoins, setCoinsRet, nValueRet)); + BOOST_CHECK_EQUAL(nValueRet, 10 * CENT); + BOOST_CHECK_EQUAL(setCoinsRet.size(), 1); + + // now clear out the wallet and start again to test choosing between subsets of smaller coins and the next biggest coin + empty_wallet(); + + add_coin( 6*CENT); + add_coin( 7*CENT); + add_coin( 8*CENT); + add_coin(20*CENT); + add_coin(30*CENT); // now we have 6+7+8+20+30 = 71 cents total + + // check that we have 71 and not 72 + BOOST_CHECK( wallet.SelectCoinsMinConf(71 * CENT, 1, 1, vCoins, setCoinsRet, nValueRet)); + BOOST_CHECK(!wallet.SelectCoinsMinConf(72 * CENT, 1, 1, vCoins, setCoinsRet, nValueRet)); + + // now try making 16 cents. the best smaller coins can do is 6+7+8 = 21; not as good at the next biggest coin, 20 + BOOST_CHECK( wallet.SelectCoinsMinConf(16 * CENT, 1, 1, vCoins, setCoinsRet, nValueRet)); + BOOST_CHECK_EQUAL(nValueRet, 20 * CENT); // we should get 20 in one coin + BOOST_CHECK_EQUAL(setCoinsRet.size(), 1); + + add_coin( 5*CENT); // now we have 5+6+7+8+20+30 = 75 cents total + + // now if we try making 16 cents again, the smaller coins can make 5+6+7 = 18 cents, better than the next biggest coin, 20 + BOOST_CHECK( wallet.SelectCoinsMinConf(16 * CENT, 1, 1, vCoins, setCoinsRet, nValueRet)); + BOOST_CHECK_EQUAL(nValueRet, 18 * CENT); // we should get 18 in 3 coins + BOOST_CHECK_EQUAL(setCoinsRet.size(), 3); + + add_coin( 18*CENT); // now we have 5+6+7+8+18+20+30 + + // and now if we try making 16 cents again, the smaller coins can make 5+6+7 = 18 cents, the same as the next biggest coin, 18 + BOOST_CHECK( wallet.SelectCoinsMinConf(16 * CENT, 1, 1, vCoins, setCoinsRet, nValueRet)); + BOOST_CHECK_EQUAL(nValueRet, 18 * CENT); // we should get 18 in 1 coin + BOOST_CHECK_EQUAL(setCoinsRet.size(), 1); // because in the event of a tie, the biggest coin wins + + // now try making 11 cents. we should get 5+6 + BOOST_CHECK( wallet.SelectCoinsMinConf(11 * CENT, 1, 1, vCoins, setCoinsRet, nValueRet)); + BOOST_CHECK_EQUAL(nValueRet, 11 * CENT); + BOOST_CHECK_EQUAL(setCoinsRet.size(), 2); + + // check that the smallest bigger coin is used + add_coin( 1*COIN); + add_coin( 2*COIN); + add_coin( 3*COIN); + add_coin( 4*COIN); // now we have 5+6+7+8+18+20+30+100+200+300+400 = 1094 cents + BOOST_CHECK( wallet.SelectCoinsMinConf(95 * CENT, 1, 1, vCoins, setCoinsRet, nValueRet)); + BOOST_CHECK_EQUAL(nValueRet, 1 * COIN); // we should get 1 BTC in 1 coin + BOOST_CHECK_EQUAL(setCoinsRet.size(), 1); + + BOOST_CHECK( wallet.SelectCoinsMinConf(195 * CENT, 1, 1, vCoins, setCoinsRet, nValueRet)); + BOOST_CHECK_EQUAL(nValueRet, 2 * COIN); // we should get 2 BTC in 1 coin + BOOST_CHECK_EQUAL(setCoinsRet.size(), 1); + + // empty the wallet and start again, now with fractions of a cent, to test sub-cent change avoidance + empty_wallet(); + add_coin(0.1*CENT); + add_coin(0.2*CENT); + add_coin(0.3*CENT); + add_coin(0.4*CENT); + add_coin(0.5*CENT); + + // try making 1 cent from 0.1 + 0.2 + 0.3 + 0.4 + 0.5 = 1.5 cents + // we'll get sub-cent change whatever happens, so can expect 1.0 exactly + BOOST_CHECK( wallet.SelectCoinsMinConf(1 * CENT, 1, 1, vCoins, setCoinsRet, nValueRet)); + BOOST_CHECK_EQUAL(nValueRet, 1 * CENT); + + // but if we add a bigger coin, making it possible to avoid sub-cent change, things change: + add_coin(1111*CENT); + + // try making 1 cent from 0.1 + 0.2 + 0.3 + 0.4 + 0.5 + 1111 = 1112.5 cents + BOOST_CHECK( wallet.SelectCoinsMinConf(1 * CENT, 1, 1, vCoins, setCoinsRet, nValueRet)); + BOOST_CHECK_EQUAL(nValueRet, 1 * CENT); // we should get the exact amount + + // if we add more sub-cent coins: + add_coin(0.6*CENT); + add_coin(0.7*CENT); + + // and try again to make 1.0 cents, we can still make 1.0 cents + BOOST_CHECK( wallet.SelectCoinsMinConf(1 * CENT, 1, 1, vCoins, setCoinsRet, nValueRet)); + BOOST_CHECK_EQUAL(nValueRet, 1 * CENT); // we should get the exact amount + + // run the 'mtgox' test (see http://blockexplorer.com/tx/29a3efd3ef04f9153d47a990bd7b048a4b2d213daaa5fb8ed670fb85f13bdbcf) + // they tried to consolidate 10 50k coins into one 500k coin, and ended up with 50k in change + empty_wallet(); + for (int i = 0; i < 20; i++) + add_coin(50000 * COIN); + + BOOST_CHECK( wallet.SelectCoinsMinConf(500000 * COIN, 1, 1, vCoins, setCoinsRet, nValueRet)); + BOOST_CHECK_EQUAL(nValueRet, 500000 * COIN); // we should get the exact amount + BOOST_CHECK_EQUAL(setCoinsRet.size(), 10); // in ten coins + + // if there's not enough in the smaller coins to make at least 1 cent change (0.5+0.6+0.7 < 1.0+1.0), + // we need to try finding an exact subset anyway + + // sometimes it will fail, and so we use the next biggest coin: + empty_wallet(); + add_coin(0.5 * CENT); + add_coin(0.6 * CENT); + add_coin(0.7 * CENT); + add_coin(1111 * CENT); + BOOST_CHECK( wallet.SelectCoinsMinConf(1 * CENT, 1, 1, vCoins, setCoinsRet, nValueRet)); + BOOST_CHECK_EQUAL(nValueRet, 1111 * CENT); // we get the bigger coin + BOOST_CHECK_EQUAL(setCoinsRet.size(), 1); + + // but sometimes it's possible, and we use an exact subset (0.4 + 0.6 = 1.0) + empty_wallet(); + add_coin(0.4 * CENT); + add_coin(0.6 * CENT); + add_coin(0.8 * CENT); + add_coin(1111 * CENT); + BOOST_CHECK( wallet.SelectCoinsMinConf(1 * CENT, 1, 1, vCoins, setCoinsRet, nValueRet)); + BOOST_CHECK_EQUAL(nValueRet, 1 * CENT); // we should get the exact amount + BOOST_CHECK_EQUAL(setCoinsRet.size(), 2); // in two coins 0.4+0.6 + + // test avoiding sub-cent change + empty_wallet(); + add_coin(0.0005 * COIN); + add_coin(0.01 * COIN); + add_coin(1 * COIN); + + // trying to make 1.0001 from these three coins + BOOST_CHECK( wallet.SelectCoinsMinConf(1.0001 * COIN, 1, 1, vCoins, setCoinsRet, nValueRet)); + BOOST_CHECK_EQUAL(nValueRet, 1.0105 * COIN); // we should get all coins + BOOST_CHECK_EQUAL(setCoinsRet.size(), 3); + + // but if we try to make 0.999, we should take the bigger of the two small coins to avoid sub-cent change + BOOST_CHECK( wallet.SelectCoinsMinConf(0.999 * COIN, 1, 1, vCoins, setCoinsRet, nValueRet)); + BOOST_CHECK_EQUAL(nValueRet, 1.01 * COIN); // we should get 1 + 0.01 + BOOST_CHECK_EQUAL(setCoinsRet.size(), 2); + + // test randomness + { + empty_wallet(); + for (int i2 = 0; i2 < 100; i2++) + add_coin(COIN); + + // picking 50 from 100 coins doesn't depend on the shuffle, + // but does depend on randomness in the stochastic approximation code + BOOST_CHECK(wallet.SelectCoinsMinConf(50 * COIN, 1, 6, vCoins, setCoinsRet , nValueRet)); + BOOST_CHECK(wallet.SelectCoinsMinConf(50 * COIN, 1, 6, vCoins, setCoinsRet2, nValueRet)); + BOOST_CHECK(!equal_sets(setCoinsRet, setCoinsRet2)); + + int fails = 0; + for (int i = 0; i < RANDOM_REPEATS; i++) + { + // selecting 1 from 100 identical coins depends on the shuffle; this test will fail 1% of the time + // run the test RANDOM_REPEATS times and only complain if all of them fail + BOOST_CHECK(wallet.SelectCoinsMinConf(COIN, 1, 6, vCoins, setCoinsRet , nValueRet)); + BOOST_CHECK(wallet.SelectCoinsMinConf(COIN, 1, 6, vCoins, setCoinsRet2, nValueRet)); + if (equal_sets(setCoinsRet, setCoinsRet2)) + fails++; + } + BOOST_CHECK_NE(fails, RANDOM_REPEATS); + + // add 75 cents in small change. not enough to make 90 cents, + // then try making 90 cents. there are multiple competing "smallest bigger" coins, + // one of which should be picked at random + add_coin( 5*CENT); add_coin(10*CENT); add_coin(15*CENT); add_coin(20*CENT); add_coin(25*CENT); + + fails = 0; + for (int i = 0; i < RANDOM_REPEATS; i++) + { + // selecting 1 from 100 identical coins depends on the shuffle; this test will fail 1% of the time + // run the test RANDOM_REPEATS times and only complain if all of them fail + BOOST_CHECK(wallet.SelectCoinsMinConf(90*CENT, 1, 6, vCoins, setCoinsRet , nValueRet)); + BOOST_CHECK(wallet.SelectCoinsMinConf(90*CENT, 1, 6, vCoins, setCoinsRet2, nValueRet)); + if (equal_sets(setCoinsRet, setCoinsRet2)) + fails++; + } + BOOST_CHECK_NE(fails, RANDOM_REPEATS); + } + } +} + +BOOST_AUTO_TEST_SUITE_END() diff --git a/src/threadsafety.h b/src/threadsafety.h new file mode 100644 index 0000000..176060a --- /dev/null +++ b/src/threadsafety.h @@ -0,0 +1,54 @@ +// Copyright (c) 2009-2010 Satoshi Nakamoto +// Copyright (c) 2009-2012 The Bitcoin developers +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifndef BITCOIN_THREADSAFETY_H +#define BITCOIN_THREADSAFETY_H + +#ifdef __clang__ +// TL;DR Add GUARDED_BY(mutex) to member variables. The others are +// rarely necessary. Ex: int nFoo GUARDED_BY(cs_foo); +// +// See http://clang.llvm.org/docs/LanguageExtensions.html#threadsafety +// for documentation. The clang compiler can do advanced static analysis +// of locking when given the -Wthread-safety option. +#define LOCKABLE __attribute__ ((lockable)) +#define SCOPED_LOCKABLE __attribute__ ((scoped_lockable)) +#define GUARDED_BY(x) __attribute__ ((guarded_by(x))) +#define GUARDED_VAR __attribute__ ((guarded_var)) +#define PT_GUARDED_BY(x) __attribute__ ((pt_guarded_by(x))) +#define PT_GUARDED_VAR __attribute__ ((pt_guarded_var)) +#define ACQUIRED_AFTER(...) __attribute__ ((acquired_after(__VA_ARGS__))) +#define ACQUIRED_BEFORE(...) __attribute__ ((acquired_before(__VA_ARGS__))) +#define EXCLUSIVE_LOCK_FUNCTION(...) __attribute__ ((exclusive_lock_function(__VA_ARGS__))) +#define SHARED_LOCK_FUNCTION(...) __attribute__ ((shared_lock_function(__VA_ARGS__))) +#define EXCLUSIVE_TRYLOCK_FUNCTION(...) __attribute__ ((exclusive_trylock_function(__VA_ARGS__))) +#define SHARED_TRYLOCK_FUNCTION(...) __attribute__ ((shared_trylock_function(__VA_ARGS__))) +#define UNLOCK_FUNCTION(...) __attribute__ ((unlock_function(__VA_ARGS__))) +#define LOCK_RETURNED(x) __attribute__ ((lock_returned(x))) +#define LOCKS_EXCLUDED(...) __attribute__ ((locks_excluded(__VA_ARGS__))) +#define EXCLUSIVE_LOCKS_REQUIRED(...) __attribute__ ((exclusive_locks_required(__VA_ARGS__))) +#define SHARED_LOCKS_REQUIRED(...) __attribute__ ((shared_locks_required(__VA_ARGS__))) +#define NO_THREAD_SAFETY_ANALYSIS __attribute__ ((no_thread_safety_analysis)) +#else +#define LOCKABLE +#define SCOPED_LOCKABLE +#define GUARDED_BY(x) +#define GUARDED_VAR +#define PT_GUARDED_BY(x) +#define PT_GUARDED_VAR +#define ACQUIRED_AFTER(...) +#define ACQUIRED_BEFORE(...) +#define EXCLUSIVE_LOCK_FUNCTION(...) +#define SHARED_LOCK_FUNCTION(...) +#define EXCLUSIVE_TRYLOCK_FUNCTION(...) +#define SHARED_TRYLOCK_FUNCTION(...) +#define UNLOCK_FUNCTION(...) +#define LOCK_RETURNED(x) +#define LOCKS_EXCLUDED(...) +#define EXCLUSIVE_LOCKS_REQUIRED(...) +#define SHARED_LOCKS_REQUIRED(...) +#define NO_THREAD_SAFETY_ANALYSIS +#endif // __GNUC__ +#endif // BITCOIN_THREADSAFETY_H diff --git a/src/txdb-leveldb.cpp b/src/txdb-leveldb.cpp new file mode 100644 index 0000000..fd6305d --- /dev/null +++ b/src/txdb-leveldb.cpp @@ -0,0 +1,566 @@ +// Copyright (c) 2009-2010 Satoshi Nakamoto +// Copyright (c) 2009-2012 The Bitcoin developers +// Distributed under the MIT/X11 software license, see the accompanying +// file license.txt or http://www.opensource.org/licenses/mit-license.php. + +#include + +#include +#include +#include + +#include +#include +#include +#include + +#include "kernel.h" +#include "checkpoints.h" +#include "txdb.h" +#include "util.h" +#include "main.h" + +using namespace std; +using namespace boost; + +leveldb::DB *txdb; // global pointer for LevelDB object instance + +static leveldb::Options GetOptions() { + leveldb::Options options; + int nCacheSizeMB = GetArg("-dbcache", 25); + options.block_cache = leveldb::NewLRUCache(nCacheSizeMB * 1048576); + options.filter_policy = leveldb::NewBloomFilterPolicy(10); + return options; +} + +void init_blockindex(leveldb::Options& options, bool fRemoveOld = false) { + // First time init. + filesystem::path directory = GetDataDir() / "txleveldb"; + + if (fRemoveOld) { + filesystem::remove_all(directory); // remove directory + unsigned int nFile = 1; + + while (true) + { + filesystem::path strBlockFile = GetDataDir() / strprintf("blk%04u.dat", nFile); + + // Break if no such file + if( !filesystem::exists( strBlockFile ) ) + break; + + filesystem::remove(strBlockFile); + + nFile++; + } + } + + filesystem::create_directory(directory); + printf("Opening LevelDB in %s\n", directory.string().c_str()); + leveldb::Status status = leveldb::DB::Open(options, directory.string(), &txdb); + if (!status.ok()) { + throw runtime_error(strprintf("init_blockindex(): error opening database environment %s", status.ToString().c_str())); + } +} + +// CDB subclasses are created and destroyed VERY OFTEN. That's why +// we shouldn't treat this as a free operations. +CTxDB::CTxDB(const char* pszMode) +{ + assert(pszMode); + activeBatch = NULL; + fReadOnly = (!strchr(pszMode, '+') && !strchr(pszMode, 'w')); + + if (txdb) { + pdb = txdb; + return; + } + + bool fCreate = strchr(pszMode, 'c'); + + options = GetOptions(); + options.create_if_missing = fCreate; + options.filter_policy = leveldb::NewBloomFilterPolicy(10); + + init_blockindex(options); // Init directory + pdb = txdb; + + if (Exists(string("version"))) + { + ReadVersion(nVersion); + printf("Transaction index version is %d\n", nVersion); + + if (nVersion < DATABASE_VERSION) + { + printf("Required index version is %d, removing old database\n", DATABASE_VERSION); + + // Leveldb instance destruction + delete txdb; + txdb = pdb = NULL; + delete activeBatch; + activeBatch = NULL; + + init_blockindex(options, true); // Remove directory and create new database + pdb = txdb; + + bool fTmp = fReadOnly; + fReadOnly = false; + WriteVersion(DATABASE_VERSION); // Save transaction index version + fReadOnly = fTmp; + } + } + else if (fCreate) + { + bool fTmp = fReadOnly; + fReadOnly = false; + WriteVersion(DATABASE_VERSION); + fReadOnly = fTmp; + } + + printf("Opened LevelDB successfully\n"); +} + +void CTxDB::Close() +{ + delete txdb; + txdb = pdb = NULL; + delete options.filter_policy; + options.filter_policy = NULL; + delete options.block_cache; + options.block_cache = NULL; + delete activeBatch; + activeBatch = NULL; +} + +bool CTxDB::TxnBegin() +{ + assert(!activeBatch); + activeBatch = new leveldb::WriteBatch(); + return true; +} + +bool CTxDB::TxnCommit() +{ + assert(activeBatch); + leveldb::Status status = pdb->Write(leveldb::WriteOptions(), activeBatch); + delete activeBatch; + activeBatch = NULL; + if (!status.ok()) { + printf("LevelDB batch commit failure: %s\n", status.ToString().c_str()); + return false; + } + return true; +} + +class CBatchScanner : public leveldb::WriteBatch::Handler { +public: + std::string needle; + bool *deleted; + std::string *foundValue; + bool foundEntry; + + CBatchScanner() : foundEntry(false) {} + + virtual void Put(const leveldb::Slice& key, const leveldb::Slice& value) { + if (key.ToString() == needle) { + foundEntry = true; + *deleted = false; + *foundValue = value.ToString(); + } + } + + virtual void Delete(const leveldb::Slice& key) { + if (key.ToString() == needle) { + foundEntry = true; + *deleted = true; + } + } +}; + +// When performing a read, if we have an active batch we need to check it first +// before reading from the database, as the rest of the code assumes that once +// a database transaction begins reads are consistent with it. It would be good +// to change that assumption in future and avoid the performance hit, though in +// practice it does not appear to be large. +bool CTxDB::ScanBatch(const CDataStream &key, string *value, bool *deleted) const { + assert(activeBatch); + *deleted = false; + CBatchScanner scanner; + scanner.needle = key.str(); + scanner.deleted = deleted; + scanner.foundValue = value; + leveldb::Status status = activeBatch->Iterate(&scanner); + if (!status.ok()) { + throw runtime_error(status.ToString()); + } + return scanner.foundEntry; +} + +bool CTxDB::ReadTxIndex(uint256 hash, CTxIndex& txindex) +{ + txindex.SetNull(); + return Read(make_pair(string("tx"), hash), txindex); +} + +bool CTxDB::UpdateTxIndex(uint256 hash, const CTxIndex& txindex) +{ + return Write(make_pair(string("tx"), hash), txindex); +} + +bool CTxDB::AddTxIndex(const CTransaction& tx, const CDiskTxPos& pos, int nHeight) +{ + // Add to tx index + uint256 hash = tx.GetHash(); + CTxIndex txindex(pos, tx.vout.size()); + return Write(make_pair(string("tx"), hash), txindex); +} + +bool CTxDB::EraseTxIndex(const CTransaction& tx) +{ + uint256 hash = tx.GetHash(); + + return Erase(make_pair(string("tx"), hash)); +} + +bool CTxDB::ContainsTx(uint256 hash) +{ + return Exists(make_pair(string("tx"), hash)); +} + +bool CTxDB::ReadDiskTx(uint256 hash, CTransaction& tx, CTxIndex& txindex) +{ + tx.SetNull(); + if (!ReadTxIndex(hash, txindex)) + return false; + return (tx.ReadFromDisk(txindex.pos)); +} + +bool CTxDB::ReadDiskTx(uint256 hash, CTransaction& tx) +{ + CTxIndex txindex; + return ReadDiskTx(hash, tx, txindex); +} + +bool CTxDB::ReadDiskTx(COutPoint outpoint, CTransaction& tx, CTxIndex& txindex) +{ + return ReadDiskTx(outpoint.hash, tx, txindex); +} + +bool CTxDB::ReadDiskTx(COutPoint outpoint, CTransaction& tx) +{ + CTxIndex txindex; + return ReadDiskTx(outpoint.hash, tx, txindex); +} + +bool CTxDB::WriteBlockIndex(const CDiskBlockIndex& blockindex) +{ + return Write(make_pair(string("blockindex"), blockindex.GetBlockHash()), blockindex); +} + +bool CTxDB::ReadHashBestChain(uint256& hashBestChain) +{ + return Read(string("hashBestChain"), hashBestChain); +} + +bool CTxDB::WriteHashBestChain(uint256 hashBestChain) +{ + return Write(string("hashBestChain"), hashBestChain); +} + +bool CTxDB::ReadBestInvalidTrust(CBigNum& bnBestInvalidTrust) +{ + return Read(string("bnBestInvalidTrust"), bnBestInvalidTrust); +} + +bool CTxDB::WriteBestInvalidTrust(CBigNum bnBestInvalidTrust) +{ + return Write(string("bnBestInvalidTrust"), bnBestInvalidTrust); +} + +bool CTxDB::ReadSyncCheckpoint(uint256& hashCheckpoint) +{ + return Read(string("hashSyncCheckpoint"), hashCheckpoint); +} + +bool CTxDB::WriteSyncCheckpoint(uint256 hashCheckpoint) +{ + return Write(string("hashSyncCheckpoint"), hashCheckpoint); +} + +bool CTxDB::ReadCheckpointPubKey(string& strPubKey) +{ + return Read(string("strCheckpointPubKey"), strPubKey); +} + +bool CTxDB::WriteCheckpointPubKey(const string& strPubKey) +{ + return Write(string("strCheckpointPubKey"), strPubKey); +} + +static CBlockIndex *InsertBlockIndex(uint256 hash) +{ + if (hash == 0) + return NULL; + + // Return existing + map::iterator mi = mapBlockIndex.find(hash); + if (mi != mapBlockIndex.end()) + return (*mi).second; + + // Create new + CBlockIndex* pindexNew = new CBlockIndex(); + if (!pindexNew) + throw runtime_error("LoadBlockIndex() : new CBlockIndex failed"); + mi = mapBlockIndex.insert(make_pair(hash, pindexNew)).first; + pindexNew->phashBlock = &((*mi).first); + + return pindexNew; +} + +bool CTxDB::LoadBlockIndex() +{ + if (mapBlockIndex.size() > 0) { + // Already loaded once in this session. It can happen during migration + // from BDB. + return true; + } + // The block index is an in-memory structure that maps hashes to on-disk + // locations where the contents of the block can be found. Here, we scan it + // out of the DB and into mapBlockIndex. + leveldb::Iterator *iterator = pdb->NewIterator(leveldb::ReadOptions()); + // Seek to start key. + CDataStream ssStartKey(SER_DISK, CLIENT_VERSION); + ssStartKey << make_pair(string("blockindex"), uint256(0)); + iterator->Seek(ssStartKey.str()); + // Now read each entry. + while (iterator->Valid()) + { + // Unpack keys and values. + CDataStream ssKey(SER_DISK, CLIENT_VERSION); + ssKey.write(iterator->key().data(), iterator->key().size()); + CDataStream ssValue(SER_DISK, CLIENT_VERSION); + ssValue.write(iterator->value().data(), iterator->value().size()); + string strType; + ssKey >> strType; + // Did we reach the end of the data to read? + if (fRequestShutdown || strType != "blockindex") + break; + CDiskBlockIndex diskindex; + ssValue >> diskindex; + + uint256 blockHash = diskindex.GetBlockHash(); + + // Construct block index object + CBlockIndex* pindexNew = InsertBlockIndex(blockHash); + pindexNew->pprev = InsertBlockIndex(diskindex.hashPrev); + pindexNew->pnext = InsertBlockIndex(diskindex.hashNext); + pindexNew->nFile = diskindex.nFile; + pindexNew->nBlockPos = diskindex.nBlockPos; + pindexNew->nHeight = diskindex.nHeight; + pindexNew->nMint = diskindex.nMint; + pindexNew->nMoneySupply = diskindex.nMoneySupply; + pindexNew->nFlags = diskindex.nFlags; + pindexNew->nStakeModifier = diskindex.nStakeModifier; + pindexNew->prevoutStake = diskindex.prevoutStake; + pindexNew->nStakeTime = diskindex.nStakeTime; + pindexNew->hashProof = diskindex.hashProof; + pindexNew->nVersion = diskindex.nVersion; + pindexNew->hashMerkleRoot = diskindex.hashMerkleRoot; + pindexNew->nTime = diskindex.nTime; + pindexNew->nBits = diskindex.nBits; + pindexNew->nNonce = diskindex.nNonce; + + // Watch for genesis block + if (pindexGenesisBlock == NULL && blockHash == (!fTestNet ? hashGenesisBlock : hashGenesisBlockTestNet)) + pindexGenesisBlock = pindexNew; + + if (!pindexNew->CheckIndex()) { + delete iterator; + return error("LoadBlockIndex() : CheckIndex failed at %d", pindexNew->nHeight); + } + + // NovaCoin: build setStakeSeen + if (pindexNew->IsProofOfStake()) + setStakeSeen.insert(make_pair(pindexNew->prevoutStake, pindexNew->nStakeTime)); + + iterator->Next(); + } + delete iterator; + + if (fRequestShutdown) + return true; + + // Calculate nChainTrust + vector > vSortedByHeight; + vSortedByHeight.reserve(mapBlockIndex.size()); + BOOST_FOREACH(const PAIRTYPE(uint256, CBlockIndex*)& item, mapBlockIndex) + { + CBlockIndex* pindex = item.second; + vSortedByHeight.push_back(make_pair(pindex->nHeight, pindex)); + } + sort(vSortedByHeight.begin(), vSortedByHeight.end()); + BOOST_FOREACH(const PAIRTYPE(int, CBlockIndex*)& item, vSortedByHeight) + { + CBlockIndex* pindex = item.second; + pindex->nChainTrust = (pindex->pprev ? pindex->pprev->nChainTrust : 0) + pindex->GetBlockTrust(); + // NovaCoin: calculate stake modifier checksum + pindex->nStakeModifierChecksum = GetStakeModifierChecksum(pindex); + if (!CheckStakeModifierCheckpoints(pindex->nHeight, pindex->nStakeModifierChecksum)) + return error("CTxDB::LoadBlockIndex() : Failed stake modifier checkpoint height=%d, modifier=0x%016" PRIx64, pindex->nHeight, pindex->nStakeModifier); + } + + // Load hashBestChain pointer to end of best chain + if (!ReadHashBestChain(hashBestChain)) + { + if (pindexGenesisBlock == NULL) + return true; + return error("CTxDB::LoadBlockIndex() : hashBestChain not loaded"); + } + if (!mapBlockIndex.count(hashBestChain)) + return error("CTxDB::LoadBlockIndex() : hashBestChain not found in the block index"); + pindexBest = mapBlockIndex[hashBestChain]; + nBestHeight = pindexBest->nHeight; + nBestChainTrust = pindexBest->nChainTrust; + + printf("LoadBlockIndex(): hashBestChain=%s height=%d trust=%s date=%s\n", + hashBestChain.ToString().substr(0,20).c_str(), nBestHeight, CBigNum(nBestChainTrust).ToString().c_str(), + DateTimeStrFormat("%x %H:%M:%S", pindexBest->GetBlockTime()).c_str()); + + // NovaCoin: load hashSyncCheckpoint + if (!ReadSyncCheckpoint(Checkpoints::hashSyncCheckpoint)) + return error("CTxDB::LoadBlockIndex() : hashSyncCheckpoint not loaded"); + printf("LoadBlockIndex(): synchronized checkpoint %s\n", Checkpoints::hashSyncCheckpoint.ToString().c_str()); + + // Load bnBestInvalidTrust, OK if it doesn't exist + CBigNum bnBestInvalidTrust; + ReadBestInvalidTrust(bnBestInvalidTrust); + nBestInvalidTrust = bnBestInvalidTrust.getuint256(); + + // Verify blocks in the best chain + int nCheckLevel = GetArg("-checklevel", 1); + int nCheckDepth = GetArg( "-checkblocks", 2500); + if (nCheckDepth == 0) + nCheckDepth = 1000000000; // suffices until the year 19000 + if (nCheckDepth > nBestHeight) + nCheckDepth = nBestHeight; + printf("Verifying last %i blocks at level %i\n", nCheckDepth, nCheckLevel); + CBlockIndex* pindexFork = NULL; + map, CBlockIndex*> mapBlockPos; + for (CBlockIndex* pindex = pindexBest; pindex && pindex->pprev; pindex = pindex->pprev) + { + if (fRequestShutdown || pindex->nHeight < nBestHeight-nCheckDepth) + break; + CBlock block; + if (!block.ReadFromDisk(pindex)) + return error("LoadBlockIndex() : block.ReadFromDisk failed"); + // check level 1: verify block validity + // check level 7: verify block signature too + if (nCheckLevel>0 && !block.CheckBlock(true, true, (nCheckLevel>6))) + { + printf("LoadBlockIndex() : *** found bad block at %d, hash=%s\n", pindex->nHeight, pindex->GetBlockHash().ToString().c_str()); + pindexFork = pindex->pprev; + } + // check level 2: verify transaction index validity + if (nCheckLevel>1) + { + pair pos = make_pair(pindex->nFile, pindex->nBlockPos); + mapBlockPos[pos] = pindex; + BOOST_FOREACH(const CTransaction &tx, block.vtx) + { + uint256 hashTx = tx.GetHash(); + CTxIndex txindex; + if (ReadTxIndex(hashTx, txindex)) + { + // check level 3: checker transaction hashes + if (nCheckLevel>2 || pindex->nFile != txindex.pos.nFile || pindex->nBlockPos != txindex.pos.nBlockPos) + { + // either an error or a duplicate transaction + CTransaction txFound; + if (!txFound.ReadFromDisk(txindex.pos)) + { + printf("LoadBlockIndex() : *** cannot read mislocated transaction %s\n", hashTx.ToString().c_str()); + pindexFork = pindex->pprev; + } + else + if (txFound.GetHash() != hashTx) // not a duplicate tx + { + printf("LoadBlockIndex(): *** invalid tx position for %s\n", hashTx.ToString().c_str()); + pindexFork = pindex->pprev; + } + } + // check level 4: check whether spent txouts were spent within the main chain + unsigned int nOutput = 0; + if (nCheckLevel>3) + { + BOOST_FOREACH(const CDiskTxPos &txpos, txindex.vSpent) + { + if (!txpos.IsNull()) + { + pair posFind = make_pair(txpos.nFile, txpos.nBlockPos); + if (!mapBlockPos.count(posFind)) + { + printf("LoadBlockIndex(): *** found bad spend at %d, hashBlock=%s, hashTx=%s\n", pindex->nHeight, pindex->GetBlockHash().ToString().c_str(), hashTx.ToString().c_str()); + pindexFork = pindex->pprev; + } + // check level 6: check whether spent txouts were spent by a valid transaction that consume them + if (nCheckLevel>5) + { + CTransaction txSpend; + if (!txSpend.ReadFromDisk(txpos)) + { + printf("LoadBlockIndex(): *** cannot read spending transaction of %s:%i from disk\n", hashTx.ToString().c_str(), nOutput); + pindexFork = pindex->pprev; + } + else if (!txSpend.CheckTransaction()) + { + printf("LoadBlockIndex(): *** spending transaction of %s:%i is invalid\n", hashTx.ToString().c_str(), nOutput); + pindexFork = pindex->pprev; + } + else + { + bool fFound = false; + BOOST_FOREACH(const CTxIn &txin, txSpend.vin) + if (txin.prevout.hash == hashTx && txin.prevout.n == nOutput) + fFound = true; + if (!fFound) + { + printf("LoadBlockIndex(): *** spending transaction of %s:%i does not spend it\n", hashTx.ToString().c_str(), nOutput); + pindexFork = pindex->pprev; + } + } + } + } + nOutput++; + } + } + } + // check level 5: check whether all prevouts are marked spent + if (nCheckLevel>4) + { + BOOST_FOREACH(const CTxIn &txin, tx.vin) + { + CTxIndex txindex; + if (ReadTxIndex(txin.prevout.hash, txindex)) + if (txindex.vSpent.size()-1 < txin.prevout.n || txindex.vSpent[txin.prevout.n].IsNull()) + { + printf("LoadBlockIndex(): *** found unspent prevout %s:%i in %s\n", txin.prevout.hash.ToString().c_str(), txin.prevout.n, hashTx.ToString().c_str()); + pindexFork = pindex->pprev; + } + } + } + } + } + } + if (pindexFork && !fRequestShutdown) + { + // Reorg back to the fork + printf("LoadBlockIndex() : *** moving best chain pointer back to block %d\n", pindexFork->nHeight); + CBlock block; + if (!block.ReadFromDisk(pindexFork)) + return error("LoadBlockIndex() : block.ReadFromDisk failed"); + CTxDB txdb; + block.SetBestChain(txdb, pindexFork); + } + + return true; +} diff --git a/src/txdb-leveldb.h b/src/txdb-leveldb.h new file mode 100644 index 0000000..67b4036 --- /dev/null +++ b/src/txdb-leveldb.h @@ -0,0 +1,210 @@ +// Copyright (c) 2009-2012 The Bitcoin Developers. +// Authored by Google, Inc. +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifndef BITCOIN_LEVELDB_H +#define BITCOIN_LEVELDB_H + +#include "main.h" + +#include +#include +#include + +#include +#include + +// Class that provides access to a LevelDB. Note that this class is frequently +// instantiated on the stack and then destroyed again, so instantiation has to +// be very cheap. Unfortunately that means, a CTxDB instance is actually just a +// wrapper around some global state. +// +// A LevelDB is a key/value store that is optimized for fast usage on hard +// disks. It prefers long read/writes to seeks and is based on a series of +// sorted key/value mapping files that are stacked on top of each other, with +// newer files overriding older files. A background thread compacts them +// together when too many files stack up. +// +// Learn more: http://code.google.com/p/leveldb/ +class CTxDB +{ +public: + CTxDB(const char* pszMode="r+"); + ~CTxDB() { + // Note that this is not the same as Close() because it deletes only + // data scoped to this TxDB object. + delete activeBatch; + } + + // Destroys the underlying shared global state accessed by this TxDB. + void Close(); + +private: + leveldb::DB *pdb; // Points to the global instance. + + // A batch stores up writes and deletes for atomic application. When this + // field is non-NULL, writes/deletes go there instead of directly to disk. + leveldb::WriteBatch *activeBatch; + leveldb::Options options; + bool fReadOnly; + int nVersion; + +protected: + // Returns true and sets (value,false) if activeBatch contains the given key + // or leaves value alone and sets deleted = true if activeBatch contains a + // delete for it. + bool ScanBatch(const CDataStream &key, std::string *value, bool *deleted) const; + + template + bool Read(const K& key, T& value) + { + CDataStream ssKey(SER_DISK, CLIENT_VERSION); + ssKey.reserve(1000); + ssKey << key; + std::string strValue; + + bool readFromDb = true; + if (activeBatch) { + // First we must search for it in the currently pending set of + // changes to the db. If not found in the batch, go on to read disk. + bool deleted = false; + readFromDb = ScanBatch(ssKey, &strValue, &deleted) == false; + if (deleted) { + return false; + } + } + if (readFromDb) { + leveldb::Status status = pdb->Get(leveldb::ReadOptions(), + ssKey.str(), &strValue); + if (!status.ok()) { + if (status.IsNotFound()) + return false; + // Some unexpected error. + printf("LevelDB read failure: %s\n", status.ToString().c_str()); + return false; + } + } + // Unserialize value + try { + CDataStream ssValue(strValue.data(), strValue.data() + strValue.size(), + SER_DISK, CLIENT_VERSION); + ssValue >> value; + } + catch (std::exception &e) { + return false; + } + return true; + } + + template + bool Write(const K& key, const T& value) + { + if (fReadOnly) + assert(!"Write called on database in read-only mode"); + + CDataStream ssKey(SER_DISK, CLIENT_VERSION); + ssKey.reserve(1000); + ssKey << key; + CDataStream ssValue(SER_DISK, CLIENT_VERSION); + ssValue.reserve(10000); + ssValue << value; + + if (activeBatch) { + activeBatch->Put(ssKey.str(), ssValue.str()); + return true; + } + leveldb::Status status = pdb->Put(leveldb::WriteOptions(), ssKey.str(), ssValue.str()); + if (!status.ok()) { + printf("LevelDB write failure: %s\n", status.ToString().c_str()); + return false; + } + return true; + } + + template + bool Erase(const K& key) + { + if (!pdb) + return false; + if (fReadOnly) + assert(!"Erase called on database in read-only mode"); + + CDataStream ssKey(SER_DISK, CLIENT_VERSION); + ssKey.reserve(1000); + ssKey << key; + if (activeBatch) { + activeBatch->Delete(ssKey.str()); + return true; + } + leveldb::Status status = pdb->Delete(leveldb::WriteOptions(), ssKey.str()); + return (status.ok() || status.IsNotFound()); + } + + template + bool Exists(const K& key) + { + CDataStream ssKey(SER_DISK, CLIENT_VERSION); + ssKey.reserve(1000); + ssKey << key; + std::string unused; + + if (activeBatch) { + bool deleted; + if (ScanBatch(ssKey, &unused, &deleted) && !deleted) { + return true; + } + } + + + leveldb::Status status = pdb->Get(leveldb::ReadOptions(), ssKey.str(), &unused); + return status.IsNotFound() == false; + } + + +public: + bool TxnBegin(); + bool TxnCommit(); + bool TxnAbort() + { + delete activeBatch; + activeBatch = NULL; + return true; + } + + bool ReadVersion(int& nVersion) + { + nVersion = 0; + return Read(std::string("version"), nVersion); + } + + bool WriteVersion(int nVersion) + { + return Write(std::string("version"), nVersion); + } + + bool ReadTxIndex(uint256 hash, CTxIndex& txindex); + bool UpdateTxIndex(uint256 hash, const CTxIndex& txindex); + bool AddTxIndex(const CTransaction& tx, const CDiskTxPos& pos, int nHeight); + bool EraseTxIndex(const CTransaction& tx); + bool ContainsTx(uint256 hash); + bool ReadDiskTx(uint256 hash, CTransaction& tx, CTxIndex& txindex); + bool ReadDiskTx(uint256 hash, CTransaction& tx); + bool ReadDiskTx(COutPoint outpoint, CTransaction& tx, CTxIndex& txindex); + bool ReadDiskTx(COutPoint outpoint, CTransaction& tx); + bool WriteBlockIndex(const CDiskBlockIndex& blockindex); + bool ReadHashBestChain(uint256& hashBestChain); + bool WriteHashBestChain(uint256 hashBestChain); + bool ReadBestInvalidTrust(CBigNum& bnBestInvalidTrust); + bool WriteBestInvalidTrust(CBigNum bnBestInvalidTrust); + bool ReadSyncCheckpoint(uint256& hashCheckpoint); + bool WriteSyncCheckpoint(uint256 hashCheckpoint); + bool ReadCheckpointPubKey(std::string& strPubKey); + bool WriteCheckpointPubKey(const std::string& strPubKey); + bool LoadBlockIndex(); +private: + bool LoadBlockIndexGuts(); +}; + + +#endif // BITCOIN_DB_H diff --git a/src/txdb.h b/src/txdb.h new file mode 100644 index 0000000..a8e9f5b --- /dev/null +++ b/src/txdb.h @@ -0,0 +1,11 @@ +// Copyright (c) 2009-2010 Satoshi Nakamoto +// Copyright (c) 2009-2012 The Bitcoin developers +// Distributed under the MIT/X11 software license, see the accompanying +// file license.txt or http://www.opensource.org/licenses/mit-license.php. + +#ifndef BITCOIN_TXDB_H +#define BITCOIN_TXDB_H + +#include "txdb-leveldb.h" + +#endif // BITCOIN_TXDB_H diff --git a/src/ui_interface.h b/src/ui_interface.h new file mode 100644 index 0000000..dc9b587 --- /dev/null +++ b/src/ui_interface.h @@ -0,0 +1,108 @@ +// Copyright (c) 2010 Satoshi Nakamoto +// Copyright (c) 2012 The Bitcoin developers +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifndef BITCOIN_UI_INTERFACE_H +#define BITCOIN_UI_INTERFACE_H + +#include +#include + +#include + +#include + +class CBasicKeyStore; +class CWallet; +class uint256; + +/** General change type (added, updated, removed). */ +enum ChangeType +{ + CT_NEW, + CT_UPDATED, + CT_DELETED +}; + +/** Signals for UI communication. */ +class CClientUIInterface +{ +public: + /** Flags for CClientUIInterface::ThreadSafeMessageBox */ + enum MessageBoxFlags + { + YES = 0x00000002, + OK = 0x00000004, + NO = 0x00000008, + YES_NO = (YES|NO), + CANCEL = 0x00000010, + APPLY = 0x00000020, + CLOSE = 0x00000040, + OK_DEFAULT = 0x00000000, + YES_DEFAULT = 0x00000000, + NO_DEFAULT = 0x00000080, + CANCEL_DEFAULT = 0x80000000, + ICON_EXCLAMATION = 0x00000100, + ICON_HAND = 0x00000200, + ICON_WARNING = ICON_EXCLAMATION, + ICON_ERROR = ICON_HAND, + ICON_QUESTION = 0x00000400, + ICON_INFORMATION = 0x00000800, + ICON_STOP = ICON_HAND, + ICON_ASTERISK = ICON_INFORMATION, + ICON_MASK = (0x00000100|0x00000200|0x00000400|0x00000800), + FORWARD = 0x00001000, + BACKWARD = 0x00002000, + RESET = 0x00004000, + HELP = 0x00008000, + MORE = 0x00010000, + SETUP = 0x00020000, + // Force blocking, modal message box dialog (not just OS notification) + MODAL = 0x00040000 + }; + + /** Show message box. */ + boost::signals2::signal ThreadSafeMessageBox; + + /** Ask the user whether they want to pay a fee or not. */ + boost::signals2::signal > ThreadSafeAskFee; + + /** Handle a URL passed at the command line. */ + boost::signals2::signal ThreadSafeHandleURI; + + /** Progress message during initialization. */ + boost::signals2::signal InitMessage; + + /** Initiate client shutdown. */ + boost::signals2::signal QueueShutdown; + + /** Translate a message to the native language of the user. */ + boost::signals2::signal Translate; + + /** Block chain changed. */ + boost::signals2::signal NotifyBlocksChanged; + + /** Number of network connections changed. */ + boost::signals2::signal NotifyNumConnectionsChanged; + + /** + * New, updated or cancelled alert. + * @note called with lock cs_mapAlerts held. + */ + boost::signals2::signal NotifyAlertChanged; +}; + +extern CClientUIInterface uiInterface; + +/** + * Translation function: Call Translate signal on UI interface, which returns a boost::optional result. + * If no translation slot is registered, nothing is returned, and simply return the input. + */ +inline std::string _(const char* psz) +{ + boost::optional rv = uiInterface.Translate(psz); + return rv ? (*rv) : psz; +} + +#endif diff --git a/src/uint256.h b/src/uint256.h new file mode 100644 index 0000000..f95b349 --- /dev/null +++ b/src/uint256.h @@ -0,0 +1,764 @@ +// Copyright (c) 2009-2010 Satoshi Nakamoto +// Copyright (c) 2009-2012 The Bitcoin developers +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifndef BITCOIN_UINT256_H +#define BITCOIN_UINT256_H + +#include +#include + +#include +#include +#include + +inline int Testuint256AdHoc(std::vector vArg); + + +/** Base class without constructors for uint256 and uint160. + * This makes the compiler let u use it in a union. + */ +template +class base_uint +{ +protected: + enum { WIDTH=BITS/32 }; + unsigned int pn[WIDTH]; +public: + + bool operator!() const + { + for (int i = 0; i < WIDTH; i++) + if (pn[i] != 0) + return false; + return true; + } + + const base_uint operator~() const + { + base_uint ret; + for (int i = 0; i < WIDTH; i++) + ret.pn[i] = ~pn[i]; + return ret; + } + + const base_uint operator-() const + { + base_uint ret; + for (int i = 0; i < WIDTH; i++) + ret.pn[i] = ~pn[i]; + ret++; + return ret; + } + + double getdouble() const + { + double ret = 0.0; + double fact = 1.0; + for (int i = 0; i < WIDTH; i++) { + ret += fact * pn[i]; + fact *= 4294967296.0; + } + return ret; + } + + base_uint& operator=(uint64_t b) + { + pn[0] = (unsigned int)b; + pn[1] = (unsigned int)(b >> 32); + for (int i = 2; i < WIDTH; i++) + pn[i] = 0; + return *this; + } + + base_uint& operator^=(const base_uint& b) + { + for (int i = 0; i < WIDTH; i++) + pn[i] ^= b.pn[i]; + return *this; + } + + base_uint& operator&=(const base_uint& b) + { + for (int i = 0; i < WIDTH; i++) + pn[i] &= b.pn[i]; + return *this; + } + + base_uint& operator|=(const base_uint& b) + { + for (int i = 0; i < WIDTH; i++) + pn[i] |= b.pn[i]; + return *this; + } + + base_uint& operator^=(uint64_t b) + { + pn[0] ^= (unsigned int)b; + pn[1] ^= (unsigned int)(b >> 32); + return *this; + } + + base_uint& operator|=(uint64_t b) + { + pn[0] |= (unsigned int)b; + pn[1] |= (unsigned int)(b >> 32); + return *this; + } + + base_uint& operator<<=(unsigned int shift) + { + base_uint a(*this); + for (int i = 0; i < WIDTH; i++) + pn[i] = 0; + int k = shift / 32; + shift = shift % 32; + for (int i = 0; i < WIDTH; i++) + { + if (i+k+1 < WIDTH && shift != 0) + pn[i+k+1] |= (a.pn[i] >> (32-shift)); + if (i+k < WIDTH) + pn[i+k] |= (a.pn[i] << shift); + } + return *this; + } + + base_uint& operator>>=(unsigned int shift) + { + base_uint a(*this); + for (int i = 0; i < WIDTH; i++) + pn[i] = 0; + int k = shift / 32; + shift = shift % 32; + for (int i = 0; i < WIDTH; i++) + { + if (i-k-1 >= 0 && shift != 0) + pn[i-k-1] |= (a.pn[i] << (32-shift)); + if (i-k >= 0) + pn[i-k] |= (a.pn[i] >> shift); + } + return *this; + } + + base_uint& operator+=(const base_uint& b) + { + uint64_t carry = 0; + for (int i = 0; i < WIDTH; i++) + { + uint64_t n = carry + pn[i] + b.pn[i]; + pn[i] = n & 0xffffffff; + carry = n >> 32; + } + return *this; + } + + base_uint& operator-=(const base_uint& b) + { + *this += -b; + return *this; + } + + base_uint& operator+=(uint64_t b64) + { + base_uint b; + b = b64; + *this += b; + return *this; + } + + base_uint& operator-=(uint64_t b64) + { + base_uint b; + b = b64; + *this += -b; + return *this; + } + + + base_uint& operator++() + { + // prefix operator + int i = 0; + while (++pn[i] == 0 && i < WIDTH-1) + i++; + return *this; + } + + const base_uint operator++(int) + { + // postfix operator + const base_uint ret = *this; + ++(*this); + return ret; + } + + base_uint& operator--() + { + // prefix operator + int i = 0; + while (--pn[i] == -1 && i < WIDTH-1) + i++; + return *this; + } + + const base_uint operator--(int) + { + // postfix operator + const base_uint ret = *this; + --(*this); + return ret; + } + + + friend inline bool operator<(const base_uint& a, const base_uint& b) + { + for (int i = base_uint::WIDTH-1; i >= 0; i--) + { + if (a.pn[i] < b.pn[i]) + return true; + else if (a.pn[i] > b.pn[i]) + return false; + } + return false; + } + + friend inline bool operator<=(const base_uint& a, const base_uint& b) + { + for (int i = base_uint::WIDTH-1; i >= 0; i--) + { + if (a.pn[i] < b.pn[i]) + return true; + else if (a.pn[i] > b.pn[i]) + return false; + } + return true; + } + + friend inline bool operator>(const base_uint& a, const base_uint& b) + { + for (int i = base_uint::WIDTH-1; i >= 0; i--) + { + if (a.pn[i] > b.pn[i]) + return true; + else if (a.pn[i] < b.pn[i]) + return false; + } + return false; + } + + friend inline bool operator>=(const base_uint& a, const base_uint& b) + { + for (int i = base_uint::WIDTH-1; i >= 0; i--) + { + if (a.pn[i] > b.pn[i]) + return true; + else if (a.pn[i] < b.pn[i]) + return false; + } + return true; + } + + friend inline bool operator==(const base_uint& a, const base_uint& b) + { + for (int i = 0; i < base_uint::WIDTH; i++) + if (a.pn[i] != b.pn[i]) + return false; + return true; + } + + friend inline bool operator==(const base_uint& a, uint64_t b) + { + if (a.pn[0] != (unsigned int)b) + return false; + if (a.pn[1] != (unsigned int)(b >> 32)) + return false; + for (int i = 2; i < base_uint::WIDTH; i++) + if (a.pn[i] != 0) + return false; + return true; + } + + friend inline bool operator!=(const base_uint& a, const base_uint& b) + { + return (!(a == b)); + } + + friend inline bool operator!=(const base_uint& a, uint64_t b) + { + return (!(a == b)); + } + + + + std::string GetHex() const + { + char psz[sizeof(pn)*2 + 1]; + for (unsigned int i = 0; i < sizeof(pn); i++) + sprintf(psz + i*2, "%02x", ((unsigned char*)pn)[sizeof(pn) - i - 1]); + return std::string(psz, psz + sizeof(pn)*2); + } + + void SetHex(const char* psz) + { + for (int i = 0; i < WIDTH; i++) + pn[i] = 0; + + // skip leading spaces + while (isspace(*psz)) + psz++; + + // skip 0x + if (psz[0] == '0' && tolower(psz[1]) == 'x') + psz += 2; + + // hex string to uint + static const unsigned 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 }; + const char* pbegin = psz; + while (phexdigit[(unsigned char)*psz] || *psz == '0') + psz++; + psz--; + unsigned char* p1 = (unsigned char*)pn; + unsigned char* pend = p1 + WIDTH * 4; + while (psz >= pbegin && p1 < pend) + { + *p1 = phexdigit[(unsigned char)*psz--]; + if (psz >= pbegin) + { + *p1 |= (phexdigit[(unsigned char)*psz--] << 4); + p1++; + } + } + } + + void SetHex(const std::string& str) + { + SetHex(str.c_str()); + } + + std::string ToString() const + { + return (GetHex()); + } + + unsigned char* begin() + { + return (unsigned char*)&pn[0]; + } + + unsigned char* end() + { + return (unsigned char*)&pn[WIDTH]; + } + + unsigned int size() + { + return sizeof(pn); + } + + uint64_t Get64(int n=0) const + { + return pn[2*n] | (uint64_t)pn[2*n+1] << 32; + } + + unsigned int GetSerializeSize(int nType, int nVersion) const + { + return sizeof(pn); + } + + template + void Serialize(Stream& s, int nType, int nVersion) const + { + s.write((char*)pn, sizeof(pn)); + } + + template + void Unserialize(Stream& s, int nType, int nVersion) + { + s.read((char*)pn, sizeof(pn)); + } + + friend class uint160; + friend class uint256; + friend inline int Testuint256AdHoc(std::vector vArg); +}; + +typedef base_uint<160> base_uint160; +typedef base_uint<256> base_uint256; + +// +// uint160 and uint256 could be implemented as templates, but to keep +// compile errors and debugging cleaner, they're copy and pasted. +// + + + +////////////////////////////////////////////////////////////////////////////// +// +// uint160 +// + +/** 160-bit unsigned integer */ +class uint160 : public base_uint160 +{ +public: + typedef base_uint160 basetype; + + uint160() + { + for (int i = 0; i < WIDTH; i++) + pn[i] = 0; + } + + uint160(const basetype& b) + { + for (int i = 0; i < WIDTH; i++) + pn[i] = b.pn[i]; + } + + uint160& operator=(const basetype& b) + { + for (int i = 0; i < WIDTH; i++) + pn[i] = b.pn[i]; + return *this; + } + + uint160(uint64_t b) + { + pn[0] = (unsigned int)b; + pn[1] = (unsigned int)(b >> 32); + for (int i = 2; i < WIDTH; i++) + pn[i] = 0; + } + + uint160& operator=(uint64_t b) + { + pn[0] = (unsigned int)b; + pn[1] = (unsigned int)(b >> 32); + for (int i = 2; i < WIDTH; i++) + pn[i] = 0; + return *this; + } + + explicit uint160(const std::string& str) + { + SetHex(str); + } + + explicit uint160(const std::vector& vch) + { + if (vch.size() == sizeof(pn)) + memcpy(pn, &vch[0], sizeof(pn)); + else + *this = 0; + } +}; + +inline bool operator==(const uint160& a, uint64_t b) { return (base_uint160)a == b; } +inline bool operator!=(const uint160& a, uint64_t b) { return (base_uint160)a != b; } +inline const uint160 operator<<(const base_uint160& a, unsigned int shift) { return uint160(a) <<= shift; } +inline const uint160 operator>>(const base_uint160& a, unsigned int shift) { return uint160(a) >>= shift; } +inline const uint160 operator<<(const uint160& a, unsigned int shift) { return uint160(a) <<= shift; } +inline const uint160 operator>>(const uint160& a, unsigned int shift) { return uint160(a) >>= shift; } + +inline const uint160 operator^(const base_uint160& a, const base_uint160& b) { return uint160(a) ^= b; } +inline const uint160 operator&(const base_uint160& a, const base_uint160& b) { return uint160(a) &= b; } +inline const uint160 operator|(const base_uint160& a, const base_uint160& b) { return uint160(a) |= b; } +inline const uint160 operator+(const base_uint160& a, const base_uint160& b) { return uint160(a) += b; } +inline const uint160 operator-(const base_uint160& a, const base_uint160& b) { return uint160(a) -= b; } + +inline bool operator<(const base_uint160& a, const uint160& b) { return (base_uint160)a < (base_uint160)b; } +inline bool operator<=(const base_uint160& a, const uint160& b) { return (base_uint160)a <= (base_uint160)b; } +inline bool operator>(const base_uint160& a, const uint160& b) { return (base_uint160)a > (base_uint160)b; } +inline bool operator>=(const base_uint160& a, const uint160& b) { return (base_uint160)a >= (base_uint160)b; } +inline bool operator==(const base_uint160& a, const uint160& b) { return (base_uint160)a == (base_uint160)b; } +inline bool operator!=(const base_uint160& a, const uint160& b) { return (base_uint160)a != (base_uint160)b; } +inline const uint160 operator^(const base_uint160& a, const uint160& b) { return (base_uint160)a ^ (base_uint160)b; } +inline const uint160 operator&(const base_uint160& a, const uint160& b) { return (base_uint160)a & (base_uint160)b; } +inline const uint160 operator|(const base_uint160& a, const uint160& b) { return (base_uint160)a | (base_uint160)b; } +inline const uint160 operator+(const base_uint160& a, const uint160& b) { return (base_uint160)a + (base_uint160)b; } +inline const uint160 operator-(const base_uint160& a, const uint160& b) { return (base_uint160)a - (base_uint160)b; } + +inline bool operator<(const uint160& a, const base_uint160& b) { return (base_uint160)a < (base_uint160)b; } +inline bool operator<=(const uint160& a, const base_uint160& b) { return (base_uint160)a <= (base_uint160)b; } +inline bool operator>(const uint160& a, const base_uint160& b) { return (base_uint160)a > (base_uint160)b; } +inline bool operator>=(const uint160& a, const base_uint160& b) { return (base_uint160)a >= (base_uint160)b; } +inline bool operator==(const uint160& a, const base_uint160& b) { return (base_uint160)a == (base_uint160)b; } +inline bool operator!=(const uint160& a, const base_uint160& b) { return (base_uint160)a != (base_uint160)b; } +inline const uint160 operator^(const uint160& a, const base_uint160& b) { return (base_uint160)a ^ (base_uint160)b; } +inline const uint160 operator&(const uint160& a, const base_uint160& b) { return (base_uint160)a & (base_uint160)b; } +inline const uint160 operator|(const uint160& a, const base_uint160& b) { return (base_uint160)a | (base_uint160)b; } +inline const uint160 operator+(const uint160& a, const base_uint160& b) { return (base_uint160)a + (base_uint160)b; } +inline const uint160 operator-(const uint160& a, const base_uint160& b) { return (base_uint160)a - (base_uint160)b; } + +inline bool operator<(const uint160& a, const uint160& b) { return (base_uint160)a < (base_uint160)b; } +inline bool operator<=(const uint160& a, const uint160& b) { return (base_uint160)a <= (base_uint160)b; } +inline bool operator>(const uint160& a, const uint160& b) { return (base_uint160)a > (base_uint160)b; } +inline bool operator>=(const uint160& a, const uint160& b) { return (base_uint160)a >= (base_uint160)b; } +inline bool operator==(const uint160& a, const uint160& b) { return (base_uint160)a == (base_uint160)b; } +inline bool operator!=(const uint160& a, const uint160& b) { return (base_uint160)a != (base_uint160)b; } +inline const uint160 operator^(const uint160& a, const uint160& b) { return (base_uint160)a ^ (base_uint160)b; } +inline const uint160 operator&(const uint160& a, const uint160& b) { return (base_uint160)a & (base_uint160)b; } +inline const uint160 operator|(const uint160& a, const uint160& b) { return (base_uint160)a | (base_uint160)b; } +inline const uint160 operator+(const uint160& a, const uint160& b) { return (base_uint160)a + (base_uint160)b; } +inline const uint160 operator-(const uint160& a, const uint160& b) { return (base_uint160)a - (base_uint160)b; } + + + + + + +////////////////////////////////////////////////////////////////////////////// +// +// uint256 +// + +/** 256-bit unsigned integer */ +class uint256 : public base_uint256 +{ +public: + typedef base_uint256 basetype; + + uint256() + { + for (int i = 0; i < WIDTH; i++) + pn[i] = 0; + } + + uint256(const basetype& b) + { + for (int i = 0; i < WIDTH; i++) + pn[i] = b.pn[i]; + } + + uint256& operator=(const basetype& b) + { + for (int i = 0; i < WIDTH; i++) + pn[i] = b.pn[i]; + return *this; + } + + uint256(uint64_t b) + { + pn[0] = (unsigned int)b; + pn[1] = (unsigned int)(b >> 32); + for (int i = 2; i < WIDTH; i++) + pn[i] = 0; + } + + uint256& operator=(uint64_t b) + { + pn[0] = (unsigned int)b; + pn[1] = (unsigned int)(b >> 32); + for (int i = 2; i < WIDTH; i++) + pn[i] = 0; + return *this; + } + + explicit uint256(const std::string& str) + { + SetHex(str); + } + + explicit uint256(const std::vector& vch) + { + if (vch.size() == sizeof(pn)) + memcpy(pn, &vch[0], sizeof(pn)); + else + *this = 0; + } +}; + +inline bool operator==(const uint256& a, uint64_t b) { return (base_uint256)a == b; } +inline bool operator!=(const uint256& a, uint64_t b) { return (base_uint256)a != b; } +inline const uint256 operator<<(const base_uint256& a, unsigned int shift) { return uint256(a) <<= shift; } +inline const uint256 operator>>(const base_uint256& a, unsigned int shift) { return uint256(a) >>= shift; } +inline const uint256 operator<<(const uint256& a, unsigned int shift) { return uint256(a) <<= shift; } +inline const uint256 operator>>(const uint256& a, unsigned int shift) { return uint256(a) >>= shift; } + +inline const uint256 operator^(const base_uint256& a, const base_uint256& b) { return uint256(a) ^= b; } +inline const uint256 operator&(const base_uint256& a, const base_uint256& b) { return uint256(a) &= b; } +inline const uint256 operator|(const base_uint256& a, const base_uint256& b) { return uint256(a) |= b; } +inline const uint256 operator+(const base_uint256& a, const base_uint256& b) { return uint256(a) += b; } +inline const uint256 operator-(const base_uint256& a, const base_uint256& b) { return uint256(a) -= b; } + +inline bool operator<(const base_uint256& a, const uint256& b) { return (base_uint256)a < (base_uint256)b; } +inline bool operator<=(const base_uint256& a, const uint256& b) { return (base_uint256)a <= (base_uint256)b; } +inline bool operator>(const base_uint256& a, const uint256& b) { return (base_uint256)a > (base_uint256)b; } +inline bool operator>=(const base_uint256& a, const uint256& b) { return (base_uint256)a >= (base_uint256)b; } +inline bool operator==(const base_uint256& a, const uint256& b) { return (base_uint256)a == (base_uint256)b; } +inline bool operator!=(const base_uint256& a, const uint256& b) { return (base_uint256)a != (base_uint256)b; } +inline const uint256 operator^(const base_uint256& a, const uint256& b) { return (base_uint256)a ^ (base_uint256)b; } +inline const uint256 operator&(const base_uint256& a, const uint256& b) { return (base_uint256)a & (base_uint256)b; } +inline const uint256 operator|(const base_uint256& a, const uint256& b) { return (base_uint256)a | (base_uint256)b; } +inline const uint256 operator+(const base_uint256& a, const uint256& b) { return (base_uint256)a + (base_uint256)b; } +inline const uint256 operator-(const base_uint256& a, const uint256& b) { return (base_uint256)a - (base_uint256)b; } + +inline bool operator<(const uint256& a, const base_uint256& b) { return (base_uint256)a < (base_uint256)b; } +inline bool operator<=(const uint256& a, const base_uint256& b) { return (base_uint256)a <= (base_uint256)b; } +inline bool operator>(const uint256& a, const base_uint256& b) { return (base_uint256)a > (base_uint256)b; } +inline bool operator>=(const uint256& a, const base_uint256& b) { return (base_uint256)a >= (base_uint256)b; } +inline bool operator==(const uint256& a, const base_uint256& b) { return (base_uint256)a == (base_uint256)b; } +inline bool operator!=(const uint256& a, const base_uint256& b) { return (base_uint256)a != (base_uint256)b; } +inline const uint256 operator^(const uint256& a, const base_uint256& b) { return (base_uint256)a ^ (base_uint256)b; } +inline const uint256 operator&(const uint256& a, const base_uint256& b) { return (base_uint256)a & (base_uint256)b; } +inline const uint256 operator|(const uint256& a, const base_uint256& b) { return (base_uint256)a | (base_uint256)b; } +inline const uint256 operator+(const uint256& a, const base_uint256& b) { return (base_uint256)a + (base_uint256)b; } +inline const uint256 operator-(const uint256& a, const base_uint256& b) { return (base_uint256)a - (base_uint256)b; } + +inline bool operator<(const uint256& a, const uint256& b) { return (base_uint256)a < (base_uint256)b; } +inline bool operator<=(const uint256& a, const uint256& b) { return (base_uint256)a <= (base_uint256)b; } +inline bool operator>(const uint256& a, const uint256& b) { return (base_uint256)a > (base_uint256)b; } +inline bool operator>=(const uint256& a, const uint256& b) { return (base_uint256)a >= (base_uint256)b; } +inline bool operator==(const uint256& a, const uint256& b) { return (base_uint256)a == (base_uint256)b; } +inline bool operator!=(const uint256& a, const uint256& b) { return (base_uint256)a != (base_uint256)b; } +inline const uint256 operator^(const uint256& a, const uint256& b) { return (base_uint256)a ^ (base_uint256)b; } +inline const uint256 operator&(const uint256& a, const uint256& b) { return (base_uint256)a & (base_uint256)b; } +inline const uint256 operator|(const uint256& a, const uint256& b) { return (base_uint256)a | (base_uint256)b; } +inline const uint256 operator+(const uint256& a, const uint256& b) { return (base_uint256)a + (base_uint256)b; } +inline const uint256 operator-(const uint256& a, const uint256& b) { return (base_uint256)a - (base_uint256)b; } + + + + + + + + + + +#ifdef TEST_UINT256 + +inline int Testuint256AdHoc(std::vector vArg) +{ + uint256 g(0); + + + printf("%s\n", g.ToString().c_str()); + g--; printf("g--\n"); + printf("%s\n", g.ToString().c_str()); + g--; printf("g--\n"); + printf("%s\n", g.ToString().c_str()); + g++; printf("g++\n"); + printf("%s\n", g.ToString().c_str()); + g++; printf("g++\n"); + printf("%s\n", g.ToString().c_str()); + g++; printf("g++\n"); + printf("%s\n", g.ToString().c_str()); + g++; printf("g++\n"); + printf("%s\n", g.ToString().c_str()); + + + + uint256 a(7); + printf("a=7\n"); + printf("%s\n", a.ToString().c_str()); + + uint256 b; + printf("b undefined\n"); + printf("%s\n", b.ToString().c_str()); + int c = 3; + + a = c; + a.pn[3] = 15; + printf("%s\n", a.ToString().c_str()); + uint256 k(c); + + a = 5; + a.pn[3] = 15; + printf("%s\n", a.ToString().c_str()); + b = 1; + b <<= 52; + + a |= b; + + a ^= 0x500; + + printf("a %s\n", a.ToString().c_str()); + + a = a | b | (uint256)0x1000; + + + printf("a %s\n", a.ToString().c_str()); + printf("b %s\n", b.ToString().c_str()); + + a = 0xfffffffe; + a.pn[4] = 9; + + printf("%s\n", a.ToString().c_str()); + a++; + printf("%s\n", a.ToString().c_str()); + a++; + printf("%s\n", a.ToString().c_str()); + a++; + printf("%s\n", a.ToString().c_str()); + a++; + printf("%s\n", a.ToString().c_str()); + + a--; + printf("%s\n", a.ToString().c_str()); + a--; + printf("%s\n", a.ToString().c_str()); + a--; + printf("%s\n", a.ToString().c_str()); + uint256 d = a--; + printf("%s\n", d.ToString().c_str()); + printf("%s\n", a.ToString().c_str()); + a--; + printf("%s\n", a.ToString().c_str()); + a--; + printf("%s\n", a.ToString().c_str()); + + d = a; + + printf("%s\n", d.ToString().c_str()); + for (int i = uint256::WIDTH-1; i >= 0; i--) printf("%08x", d.pn[i]); printf("\n"); + + uint256 neg = d; + neg = ~neg; + printf("%s\n", neg.ToString().c_str()); + + + uint256 e = uint256("0xABCDEF123abcdef12345678909832180000011111111"); + printf("\n"); + printf("%s\n", e.ToString().c_str()); + + + printf("\n"); + uint256 x1 = uint256("0xABCDEF123abcdef12345678909832180000011111111"); + uint256 x2; + printf("%s\n", x1.ToString().c_str()); + for (int i = 0; i < 270; i += 4) + { + x2 = x1 << i; + printf("%s\n", x2.ToString().c_str()); + } + + printf("\n"); + printf("%s\n", x1.ToString().c_str()); + for (int i = 0; i < 270; i += 4) + { + x2 = x1; + x2 >>= i; + printf("%s\n", x2.ToString().c_str()); + } + + + for (int i = 0; i < 100; i++) + { + uint256 k = (~uint256(0) >> i); + printf("%s\n", k.ToString().c_str()); + } + + for (int i = 0; i < 100; i++) + { + uint256 k = (~uint256(0) << i); + printf("%s\n", k.ToString().c_str()); + } + + return (0); +} + +#endif + +#endif diff --git a/src/util.cpp b/src/util.cpp new file mode 100644 index 0000000..03e3a88 --- /dev/null +++ b/src/util.cpp @@ -0,0 +1,1329 @@ +// Copyright (c) 2009-2010 Satoshi Nakamoto +// Copyright (c) 2009-2012 The Bitcoin developers +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include "util.h" +#include "sync.h" +#include "strlcpy.h" +#include "version.h" +#include "ui_interface.h" +#include + +// Work around clang compilation problem in Boost 1.46: +// /usr/include/boost/program_options/detail/config_file.hpp:163:17: error: call to function 'to_internal' that is neither visible in the template definition nor found by argument-dependent lookup +// See also: http://stackoverflow.com/questions/10020179/compilation-fail-in-boost-librairies-program-options +// http://clang.debian.net/status.php?version=3.0&key=CANNOT_FIND_FUNCTION +namespace boost { + namespace program_options { + std::string to_internal(const std::string&); + } +} + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef WIN32 +#ifdef _MSC_VER +#pragma warning(disable:4786) +#pragma warning(disable:4804) +#pragma warning(disable:4805) +#pragma warning(disable:4717) +#endif +#ifdef _WIN32_WINNT +#undef _WIN32_WINNT +#endif +#define _WIN32_WINNT 0x0501 +#ifdef _WIN32_IE +#undef _WIN32_IE +#endif +#define _WIN32_IE 0x0501 +#define WIN32_LEAN_AND_MEAN 1 +#ifndef NOMINMAX +#define NOMINMAX +#endif +#include /* for _commit */ +#include "shlobj.h" +#elif defined(__linux__) +# include +#endif + +using namespace std; + +map mapArgs; +map > mapMultiArgs; +bool fDebug = false; +bool fDebugNet = false; +bool fPrintToConsole = false; +bool fPrintToDebugger = false; +bool fRequestShutdown = false; +bool fShutdown = false; +bool fDaemon = false; +bool fServer = false; +bool fCommandLine = false; +string strMiscWarning; +bool fTestNet = false; +bool fNoListen = false; +bool fLogTimestamps = false; +CMedianFilter vTimeOffsets(200,0); +bool fReopenDebugLog = false; + +// Init OpenSSL library multithreading support +static CCriticalSection** ppmutexOpenSSL; +void locking_callback(int mode, int i, const char* file, int line) +{ + if (mode & CRYPTO_LOCK) { + ENTER_CRITICAL_SECTION(*ppmutexOpenSSL[i]); + } else { + LEAVE_CRITICAL_SECTION(*ppmutexOpenSSL[i]); + } +} + +LockedPageManager LockedPageManager::instance; + +// Init +class CInit +{ +public: + CInit() + { + // Init OpenSSL library multithreading support + ppmutexOpenSSL = (CCriticalSection**)OPENSSL_malloc(CRYPTO_num_locks() * sizeof(CCriticalSection*)); + for (int i = 0; i < CRYPTO_num_locks(); i++) + ppmutexOpenSSL[i] = new CCriticalSection(); + CRYPTO_set_locking_callback(locking_callback); + +#ifdef WIN32 + // Seed random number generator with screen scrape and other hardware sources + RAND_screen(); +#endif + + // Seed random number generator with performance counter + RandAddSeed(); + } + ~CInit() + { + // Shutdown OpenSSL library multithreading support + CRYPTO_set_locking_callback(NULL); + for (int i = 0; i < CRYPTO_num_locks(); i++) + delete ppmutexOpenSSL[i]; + OPENSSL_free(ppmutexOpenSSL); + } +} +instance_of_cinit; + + + + + + + + +void RandAddSeed() +{ + // Seed with CPU performance counter + int64_t nCounter = GetPerformanceCounter(); + RAND_add(&nCounter, sizeof(nCounter), 1.5); + memset(&nCounter, 0, sizeof(nCounter)); +} + +void RandAddSeedPerfmon() +{ + RandAddSeed(); + + // This can take up to 2 seconds, so only do it every 10 minutes + static int64_t nLastPerfmon; + if (GetTime() < nLastPerfmon + 10 * 60) + return; + nLastPerfmon = GetTime(); + +#ifdef WIN32 + // Don't need this on Linux, OpenSSL automatically uses /dev/urandom + // Seed with the entire set of perfmon data + unsigned char pdata[250000]; + memset(pdata, 0, sizeof(pdata)); + unsigned long nSize = sizeof(pdata); + long ret = RegQueryValueExA(HKEY_PERFORMANCE_DATA, "Global", NULL, NULL, pdata, &nSize); + RegCloseKey(HKEY_PERFORMANCE_DATA); + if (ret == ERROR_SUCCESS) + { + RAND_add(pdata, nSize, nSize/100.0); + OPENSSL_cleanse(pdata, nSize); + printf("RandAddSeed() %lu bytes\n", nSize); + } +#endif +} + +uint64_t GetRand(uint64_t nMax) +{ + if (nMax == 0) + return 0; + + // The range of the random source must be a multiple of the modulus + // to give every possible output value an equal possibility + uint64_t nRange = (std::numeric_limits::max() / nMax) * nMax; + uint64_t nRand = 0; + do + RAND_bytes((unsigned char*)&nRand, sizeof(nRand)); + while (nRand >= nRange); + return (nRand % nMax); +} + +int GetRandInt(int nMax) +{ + return GetRand(nMax); +} + +uint256 GetRandHash() +{ + uint256 hash; + RAND_bytes((unsigned char*)&hash, sizeof(hash)); + return hash; +} + + + + + + + +inline int OutputDebugStringF(const char* pszFormat, ...) +{ + int ret = 0; + if (fPrintToConsole) + { + // print to console + va_list arg_ptr; + va_start(arg_ptr, pszFormat); + ret = vprintf(pszFormat, arg_ptr); + va_end(arg_ptr); + } + else if (!fPrintToDebugger) + { + // print to debug.log + static FILE* fileout = NULL; + + if (!fileout) + { + boost::filesystem::path pathDebug = GetDataDir() / "debug.log"; + fileout = fopen(pathDebug.string().c_str(), "a"); + if (fileout) setbuf(fileout, NULL); // unbuffered + } + if (fileout) + { + static bool fStartedNewLine = true; + + // This routine may be called by global destructors during shutdown. + // Since the order of destruction of static/global objects is undefined, + // allocate mutexDebugLog on the heap the first time this routine + // is called to avoid crashes during shutdown. + static boost::mutex* mutexDebugLog = NULL; + if (mutexDebugLog == NULL) mutexDebugLog = new boost::mutex(); + boost::mutex::scoped_lock scoped_lock(*mutexDebugLog); + + // reopen the log file, if requested + if (fReopenDebugLog) { + fReopenDebugLog = false; + boost::filesystem::path pathDebug = GetDataDir() / "debug.log"; + if (freopen(pathDebug.string().c_str(),"a",fileout) != NULL) + setbuf(fileout, NULL); // unbuffered + } + + // Debug print useful for profiling + if (fLogTimestamps && fStartedNewLine) + fprintf(fileout, "%s ", DateTimeStrFormat("%x %H:%M:%S", GetTime()).c_str()); + if (pszFormat[strlen(pszFormat) - 1] == '\n') + fStartedNewLine = true; + else + fStartedNewLine = false; + + va_list arg_ptr; + va_start(arg_ptr, pszFormat); + ret = vfprintf(fileout, pszFormat, arg_ptr); + va_end(arg_ptr); + } + } + +#ifdef WIN32 + if (fPrintToDebugger) + { + static CCriticalSection cs_OutputDebugStringF; + + // accumulate and output a line at a time + { + LOCK(cs_OutputDebugStringF); + static std::string buffer; + + va_list arg_ptr; + va_start(arg_ptr, pszFormat); + buffer += vstrprintf(pszFormat, arg_ptr); + va_end(arg_ptr); + + int line_start = 0, line_end; + while((line_end = buffer.find('\n', line_start)) != -1) + { + OutputDebugStringA(buffer.substr(line_start, line_end - line_start).c_str()); + line_start = line_end + 1; + } + buffer.erase(0, line_start); + } + } +#endif + return ret; +} + +string vstrprintf(const char *format, va_list ap) +{ + char buffer[50000]; + char* p = buffer; + int limit = sizeof(buffer); + int ret; + while (true) + { + va_list arg_ptr; + va_copy(arg_ptr, ap); +#ifdef WIN32 + ret = _vsnprintf(p, limit, format, arg_ptr); +#else + ret = vsnprintf(p, limit, format, arg_ptr); +#endif + va_end(arg_ptr); + if (ret >= 0 && ret < limit) + break; + if (p != buffer) + delete[] p; + limit *= 2; + p = new char[limit]; + if (p == NULL) + throw std::bad_alloc(); + } + string str(p, p+ret); + if (p != buffer) + delete[] p; + return str; +} + +string real_strprintf(const char *format, int dummy, ...) +{ + va_list arg_ptr; + va_start(arg_ptr, dummy); + string str = vstrprintf(format, arg_ptr); + va_end(arg_ptr); + return str; +} + +string real_strprintf(const std::string &format, int dummy, ...) +{ + va_list arg_ptr; + va_start(arg_ptr, dummy); + string str = vstrprintf(format.c_str(), arg_ptr); + va_end(arg_ptr); + return str; +} + +bool error(const char *format, ...) +{ + va_list arg_ptr; + va_start(arg_ptr, format); + std::string str = vstrprintf(format, arg_ptr); + va_end(arg_ptr); + printf("ERROR: %s\n", str.c_str()); + return false; +} + + +void ParseString(const string& str, char c, vector& v) +{ + if (str.empty()) + return; + string::size_type i1 = 0; + string::size_type i2; + while (true) + { + i2 = str.find(c, i1); + if (i2 == str.npos) + { + v.push_back(str.substr(i1)); + return; + } + v.push_back(str.substr(i1, i2-i1)); + i1 = i2+1; + } +} + + +string FormatMoney(int64_t n, bool fPlus) +{ + // Note: not using straight sprintf here because we do NOT want + // localized number formatting. + int64_t n_abs = (n > 0 ? n : -n); + int64_t quotient = n_abs/COIN; + int64_t remainder = n_abs%COIN; + string str = strprintf("%" PRId64".%08" PRId64, quotient, remainder); + + // Right-trim excess zeros before the decimal point: + int nTrim = 0; + for (int i = str.size()-1; (str[i] == '0' && isdigit(str[i-2])); --i) + ++nTrim; + if (nTrim) + str.erase(str.size()-nTrim, nTrim); + + if (n < 0) + str.insert((unsigned int)0, 1, '-'); + else if (fPlus && n > 0) + str.insert((unsigned int)0, 1, '+'); + return str; +} + + +bool ParseMoney(const string& str, int64_t& nRet) +{ + return ParseMoney(str.c_str(), nRet); +} + +bool ParseMoney(const char* pszIn, int64_t& nRet) +{ + string strWhole; + int64_t nUnits = 0; + const char* p = pszIn; + while (isspace(*p)) + p++; + for (; *p; p++) + { + if (*p == '.') + { + p++; + int64_t nMult = CENT*10; + while (isdigit(*p) && (nMult > 0)) + { + nUnits += nMult * (*p++ - '0'); + nMult /= 10; + } + break; + } + if (isspace(*p)) + break; + if (!isdigit(*p)) + return false; + strWhole.insert(strWhole.end(), *p); + } + for (; *p; p++) + if (!isspace(*p)) + return false; + if (strWhole.size() > 10) // guard against 63 bit overflow + return false; + if (nUnits < 0 || nUnits > COIN) + return false; + int64_t nWhole = atoi64(strWhole); + int64_t nValue = nWhole*COIN + nUnits; + + nRet = nValue; + return true; +} + + +static const signed char phexdigit[256] = +{ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 0,1,2,3,4,5,6,7,8,9,-1,-1,-1,-1,-1,-1, + -1,0xa,0xb,0xc,0xd,0xe,0xf,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,0xa,0xb,0xc,0xd,0xe,0xf,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, }; + +bool IsHex(const string& str) +{ + BOOST_FOREACH(unsigned char c, str) + { + if (phexdigit[c] < 0) + return false; + } + return (str.size() > 0) && (str.size()%2 == 0); +} + +vector ParseHex(const char* psz) +{ + // convert hex dump to vector + vector vch; + while (true) + { + while (isspace(*psz)) + psz++; + signed char c = phexdigit[(unsigned char)*psz++]; + if (c == (signed char)-1) + break; + unsigned char n = (c << 4); + c = phexdigit[(unsigned char)*psz++]; + if (c == (signed char)-1) + break; + n |= c; + vch.push_back(n); + } + return vch; +} + +vector ParseHex(const string& str) +{ + return ParseHex(str.c_str()); +} + +static void InterpretNegativeSetting(string name, map& mapSettingsRet) +{ + // interpret -nofoo as -foo=0 (and -nofoo=0 as -foo=1) as long as -foo not set + if (name.find("-no") == 0) + { + std::string positive("-"); + positive.append(name.begin()+3, name.end()); + if (mapSettingsRet.count(positive) == 0) + { + bool value = !GetBoolArg(name); + mapSettingsRet[positive] = (value ? "1" : "0"); + } + } +} + +void ParseParameters(int argc, const char* const argv[]) +{ + mapArgs.clear(); + mapMultiArgs.clear(); + for (int i = 1; i < argc; i++) + { + char psz[10000]; + strlcpy(psz, argv[i], sizeof(psz)); + char* pszValue = (char*)""; + if (strchr(psz, '=')) + { + pszValue = strchr(psz, '='); + *pszValue++ = '\0'; + } + #ifdef WIN32 + _strlwr(psz); + if (psz[0] == '/') + psz[0] = '-'; + #endif + if (psz[0] != '-') + break; + + mapArgs[psz] = pszValue; + mapMultiArgs[psz].push_back(pszValue); + } + + // New 0.6 features: + BOOST_FOREACH(const PAIRTYPE(string,string)& entry, mapArgs) + { + string name = entry.first; + + // interpret --foo as -foo (as long as both are not set) + if (name.find("--") == 0) + { + std::string singleDash(name.begin()+1, name.end()); + if (mapArgs.count(singleDash) == 0) + mapArgs[singleDash] = entry.second; + name = singleDash; + } + + // interpret -nofoo as -foo=0 (and -nofoo=0 as -foo=1) as long as -foo not set + InterpretNegativeSetting(name, mapArgs); + } +} + +std::string GetArg(const std::string& strArg, const std::string& strDefault) +{ + if (mapArgs.count(strArg)) + return mapArgs[strArg]; + return strDefault; +} + +int64_t GetArg(const std::string& strArg, int64_t nDefault) +{ + if (mapArgs.count(strArg)) + return atoi64(mapArgs[strArg]); + return nDefault; +} + +bool GetBoolArg(const std::string& strArg, bool fDefault) +{ + if (mapArgs.count(strArg)) + { + if (mapArgs[strArg].empty()) + return true; + return (atoi(mapArgs[strArg]) != 0); + } + return fDefault; +} + +bool SoftSetArg(const std::string& strArg, const std::string& strValue) +{ + if (mapArgs.count(strArg)) + return false; + mapArgs[strArg] = strValue; + return true; +} + +bool SoftSetBoolArg(const std::string& strArg, bool fValue) +{ + if (fValue) + return SoftSetArg(strArg, std::string("1")); + else + return SoftSetArg(strArg, std::string("0")); +} + + +string EncodeBase64(const unsigned char* pch, size_t len) +{ + static const char *pbase64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + + string strRet=""; + strRet.reserve((len+2)/3*4); + + int mode=0, left=0; + const unsigned char *pchEnd = pch+len; + + while (pch> 2]; + left = (enc & 3) << 4; + mode = 1; + break; + + case 1: // we have two bits + strRet += pbase64[left | (enc >> 4)]; + left = (enc & 15) << 2; + mode = 2; + break; + + case 2: // we have four bits + strRet += pbase64[left | (enc >> 6)]; + strRet += pbase64[enc & 63]; + mode = 0; + break; + } + } + + if (mode) + { + strRet += pbase64[left]; + strRet += '='; + if (mode == 1) + strRet += '='; + } + + return strRet; +} + +string EncodeBase64(const string& str) +{ + return EncodeBase64((const unsigned char*)str.c_str(), str.size()); +} + +vector DecodeBase64(const char* p, bool* pfInvalid) +{ + static const int decode64_table[256] = + { + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 62, -1, -1, -1, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, + -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, -1, 26, 27, 28, + 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, + 49, 50, 51, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 + }; + + if (pfInvalid) + *pfInvalid = false; + + vector vchRet; + vchRet.reserve(strlen(p)*3/4); + + int mode = 0; + int left = 0; + + while (1) + { + int dec = decode64_table[(unsigned char)*p]; + if (dec == -1) break; + p++; + switch (mode) + { + case 0: // we have no bits and get 6 + left = dec; + mode = 1; + break; + + case 1: // we have 6 bits and keep 4 + vchRet.push_back((left<<2) | (dec>>4)); + left = dec & 15; + mode = 2; + break; + + case 2: // we have 4 bits and get 6, we keep 2 + vchRet.push_back((left<<4) | (dec>>2)); + left = dec & 3; + mode = 3; + break; + + case 3: // we have 2 bits and get 6 + vchRet.push_back((left<<6) | dec); + mode = 0; + break; + } + } + + if (pfInvalid) + switch (mode) + { + case 0: // 4n base64 characters processed: ok + break; + + case 1: // 4n+1 base64 character processed: impossible + *pfInvalid = true; + break; + + case 2: // 4n+2 base64 characters processed: require '==' + if (left || p[0] != '=' || p[1] != '=' || decode64_table[(unsigned char)p[2]] != -1) + *pfInvalid = true; + break; + + case 3: // 4n+3 base64 characters processed: require '=' + if (left || p[0] != '=' || decode64_table[(unsigned char)p[1]] != -1) + *pfInvalid = true; + break; + } + + return vchRet; +} + +string DecodeBase64(const string& str) +{ + vector vchRet = DecodeBase64(str.c_str()); + return string((const char*)&vchRet[0], vchRet.size()); +} + +string EncodeBase32(const unsigned char* pch, size_t len) +{ + static const char *pbase32 = "abcdefghijklmnopqrstuvwxyz234567"; + + string strRet=""; + strRet.reserve((len+4)/5*8); + + int mode=0, left=0; + const unsigned char *pchEnd = pch+len; + + while (pch> 3]; + left = (enc & 7) << 2; + mode = 1; + break; + + case 1: // we have three bits + strRet += pbase32[left | (enc >> 6)]; + strRet += pbase32[(enc >> 1) & 31]; + left = (enc & 1) << 4; + mode = 2; + break; + + case 2: // we have one bit + strRet += pbase32[left | (enc >> 4)]; + left = (enc & 15) << 1; + mode = 3; + break; + + case 3: // we have four bits + strRet += pbase32[left | (enc >> 7)]; + strRet += pbase32[(enc >> 2) & 31]; + left = (enc & 3) << 3; + mode = 4; + break; + + case 4: // we have two bits + strRet += pbase32[left | (enc >> 5)]; + strRet += pbase32[enc & 31]; + mode = 0; + } + } + + static const int nPadding[5] = {0, 6, 4, 3, 1}; + if (mode) + { + strRet += pbase32[left]; + for (int n=0; n DecodeBase32(const char* p, bool* pfInvalid) +{ + static const int decode32_table[256] = + { + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 26, 27, 28, 29, 30, 31, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, -1, 0, 1, 2, + 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, + 23, 24, 25, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 + }; + + if (pfInvalid) + *pfInvalid = false; + + vector vchRet; + vchRet.reserve((strlen(p))*5/8); + + int mode = 0; + int left = 0; + + while (1) + { + int dec = decode32_table[(unsigned char)*p]; + if (dec == -1) break; + p++; + switch (mode) + { + case 0: // we have no bits and get 5 + left = dec; + mode = 1; + break; + + case 1: // we have 5 bits and keep 2 + vchRet.push_back((left<<3) | (dec>>2)); + left = dec & 3; + mode = 2; + break; + + case 2: // we have 2 bits and keep 7 + left = left << 5 | dec; + mode = 3; + break; + + case 3: // we have 7 bits and keep 4 + vchRet.push_back((left<<1) | (dec>>4)); + left = dec & 15; + mode = 4; + break; + + case 4: // we have 4 bits, and keep 1 + vchRet.push_back((left<<4) | (dec>>1)); + left = dec & 1; + mode = 5; + break; + + case 5: // we have 1 bit, and keep 6 + left = left << 5 | dec; + mode = 6; + break; + + case 6: // we have 6 bits, and keep 3 + vchRet.push_back((left<<2) | (dec>>3)); + left = dec & 7; + mode = 7; + break; + + case 7: // we have 3 bits, and keep 0 + vchRet.push_back((left<<5) | dec); + mode = 0; + break; + } + } + + if (pfInvalid) + switch (mode) + { + case 0: // 8n base32 characters processed: ok + break; + + case 1: // 8n+1 base32 characters processed: impossible + case 3: // +3 + case 6: // +6 + *pfInvalid = true; + break; + + case 2: // 8n+2 base32 characters processed: require '======' + if (left || p[0] != '=' || p[1] != '=' || p[2] != '=' || p[3] != '=' || p[4] != '=' || p[5] != '=' || decode32_table[(unsigned char)p[6]] != -1) + *pfInvalid = true; + break; + + case 4: // 8n+4 base32 characters processed: require '====' + if (left || p[0] != '=' || p[1] != '=' || p[2] != '=' || p[3] != '=' || decode32_table[(unsigned char)p[4]] != -1) + *pfInvalid = true; + break; + + case 5: // 8n+5 base32 characters processed: require '===' + if (left || p[0] != '=' || p[1] != '=' || p[2] != '=' || decode32_table[(unsigned char)p[3]] != -1) + *pfInvalid = true; + break; + + case 7: // 8n+7 base32 characters processed: require '=' + if (left || p[0] != '=' || decode32_table[(unsigned char)p[1]] != -1) + *pfInvalid = true; + break; + } + + return vchRet; +} + +string DecodeBase32(const string& str) +{ + vector vchRet = DecodeBase32(str.c_str()); + return string((const char*)&vchRet[0], vchRet.size()); +} + + +bool WildcardMatch(const char* psz, const char* mask) +{ + while (true) + { + switch (*mask) + { + case '\0': + return (*psz == '\0'); + case '*': + return WildcardMatch(psz, mask+1) || (*psz && WildcardMatch(psz+1, mask)); + case '?': + if (*psz == '\0') + return false; + break; + default: + if (*psz != *mask) + return false; + break; + } + psz++; + mask++; + } +} + +bool WildcardMatch(const string& str, const string& mask) +{ + return WildcardMatch(str.c_str(), mask.c_str()); +} + + + + + + + + +static std::string FormatException(std::exception* pex, const char* pszThread) +{ +#ifdef WIN32 + char pszModule[MAX_PATH] = ""; + GetModuleFileNameA(NULL, pszModule, sizeof(pszModule)); +#else + const char* pszModule = "arepacoin"; +#endif + if (pex) + return strprintf( + "EXCEPTION: %s \n%s \n%s in %s \n", typeid(*pex).name(), pex->what(), pszModule, pszThread); + else + return strprintf( + "UNKNOWN EXCEPTION \n%s in %s \n", pszModule, pszThread); +} + +void PrintException(std::exception* pex, const char* pszThread) +{ + std::string message = FormatException(pex, pszThread); + printf("\n\n************************\n%s\n", message.c_str()); + fprintf(stderr, "\n\n************************\n%s\n", message.c_str()); + strMiscWarning = message; + throw; +} + +void PrintExceptionContinue(std::exception* pex, const char* pszThread) +{ + std::string message = FormatException(pex, pszThread); + printf("\n\n************************\n%s\n", message.c_str()); + fprintf(stderr, "\n\n************************\n%s\n", message.c_str()); + strMiscWarning = message; +} + +boost::filesystem::path GetDefaultDataDir() +{ + namespace fs = boost::filesystem; + // Windows < Vista: C:\Documents and Settings\Username\Application Data\arepacoin + // Windows >= Vista: C:\Users\Username\AppData\Roaming\arepacoin + // Mac: ~/Library/Application Support/arepacoin + // Unix: ~/.arepacoin +#ifdef WIN32 + // Windows + return GetSpecialFolderPath(CSIDL_APPDATA) / "arepacoin"; +#else + fs::path pathRet; + char* pszHome = getenv("HOME"); + if (pszHome == NULL || strlen(pszHome) == 0) + pathRet = fs::path("/"); + else + pathRet = fs::path(pszHome); +#ifdef MAC_OSX + // Mac + pathRet /= "Library/Application Support"; + fs::create_directory(pathRet); + return pathRet / "arepacoin"; +#else + // Unix + return pathRet / ".arepacoin"; +#endif +#endif +} + +const boost::filesystem::path &GetDataDir(bool fNetSpecific) +{ + namespace fs = boost::filesystem; + + static fs::path pathCached[2]; + static CCriticalSection csPathCached; + static bool cachedPath[2] = {false, false}; + + fs::path &path = pathCached[fNetSpecific]; + + // This can be called during exceptions by printf, so we cache the + // value so we don't have to do memory allocations after that. + if (cachedPath[fNetSpecific]) + return path; + + LOCK(csPathCached); + + if (mapArgs.count("-datadir")) { + path = fs::system_complete(mapArgs["-datadir"]); + if (!fs::is_directory(path)) { + path = ""; + return path; + } + } else { + path = GetDefaultDataDir(); + } + if (fNetSpecific && GetBoolArg("-testnet", false)) + path /= "testnet"; + + fs::create_directory(path); + + cachedPath[fNetSpecific]=true; + return path; +} + +boost::filesystem::path GetConfigFile() +{ + boost::filesystem::path pathConfigFile(GetArg("-conf", "arepacoin.conf")); + if (!pathConfigFile.is_complete()) pathConfigFile = GetDataDir(false) / pathConfigFile; + return pathConfigFile; +} + +void ReadConfigFile(map& mapSettingsRet, + map >& mapMultiSettingsRet) +{ + boost::filesystem::ifstream streamConfig(GetConfigFile()); + if (!streamConfig.good()) + return; // No bitcoin.conf file is OK + + set setOptions; + setOptions.insert("*"); + + for (boost::program_options::detail::config_file_iterator it(streamConfig, setOptions), end; it != end; ++it) + { + // Don't overwrite existing settings so command line settings override bitcoin.conf + string strKey = string("-") + it->string_key; + if (mapSettingsRet.count(strKey) == 0) + { + mapSettingsRet[strKey] = it->value[0]; + // interpret nofoo=1 as foo=0 (and nofoo=0 as foo=1) as long as foo not set) + InterpretNegativeSetting(strKey, mapSettingsRet); + } + mapMultiSettingsRet[strKey].push_back(it->value[0]); + } +} + +boost::filesystem::path GetPidFile() +{ + boost::filesystem::path pathPidFile(GetArg("-pid", "arepacoind.pid")); + if (!pathPidFile.is_complete()) pathPidFile = GetDataDir() / pathPidFile; + return pathPidFile; +} + +#ifndef WIN32 +void CreatePidFile(const boost::filesystem::path &path, pid_t pid) +{ + FILE* file = fopen(path.string().c_str(), "w"); + if (file) + { + fprintf(file, "%d\n", pid); + fclose(file); + } +} +#endif + +bool RenameOver(boost::filesystem::path src, boost::filesystem::path dest) +{ +#ifdef WIN32 + return MoveFileExA(src.string().c_str(), dest.string().c_str(), + MOVEFILE_REPLACE_EXISTING); +#else + int rc = std::rename(src.string().c_str(), dest.string().c_str()); + return (rc == 0); +#endif /* WIN32 */ +} + +void FileCommit(FILE *fileout) +{ + fflush(fileout); // harmless if redundantly called +#ifdef WIN32 + _commit(_fileno(fileout)); +#else + fsync(fileno(fileout)); +#endif +} + +void ShrinkDebugFile() +{ + // Scroll debug.log if it's getting too big + boost::filesystem::path pathLog = GetDataDir() / "debug.log"; + FILE* file = fopen(pathLog.string().c_str(), "r"); + if (file && boost::filesystem::file_size(pathLog) > 10 * 1000000) + { + // Restart the file with some of the end + char pch[200000]; + fseek(file, -sizeof(pch), SEEK_END); + int nBytes = fread(pch, 1, sizeof(pch), file); + fclose(file); + + file = fopen(pathLog.string().c_str(), "w"); + if (file) + { + fwrite(pch, 1, nBytes, file); + fclose(file); + } + } +} + +// +// "Never go to sea with two chronometers; take one or three." +// Our three time sources are: +// - System clock +// - Median of other nodes clocks +// - The user (asking the user to fix the system clock if the first two disagree) +// +static int64_t nMockTime = 0; // For unit testing + +int64_t GetTime() +{ + if (nMockTime) return nMockTime; + + return time(NULL); +} + +void SetMockTime(int64_t nMockTimeIn) +{ + nMockTime = nMockTimeIn; +} + +static int64_t nTimeOffset = 0; + +int64_t GetTimeOffset() +{ + return nTimeOffset; +} + +int64_t GetAdjustedTime() +{ + return GetTime() + GetTimeOffset(); +} + +void AddTimeData(const CNetAddr& ip, int64_t nTime) +{ + int64_t nOffsetSample = nTime - GetTime(); + + // Ignore duplicates + static set setKnown; + if (!setKnown.insert(ip).second) + return; + + // Add data + vTimeOffsets.input(nOffsetSample); + printf("Added time data, samples %d, offset %+" PRId64" (%+" PRId64" minutes)\n", vTimeOffsets.size(), nOffsetSample, nOffsetSample/60); + if (vTimeOffsets.size() >= 5 && vTimeOffsets.size() % 2 == 1) + { + int64_t nMedian = vTimeOffsets.median(); + std::vector vSorted = vTimeOffsets.sorted(); + // Only let other nodes change our time by so much + if (abs64(nMedian) < 70 * 60) + { + nTimeOffset = nMedian; + } + else + { + nTimeOffset = 0; + + static bool fDone; + if (!fDone) + { + // If nobody has a time different than ours but within 5 minutes of ours, give a warning + bool fMatch = false; + BOOST_FOREACH(int64_t nOffset, vSorted) + if (nOffset != 0 && abs64(nOffset) < 5 * 60) + fMatch = true; + + if (!fMatch) + { + fDone = true; + string strMessage = _("Warning: Please check that your computer's date and time are correct! If your clock is wrong arepacoin will not work properly."); + strMiscWarning = strMessage; + printf("*** %s\n", strMessage.c_str()); + uiInterface.ThreadSafeMessageBox(strMessage+" ", string("arepacoin"), CClientUIInterface::OK | CClientUIInterface::ICON_EXCLAMATION); + } + } + } + if (fDebug) { + BOOST_FOREACH(int64_t n, vSorted) + printf("%+" PRId64" ", n); + printf("| "); + } + printf("nTimeOffset = %+" PRId64" (%+" PRId64" minutes)\n", nTimeOffset, nTimeOffset/60); + } +} + +uint32_t insecure_rand_Rz = 11; +uint32_t insecure_rand_Rw = 11; +void seed_insecure_rand(bool fDeterministic) +{ + //The seed values have some unlikely fixed points which we avoid. + if(fDeterministic) + { + insecure_rand_Rz = insecure_rand_Rw = 11; + } else { + uint32_t tmp; + do{ + RAND_bytes((unsigned char*)&tmp,4); + }while(tmp==0 || tmp==0x9068ffffU); + insecure_rand_Rz=tmp; + do{ + RAND_bytes((unsigned char*)&tmp,4); + }while(tmp==0 || tmp==0x464fffffU); + insecure_rand_Rw=tmp; + } +} + +string FormatVersion(int nVersion) +{ + if (nVersion%100 == 0) + return strprintf("%d.%d.%d", nVersion/1000000, (nVersion/10000)%100, (nVersion/100)%100); + else + return strprintf("%d.%d.%d.%d", nVersion/1000000, (nVersion/10000)%100, (nVersion/100)%100, nVersion%100); +} + +string FormatFullVersion() +{ + return CLIENT_BUILD; +} + +// Format the subversion field according to BIP 14 spec (https://en.bitcoin.it/wiki/BIP_0014) +std::string FormatSubVersion(const std::string& name, int nClientVersion, const std::vector& comments) +{ + std::ostringstream ss; + ss << "/"; + ss << name << ":" << FormatVersion(nClientVersion); + if (!comments.empty()) + ss << "(" << boost::algorithm::join(comments, "; ") << ")"; + ss << "/"; + return ss.str(); +} + +#ifdef WIN32 +boost::filesystem::path GetSpecialFolderPath(int nFolder, bool fCreate) +{ + namespace fs = boost::filesystem; + + char pszPath[MAX_PATH] = ""; + + if(SHGetSpecialFolderPathA(NULL, pszPath, nFolder, fCreate)) + { + return fs::path(pszPath); + } + + printf("SHGetSpecialFolderPathA() failed, could not obtain requested path.\n"); + return fs::path(""); +} +#endif + +void runCommand(std::string strCommand) +{ + int nErr = ::system(strCommand.c_str()); + if (nErr) + printf("runCommand error: system(%s) returned %d\n", strCommand.c_str(), nErr); +} + +void RenameThread(const char* name) +{ +#if defined(PR_SET_NAME) + // Only the first 15 characters are used (16 - NUL terminator) + ::prctl(PR_SET_NAME, name, 0, 0, 0); +#elif 0 && (defined(__FreeBSD__) || defined(__OpenBSD__)) + // TODO: This is currently disabled because it needs to be verified to work + // on FreeBSD or OpenBSD first. When verified the '0 &&' part can be + // removed. + pthread_set_name_np(pthread_self(), name); + +// This is XCode 10.6-and-later; bring back if we drop 10.5 support: +// #elif defined(MAC_OSX) +// pthread_setname_np(name); + +#else + // Prevent warnings for unused parameters... + (void)name; +#endif +} + +bool NewThread(void(*pfn)(void*), void* parg) +{ + try + { + boost::thread(pfn, parg); // thread detaches when out of scope + } catch(boost::thread_resource_error &e) { + printf("Error creating thread: %s\n", e.what()); + return false; + } + return true; +} diff --git a/src/util.h b/src/util.h new file mode 100644 index 0000000..243632b --- /dev/null +++ b/src/util.h @@ -0,0 +1,662 @@ +// Copyright (c) 2009-2010 Satoshi Nakamoto +// Copyright (c) 2009-2012 The Bitcoin developers +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifndef BITCOIN_UTIL_H +#define BITCOIN_UTIL_H + +#include "uint256.h" + +#ifndef WIN32 +#include +#include +#include +#endif + +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include + +#include "netbase.h" // for AddTimeData + +// to obtain PRId64 on some old systems +#define __STDC_FORMAT_MACROS 1 + +#include +#include + +static const int64_t COIN = 100000000; +static const int64_t CENT = 1000000; + +#define BEGIN(a) ((char*)&(a)) +#define END(a) ((char*)&((&(a))[1])) +#define UBEGIN(a) ((unsigned char*)&(a)) +#define UEND(a) ((unsigned char*)&((&(a))[1])) +#define ARRAYLEN(array) (sizeof(array)/sizeof((array)[0])) + +#define UVOIDBEGIN(a) ((void*)&(a)) +#define CVOIDBEGIN(a) ((const void*)&(a)) +#define UINTBEGIN(a) ((uint32_t*)&(a)) +#define CUINTBEGIN(a) ((const uint32_t*)&(a)) + +#ifndef PRId64 +#if defined(_MSC_VER) || defined(__MSVCRT__) +#define PRId64 "I64d" +#define PRIu64 "I64u" +#define PRIx64 "I64x" +#else +#define PRId64 "lld" +#define PRIu64 "llu" +#define PRIx64 "llx" +#endif +#endif + +#ifndef THROW_WITH_STACKTRACE +#define THROW_WITH_STACKTRACE(exception) \ +{ \ + LogStackTrace(); \ + throw (exception); \ +} +void LogStackTrace(); +#endif + +/* Format characters for (s)size_t and ptrdiff_t */ +#if defined(_MSC_VER) || defined(__MSVCRT__) + /* (s)size_t and ptrdiff_t have the same size specifier in MSVC: + http://msdn.microsoft.com/en-us/library/tcxf1dw6%28v=vs.100%29.aspx + */ + #define PRIszx "Ix" + #define PRIszu "Iu" + #define PRIszd "Id" + #define PRIpdx "Ix" + #define PRIpdu "Iu" + #define PRIpdd "Id" +#else /* C99 standard */ + #define PRIszx "zx" + #define PRIszu "zu" + #define PRIszd "zd" + #define PRIpdx "tx" + #define PRIpdu "tu" + #define PRIpdd "td" +#endif + +// This is needed because the foreach macro can't get over the comma in pair +#define PAIRTYPE(t1, t2) std::pair + +// Align by increasing pointer, must have extra space at end of buffer +template +T* alignup(T* p) +{ + union + { + T* ptr; + size_t n; + } u; + u.ptr = p; + u.n = (u.n + (nBytes-1)) & ~(nBytes-1); + return u.ptr; +} + +#ifdef WIN32 +#define MSG_NOSIGNAL 0 +#define MSG_DONTWAIT 0 + +#ifndef S_IRUSR +#define S_IRUSR 0400 +#define S_IWUSR 0200 +#endif +#else +#define MAX_PATH 1024 +#endif + +inline void MilliSleep(int64_t n) +{ +#if BOOST_VERSION >= 105000 + boost::this_thread::sleep_for(boost::chrono::milliseconds(n)); +#else + boost::this_thread::sleep(boost::posix_time::milliseconds(n)); +#endif +} + +/* This GNU C extension enables the compiler to check the format string against the parameters provided. + * X is the number of the "format string" parameter, and Y is the number of the first variadic parameter. + * Parameters count from 1. + */ +#ifdef __GNUC__ +#define ATTR_WARN_PRINTF(X,Y) __attribute__((format(printf,X,Y))) +#else +#define ATTR_WARN_PRINTF(X,Y) +#endif + + + + + + + + +extern std::map mapArgs; +extern std::map > mapMultiArgs; +extern bool fDebug; +extern bool fDebugNet; +extern bool fPrintToConsole; +extern bool fPrintToDebugger; +extern bool fRequestShutdown; +extern bool fShutdown; +extern bool fDaemon; +extern bool fServer; +extern bool fCommandLine; +extern std::string strMiscWarning; +extern bool fTestNet; +extern bool fNoListen; +extern bool fLogTimestamps; +extern bool fReopenDebugLog; + +void RandAddSeed(); +void RandAddSeedPerfmon(); +int ATTR_WARN_PRINTF(1,2) OutputDebugStringF(const char* pszFormat, ...); + +/* + Rationale for the real_strprintf / strprintf construction: + It is not allowed to use va_start with a pass-by-reference argument. + (C++ standard, 18.7, paragraph 3). Use a dummy argument to work around this, and use a + macro to keep similar semantics. +*/ + +/** Overload strprintf for char*, so that GCC format type warnings can be given */ +std::string ATTR_WARN_PRINTF(1,3) real_strprintf(const char *format, int dummy, ...); +/** Overload strprintf for std::string, to be able to use it with _ (translation). + * This will not support GCC format type warnings (-Wformat) so be careful. + */ +std::string real_strprintf(const std::string &format, int dummy, ...); +#define strprintf(format, ...) real_strprintf(format, 0, __VA_ARGS__) +std::string vstrprintf(const char *format, va_list ap); + +bool ATTR_WARN_PRINTF(1,2) error(const char *format, ...); + +/* Redefine printf so that it directs output to debug.log + * + * Do this *after* defining the other printf-like functions, because otherwise the + * __attribute__((format(printf,X,Y))) gets expanded to __attribute__((format(OutputDebugStringF,X,Y))) + * which confuses gcc. + */ +#define printf OutputDebugStringF + +void PrintException(std::exception* pex, const char* pszThread); +void PrintExceptionContinue(std::exception* pex, const char* pszThread); +void ParseString(const std::string& str, char c, std::vector& v); +std::string FormatMoney(int64_t n, bool fPlus=false); +bool ParseMoney(const std::string& str, int64_t& nRet); +bool ParseMoney(const char* pszIn, int64_t& nRet); +std::vector ParseHex(const char* psz); +std::vector ParseHex(const std::string& str); +bool IsHex(const std::string& str); +std::vector DecodeBase64(const char* p, bool* pfInvalid = NULL); +std::string DecodeBase64(const std::string& str); +std::string EncodeBase64(const unsigned char* pch, size_t len); +std::string EncodeBase64(const std::string& str); +std::vector DecodeBase32(const char* p, bool* pfInvalid = NULL); +std::string DecodeBase32(const std::string& str); +std::string EncodeBase32(const unsigned char* pch, size_t len); +std::string EncodeBase32(const std::string& str); +void ParseParameters(int argc, const char*const argv[]); +bool WildcardMatch(const char* psz, const char* mask); +bool WildcardMatch(const std::string& str, const std::string& mask); +void FileCommit(FILE *fileout); +bool RenameOver(boost::filesystem::path src, boost::filesystem::path dest); +boost::filesystem::path GetDefaultDataDir(); +const boost::filesystem::path &GetDataDir(bool fNetSpecific = true); +boost::filesystem::path GetConfigFile(); +boost::filesystem::path GetPidFile(); +#ifndef WIN32 +void CreatePidFile(const boost::filesystem::path &path, pid_t pid); +#endif +void ReadConfigFile(std::map& mapSettingsRet, std::map >& mapMultiSettingsRet); +#ifdef WIN32 +boost::filesystem::path GetSpecialFolderPath(int nFolder, bool fCreate = true); +#endif +void ShrinkDebugFile(); +int GetRandInt(int nMax); +uint64_t GetRand(uint64_t nMax); +uint256 GetRandHash(); +int64_t GetTime(); +void SetMockTime(int64_t nMockTimeIn); +int64_t GetAdjustedTime(); +int64_t GetTimeOffset(); +std::string FormatFullVersion(); +std::string FormatSubVersion(const std::string& name, int nClientVersion, const std::vector& comments); +void AddTimeData(const CNetAddr& ip, int64_t nTime); +void runCommand(std::string strCommand); + + + + + + + + + +inline std::string i64tostr(int64_t n) +{ + return strprintf("%" PRId64, n); +} + +inline std::string itostr(int n) +{ + return strprintf("%d", n); +} + +inline int64_t atoi64(const char* psz) +{ +#ifdef _MSC_VER + return _atoi64(psz); +#else + return strtoll(psz, NULL, 10); +#endif +} + +inline int64_t atoi64(const std::string& str) +{ +#ifdef _MSC_VER + return _atoi64(str.c_str()); +#else + return strtoll(str.c_str(), NULL, 10); +#endif +} + +inline int atoi(const std::string& str) +{ + return atoi(str.c_str()); +} + +inline int roundint(double d) +{ + return (int)(d > 0 ? d + 0.5 : d - 0.5); +} + +inline int64_t roundint64(double d) +{ + return (int64_t)(d > 0 ? d + 0.5 : d - 0.5); +} + +inline int64_t abs64(int64_t n) +{ + return (n >= 0 ? n : -n); +} + +inline std::string leftTrim(std::string src, char chr) +{ + std::string::size_type pos = src.find_first_not_of(chr, 0); + + if(pos > 0) + src.erase(0, pos); + + return src; +} + +template +std::string HexStr(const T itbegin, const T itend, bool fSpaces=false) +{ + std::string rv; + static const char hexmap[16] = { '0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; + rv.reserve((itend-itbegin)*3); + for(T it = itbegin; it < itend; ++it) + { + unsigned char val = (unsigned char)(*it); + if(fSpaces && it != itbegin) + rv.push_back(' '); + rv.push_back(hexmap[val>>4]); + rv.push_back(hexmap[val&15]); + } + + return rv; +} + +inline std::string HexStr(const std::vector& vch, bool fSpaces=false) +{ + return HexStr(vch.begin(), vch.end(), fSpaces); +} + +inline int64_t GetPerformanceCounter() +{ + int64_t nCounter = 0; +#ifdef WIN32 + QueryPerformanceCounter((LARGE_INTEGER*)&nCounter); +#else + timeval t; + gettimeofday(&t, NULL); + nCounter = (int64_t) t.tv_sec * 1000000 + t.tv_usec; +#endif + return nCounter; +} + +inline int64_t GetTimeMillis() +{ + return (boost::posix_time::ptime(boost::posix_time::microsec_clock::universal_time()) - + boost::posix_time::ptime(boost::gregorian::date(1970,1,1))).total_milliseconds(); +} + +inline std::string DateTimeStrFormat(const char* pszFormat, int64_t nTime) +{ + time_t n = nTime; + struct tm* ptmTime = gmtime(&n); + char pszTime[200]; + strftime(pszTime, sizeof(pszTime), pszFormat, ptmTime); + return pszTime; +} + +static const std::string strTimestampFormat = "%Y-%m-%d %H:%M:%S UTC"; +inline std::string DateTimeStrFormat(int64_t nTime) +{ + return DateTimeStrFormat(strTimestampFormat.c_str(), nTime); +} + + +template +void skipspaces(T& it) +{ + while (isspace(*it)) + ++it; +} + +inline bool IsSwitchChar(char c) +{ +#ifdef WIN32 + return c == '-' || c == '/'; +#else + return c == '-'; +#endif +} + +/** + * Return string argument or default value + * + * @param strArg Argument to get (e.g. "-foo") + * @param default (e.g. "1") + * @return command-line argument or default value + */ +std::string GetArg(const std::string& strArg, const std::string& strDefault); + +/** + * Return integer argument or default value + * + * @param strArg Argument to get (e.g. "-foo") + * @param default (e.g. 1) + * @return command-line argument (0 if invalid number) or default value + */ +int64_t GetArg(const std::string& strArg, int64_t nDefault); + +/** + * Return boolean argument or default value + * + * @param strArg Argument to get (e.g. "-foo") + * @param default (true or false) + * @return command-line argument or default value + */ +bool GetBoolArg(const std::string& strArg, bool fDefault=false); + +/** + * Set an argument if it doesn't already have a value + * + * @param strArg Argument to set (e.g. "-foo") + * @param strValue Value (e.g. "1") + * @return true if argument gets set, false if it already had a value + */ +bool SoftSetArg(const std::string& strArg, const std::string& strValue); + +/** + * Set a boolean argument if it doesn't already have a value + * + * @param strArg Argument to set (e.g. "-foo") + * @param fValue Value (e.g. false) + * @return true if argument gets set, false if it already had a value + */ +bool SoftSetBoolArg(const std::string& strArg, bool fValue); + +/** + * MWC RNG of George Marsaglia + * This is intended to be fast. It has a period of 2^59.3, though the + * least significant 16 bits only have a period of about 2^30.1. + * + * @return random value + */ +extern uint32_t insecure_rand_Rz; +extern uint32_t insecure_rand_Rw; +static inline uint32_t insecure_rand(void) +{ + insecure_rand_Rz=36969*(insecure_rand_Rz&65535)+(insecure_rand_Rz>>16); + insecure_rand_Rw=18000*(insecure_rand_Rw&65535)+(insecure_rand_Rw>>16); + return (insecure_rand_Rw<<16)+insecure_rand_Rz; +} + +/** + * Seed insecure_rand using the random pool. + * @param Deterministic Use a determinstic seed + */ +void seed_insecure_rand(bool fDeterministic=false); + +template +inline uint256 Hash(const T1 pbegin, const T1 pend) +{ + static unsigned char pblank[1]; + uint256 hash1; + SHA256((pbegin == pend ? pblank : (unsigned char*)&pbegin[0]), (pend - pbegin) * sizeof(pbegin[0]), (unsigned char*)&hash1); + uint256 hash2; + SHA256((unsigned char*)&hash1, sizeof(hash1), (unsigned char*)&hash2); + return hash2; +} + +class CHashWriter +{ +private: + SHA256_CTX ctx; + +public: + int nType; + int nVersion; + + void Init() { + SHA256_Init(&ctx); + } + + CHashWriter(int nTypeIn, int nVersionIn) : nType(nTypeIn), nVersion(nVersionIn) { + Init(); + } + + CHashWriter& write(const char *pch, size_t size) { + SHA256_Update(&ctx, pch, size); + return (*this); + } + + // invalidates the object + uint256 GetHash() { + uint256 hash1; + SHA256_Final((unsigned char*)&hash1, &ctx); + uint256 hash2; + SHA256((unsigned char*)&hash1, sizeof(hash1), (unsigned char*)&hash2); + return hash2; + } + + template + CHashWriter& operator<<(const T& obj) { + // Serialize to this stream + ::Serialize(*this, obj, nType, nVersion); + return (*this); + } +}; + + +template +inline uint256 Hash(const T1 p1begin, const T1 p1end, + const T2 p2begin, const T2 p2end) +{ + static unsigned char pblank[1]; + uint256 hash1; + SHA256_CTX ctx; + SHA256_Init(&ctx); + SHA256_Update(&ctx, (p1begin == p1end ? pblank : (unsigned char*)&p1begin[0]), (p1end - p1begin) * sizeof(p1begin[0])); + SHA256_Update(&ctx, (p2begin == p2end ? pblank : (unsigned char*)&p2begin[0]), (p2end - p2begin) * sizeof(p2begin[0])); + SHA256_Final((unsigned char*)&hash1, &ctx); + uint256 hash2; + SHA256((unsigned char*)&hash1, sizeof(hash1), (unsigned char*)&hash2); + return hash2; +} + +template +inline uint256 Hash(const T1 p1begin, const T1 p1end, + const T2 p2begin, const T2 p2end, + const T3 p3begin, const T3 p3end) +{ + static unsigned char pblank[1]; + uint256 hash1; + SHA256_CTX ctx; + SHA256_Init(&ctx); + SHA256_Update(&ctx, (p1begin == p1end ? pblank : (unsigned char*)&p1begin[0]), (p1end - p1begin) * sizeof(p1begin[0])); + SHA256_Update(&ctx, (p2begin == p2end ? pblank : (unsigned char*)&p2begin[0]), (p2end - p2begin) * sizeof(p2begin[0])); + SHA256_Update(&ctx, (p3begin == p3end ? pblank : (unsigned char*)&p3begin[0]), (p3end - p3begin) * sizeof(p3begin[0])); + SHA256_Final((unsigned char*)&hash1, &ctx); + uint256 hash2; + SHA256((unsigned char*)&hash1, sizeof(hash1), (unsigned char*)&hash2); + return hash2; +} + +template +uint256 SerializeHash(const T& obj, int nType=SER_GETHASH, int nVersion=PROTOCOL_VERSION) +{ + CHashWriter ss(nType, nVersion); + ss << obj; + return ss.GetHash(); +} + +inline uint160 Hash160(const std::vector& vch) +{ + uint256 hash1; + SHA256(&vch[0], vch.size(), (unsigned char*)&hash1); + uint160 hash2; + RIPEMD160((unsigned char*)&hash1, sizeof(hash1), (unsigned char*)&hash2); + return hash2; +} + +/** + * Timing-attack-resistant comparison. + * Takes time proportional to length + * of first argument. + */ +template +bool TimingResistantEqual(const T& a, const T& b) +{ + if (b.size() == 0) return a.size() == 0; + size_t accumulator = a.size() ^ b.size(); + for (size_t i = 0; i < a.size(); i++) + accumulator |= a[i] ^ b[i%b.size()]; + return accumulator == 0; +} + +/** Median filter over a stream of values. + * Returns the median of the last N numbers + */ +template class CMedianFilter +{ +private: + std::vector vValues; + std::vector vSorted; + unsigned int nSize; +public: + CMedianFilter(unsigned int size, T initial_value): + nSize(size) + { + vValues.reserve(size); + vValues.push_back(initial_value); + vSorted = vValues; + } + + void input(T value) + { + if(vValues.size() == nSize) + { + vValues.erase(vValues.begin()); + } + vValues.push_back(value); + + vSorted.resize(vValues.size()); + std::copy(vValues.begin(), vValues.end(), vSorted.begin()); + std::sort(vSorted.begin(), vSorted.end()); + } + + T median() const + { + int size = vSorted.size(); + assert(size>0); + if(size & 1) // Odd number of elements + { + return vSorted[size/2]; + } + else // Even number of elements + { + return (vSorted[size/2-1] + vSorted[size/2]) / 2; + } + } + + int size() const + { + return vValues.size(); + } + + std::vector sorted () const + { + return vSorted; + } +}; + +bool NewThread(void(*pfn)(void*), void* parg); + +#ifdef WIN32 +inline void SetThreadPriority(int nPriority) +{ + SetThreadPriority(GetCurrentThread(), nPriority); +} +#else + +#define THREAD_PRIORITY_LOWEST PRIO_MAX +#define THREAD_PRIORITY_BELOW_NORMAL 2 +#define THREAD_PRIORITY_NORMAL 0 +#define THREAD_PRIORITY_ABOVE_NORMAL 0 + +inline void SetThreadPriority(int nPriority) +{ + // It's unclear if it's even possible to change thread priorities on Linux, + // but we really and truly need it for the generation threads. +#ifdef PRIO_THREAD + setpriority(PRIO_THREAD, 0, nPriority); +#else + setpriority(PRIO_PROCESS, 0, nPriority); +#endif +} + +inline void ExitThread(size_t nExitCode) +{ + pthread_exit((void*)nExitCode); +} +#endif + +void RenameThread(const char* name); + +inline uint32_t ByteReverse(uint32_t value) +{ + value = ((value & 0xFF00FF00) >> 8) | ((value & 0x00FF00FF) << 8); + return (value<<16) | (value>>16); +} + +#endif + diff --git a/src/version.cpp b/src/version.cpp new file mode 100644 index 0000000..de40c83 --- /dev/null +++ b/src/version.cpp @@ -0,0 +1,66 @@ +// Copyright (c) 2012 The Bitcoin developers +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. +#include + +#include "version.h" + +// Name of client reported in the 'version' message. Report the same name +// for both bitcoind and bitcoin-qt, to make it harder for attackers to +// target servers or GUI users specifically. +const std::string CLIENT_NAME("ArepaCore"); + +// Client version number +#define CLIENT_VERSION_SUFFIX "" + + +// The following part of the code determines the CLIENT_BUILD variable. +// Several mechanisms are used for this: +// * first, if HAVE_BUILD_INFO is defined, include build.h, a file that is +// generated by the build environment, possibly containing the output +// of git-describe in a macro called BUILD_DESC +// * secondly, if this is an exported version of the code, GIT_ARCHIVE will +// be defined (automatically using the export-subst git attribute), and +// GIT_COMMIT will contain the commit id. +// * then, three options exist for determining CLIENT_BUILD: +// * if BUILD_DESC is defined, use that literally (output of git-describe) +// * if not, but GIT_COMMIT is defined, use v[maj].[min].[rev].[build]-g[commit] +// * otherwise, use v[maj].[min].[rev].[build]-unk +// finally CLIENT_VERSION_SUFFIX is added + +// First, include build.h if requested +#ifdef HAVE_BUILD_INFO +# include "build.h" +#endif + +// git will put "#define GIT_ARCHIVE 1" on the next line inside archives. +#define GIT_ARCHIVE 1 +#ifdef GIT_ARCHIVE +# define GIT_COMMIT_ID "" +# define GIT_COMMIT_DATE "" +#endif + +#define BUILD_DESC_FROM_COMMIT(maj,min,rev,build,commit) \ + "v" DO_STRINGIZE(maj) "." DO_STRINGIZE(min) "." DO_STRINGIZE(rev) "." DO_STRINGIZE(build) + +#define BUILD_DESC_FROM_UNKNOWN(maj,min,rev,build) \ + "v" DO_STRINGIZE(maj) "." DO_STRINGIZE(min) "." DO_STRINGIZE(rev) "." DO_STRINGIZE(build) "-unk" + +#ifndef BUILD_DESC +# ifdef GIT_COMMIT_ID +# define BUILD_DESC BUILD_DESC_FROM_COMMIT(CLIENT_VERSION_MAJOR, CLIENT_VERSION_MINOR, CLIENT_VERSION_REVISION, CLIENT_VERSION_BUILD, GIT_COMMIT_ID) +# else +# define BUILD_DESC BUILD_DESC_FROM_UNKNOWN(CLIENT_VERSION_MAJOR, CLIENT_VERSION_MINOR, CLIENT_VERSION_REVISION, CLIENT_VERSION_BUILD) +# endif +#endif + +#ifndef BUILD_DATE +# ifdef GIT_COMMIT_DATE +# define BUILD_DATE GIT_COMMIT_DATE +# else +# define BUILD_DATE __DATE__ ", " __TIME__ +# endif +#endif + +const std::string CLIENT_BUILD(BUILD_DESC CLIENT_VERSION_SUFFIX); +const std::string CLIENT_DATE(BUILD_DATE); diff --git a/src/version.h b/src/version.h new file mode 100644 index 0000000..605d74f --- /dev/null +++ b/src/version.h @@ -0,0 +1,55 @@ +// Copyright (c) 2012 The Bitcoin developers +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. +#ifndef BITCOIN_VERSION_H +#define BITCOIN_VERSION_H + +#include "clientversion.h" +#include + +// +// client versioning +// + +static const int CLIENT_VERSION = + 1000000 * CLIENT_VERSION_MAJOR + + 10000 * CLIENT_VERSION_MINOR + + 100 * CLIENT_VERSION_REVISION + + 1 * CLIENT_VERSION_BUILD; + +extern const std::string CLIENT_NAME; +extern const std::string CLIENT_BUILD; +extern const std::string CLIENT_DATE; + +// +// database format versioning +// +static const int DATABASE_VERSION = 70509; + +// +// network protocol versioning +// + +static const int PROTOCOL_VERSION = 60016; + +// intial proto version, to be increased after version/verack negotiation +static const int INIT_PROTO_VERSION = 209; + +// disconnect from peers older than this proto version +static const int MIN_PEER_PROTO_VERSION = 60014; + +// nTime field added to CAddress, starting with this version; +// if possible, avoid requesting addresses nodes older than this +static const int CADDR_TIME_VERSION = 31402; + +// only request blocks from nodes outside this range of versions +static const int NOBLKS_VERSION_START = 60002; +static const int NOBLKS_VERSION_END = 60006; + +// BIP 0031, pong message, is enabled for all versions AFTER this one +static const int BIP0031_VERSION = 60000; + +// "mempool" command, enhanced "getdata" behavior starts with this version: +static const int MEMPOOL_GD_VERSION = 60002; + +#endif diff --git a/src/wallet.cpp b/src/wallet.cpp new file mode 100644 index 0000000..10ea799 --- /dev/null +++ b/src/wallet.cpp @@ -0,0 +1,2466 @@ +// Copyright (c) 2009-2010 Satoshi Nakamoto +// Copyright (c) 2009-2012 The Bitcoin developers +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include "txdb.h" +#include "wallet.h" +#include "walletdb.h" +#include "crypter.h" +#include "ui_interface.h" +#include "base58.h" +#include "kernel.h" +#include "coincontrol.h" +#include + +using namespace std; + +unsigned int nStakeSplitAge = 1 * 24 * 60 * 60; +int64_t nStakeCombineThreshold = 1000 * COIN; + +////////////////////////////////////////////////////////////////////////////// +// +// mapWallet +// + +struct CompareValueOnly +{ + bool operator()(const pair >& t1, + const pair >& t2) const + { + return t1.first < t2.first; + } +}; + +CPubKey CWallet::GenerateNewKey() +{ + AssertLockHeld(cs_wallet); // mapKeyMetadata + bool fCompressed = CanSupportFeature(FEATURE_COMPRPUBKEY); // default to compressed public keys if we want 0.6.0 wallets + + RandAddSeedPerfmon(); + CKey key; + key.MakeNewKey(fCompressed); + + // Compressed public keys were introduced in version 0.6.0 + if (fCompressed) + SetMinVersion(FEATURE_COMPRPUBKEY); + + CPubKey pubkey = key.GetPubKey(); + + // Create new metadata + int64_t nCreationTime = GetTime(); + mapKeyMetadata[pubkey.GetID()] = CKeyMetadata(nCreationTime); + if (!nTimeFirstKey || nCreationTime < nTimeFirstKey) + nTimeFirstKey = nCreationTime; + + if (!AddKey(key)) + throw std::runtime_error("CWallet::GenerateNewKey() : AddKey failed"); + return key.GetPubKey(); +} + +bool CWallet::AddKey(const CKey& key) +{ + AssertLockHeld(cs_wallet); // mapKeyMetadata + + CPubKey pubkey = key.GetPubKey(); + + if (!CCryptoKeyStore::AddKey(key)) + return false; + if (!fFileBacked) + return true; + if (!IsCrypted()) + return CWalletDB(strWalletFile).WriteKey(pubkey, key.GetPrivKey(), mapKeyMetadata[pubkey.GetID()]); + return true; +} + +bool CWallet::AddCryptedKey(const CPubKey &vchPubKey, const vector &vchCryptedSecret) +{ + if (!CCryptoKeyStore::AddCryptedKey(vchPubKey, vchCryptedSecret)) + return false; + if (!fFileBacked) + return true; + { + LOCK(cs_wallet); + if (pwalletdbEncryption) + return pwalletdbEncryption->WriteCryptedKey(vchPubKey, vchCryptedSecret, mapKeyMetadata[vchPubKey.GetID()]); + else + return CWalletDB(strWalletFile).WriteCryptedKey(vchPubKey, vchCryptedSecret, mapKeyMetadata[vchPubKey.GetID()]); + } + return false; +} + +bool CWallet::LoadKeyMetadata(const CPubKey &pubkey, const CKeyMetadata &meta) +{ + AssertLockHeld(cs_wallet); // mapKeyMetadata + if (meta.nCreateTime && (!nTimeFirstKey || meta.nCreateTime < nTimeFirstKey)) + nTimeFirstKey = meta.nCreateTime; + + mapKeyMetadata[pubkey.GetID()] = meta; + return true; +} + +bool CWallet::LoadCryptedKey(const CPubKey &vchPubKey, const std::vector &vchCryptedSecret) +{ + return CCryptoKeyStore::AddCryptedKey(vchPubKey, vchCryptedSecret); +} + +bool CWallet::AddCScript(const CScript& redeemScript) +{ + if (!CCryptoKeyStore::AddCScript(redeemScript)) + return false; + if (!fFileBacked) + return true; + return CWalletDB(strWalletFile).WriteCScript(Hash160(redeemScript), redeemScript); +} + +// optional setting to unlock wallet for staking only +// serves to disable the trivial sendmoney when OS account compromised +// provides no real security +bool fWalletUnlockStakingOnly = false; + +bool CWallet::LoadCScript(const CScript& redeemScript) +{ + /* A sanity check was added in pull #3843 to avoid adding redeemScripts + * that never can be redeemed. However, old wallets may still contain + * these. Do not add them to the wallet and warn. */ + if (redeemScript.size() > MAX_SCRIPT_ELEMENT_SIZE) + { + std::string strAddr = CBitcoinAddress(redeemScript.GetID()).ToString(); + printf("%s: Warning: This wallet contains a redeemScript of size %" PRIszu" which exceeds maximum size %i thus can never be redeemed. Do not use address %s.\n", + __func__, redeemScript.size(), MAX_SCRIPT_ELEMENT_SIZE, strAddr.c_str()); + return true; + } + + return CCryptoKeyStore::AddCScript(redeemScript); +} + +bool CWallet::Unlock(const SecureString& strWalletPassphrase) +{ + if (!IsLocked()) + return false; + + CCrypter crypter; + CKeyingMaterial vMasterKey; + + { + LOCK(cs_wallet); + BOOST_FOREACH(const MasterKeyMap::value_type& pMasterKey, mapMasterKeys) + { + if(!crypter.SetKeyFromPassphrase(strWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod)) + return false; + if (!crypter.Decrypt(pMasterKey.second.vchCryptedKey, vMasterKey)) + return false; + if (CCryptoKeyStore::Unlock(vMasterKey)) + return true; + } + } + return false; +} + +bool CWallet::ChangeWalletPassphrase(const SecureString& strOldWalletPassphrase, const SecureString& strNewWalletPassphrase) +{ + bool fWasLocked = IsLocked(); + + { + LOCK(cs_wallet); + Lock(); + + CCrypter crypter; + CKeyingMaterial vMasterKey; + BOOST_FOREACH(MasterKeyMap::value_type& pMasterKey, mapMasterKeys) + { + if(!crypter.SetKeyFromPassphrase(strOldWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod)) + return false; + if (!crypter.Decrypt(pMasterKey.second.vchCryptedKey, vMasterKey)) + return false; + if (CCryptoKeyStore::Unlock(vMasterKey)) + { + int64_t nStartTime = GetTimeMillis(); + crypter.SetKeyFromPassphrase(strNewWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod); + pMasterKey.second.nDeriveIterations = pMasterKey.second.nDeriveIterations * (100 / ((double)(GetTimeMillis() - nStartTime))); + + nStartTime = GetTimeMillis(); + crypter.SetKeyFromPassphrase(strNewWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod); + pMasterKey.second.nDeriveIterations = (pMasterKey.second.nDeriveIterations + pMasterKey.second.nDeriveIterations * 100 / ((double)(GetTimeMillis() - nStartTime))) / 2; + + if (pMasterKey.second.nDeriveIterations < 25000) + pMasterKey.second.nDeriveIterations = 25000; + + printf("Wallet passphrase changed to an nDeriveIterations of %i\n", pMasterKey.second.nDeriveIterations); + + if (!crypter.SetKeyFromPassphrase(strNewWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod)) + return false; + if (!crypter.Encrypt(vMasterKey, pMasterKey.second.vchCryptedKey)) + return false; + CWalletDB(strWalletFile).WriteMasterKey(pMasterKey.first, pMasterKey.second); + if (fWasLocked) + Lock(); + return true; + } + } + } + + return false; +} + +void CWallet::SetBestChain(const CBlockLocator& loc) +{ + CWalletDB walletdb(strWalletFile); + walletdb.WriteBestBlock(loc); +} + +bool CWallet::SetMinVersion(enum WalletFeature nVersion, CWalletDB* pwalletdbIn, bool fExplicit) +{ + LOCK(cs_wallet); // nWalletVersion + if (nWalletVersion >= nVersion) + return true; + + // when doing an explicit upgrade, if we pass the max version permitted, upgrade all the way + if (fExplicit && nVersion > nWalletMaxVersion) + nVersion = FEATURE_LATEST; + + nWalletVersion = nVersion; + + if (nVersion > nWalletMaxVersion) + nWalletMaxVersion = nVersion; + + if (fFileBacked) + { + CWalletDB* pwalletdb = pwalletdbIn ? pwalletdbIn : new CWalletDB(strWalletFile); + if (nWalletVersion > 40000) + pwalletdb->WriteMinVersion(nWalletVersion); + if (!pwalletdbIn) + delete pwalletdb; + } + + return true; +} + +bool CWallet::SetMaxVersion(int nVersion) +{ + LOCK(cs_wallet); // nWalletVersion, nWalletMaxVersion + // cannot downgrade below current version + if (nWalletVersion > nVersion) + return false; + + nWalletMaxVersion = nVersion; + + return true; +} + +bool CWallet::EncryptWallet(const SecureString& strWalletPassphrase) +{ + if (IsCrypted()) + return false; + + CKeyingMaterial vMasterKey; + RandAddSeedPerfmon(); + + vMasterKey.resize(WALLET_CRYPTO_KEY_SIZE); + RAND_bytes(&vMasterKey[0], WALLET_CRYPTO_KEY_SIZE); + + CMasterKey kMasterKey(nDerivationMethodIndex); + + RandAddSeedPerfmon(); + kMasterKey.vchSalt.resize(WALLET_CRYPTO_SALT_SIZE); + RAND_bytes(&kMasterKey.vchSalt[0], WALLET_CRYPTO_SALT_SIZE); + + CCrypter crypter; + int64_t nStartTime = GetTimeMillis(); + crypter.SetKeyFromPassphrase(strWalletPassphrase, kMasterKey.vchSalt, 25000, kMasterKey.nDerivationMethod); + kMasterKey.nDeriveIterations = 2500000 / ((double)(GetTimeMillis() - nStartTime)); + + nStartTime = GetTimeMillis(); + crypter.SetKeyFromPassphrase(strWalletPassphrase, kMasterKey.vchSalt, kMasterKey.nDeriveIterations, kMasterKey.nDerivationMethod); + kMasterKey.nDeriveIterations = (kMasterKey.nDeriveIterations + kMasterKey.nDeriveIterations * 100 / ((double)(GetTimeMillis() - nStartTime))) / 2; + + if (kMasterKey.nDeriveIterations < 25000) + kMasterKey.nDeriveIterations = 25000; + + printf("Encrypting Wallet with an nDeriveIterations of %i\n", kMasterKey.nDeriveIterations); + + if (!crypter.SetKeyFromPassphrase(strWalletPassphrase, kMasterKey.vchSalt, kMasterKey.nDeriveIterations, kMasterKey.nDerivationMethod)) + return false; + if (!crypter.Encrypt(vMasterKey, kMasterKey.vchCryptedKey)) + return false; + + { + LOCK(cs_wallet); + mapMasterKeys[++nMasterKeyMaxID] = kMasterKey; + if (fFileBacked) + { + pwalletdbEncryption = new CWalletDB(strWalletFile); + if (!pwalletdbEncryption->TxnBegin()) + return false; + pwalletdbEncryption->WriteMasterKey(nMasterKeyMaxID, kMasterKey); + } + + if (!EncryptKeys(vMasterKey)) + { + if (fFileBacked) + pwalletdbEncryption->TxnAbort(); + exit(1); //We now probably have half of our keys encrypted in memory, and half not...die and let the user reload their unencrypted wallet. + } + + // Encryption was introduced in version 0.4.0 + SetMinVersion(FEATURE_WALLETCRYPT, pwalletdbEncryption, true); + + if (fFileBacked) + { + if (!pwalletdbEncryption->TxnCommit()) + exit(1); //We now have keys encrypted in memory, but no on disk...die to avoid confusion and let the user reload their unencrypted wallet. + + delete pwalletdbEncryption; + pwalletdbEncryption = NULL; + } + + Lock(); + Unlock(strWalletPassphrase); + NewKeyPool(); + Lock(); + + // Need to completely rewrite the wallet file; if we don't, bdb might keep + // bits of the unencrypted private key in slack space in the database file. + CDB::Rewrite(strWalletFile); + + } + NotifyStatusChanged(this); + + return true; +} + +int64_t CWallet::IncOrderPosNext(CWalletDB *pwalletdb) +{ + AssertLockHeld(cs_wallet); // nOrderPosNext + int64_t nRet = nOrderPosNext++; + if (pwalletdb) { + pwalletdb->WriteOrderPosNext(nOrderPosNext); + } else { + CWalletDB(strWalletFile).WriteOrderPosNext(nOrderPosNext); + } + return nRet; +} + +CWallet::TxItems CWallet::OrderedTxItems(std::list& acentries, std::string strAccount) +{ + AssertLockHeld(cs_wallet); // mapWallet + CWalletDB walletdb(strWalletFile); + + // First: get all CWalletTx and CAccountingEntry into a sorted-by-order multimap. + TxItems txOrdered; + + // Note: maintaining indices in the database of (account,time) --> txid and (account, time) --> acentry + // would make this much faster for applications that do this a lot. + for (map::iterator it = mapWallet.begin(); it != mapWallet.end(); ++it) + { + CWalletTx* wtx = &((*it).second); + txOrdered.insert(make_pair(wtx->nOrderPos, TxPair(wtx, (CAccountingEntry*)0))); + } + acentries.clear(); + walletdb.ListAccountCreditDebit(strAccount, acentries); + BOOST_FOREACH(CAccountingEntry& entry, acentries) + { + txOrdered.insert(make_pair(entry.nOrderPos, TxPair((CWalletTx*)0, &entry))); + } + + return txOrdered; +} + +void CWallet::WalletUpdateSpent(const CTransaction &tx, bool fBlock) +{ + // 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. + { + LOCK(cs_wallet); + BOOST_FOREACH(const CTxIn& txin, tx.vin) + { + map::iterator mi = mapWallet.find(txin.prevout.hash); + if (mi != mapWallet.end()) + { + CWalletTx& wtx = (*mi).second; + if (txin.prevout.n >= wtx.vout.size()) + printf("WalletUpdateSpent: bad wtx %s\n", wtx.GetHash().ToString().c_str()); + else if (!wtx.IsSpent(txin.prevout.n) && IsMine(wtx.vout[txin.prevout.n])) + { + printf("WalletUpdateSpent found spent coin %s BC %s\n", FormatMoney(wtx.GetCredit()).c_str(), wtx.GetHash().ToString().c_str()); + wtx.MarkSpent(txin.prevout.n); + wtx.WriteToDisk(); + NotifyTransactionChanged(this, txin.prevout.hash, CT_UPDATED); + } + } + } + + if (fBlock) + { + uint256 hash = tx.GetHash(); + map::iterator mi = mapWallet.find(hash); + CWalletTx& wtx = (*mi).second; + + BOOST_FOREACH(const CTxOut& txout, tx.vout) + { + if (IsMine(txout)) + { + wtx.MarkUnspent(&txout - &tx.vout[0]); + wtx.WriteToDisk(); + NotifyTransactionChanged(this, hash, CT_UPDATED); + } + } + } + + } +} + +void CWallet::MarkDirty() +{ + { + LOCK(cs_wallet); + BOOST_FOREACH(PAIRTYPE(const uint256, CWalletTx)& item, mapWallet) + item.second.MarkDirty(); + } +} + +bool CWallet::AddToWallet(const CWalletTx& wtxIn) +{ + uint256 hash = wtxIn.GetHash(); + { + LOCK(cs_wallet); + // Inserts only if not already there, returns tx inserted or tx found + pair::iterator, bool> ret = mapWallet.insert(make_pair(hash, wtxIn)); + CWalletTx& wtx = (*ret.first).second; + wtx.BindWallet(this); + bool fInsertedNew = ret.second; + if (fInsertedNew) + { + wtx.nTimeReceived = GetAdjustedTime(); + wtx.nOrderPos = IncOrderPosNext(); + + wtx.nTimeSmart = wtx.nTimeReceived; + if (wtxIn.hashBlock != 0) + { + if (mapBlockIndex.count(wtxIn.hashBlock)) + { + unsigned int latestNow = wtx.nTimeReceived; + unsigned int latestEntry = 0; + { + // Tolerate times up to the last timestamp in the wallet not more than 5 minutes into the future + int64_t latestTolerated = latestNow + 300; + std::list acentries; + TxItems txOrdered = OrderedTxItems(acentries); + for (TxItems::reverse_iterator it = txOrdered.rbegin(); it != txOrdered.rend(); ++it) + { + CWalletTx *const pwtx = (*it).second.first; + if (pwtx == &wtx) + continue; + CAccountingEntry *const pacentry = (*it).second.second; + int64_t nSmartTime; + if (pwtx) + { + nSmartTime = pwtx->nTimeSmart; + if (!nSmartTime) + nSmartTime = pwtx->nTimeReceived; + } + else + nSmartTime = pacentry->nTime; + if (nSmartTime <= latestTolerated) + { + latestEntry = nSmartTime; + if (nSmartTime > latestNow) + latestNow = nSmartTime; + break; + } + } + } + + unsigned int& blocktime = mapBlockIndex[wtxIn.hashBlock]->nTime; + wtx.nTimeSmart = std::max(latestEntry, std::min(blocktime, latestNow)); + } + else + printf("AddToWallet() : found %s in block %s not in index\n", + wtxIn.GetHash().ToString().substr(0,10).c_str(), + wtxIn.hashBlock.ToString().c_str()); + } + } + + bool fUpdated = false; + if (!fInsertedNew) + { + // Merge + if (wtxIn.hashBlock != 0 && wtxIn.hashBlock != wtx.hashBlock) + { + wtx.hashBlock = wtxIn.hashBlock; + fUpdated = true; + } + if (wtxIn.nIndex != -1 && (wtxIn.vMerkleBranch != wtx.vMerkleBranch || wtxIn.nIndex != wtx.nIndex)) + { + wtx.vMerkleBranch = wtxIn.vMerkleBranch; + wtx.nIndex = wtxIn.nIndex; + fUpdated = true; + } + if (wtxIn.fFromMe && wtxIn.fFromMe != wtx.fFromMe) + { + wtx.fFromMe = wtxIn.fFromMe; + fUpdated = true; + } + fUpdated |= wtx.UpdateSpent(wtxIn.vfSpent); + } + + //// debug print + printf("AddToWallet %s %s%s\n", wtxIn.GetHash().ToString().substr(0,10).c_str(), (fInsertedNew ? "new" : ""), (fUpdated ? "update" : "")); + + // Write to disk + if (fInsertedNew || fUpdated) + if (!wtx.WriteToDisk()) + return false; +#ifndef QT_GUI + // If default receiving address gets used, replace it with a new one + if (vchDefaultKey.IsValid()) { + CScript scriptDefaultKey; + scriptDefaultKey.SetDestination(vchDefaultKey.GetID()); + BOOST_FOREACH(const CTxOut& txout, wtx.vout) + { + if (txout.scriptPubKey == scriptDefaultKey) + { + CPubKey newDefaultKey; + if (GetKeyFromPool(newDefaultKey, false)) + { + SetDefaultKey(newDefaultKey); + SetAddressBookName(vchDefaultKey.GetID(), ""); + } + } + } + } +#endif + // since AddToWallet is called directly for self-originating transactions, check for consumption of own coins + WalletUpdateSpent(wtx, (wtxIn.hashBlock != 0)); + + // Notify UI of new or updated transaction + NotifyTransactionChanged(this, hash, fInsertedNew ? CT_NEW : CT_UPDATED); + + // notify an external script when a wallet transaction comes in or is updated + std::string strCmd = GetArg("-walletnotify", ""); + + if ( !strCmd.empty()) + { + boost::replace_all(strCmd, "%s", wtxIn.GetHash().GetHex()); + boost::thread t(runCommand, strCmd); // thread runs free + } + + } + return true; +} + +// Add a transaction to the wallet, or update it. +// pblock is optional, but should be provided if the transaction is known to be in a block. +// If fUpdate is true, existing transactions will be updated. +bool CWallet::AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlock* pblock, bool fUpdate, bool fFindBlock) +{ + uint256 hash = tx.GetHash(); + { + LOCK(cs_wallet); + bool fExisted = mapWallet.count(hash); + if (fExisted && !fUpdate) return false; + if (fExisted || IsMine(tx) || IsFromMe(tx)) + { + CWalletTx wtx(this,tx); + // Get merkle branch if transaction was found in a block + if (pblock) + wtx.SetMerkleBranch(pblock); + return AddToWallet(wtx); + } + else + WalletUpdateSpent(tx); + } + return false; +} + +bool CWallet::EraseFromWallet(uint256 hash) +{ + if (!fFileBacked) + return false; + { + LOCK(cs_wallet); + if (mapWallet.erase(hash)) + CWalletDB(strWalletFile).EraseTx(hash); + } + return true; +} + + +bool CWallet::IsMine(const CTxIn &txin) const +{ + { + LOCK(cs_wallet); + map::const_iterator mi = mapWallet.find(txin.prevout.hash); + if (mi != mapWallet.end()) + { + const CWalletTx& prev = (*mi).second; + if (txin.prevout.n < prev.vout.size()) + if (IsMine(prev.vout[txin.prevout.n])) + return true; + } + } + return false; +} + +int64_t CWallet::GetDebit(const CTxIn &txin) const +{ + { + LOCK(cs_wallet); + map::const_iterator mi = mapWallet.find(txin.prevout.hash); + if (mi != mapWallet.end()) + { + const CWalletTx& prev = (*mi).second; + if (txin.prevout.n < prev.vout.size()) + if (IsMine(prev.vout[txin.prevout.n])) + return prev.vout[txin.prevout.n].nValue; + } + } + return 0; +} + +bool CWallet::IsChange(const CTxOut& txout) const +{ + CTxDestination address; + + // TODO: fix handling of 'change' outputs. The assumption is that any + // payment to a TX_PUBKEYHASH that is mine but isn't in the address book + // is change. That assumption is likely to break when we implement multisignature + // wallets that return change back into a multi-signature-protected address; + // a better way of identifying which outputs are 'the send' and which are + // 'the change' will need to be implemented (maybe extend CWalletTx to remember + // which output, if any, was change). + if (ExtractDestination(txout.scriptPubKey, address) && ::IsMine(*this, address)) + { + LOCK(cs_wallet); + if (!mapAddressBook.count(address)) + return true; + } + return false; +} + +int64_t CWalletTx::GetTxTime() const +{ + int64_t n = nTimeSmart; + return n ? n : nTimeReceived; +} + +int CWalletTx::GetRequestCount() const +{ + // Returns -1 if it wasn't being tracked + int nRequests = -1; + { + LOCK(pwallet->cs_wallet); + if (IsCoinBase() || IsCoinStake()) + { + // Generated block + if (hashBlock != 0) + { + map::const_iterator mi = pwallet->mapRequestCount.find(hashBlock); + if (mi != pwallet->mapRequestCount.end()) + nRequests = (*mi).second; + } + } + else + { + // Did anyone request this transaction? + map::const_iterator mi = pwallet->mapRequestCount.find(GetHash()); + if (mi != pwallet->mapRequestCount.end()) + { + nRequests = (*mi).second; + + // How about the block it's in? + if (nRequests == 0 && hashBlock != 0) + { + map::const_iterator mi = pwallet->mapRequestCount.find(hashBlock); + if (mi != pwallet->mapRequestCount.end()) + nRequests = (*mi).second; + else + nRequests = 1; // If it's in someone else's block it must have got out + } + } + } + } + return nRequests; +} + +void CWalletTx::GetAmounts(list >& listReceived, + list >& listSent, int64_t& nFee, string& strSentAccount) const +{ + nFee = 0; + listReceived.clear(); + listSent.clear(); + strSentAccount = strFromAccount; + + // Compute fee: + int64_t nDebit = GetDebit(); + if (nDebit > 0) // debit>0 means we signed/sent this transaction + { + int64_t nValueOut = GetValueOut(); + nFee = nDebit - nValueOut; + } + + // Sent/received. + BOOST_FOREACH(const CTxOut& txout, vout) + { + // Skip special stake out + if (txout.scriptPubKey.empty()) + continue; + + bool fIsMine; + // Only need to handle txouts if AT LEAST one of these is true: + // 1) they debit from us (sent) + // 2) the output is to us (received) + if (nDebit > 0) + { + // Don't report 'change' txouts + if (pwallet->IsChange(txout)) + continue; + fIsMine = pwallet->IsMine(txout); + } + else if (!(fIsMine = pwallet->IsMine(txout))) + continue; + + // In either case, we need to get the destination address + CTxDestination address; + if (!ExtractDestination(txout.scriptPubKey, address)) + { + printf("CWalletTx::GetAmounts: Unknown transaction type found, txid %s\n", + this->GetHash().ToString().c_str()); + address = CNoDestination(); + } + + // If we are debited by the transaction, add the output as a "sent" entry + if (nDebit > 0) + listSent.push_back(make_pair(address, txout.nValue)); + + // If we are receiving the output, add it as a "received" entry + if (fIsMine) + listReceived.push_back(make_pair(address, txout.nValue)); + } + +} + +void CWalletTx::GetAccountAmounts(const string& strAccount, int64_t& nReceived, + int64_t& nSent, int64_t& nFee) const +{ + nReceived = nSent = nFee = 0; + + int64_t allFee; + string strSentAccount; + list > listReceived; + list > listSent; + GetAmounts(listReceived, listSent, allFee, strSentAccount); + + if (strAccount == strSentAccount) + { + BOOST_FOREACH(const PAIRTYPE(CTxDestination,int64_t)& s, listSent) + nSent += s.second; + nFee = allFee; + } + { + LOCK(pwallet->cs_wallet); + BOOST_FOREACH(const PAIRTYPE(CTxDestination,int64_t)& r, listReceived) + { + if (pwallet->mapAddressBook.count(r.first)) + { + map::const_iterator mi = pwallet->mapAddressBook.find(r.first); + if (mi != pwallet->mapAddressBook.end() && (*mi).second == strAccount) + nReceived += r.second; + } + else if (strAccount.empty()) + { + nReceived += r.second; + } + } + } +} + +void CWalletTx::AddSupportingTransactions(CTxDB& txdb) +{ + vtxPrev.clear(); + + const int COPY_DEPTH = 3; + if (SetMerkleBranch() < COPY_DEPTH) + { + vector vWorkQueue; + BOOST_FOREACH(const CTxIn& txin, vin) + vWorkQueue.push_back(txin.prevout.hash); + + // This critsect is OK because txdb is already open + { + LOCK(pwallet->cs_wallet); + map mapWalletPrev; + set setAlreadyDone; + for (unsigned int i = 0; i < vWorkQueue.size(); i++) + { + uint256 hash = vWorkQueue[i]; + if (setAlreadyDone.count(hash)) + continue; + setAlreadyDone.insert(hash); + + CMerkleTx tx; + map::const_iterator mi = pwallet->mapWallet.find(hash); + if (mi != pwallet->mapWallet.end()) + { + tx = (*mi).second; + BOOST_FOREACH(const CMerkleTx& txWalletPrev, (*mi).second.vtxPrev) + mapWalletPrev[txWalletPrev.GetHash()] = &txWalletPrev; + } + else if (mapWalletPrev.count(hash)) + { + tx = *mapWalletPrev[hash]; + } + else if (txdb.ReadDiskTx(hash, tx)) + { + ; + } + else + { + printf("ERROR: AddSupportingTransactions() : unsupported transaction\n"); + continue; + } + + int nDepth = tx.SetMerkleBranch(); + vtxPrev.push_back(tx); + + if (nDepth < COPY_DEPTH) + { + BOOST_FOREACH(const CTxIn& txin, tx.vin) + vWorkQueue.push_back(txin.prevout.hash); + } + } + } + } + + reverse(vtxPrev.begin(), vtxPrev.end()); +} + +bool CWalletTx::WriteToDisk() +{ + return CWalletDB(pwallet->strWalletFile).WriteTx(GetHash(), *this); +} + +// Scan the block chain (starting in pindexStart) for transactions +// from or to us. If fUpdate is true, found transactions that already +// exist in the wallet will be updated. +int CWallet::ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate) +{ + int ret = 0; + + CBlockIndex* pindex = pindexStart; + { + LOCK2(cs_main, cs_wallet); + while (pindex) + { + // no need to read and scan block, if block was created before + // our wallet birthday (as adjusted for block time variability) + if (nTimeFirstKey && (pindex->nTime < (nTimeFirstKey - 7200))) { + pindex = pindex->pnext; + continue; + } + + CBlock block; + block.ReadFromDisk(pindex, true); + BOOST_FOREACH(CTransaction& tx, block.vtx) + { + if (AddToWalletIfInvolvingMe(tx, &block, fUpdate)) + ret++; + } + pindex = pindex->pnext; + } + } + return ret; +} + +void CWallet::ReacceptWalletTransactions() +{ + CTxDB txdb("r"); + bool fRepeat = true; + while (fRepeat) + { + LOCK2(cs_main, cs_wallet); + fRepeat = false; + vector vMissingTx; + BOOST_FOREACH(PAIRTYPE(const uint256, CWalletTx)& item, mapWallet) + { + CWalletTx& wtx = item.second; + if ((wtx.IsCoinBase() && wtx.IsSpent(0)) || (wtx.IsCoinStake() && wtx.IsSpent(1))) + continue; + + CTxIndex txindex; + bool fUpdated = false; + if (txdb.ReadTxIndex(wtx.GetHash(), txindex)) + { + // Update fSpent if a tx got spent somewhere else by a copy of wallet.dat + if (txindex.vSpent.size() != wtx.vout.size()) + { + printf("ERROR: ReacceptWalletTransactions() : txindex.vSpent.size() %" PRIszu" != wtx.vout.size() %" PRIszu"\n", txindex.vSpent.size(), wtx.vout.size()); + continue; + } + for (unsigned int i = 0; i < txindex.vSpent.size(); i++) + { + if (wtx.IsSpent(i)) + continue; + if (!txindex.vSpent[i].IsNull() && IsMine(wtx.vout[i])) + { + wtx.MarkSpent(i); + fUpdated = true; + vMissingTx.push_back(txindex.vSpent[i]); + } + } + if (fUpdated) + { + printf("ReacceptWalletTransactions found spent coin %s BC %s\n", FormatMoney(wtx.GetCredit()).c_str(), wtx.GetHash().ToString().c_str()); + wtx.MarkDirty(); + wtx.WriteToDisk(); + } + } + else + { + // Re-accept any txes of ours that aren't already in a block + if (!(wtx.IsCoinBase() || wtx.IsCoinStake())) + wtx.AcceptWalletTransaction(txdb); + } + } + if (!vMissingTx.empty()) + { + // TODO: optimize this to scan just part of the block chain? + if (ScanForWalletTransactions(pindexGenesisBlock)) + fRepeat = true; // Found missing transactions: re-do re-accept. + } + } +} + +void CWalletTx::RelayWalletTransaction(CTxDB& txdb) +{ + BOOST_FOREACH(const CMerkleTx& tx, vtxPrev) + { + if (!(tx.IsCoinBase() || tx.IsCoinStake())) + { + uint256 hash = tx.GetHash(); + if (!txdb.ContainsTx(hash)) + RelayTransaction((CTransaction)tx, hash); + } + } + if (!(IsCoinBase() || IsCoinStake())) + { + uint256 hash = GetHash(); + if (!txdb.ContainsTx(hash)) + { + printf("Relaying wtx %s\n", hash.ToString().substr(0,10).c_str()); + RelayTransaction((CTransaction)*this, hash); + } + } +} + +void CWalletTx::RelayWalletTransaction() +{ + CTxDB txdb("r"); + RelayWalletTransaction(txdb); +} + +void CWallet::ResendWalletTransactions(bool fForce) +{ + if (!fForce) + { + // Do this infrequently and randomly to avoid giving away + // that these are our transactions. + static int64_t nNextTime; + if (GetTime() < nNextTime) + return; + bool fFirst = (nNextTime == 0); + nNextTime = GetTime() + GetRand(30 * 60); + if (fFirst) + return; + + // Only do it if there's been a new block since last time + static int64_t nLastTime; + if (nTimeBestReceived < nLastTime) + return; + nLastTime = GetTime(); + } + + // Rebroadcast any of our txes that aren't in a block yet + printf("ResendWalletTransactions()\n"); + CTxDB txdb("r"); + { + LOCK(cs_wallet); + // Sort them in chronological order + multimap mapSorted; + BOOST_FOREACH(PAIRTYPE(const uint256, CWalletTx)& item, mapWallet) + { + CWalletTx& wtx = item.second; + // Don't rebroadcast until it's had plenty of time that + // it should have gotten in already by now. + if (fForce || nTimeBestReceived - (int64_t)wtx.nTimeReceived > 5 * 60) + mapSorted.insert(make_pair(wtx.nTimeReceived, &wtx)); + } + BOOST_FOREACH(PAIRTYPE(const unsigned int, CWalletTx*)& item, mapSorted) + { + CWalletTx& wtx = *item.second; + if (wtx.CheckTransaction()) + wtx.RelayWalletTransaction(txdb); + else + printf("ResendWalletTransactions() : CheckTransaction failed for transaction %s\n", wtx.GetHash().ToString().c_str()); + } + } +} + + + + + + +////////////////////////////////////////////////////////////////////////////// +// +// Actions +// + + +int64_t CWallet::GetBalance() const +{ + int64_t nTotal = 0; + { + LOCK2(cs_main, cs_wallet); + for (map::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it) + { + const CWalletTx* pcoin = &(*it).second; + if (pcoin->IsTrusted()) + nTotal += pcoin->GetAvailableCredit(); + } + } + + return nTotal; +} + +int64_t CWallet::GetUnconfirmedBalance() const +{ + int64_t nTotal = 0; + { + LOCK2(cs_main, cs_wallet); + for (map::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it) + { + const CWalletTx* pcoin = &(*it).second; + if (!IsFinalTx(*pcoin) || (!pcoin->IsTrusted() && pcoin->GetDepthInMainChain() == 0)) + nTotal += pcoin->GetAvailableCredit(); + } + } + return nTotal; +} + +int64_t CWallet::GetImmatureBalance() const +{ + int64_t nTotal = 0; + { + LOCK2(cs_main, cs_wallet); + for (map::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it) + { + const CWalletTx& pcoin = (*it).second; + if (pcoin.IsCoinBase() && pcoin.GetBlocksToMaturity() > 0 && pcoin.IsInMainChain()) + nTotal += GetCredit(pcoin); + } + } + return nTotal; +} + +// populate vCoins with vector of spendable COutputs +void CWallet::AvailableCoins(vector& vCoins, bool fOnlyConfirmed, const CCoinControl *coinControl) const +{ + vCoins.clear(); + + { + LOCK2(cs_main, cs_wallet); + for (map::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it) + { + const CWalletTx* pcoin = &(*it).second; + + if (!IsFinalTx(*pcoin)) + continue; + + if (fOnlyConfirmed && !pcoin->IsTrusted()) + continue; + + if (pcoin->IsCoinBase() && pcoin->GetBlocksToMaturity() > 0) + continue; + + if(pcoin->IsCoinStake() && pcoin->GetBlocksToMaturity() > 0) + continue; + + int nDepth = pcoin->GetDepthInMainChain(); + if (nDepth < 0) + continue; + + for (unsigned int i = 0; i < pcoin->vout.size(); i++) + if (!(pcoin->IsSpent(i)) && IsMine(pcoin->vout[i]) && pcoin->vout[i].nValue >= nMinimumInputValue && + (!coinControl || !coinControl->HasSelected() || coinControl->IsSelected((*it).first, i))) + vCoins.push_back(COutput(pcoin, i, nDepth)); + + } + } +} + +void CWallet::AvailableCoinsForStaking(vector& vCoins, unsigned int nSpendTime) const +{ + vCoins.clear(); + + { + LOCK2(cs_main, cs_wallet); + for (map::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it) + { + const CWalletTx* pcoin = &(*it).second; + + // Filtering by tx timestamp instead of block timestamp may give false positives but never false negatives + if (pcoin->nTime + nStakeMinAge > nSpendTime) + continue; + + if (pcoin->GetBlocksToMaturity() > 0) + continue; + + int nDepth = pcoin->GetDepthInMainChain(); + if (nDepth < 1) + continue; + + for (unsigned int i = 0; i < pcoin->vout.size(); i++) + if (!(pcoin->IsSpent(i)) && IsMine(pcoin->vout[i]) && pcoin->vout[i].nValue >= nMinimumInputValue) + vCoins.push_back(COutput(pcoin, i, nDepth)); + } + } +} + +static void ApproximateBestSubset(vector > >vValue, int64_t nTotalLower, int64_t nTargetValue, + vector& vfBest, int64_t& nBest, int iterations = 1000) +{ + vector vfIncluded; + + vfBest.assign(vValue.size(), true); + nBest = nTotalLower; + + seed_insecure_rand(); + + for (int nRep = 0; nRep < iterations && nBest != nTargetValue; nRep++) + { + vfIncluded.assign(vValue.size(), false); + int64_t nTotal = 0; + bool fReachedTarget = false; + for (int nPass = 0; nPass < 2 && !fReachedTarget; nPass++) + { + for (unsigned int i = 0; i < vValue.size(); i++) + { + //The solver here uses a randomized algorithm, + //the randomness serves no real security purpose but is just + //needed to prevent degenerate behavior and it is important + //that the rng fast. We do not use a constant random sequence, + //because there may be some privacy improvement by making + //the selection random. + if (nPass == 0 ? insecure_rand()&1 : !vfIncluded[i]) + { + nTotal += vValue[i].first; + vfIncluded[i] = true; + if (nTotal >= nTargetValue) + { + fReachedTarget = true; + if (nTotal < nBest) + { + nBest = nTotal; + vfBest = vfIncluded; + } + nTotal -= vValue[i].first; + vfIncluded[i] = false; + } + } + } + } + } +} + +// ppcoin: total coins staked (non-spendable until maturity) +int64_t CWallet::GetStake() const +{ + int64_t nTotal = 0; + LOCK2(cs_main, cs_wallet); + for (map::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it) + { + const CWalletTx* pcoin = &(*it).second; + if (pcoin->IsCoinStake() && pcoin->GetBlocksToMaturity() > 0 && pcoin->GetDepthInMainChain() > 0) + nTotal += CWallet::GetCredit(*pcoin); + } + return nTotal; +} + +int64_t CWallet::GetNewMint() const +{ + int64_t nTotal = 0; + LOCK2(cs_main, cs_wallet); + for (map::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it) + { + const CWalletTx* pcoin = &(*it).second; + if (pcoin->IsCoinBase() && pcoin->GetBlocksToMaturity() > 0 && pcoin->GetDepthInMainChain() > 0) + nTotal += CWallet::GetCredit(*pcoin); + } + return nTotal; +} + +bool CWallet::SelectCoinsMinConf(int64_t nTargetValue, unsigned int nSpendTime, int nConfMine, int nConfTheirs, vector vCoins, set >& setCoinsRet, int64_t& nValueRet) const +{ + setCoinsRet.clear(); + nValueRet = 0; + + // List of values less than target + pair > coinLowestLarger; + coinLowestLarger.first = std::numeric_limits::max(); + coinLowestLarger.second.first = NULL; + vector > > vValue; + int64_t nTotalLower = 0; + + random_shuffle(vCoins.begin(), vCoins.end(), GetRandInt); + + BOOST_FOREACH(COutput output, vCoins) + { + const CWalletTx *pcoin = output.tx; + + if (output.nDepth < (pcoin->IsFromMe() ? nConfMine : nConfTheirs)) + continue; + + int i = output.i; + + // Follow the timestamp rules + if (pcoin->nTime > nSpendTime) + continue; + + int64_t n = pcoin->vout[i].nValue; + + pair > coin = make_pair(n,make_pair(pcoin, i)); + + if (n == nTargetValue) + { + setCoinsRet.insert(coin.second); + nValueRet += coin.first; + return true; + } + else if (n < nTargetValue + CENT) + { + vValue.push_back(coin); + nTotalLower += n; + } + else if (n < coinLowestLarger.first) + { + coinLowestLarger = coin; + } + } + + if (nTotalLower == nTargetValue) + { + for (unsigned int i = 0; i < vValue.size(); ++i) + { + setCoinsRet.insert(vValue[i].second); + nValueRet += vValue[i].first; + } + return true; + } + + if (nTotalLower < nTargetValue) + { + if (coinLowestLarger.second.first == NULL) + return false; + setCoinsRet.insert(coinLowestLarger.second); + nValueRet += coinLowestLarger.first; + return true; + } + + // Solve subset sum by stochastic approximation + sort(vValue.rbegin(), vValue.rend(), CompareValueOnly()); + vector vfBest; + int64_t nBest; + + ApproximateBestSubset(vValue, nTotalLower, nTargetValue, vfBest, nBest, 1000); + if (nBest != nTargetValue && nTotalLower >= nTargetValue + CENT) + ApproximateBestSubset(vValue, nTotalLower, nTargetValue + CENT, vfBest, nBest, 1000); + + // If we have a bigger coin and (either the stochastic approximation didn't find a good solution, + // or the next bigger coin is closer), return the bigger coin + if (coinLowestLarger.second.first && + ((nBest != nTargetValue && nBest < nTargetValue + CENT) || coinLowestLarger.first <= nBest)) + { + setCoinsRet.insert(coinLowestLarger.second); + nValueRet += coinLowestLarger.first; + } + else { + for (unsigned int i = 0; i < vValue.size(); i++) + if (vfBest[i]) + { + setCoinsRet.insert(vValue[i].second); + nValueRet += vValue[i].first; + } + + if (fDebug && GetBoolArg("-printpriority")) + { + //// debug print + printf("SelectCoins() best subset: "); + for (unsigned int i = 0; i < vValue.size(); i++) + if (vfBest[i]) + printf("%s ", FormatMoney(vValue[i].first).c_str()); + printf("total %s\n", FormatMoney(nBest).c_str()); + } + } + + return true; +} + +bool CWallet::SelectCoins(int64_t nTargetValue, unsigned int nSpendTime, set >& setCoinsRet, int64_t& nValueRet, const CCoinControl* coinControl) const +{ + vector vCoins; + AvailableCoins(vCoins, true, coinControl); + + // coin control -> return all selected outputs (we want all selected to go into the transaction for sure) + if (coinControl && coinControl->HasSelected()) + { + BOOST_FOREACH(const COutput& out, vCoins) + { + nValueRet += out.tx->vout[out.i].nValue; + setCoinsRet.insert(make_pair(out.tx, out.i)); + } + return (nValueRet >= nTargetValue); + } + + return (SelectCoinsMinConf(nTargetValue, nSpendTime, 1, 10, vCoins, setCoinsRet, nValueRet) || + SelectCoinsMinConf(nTargetValue, nSpendTime, 1, 1, vCoins, setCoinsRet, nValueRet) || + SelectCoinsMinConf(nTargetValue, nSpendTime, 0, 1, vCoins, setCoinsRet, nValueRet)); +} + +// Select some coins without random shuffle or best subset approximation +bool CWallet::SelectCoinsForStaking(int64_t nTargetValue, unsigned int nSpendTime, set >& setCoinsRet, int64_t& nValueRet) const +{ + vector vCoins; + AvailableCoinsForStaking(vCoins, nSpendTime); + + setCoinsRet.clear(); + nValueRet = 0; + + BOOST_FOREACH(COutput output, vCoins) + { + const CWalletTx *pcoin = output.tx; + int i = output.i; + + // Stop if we've chosen enough inputs + if (nValueRet >= nTargetValue) + break; + + int64_t n = pcoin->vout[i].nValue; + + pair > coin = make_pair(n,make_pair(pcoin, i)); + + if (n >= nTargetValue) + { + // If input value is greater or equal to target then simply insert + // it into the current subset and exit + setCoinsRet.insert(coin.second); + nValueRet += coin.first; + break; + } + else if (n < nTargetValue + CENT) + { + setCoinsRet.insert(coin.second); + nValueRet += coin.first; + } + } + + return true; +} + +bool CWallet::CreateTransaction(const vector >& vecSend, CWalletTx& wtxNew, CReserveKey& reservekey, int64_t& nFeeRet, const CCoinControl* coinControl) +{ + int64_t nValue = 0; + BOOST_FOREACH (const PAIRTYPE(CScript, int64_t)& s, vecSend) + { + if (nValue < 0) + return false; + nValue += s.second; + } + if (vecSend.empty() || nValue < 0) + return false; + + wtxNew.BindWallet(this); + + { + LOCK2(cs_main, cs_wallet); + // txdb must be opened before the mapWallet lock + CTxDB txdb("r"); + { + nFeeRet = nTransactionFee; + while (true) + { + wtxNew.vin.clear(); + wtxNew.vout.clear(); + wtxNew.fFromMe = true; + + int64_t nTotalValue = nValue + nFeeRet; + double dPriority = 0; + // vouts to the payees + BOOST_FOREACH (const PAIRTYPE(CScript, int64_t)& s, vecSend) + wtxNew.vout.push_back(CTxOut(s.second, s.first)); + + // Choose coins to use + set > setCoins; + int64_t nValueIn = 0; + if (!SelectCoins(nTotalValue, wtxNew.nTime, setCoins, nValueIn, coinControl)) + return false; + BOOST_FOREACH(PAIRTYPE(const CWalletTx*, unsigned int) pcoin, setCoins) + { + int64_t nCredit = pcoin.first->vout[pcoin.second].nValue; + dPriority += (double)nCredit * pcoin.first->GetDepthInMainChain(); + } + + int64_t nChange = nValueIn - nValue - nFeeRet; + // if sub-cent change is required, the fee must be raised to at least MIN_TX_FEE + // or until nChange becomes zero + // NOTE: this depends on the exact behaviour of GetMinFee + if (nFeeRet < MIN_TX_FEE && nChange > 0 && nChange < CENT) + { + int64_t nMoveToFee = min(nChange, MIN_TX_FEE - nFeeRet); + nChange -= nMoveToFee; + nFeeRet += nMoveToFee; + } + + if (nChange > 0) + { + // Fill a vout to ourself + // TODO: pass in scriptChange instead of reservekey so + // change transaction isn't always pay-to-bitcoin-address + CScript scriptChange; + + // coin control: send change to custom address + if (coinControl && !boost::get(&coinControl->destChange)) + scriptChange.SetDestination(coinControl->destChange); + + // no coin control: send change to newly generated address + else + { + // 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. + + // Reserve a new key pair from key pool + CPubKey vchPubKey; + assert(reservekey.GetReservedKey(vchPubKey)); // should never fail, as we just unlocked + + scriptChange.SetDestination(vchPubKey.GetID()); + } + + // Insert change txn at random position: + vector::iterator position = wtxNew.vout.begin()+GetRandInt(wtxNew.vout.size()); + wtxNew.vout.insert(position, CTxOut(nChange, scriptChange)); + } + else + reservekey.ReturnKey(); + + // Fill vin + BOOST_FOREACH(const PAIRTYPE(const CWalletTx*,unsigned int)& coin, setCoins) + wtxNew.vin.push_back(CTxIn(coin.first->GetHash(),coin.second)); + + // Sign + int nIn = 0; + BOOST_FOREACH(const PAIRTYPE(const CWalletTx*,unsigned int)& coin, setCoins) + if (!SignSignature(*this, *coin.first, wtxNew, nIn++)) + return false; + + // Limit size + unsigned int nBytes = ::GetSerializeSize(*(CTransaction*)&wtxNew, SER_NETWORK, PROTOCOL_VERSION); + if (nBytes >= MAX_STANDARD_TX_SIZE) + return false; + dPriority /= nBytes; + + // Check that enough fee is included + int64_t nPayFee = nTransactionFee * (1 + (int64_t)nBytes / 1000); + int64_t nMinFee = wtxNew.GetMinFee(1, GMF_SEND, nBytes); + + if (nFeeRet < max(nPayFee, nMinFee)) + { + nFeeRet = max(nPayFee, nMinFee); + continue; + } + + // Fill vtxPrev by copying from previous transactions vtxPrev + wtxNew.AddSupportingTransactions(txdb); + wtxNew.fTimeReceivedIsTxTime = true; + + break; + } + } + } + return true; +} + +bool CWallet::CreateTransaction(CScript scriptPubKey, int64_t nValue, CWalletTx& wtxNew, CReserveKey& reservekey, int64_t& nFeeRet, const CCoinControl* coinControl) +{ + vector< pair > vecSend; + vecSend.push_back(make_pair(scriptPubKey, nValue)); + return CreateTransaction(vecSend, wtxNew, reservekey, nFeeRet, coinControl); +} + +// NovaCoin: get current stake weight +bool CWallet::GetStakeWeight(const CKeyStore& keystore, uint64_t& nMinWeight, uint64_t& nMaxWeight, uint64_t& nWeight) +{ + // Choose coins to use + int64_t nBalance = GetBalance(); + + if (nBalance <= nReserveBalance) + return false; + + vector vwtxPrev; + + set > setCoins; + int64_t nValueIn = 0; + + if (!SelectCoinsForStaking(nBalance - nReserveBalance, GetTime(), setCoins, nValueIn)) + return false; + + if (setCoins.empty()) + return false; + + nMinWeight = nMaxWeight = nWeight = 0; + + CTxDB txdb("r"); + BOOST_FOREACH(PAIRTYPE(const CWalletTx*, unsigned int) pcoin, setCoins) + { + CTxIndex txindex; + { + LOCK2(cs_main, cs_wallet); + if (!txdb.ReadTxIndex(pcoin.first->GetHash(), txindex)) + continue; + } + + int64_t nTimeWeight = GetWeight((int64_t)pcoin.first->nTime, (int64_t)GetTime()); + CBigNum bnCoinDayWeight = CBigNum(pcoin.first->vout[pcoin.second].nValue) * nTimeWeight / COIN / (24 * 60 * 60); + + // Weight is greater than zero + if (nTimeWeight > 0) + { + nWeight += bnCoinDayWeight.getuint64(); + } + + // Weight is greater than zero, but the maximum value isn't reached yet + if (nTimeWeight > 0 && nTimeWeight < nStakeMaxAge) + { + nMinWeight += bnCoinDayWeight.getuint64(); + } + + // Maximum weight was reached + if (nTimeWeight == nStakeMaxAge) + { + nMaxWeight += bnCoinDayWeight.getuint64(); + } + } + + return true; +} + +bool CWallet::CreateCoinStake(const CKeyStore& keystore, unsigned int nBits, int64_t nSearchInterval, int64_t nFees, CTransaction& txNew, CKey& key) +{ + CBlockIndex* pindexPrev = pindexBest; + CBigNum bnTargetPerCoinDay; + bnTargetPerCoinDay.SetCompact(nBits); + + txNew.vin.clear(); + txNew.vout.clear(); + + // Mark coin stake transaction + CScript scriptEmpty; + scriptEmpty.clear(); + txNew.vout.push_back(CTxOut(0, scriptEmpty)); + + // Choose coins to use + int64_t nBalance = GetBalance(); + + if (nBalance <= nReserveBalance) + return false; + + vector vwtxPrev; + + set > setCoins; + int64_t nValueIn = 0; + + // Select coins with suitable depth + if (!SelectCoinsForStaking(nBalance - nReserveBalance, txNew.nTime, setCoins, nValueIn)) + return false; + + if (setCoins.empty()) + return false; + + int64_t nCredit = 0; + CScript scriptPubKeyKernel; + CTxDB txdb("r"); + BOOST_FOREACH(PAIRTYPE(const CWalletTx*, unsigned int) pcoin, setCoins) + { + CTxIndex txindex; + { + LOCK2(cs_main, cs_wallet); + if (!txdb.ReadTxIndex(pcoin.first->GetHash(), txindex)) + continue; + } + + // Read block header + CBlock block; + { + LOCK2(cs_main, cs_wallet); + if (!block.ReadFromDisk(txindex.pos.nFile, txindex.pos.nBlockPos, false)) + continue; + } + + static int nMaxStakeSearchInterval = 60; + if (block.GetBlockTime() + nStakeMinAge > txNew.nTime - nMaxStakeSearchInterval) + continue; // only count coins meeting min age requirement + + bool fKernelFound = false; + for (unsigned int n=0; nGetHash(), pcoin.second); + if (CheckStakeKernelHash(nBits, block, txindex.pos.nTxPos - txindex.pos.nBlockPos, *pcoin.first, prevoutStake, txNew.nTime - n, hashProofOfStake, targetProofOfStake)) + { + // Found a kernel + if (fDebug && GetBoolArg("-printcoinstake")) + printf("CreateCoinStake : kernel found\n"); + vector vSolutions; + txnouttype whichType; + CScript scriptPubKeyOut; + scriptPubKeyKernel = pcoin.first->vout[pcoin.second].scriptPubKey; + if (!Solver(scriptPubKeyKernel, whichType, vSolutions)) + { + if (fDebug && GetBoolArg("-printcoinstake")) + printf("CreateCoinStake : failed to parse kernel\n"); + break; + } + if (fDebug && GetBoolArg("-printcoinstake")) + printf("CreateCoinStake : parsed kernel type=%d\n", whichType); + if (whichType != TX_PUBKEY && whichType != TX_PUBKEYHASH) + { + if (fDebug && GetBoolArg("-printcoinstake")) + printf("CreateCoinStake : no support for kernel type=%d\n", whichType); + break; // only support pay to public key and pay to address + } + if (whichType == TX_PUBKEYHASH) // pay to address type + { + // convert to pay to public key type + if (!keystore.GetKey(uint160(vSolutions[0]), key)) + { + if (fDebug && GetBoolArg("-printcoinstake")) + printf("CreateCoinStake : failed to get key for kernel type=%d\n", whichType); + break; // unable to find corresponding public key + } + scriptPubKeyOut << key.GetPubKey() << OP_CHECKSIG; + } + if (whichType == TX_PUBKEY) + { + valtype& vchPubKey = vSolutions[0]; + if (!keystore.GetKey(Hash160(vchPubKey), key)) + { + if (fDebug && GetBoolArg("-printcoinstake")) + printf("CreateCoinStake : failed to get key for kernel type=%d\n", whichType); + break; // unable to find corresponding public key + } + + if (key.GetPubKey() != vchPubKey) + { + if (fDebug && GetBoolArg("-printcoinstake")) + printf("CreateCoinStake : invalid key for kernel type=%d\n", whichType); + break; // keys mismatch + } + + scriptPubKeyOut = scriptPubKeyKernel; + } + + txNew.nTime -= n; + txNew.vin.push_back(CTxIn(pcoin.first->GetHash(), pcoin.second)); + nCredit += pcoin.first->vout[pcoin.second].nValue; + vwtxPrev.push_back(pcoin.first); + txNew.vout.push_back(CTxOut(0, scriptPubKeyOut)); + + if (GetWeight(block.GetBlockTime(), (int64_t)txNew.nTime) < nStakeSplitAge) + txNew.vout.push_back(CTxOut(0, scriptPubKeyOut)); //split stake + if (fDebug && GetBoolArg("-printcoinstake")) + printf("CreateCoinStake : added kernel type=%d\n", whichType); + fKernelFound = true; + break; + } + } + + if (fKernelFound || fShutdown) + break; // if kernel is found stop searching + } + + if (nCredit == 0 || nCredit > nBalance - nReserveBalance) + return false; + + BOOST_FOREACH(PAIRTYPE(const CWalletTx*, unsigned int) pcoin, setCoins) + { + // Attempt to add more inputs + // Only add coins of the same key/address as kernel + if (txNew.vout.size() == 2 && ((pcoin.first->vout[pcoin.second].scriptPubKey == scriptPubKeyKernel || pcoin.first->vout[pcoin.second].scriptPubKey == txNew.vout[1].scriptPubKey)) + && pcoin.first->GetHash() != txNew.vin[0].prevout.hash) + { + int64_t nTimeWeight = GetWeight((int64_t)pcoin.first->nTime, (int64_t)txNew.nTime); + + // Stop adding more inputs if already too many inputs + if (txNew.vin.size() >= 100) + break; + // Stop adding more inputs if value is already pretty significant + if (nCredit >= nStakeCombineThreshold) + break; + // Stop adding inputs if reached reserve limit + if (nCredit + pcoin.first->vout[pcoin.second].nValue > nBalance - nReserveBalance) + break; + // Do not add additional significant input + if (pcoin.first->vout[pcoin.second].nValue >= nStakeCombineThreshold) + continue; + // Do not add input that is still too young + if (nTimeWeight < nStakeMinAge) + continue; + + txNew.vin.push_back(CTxIn(pcoin.first->GetHash(), pcoin.second)); + nCredit += pcoin.first->vout[pcoin.second].nValue; + vwtxPrev.push_back(pcoin.first); + } + } + + // Calculate coin age reward + { + uint64_t nCoinAge; + CTxDB txdb("r"); + if (!txNew.GetCoinAge(txdb, nCoinAge)) + return error("CreateCoinStake : failed to calculate coin age"); + + int64_t nReward = GetProofOfStakeReward(nCoinAge, nFees); + if (nReward <= 0) + return false; + + nCredit += nReward; + } + + // Set output amount + if (txNew.vout.size() == 3) + { + txNew.vout[1].nValue = (nCredit / 2 / CENT) * CENT; + txNew.vout[2].nValue = nCredit - txNew.vout[1].nValue; + } + else + txNew.vout[1].nValue = nCredit; + + // Sign + int nIn = 0; + BOOST_FOREACH(const CWalletTx* pcoin, vwtxPrev) + { + if (!SignSignature(*this, *pcoin, txNew, nIn++)) + return error("CreateCoinStake : failed to sign coinstake"); + } + + // Limit size + unsigned int nBytes = ::GetSerializeSize(txNew, SER_NETWORK, PROTOCOL_VERSION); + if (nBytes >= MAX_BLOCK_SIZE_GEN/5) + return error("CreateCoinStake : exceeded coinstake size limit"); + + // Successfully generated coinstake + return true; +} + + +// Call after CreateTransaction unless you want to abort +bool CWallet::CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey) +{ + { + LOCK2(cs_main, cs_wallet); + printf("CommitTransaction:\n%s", wtxNew.ToString().c_str()); + { + // 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* pwalletdb = fFileBacked ? new CWalletDB(strWalletFile,"r") : NULL; + + // Take key pair from key pool so it won't be used again + reservekey.KeepKey(); + + // 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 setCoins; + BOOST_FOREACH(const CTxIn& txin, wtxNew.vin) + { + CWalletTx &coin = mapWallet[txin.prevout.hash]; + coin.BindWallet(this); + coin.MarkSpent(txin.prevout.n); + coin.WriteToDisk(); + NotifyTransactionChanged(this, coin.GetHash(), CT_UPDATED); + } + + if (fFileBacked) + delete pwalletdb; + } + + // Track how many getdata requests our transaction gets + mapRequestCount[wtxNew.GetHash()] = 0; + + // Broadcast + if (!wtxNew.AcceptToMemoryPool()) + { + // This must not fail. The transaction has already been signed and recorded. + printf("CommitTransaction() : Error: Transaction not valid\n"); + return false; + } + wtxNew.RelayWalletTransaction(); + } + return true; +} + + + + +string CWallet::SendMoney(CScript scriptPubKey, int64_t nValue, CWalletTx& wtxNew, bool fAskFee) +{ + CReserveKey reservekey(this); + int64_t nFeeRequired; + + if (IsLocked()) + { + string strError = _("Error: Wallet locked, unable to create transaction "); + printf("SendMoney() : %s", strError.c_str()); + return strError; + } + if (fWalletUnlockStakingOnly) + { + string strError = _("Error: Wallet unlocked for staking only, unable to create transaction."); + printf("SendMoney() : %s", strError.c_str()); + return strError; + } + if (!CreateTransaction(scriptPubKey, nValue, wtxNew, reservekey, nFeeRequired)) + { + string strError; + if (nValue + nFeeRequired > GetBalance()) + strError = strprintf(_("Error: This transaction requires a transaction fee of at least %s because of its amount, complexity, or use of recently received funds "), FormatMoney(nFeeRequired).c_str()); + else + strError = _("Error: Transaction creation failed "); + printf("SendMoney() : %s", strError.c_str()); + return strError; + } + + if (fAskFee && !uiInterface.ThreadSafeAskFee(nFeeRequired, _("Sending..."))) + return "ABORTED"; + + if (!CommitTransaction(wtxNew, reservekey)) + 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."); + + return ""; +} + + + +string CWallet::SendMoneyToDestination(const CTxDestination& address, int64_t nValue, CWalletTx& wtxNew, bool fAskFee) +{ + // Check amount + if (nValue <= 0) + return _("Invalid amount"); + if (nValue + nTransactionFee > GetBalance()) + return _("Insufficient funds"); + + // Parse Bitcoin address + CScript scriptPubKey; + scriptPubKey.SetDestination(address); + + return SendMoney(scriptPubKey, nValue, wtxNew, fAskFee); +} + + + + +DBErrors CWallet::LoadWallet(bool& fFirstRunRet) +{ + if (!fFileBacked) + return DB_LOAD_OK; + fFirstRunRet = false; + DBErrors nLoadWalletRet = CWalletDB(strWalletFile,"cr+").LoadWallet(this); + if (nLoadWalletRet == DB_NEED_REWRITE) + { + if (CDB::Rewrite(strWalletFile, "\x04pool")) + { + LOCK(cs_wallet); + setKeyPool.clear(); + // Note: can't top-up keypool here, because wallet is locked. + // User will be prompted to unlock wallet the next operation + // the requires a new key. + } + } + + if (nLoadWalletRet != DB_LOAD_OK) + return nLoadWalletRet; + fFirstRunRet = !vchDefaultKey.IsValid(); + + NewThread(ThreadFlushWalletDB, &strWalletFile); + return DB_LOAD_OK; +} + + +bool CWallet::SetAddressBookName(const CTxDestination& address, const string& strName) +{ + bool fUpdated = false; + { + LOCK(cs_wallet); // mapAddressBook + std::map::iterator mi = mapAddressBook.find(address); + fUpdated = mi != mapAddressBook.end(); + mapAddressBook[address] = strName; + } + NotifyAddressBookChanged(this, address, strName, ::IsMine(*this, address), + (fUpdated ? CT_UPDATED : CT_NEW) ); + if (!fFileBacked) + return false; + return CWalletDB(strWalletFile).WriteName(CBitcoinAddress(address).ToString(), strName); +} + +bool CWallet::DelAddressBookName(const CTxDestination& address) +{ + { + LOCK(cs_wallet); // mapAddressBook + + mapAddressBook.erase(address); + } + + NotifyAddressBookChanged(this, address, "", ::IsMine(*this, address), CT_DELETED); + + if (!fFileBacked) + return false; + return CWalletDB(strWalletFile).EraseName(CBitcoinAddress(address).ToString()); +} + + +void CWallet::PrintWallet(const CBlock& block) +{ + { + LOCK(cs_wallet); + if (block.IsProofOfWork() && mapWallet.count(block.vtx[0].GetHash())) + { + CWalletTx& wtx = mapWallet[block.vtx[0].GetHash()]; + printf(" mine: %d %d %" PRId64"", wtx.GetDepthInMainChain(), wtx.GetBlocksToMaturity(), wtx.GetCredit()); + } + if (block.IsProofOfStake() && mapWallet.count(block.vtx[1].GetHash())) + { + CWalletTx& wtx = mapWallet[block.vtx[1].GetHash()]; + printf(" stake: %d %d %" PRId64"", wtx.GetDepthInMainChain(), wtx.GetBlocksToMaturity(), wtx.GetCredit()); + } + + } + printf("\n"); +} + +bool CWallet::GetTransaction(const uint256 &hashTx, CWalletTx& wtx) +{ + { + LOCK(cs_wallet); + map::iterator mi = mapWallet.find(hashTx); + if (mi != mapWallet.end()) + { + wtx = (*mi).second; + return true; + } + } + return false; +} + +bool CWallet::SetDefaultKey(const CPubKey &vchPubKey) +{ + if (fFileBacked) + { + if (!CWalletDB(strWalletFile).WriteDefaultKey(vchPubKey)) + return false; + } + vchDefaultKey = vchPubKey; + return true; +} + +bool GetWalletFile(CWallet* pwallet, string &strWalletFileOut) +{ + if (!pwallet->fFileBacked) + return false; + strWalletFileOut = pwallet->strWalletFile; + return true; +} + +// +// Mark old keypool keys as used, +// and generate all new keys +// +bool CWallet::NewKeyPool() +{ + { + LOCK(cs_wallet); + CWalletDB walletdb(strWalletFile); + BOOST_FOREACH(int64_t nIndex, setKeyPool) + walletdb.ErasePool(nIndex); + setKeyPool.clear(); + + if (IsLocked()) + return false; + + int64_t nKeys = max(GetArg("-keypool", 100), (int64_t)0); + for (int i = 0; i < nKeys; i++) + { + int64_t nIndex = i+1; + walletdb.WritePool(nIndex, CKeyPool(GenerateNewKey())); + setKeyPool.insert(nIndex); + } + printf("CWallet::NewKeyPool wrote %" PRId64" new keys\n", nKeys); + } + return true; +} + +bool CWallet::TopUpKeyPool(unsigned int nSize) +{ + { + LOCK(cs_wallet); + + if (IsLocked()) + return false; + + CWalletDB walletdb(strWalletFile); + + // Top up key pool + unsigned int nTargetSize; + if (nSize > 0) + nTargetSize = nSize; + else + nTargetSize = max(GetArg("-keypool", 100), (int64_t)0); + + while (setKeyPool.size() < (nTargetSize + 1)) + { + int64_t nEnd = 1; + if (!setKeyPool.empty()) + nEnd = *(--setKeyPool.end()) + 1; + if (!walletdb.WritePool(nEnd, CKeyPool(GenerateNewKey()))) + throw runtime_error("TopUpKeyPool() : writing generated key failed"); + setKeyPool.insert(nEnd); + printf("keypool added key %" PRId64", size=%" PRIszu"\n", nEnd, setKeyPool.size()); + } + } + return true; +} + +void CWallet::ReserveKeyFromKeyPool(int64_t& nIndex, CKeyPool& keypool) +{ + nIndex = -1; + keypool.vchPubKey = CPubKey(); + { + LOCK(cs_wallet); + + if (!IsLocked()) + TopUpKeyPool(); + + // Get the oldest key + if(setKeyPool.empty()) + return; + + CWalletDB walletdb(strWalletFile); + + nIndex = *(setKeyPool.begin()); + setKeyPool.erase(setKeyPool.begin()); + if (!walletdb.ReadPool(nIndex, keypool)) + throw runtime_error("ReserveKeyFromKeyPool() : read failed"); + if (!HaveKey(keypool.vchPubKey.GetID())) + throw runtime_error("ReserveKeyFromKeyPool() : unknown key in key pool"); + assert(keypool.vchPubKey.IsValid()); + if (fDebug && GetBoolArg("-printkeypool")) + printf("keypool reserve %" PRId64"\n", nIndex); + } +} + +int64_t CWallet::AddReserveKey(const CKeyPool& keypool) +{ + { + LOCK2(cs_main, cs_wallet); + CWalletDB walletdb(strWalletFile); + + int64_t nIndex = 1 + *(--setKeyPool.end()); + if (!walletdb.WritePool(nIndex, keypool)) + throw runtime_error("AddReserveKey() : writing added key failed"); + setKeyPool.insert(nIndex); + return nIndex; + } + return -1; +} + +void CWallet::KeepKey(int64_t nIndex) +{ + // Remove from key pool + if (fFileBacked) + { + CWalletDB walletdb(strWalletFile); + walletdb.ErasePool(nIndex); + } + if(fDebug) + printf("keypool keep %" PRId64"\n", nIndex); +} + +void CWallet::ReturnKey(int64_t nIndex) +{ + // Return to key pool + { + LOCK(cs_wallet); + setKeyPool.insert(nIndex); + } + if(fDebug) + printf("keypool return %" PRId64"\n", nIndex); +} + +bool CWallet::GetKeyFromPool(CPubKey& result, bool fAllowReuse) +{ + int64_t nIndex = 0; + CKeyPool keypool; + { + LOCK(cs_wallet); + ReserveKeyFromKeyPool(nIndex, keypool); + if (nIndex == -1) + { + if (fAllowReuse && vchDefaultKey.IsValid()) + { + result = vchDefaultKey; + return true; + } + if (IsLocked()) return false; + result = GenerateNewKey(); + return true; + } + KeepKey(nIndex); + result = keypool.vchPubKey; + } + return true; +} + +int64_t CWallet::GetOldestKeyPoolTime() +{ + int64_t nIndex = 0; + CKeyPool keypool; + ReserveKeyFromKeyPool(nIndex, keypool); + if (nIndex == -1) + return GetTime(); + ReturnKey(nIndex); + return keypool.nTime; +} + +std::map CWallet::GetAddressBalances() +{ + map balances; + + { + LOCK(cs_wallet); + BOOST_FOREACH(PAIRTYPE(uint256, CWalletTx) walletEntry, mapWallet) + { + CWalletTx *pcoin = &walletEntry.second; + + if (!IsFinalTx(*pcoin) || !pcoin->IsTrusted()) + continue; + + if ((pcoin->IsCoinBase() || pcoin->IsCoinStake()) && pcoin->GetBlocksToMaturity() > 0) + continue; + + int nDepth = pcoin->GetDepthInMainChain(); + if (nDepth < (pcoin->IsFromMe() ? 0 : 1)) + continue; + + for (unsigned int i = 0; i < pcoin->vout.size(); i++) + { + CTxDestination addr; + if (!IsMine(pcoin->vout[i])) + continue; + if(!ExtractDestination(pcoin->vout[i].scriptPubKey, addr)) + continue; + + int64_t n = pcoin->IsSpent(i) ? 0 : pcoin->vout[i].nValue; + + if (!balances.count(addr)) + balances[addr] = 0; + balances[addr] += n; + } + } + } + + return balances; +} + +set< set > CWallet::GetAddressGroupings() +{ + AssertLockHeld(cs_wallet); // mapWallet + set< set > groupings; + set grouping; + + BOOST_FOREACH(PAIRTYPE(uint256, CWalletTx) walletEntry, mapWallet) + { + CWalletTx *pcoin = &walletEntry.second; + + if (pcoin->vin.size() > 0 && IsMine(pcoin->vin[0])) + { + // group all input addresses with each other + BOOST_FOREACH(CTxIn txin, pcoin->vin) + { + CTxDestination address; + if(!ExtractDestination(mapWallet[txin.prevout.hash].vout[txin.prevout.n].scriptPubKey, address)) + continue; + grouping.insert(address); + } + + // group change with input addresses + BOOST_FOREACH(CTxOut txout, pcoin->vout) + if (IsChange(txout)) + { + CWalletTx tx = mapWallet[pcoin->vin[0].prevout.hash]; + CTxDestination txoutAddr; + if(!ExtractDestination(txout.scriptPubKey, txoutAddr)) + continue; + grouping.insert(txoutAddr); + } + groupings.insert(grouping); + grouping.clear(); + } + + // group lone addrs by themselves + for (unsigned int i = 0; i < pcoin->vout.size(); i++) + if (IsMine(pcoin->vout[i])) + { + CTxDestination address; + if(!ExtractDestination(pcoin->vout[i].scriptPubKey, address)) + continue; + grouping.insert(address); + groupings.insert(grouping); + grouping.clear(); + } + } + + set< set* > uniqueGroupings; // a set of pointers to groups of addresses + map< CTxDestination, set* > setmap; // map addresses to the unique group containing it + BOOST_FOREACH(set grouping, groupings) + { + // make a set of all the groups hit by this new group + set< set* > hits; + map< CTxDestination, set* >::iterator it; + BOOST_FOREACH(CTxDestination address, grouping) + if ((it = setmap.find(address)) != setmap.end()) + hits.insert((*it).second); + + // merge all hit groups into a new single group and delete old groups + set* merged = new set(grouping); + BOOST_FOREACH(set* hit, hits) + { + merged->insert(hit->begin(), hit->end()); + uniqueGroupings.erase(hit); + delete hit; + } + uniqueGroupings.insert(merged); + + // update setmap + BOOST_FOREACH(CTxDestination element, *merged) + setmap[element] = merged; + } + + set< set > ret; + BOOST_FOREACH(set* uniqueGrouping, uniqueGroupings) + { + ret.insert(*uniqueGrouping); + delete uniqueGrouping; + } + + return ret; +} + +// ppcoin: check 'spent' consistency between wallet and txindex +// ppcoin: fix wallet spent state according to txindex +void CWallet::FixSpentCoins(int& nMismatchFound, int64_t& nBalanceInQuestion, bool fCheckOnly) +{ + nMismatchFound = 0; + nBalanceInQuestion = 0; + + LOCK(cs_wallet); + vector vCoins; + vCoins.reserve(mapWallet.size()); + for (map::iterator it = mapWallet.begin(); it != mapWallet.end(); ++it) + vCoins.push_back(&(*it).second); + + CTxDB txdb("r"); + BOOST_FOREACH(CWalletTx* pcoin, vCoins) + { + // Find the corresponding transaction index + CTxIndex txindex; + if (!txdb.ReadTxIndex(pcoin->GetHash(), txindex)) + continue; + for (unsigned int n=0; n < pcoin->vout.size(); n++) + { + if (IsMine(pcoin->vout[n]) && pcoin->IsSpent(n) && (txindex.vSpent.size() <= n || txindex.vSpent[n].IsNull())) + { + printf("FixSpentCoins found lost coin %s BC %s[%d], %s\n", + FormatMoney(pcoin->vout[n].nValue).c_str(), pcoin->GetHash().ToString().c_str(), n, fCheckOnly? "repair not attempted" : "repairing"); + nMismatchFound++; + nBalanceInQuestion += pcoin->vout[n].nValue; + if (!fCheckOnly) + { + pcoin->MarkUnspent(n); + pcoin->WriteToDisk(); + } + } + else if (IsMine(pcoin->vout[n]) && !pcoin->IsSpent(n) && (txindex.vSpent.size() > n && !txindex.vSpent[n].IsNull())) + { + printf("FixSpentCoins found spent coin %s BC %s[%d], %s\n", + FormatMoney(pcoin->vout[n].nValue).c_str(), pcoin->GetHash().ToString().c_str(), n, fCheckOnly? "repair not attempted" : "repairing"); + nMismatchFound++; + nBalanceInQuestion += pcoin->vout[n].nValue; + if (!fCheckOnly) + { + pcoin->MarkSpent(n); + pcoin->WriteToDisk(); + } + } + } + } +} + +// ppcoin: disable transaction (only for coinstake) +void CWallet::DisableTransaction(const CTransaction &tx) +{ + if (!tx.IsCoinStake() || !IsFromMe(tx)) + return; // only disconnecting coinstake requires marking input unspent + + LOCK(cs_wallet); + BOOST_FOREACH(const CTxIn& txin, tx.vin) + { + map::iterator mi = mapWallet.find(txin.prevout.hash); + if (mi != mapWallet.end()) + { + CWalletTx& prev = (*mi).second; + if (txin.prevout.n < prev.vout.size() && IsMine(prev.vout[txin.prevout.n])) + { + prev.MarkUnspent(txin.prevout.n); + prev.WriteToDisk(); + } + } + } +} + +bool CReserveKey::GetReservedKey(CPubKey& pubkey) +{ + if (nIndex == -1) + { + CKeyPool keypool; + pwallet->ReserveKeyFromKeyPool(nIndex, keypool); + if (nIndex != -1) + vchPubKey = keypool.vchPubKey; + else { + if (pwallet->vchDefaultKey.IsValid()) { + printf("CReserveKey::GetReservedKey(): Warning: Using default key instead of a new key, top up your keypool!"); + vchPubKey = pwallet->vchDefaultKey; + } else + return false; + } + } + assert(vchPubKey.IsValid()); + pubkey = vchPubKey; + return true; +} + +void CReserveKey::KeepKey() +{ + if (nIndex != -1) + pwallet->KeepKey(nIndex); + nIndex = -1; + vchPubKey = CPubKey(); +} + +void CReserveKey::ReturnKey() +{ + if (nIndex != -1) + pwallet->ReturnKey(nIndex); + nIndex = -1; + vchPubKey = CPubKey(); +} + +void CWallet::GetAllReserveKeys(set& setAddress) const +{ + setAddress.clear(); + + CWalletDB walletdb(strWalletFile); + + LOCK2(cs_main, cs_wallet); + BOOST_FOREACH(const int64_t& id, setKeyPool) + { + CKeyPool keypool; + if (!walletdb.ReadPool(id, keypool)) + throw runtime_error("GetAllReserveKeyHashes() : read failed"); + assert(keypool.vchPubKey.IsValid()); + CKeyID keyID = keypool.vchPubKey.GetID(); + if (!HaveKey(keyID)) + throw runtime_error("GetAllReserveKeyHashes() : unknown key in key pool"); + setAddress.insert(keyID); + } +} + +void CWallet::UpdatedTransaction(const uint256 &hashTx) +{ + { + LOCK(cs_wallet); + // Only notify UI if this transaction is in this wallet + map::const_iterator mi = mapWallet.find(hashTx); + if (mi != mapWallet.end()) + NotifyTransactionChanged(this, hashTx, CT_UPDATED); + } +} + +void CWallet::GetKeyBirthTimes(std::map &mapKeyBirth) const { + AssertLockHeld(cs_wallet); // mapKeyMetadata + mapKeyBirth.clear(); + + // get birth times for keys with metadata + for (std::map::const_iterator it = mapKeyMetadata.begin(); it != mapKeyMetadata.end(); it++) + if (it->second.nCreateTime) + mapKeyBirth[it->first] = it->second.nCreateTime; + + // map in which we'll infer heights of other keys + CBlockIndex *pindexMax = FindBlockByHeight(std::max(0, nBestHeight - 144)); // the tip can be reorganised; use a 144-block safety margin + std::map mapKeyFirstBlock; + std::set setKeys; + GetKeys(setKeys); + BOOST_FOREACH(const CKeyID &keyid, setKeys) { + if (mapKeyBirth.count(keyid) == 0) + mapKeyFirstBlock[keyid] = pindexMax; + } + setKeys.clear(); + + // if there are no such keys, we're done + if (mapKeyFirstBlock.empty()) + return; + + // find first block that affects those keys, if there are any left + std::vector vAffected; + for (std::map::const_iterator it = mapWallet.begin(); it != mapWallet.end(); it++) { + // iterate over all wallet transactions... + const CWalletTx &wtx = (*it).second; + std::map::const_iterator blit = mapBlockIndex.find(wtx.hashBlock); + if (blit != mapBlockIndex.end() && blit->second->IsInMainChain()) { + // ... which are already in a block + int nHeight = blit->second->nHeight; + BOOST_FOREACH(const CTxOut &txout, wtx.vout) { + // iterate over all their outputs + ::ExtractAffectedKeys(*this, txout.scriptPubKey, vAffected); + BOOST_FOREACH(const CKeyID &keyid, vAffected) { + // ... and all their affected keys + std::map::iterator rit = mapKeyFirstBlock.find(keyid); + if (rit != mapKeyFirstBlock.end() && nHeight < rit->second->nHeight) + rit->second = blit->second; + } + vAffected.clear(); + } + } + } + + // Extract block timestamps for those keys + for (std::map::const_iterator it = mapKeyFirstBlock.begin(); it != mapKeyFirstBlock.end(); it++) + mapKeyBirth[it->first] = it->second->nTime - 7200; // block times can be 2h off +} diff --git a/src/wallet.h b/src/wallet.h new file mode 100644 index 0000000..18e3cbe --- /dev/null +++ b/src/wallet.h @@ -0,0 +1,887 @@ +// Copyright (c) 2009-2010 Satoshi Nakamoto +// Copyright (c) 2009-2012 The Bitcoin developers +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. +#ifndef BITCOIN_WALLET_H +#define BITCOIN_WALLET_H + +#include +#include + +#include + +#include "main.h" +#include "key.h" +#include "keystore.h" +#include "script.h" +#include "ui_interface.h" +#include "util.h" +#include "walletdb.h" + +extern bool fWalletUnlockStakingOnly; +extern bool fConfChange; +class CAccountingEntry; +class CWalletTx; +class CReserveKey; +class COutput; +class CCoinControl; + +/** (client) version numbers for particular wallet features */ +enum WalletFeature +{ + FEATURE_BASE = 10500, // the earliest version new wallets supports (only useful for getinfo's clientversion output) + + FEATURE_WALLETCRYPT = 40000, // wallet encryption + FEATURE_COMPRPUBKEY = 60000, // compressed public keys + + FEATURE_LATEST = 60000 +}; + +/** A key pool entry */ +class CKeyPool +{ +public: + int64_t nTime; + CPubKey vchPubKey; + + CKeyPool() + { + nTime = GetTime(); + } + + CKeyPool(const CPubKey& vchPubKeyIn) + { + nTime = GetTime(); + vchPubKey = vchPubKeyIn; + } + + IMPLEMENT_SERIALIZE + ( + if (!(nType & SER_GETHASH)) + READWRITE(nVersion); + READWRITE(nTime); + READWRITE(vchPubKey); + ) +}; + +/** A CWallet is an extension of a keystore, which also maintains a set of transactions and balances, + * and provides the ability to create new transactions. + */ +class CWallet : public CCryptoKeyStore +{ +private: + bool SelectCoinsForStaking(int64_t nTargetValue, unsigned int nSpendTime, std::set >& setCoinsRet, int64_t& nValueRet) const; + bool SelectCoins(int64_t nTargetValue, unsigned int nSpendTime, std::set >& setCoinsRet, int64_t& nValueRet, const CCoinControl *coinControl=NULL) const; + + CWalletDB *pwalletdbEncryption; + + // the current wallet version: clients below this version are not able to load the wallet + int nWalletVersion; + + // the maximum wallet format version: memory-only variable that specifies to what version this wallet may be upgraded + int nWalletMaxVersion; + +public: + /// Main wallet lock. + /// This lock protects all the fields added by CWallet + /// except for: + /// fFileBacked (immutable after instantiation) + /// strWalletFile (immutable after instantiation) + mutable CCriticalSection cs_wallet; + + bool fFileBacked; + std::string strWalletFile; + + std::set setKeyPool; + std::map mapKeyMetadata; + + + typedef std::map MasterKeyMap; + MasterKeyMap mapMasterKeys; + unsigned int nMasterKeyMaxID; + + CWallet() + { + SetNull(); + } + CWallet(std::string strWalletFileIn) + { + SetNull(); + + strWalletFile = strWalletFileIn; + fFileBacked = true; + } + void SetNull() + { + nWalletVersion = FEATURE_BASE; + nWalletMaxVersion = FEATURE_BASE; + fFileBacked = false; + nMasterKeyMaxID = 0; + pwalletdbEncryption = NULL; + nOrderPosNext = 0; + nTimeFirstKey = 0; + } + + std::map mapWallet; + int64_t nOrderPosNext; + std::map mapRequestCount; + + std::map mapAddressBook; + + CPubKey vchDefaultKey; + int64_t nTimeFirstKey; + + // check whether we are allowed to upgrade (or already support) to the named feature + bool CanSupportFeature(enum WalletFeature wf) { AssertLockHeld(cs_wallet); return nWalletMaxVersion >= wf; } + + void AvailableCoinsForStaking(std::vector& vCoins, unsigned int nSpendTime) const; + void AvailableCoins(std::vector& vCoins, bool fOnlyConfirmed=true, const CCoinControl *coinControl=NULL) const; + bool SelectCoinsMinConf(int64_t nTargetValue, unsigned int nSpendTime, int nConfMine, int nConfTheirs, std::vector vCoins, std::set >& setCoinsRet, int64_t& nValueRet) const; + + // keystore implementation + // Generate a new key + CPubKey GenerateNewKey(); + // Adds a key to the store, and saves it to disk. + bool AddKey(const CKey& key); + // Adds a key to the store, without saving it to disk (used by LoadWallet) + bool LoadKey(const CKey& key) { return CCryptoKeyStore::AddKey(key); } + // Load metadata (used by LoadWallet) + bool LoadKeyMetadata(const CPubKey &pubkey, const CKeyMetadata &metadata); + + bool LoadMinVersion(int nVersion) { AssertLockHeld(cs_wallet); nWalletVersion = nVersion; nWalletMaxVersion = std::max(nWalletMaxVersion, nVersion); return true; } + + // Adds an encrypted key to the store, and saves it to disk. + bool AddCryptedKey(const CPubKey &vchPubKey, const std::vector &vchCryptedSecret); + // Adds an encrypted key to the store, without saving it to disk (used by LoadWallet) + bool LoadCryptedKey(const CPubKey &vchPubKey, const std::vector &vchCryptedSecret); + bool AddCScript(const CScript& redeemScript); + bool LoadCScript(const CScript& redeemScript); + + bool Unlock(const SecureString& strWalletPassphrase); + bool ChangeWalletPassphrase(const SecureString& strOldWalletPassphrase, const SecureString& strNewWalletPassphrase); + bool EncryptWallet(const SecureString& strWalletPassphrase); + + void GetKeyBirthTimes(std::map &mapKeyBirth) const; + + + /** Increment the next transaction order id + @return next transaction order id + */ + int64_t IncOrderPosNext(CWalletDB *pwalletdb = NULL); + + typedef std::pair TxPair; + typedef std::multimap TxItems; + + /** Get the wallet's activity log + @return multimap of ordered transactions and accounting entries + @warning Returned pointers are *only* valid within the scope of passed acentries + */ + TxItems OrderedTxItems(std::list& acentries, std::string strAccount = ""); + + void MarkDirty(); + bool AddToWallet(const CWalletTx& wtxIn); + bool AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlock* pblock, bool fUpdate = false, bool fFindBlock = false); + bool EraseFromWallet(uint256 hash); + void WalletUpdateSpent(const CTransaction& prevout, bool fBlock = false); + int ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate = false); + void ReacceptWalletTransactions(); + void ResendWalletTransactions(bool fForce = false); + int64_t GetBalance() const; + int64_t GetUnconfirmedBalance() const; + int64_t GetImmatureBalance() const; + int64_t GetStake() const; + int64_t GetNewMint() const; + bool CreateTransaction(const std::vector >& vecSend, CWalletTx& wtxNew, CReserveKey& reservekey, int64_t& nFeeRet, const CCoinControl *coinControl=NULL); + bool CreateTransaction(CScript scriptPubKey, int64_t nValue, CWalletTx& wtxNew, CReserveKey& reservekey, int64_t& nFeeRet, const CCoinControl *coinControl=NULL); + bool CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey); + + bool GetStakeWeight(const CKeyStore& keystore, uint64_t& nMinWeight, uint64_t& nMaxWeight, uint64_t& nWeight); + bool CreateCoinStake(const CKeyStore& keystore, unsigned int nBits, int64_t nSearchInterval, int64_t nFees, CTransaction& txNew, CKey& key); + + std::string SendMoney(CScript scriptPubKey, int64_t nValue, CWalletTx& wtxNew, bool fAskFee=false); + std::string SendMoneyToDestination(const CTxDestination &address, int64_t nValue, CWalletTx& wtxNew, bool fAskFee=false); + + bool NewKeyPool(); + bool TopUpKeyPool(unsigned int nSize = 0); + int64_t AddReserveKey(const CKeyPool& keypool); + void ReserveKeyFromKeyPool(int64_t& nIndex, CKeyPool& keypool); + void KeepKey(int64_t nIndex); + void ReturnKey(int64_t nIndex); + bool GetKeyFromPool(CPubKey &key, bool fAllowReuse=true); + int64_t GetOldestKeyPoolTime(); + void GetAllReserveKeys(std::set& setAddress) const; + + std::set< std::set > GetAddressGroupings(); + std::map GetAddressBalances(); + + bool IsMine(const CTxIn& txin) const; + int64_t GetDebit(const CTxIn& txin) const; + bool IsMine(const CTxOut& txout) const + { + return ::IsMine(*this, txout.scriptPubKey); + } + int64_t GetCredit(const CTxOut& txout) const + { + if (!MoneyRange(txout.nValue)) + throw std::runtime_error("CWallet::GetCredit() : value out of range"); + return (IsMine(txout) ? txout.nValue : 0); + } + bool IsChange(const CTxOut& txout) const; + int64_t GetChange(const CTxOut& txout) const + { + if (!MoneyRange(txout.nValue)) + throw std::runtime_error("CWallet::GetChange() : value out of range"); + return (IsChange(txout) ? txout.nValue : 0); + } + bool IsMine(const CTransaction& tx) const + { + BOOST_FOREACH(const CTxOut& txout, tx.vout) + if (IsMine(txout) && txout.nValue >= nMinimumInputValue) + return true; + return false; + } + bool IsFromMe(const CTransaction& tx) const + { + return (GetDebit(tx) > 0); + } + int64_t GetDebit(const CTransaction& tx) const + { + int64_t nDebit = 0; + BOOST_FOREACH(const CTxIn& txin, tx.vin) + { + nDebit += GetDebit(txin); + if (!MoneyRange(nDebit)) + throw std::runtime_error("CWallet::GetDebit() : value out of range"); + } + return nDebit; + } + int64_t GetCredit(const CTransaction& tx) const + { + int64_t nCredit = 0; + BOOST_FOREACH(const CTxOut& txout, tx.vout) + { + nCredit += GetCredit(txout); + if (!MoneyRange(nCredit)) + throw std::runtime_error("CWallet::GetCredit() : value out of range"); + } + return nCredit; + } + int64_t GetChange(const CTransaction& tx) const + { + int64_t nChange = 0; + BOOST_FOREACH(const CTxOut& txout, tx.vout) + { + nChange += GetChange(txout); + if (!MoneyRange(nChange)) + throw std::runtime_error("CWallet::GetChange() : value out of range"); + } + return nChange; + } + void SetBestChain(const CBlockLocator& loc); + + DBErrors LoadWallet(bool& fFirstRunRet); + + bool SetAddressBookName(const CTxDestination& address, const std::string& strName); + + bool DelAddressBookName(const CTxDestination& address); + + void UpdatedTransaction(const uint256 &hashTx); + + void PrintWallet(const CBlock& block); + + void Inventory(const uint256 &hash) + { + { + LOCK(cs_wallet); + std::map::iterator mi = mapRequestCount.find(hash); + if (mi != mapRequestCount.end()) + (*mi).second++; + } + } + + unsigned int GetKeyPoolSize() + { + AssertLockHeld(cs_wallet); // setKeyPool + return setKeyPool.size(); + } + + bool GetTransaction(const uint256 &hashTx, CWalletTx& wtx); + + bool SetDefaultKey(const CPubKey &vchPubKey); + + // signify that a particular wallet feature is now used. this may change nWalletVersion and nWalletMaxVersion if those are lower + bool SetMinVersion(enum WalletFeature, CWalletDB* pwalletdbIn = NULL, bool fExplicit = false); + + // change which version we're allowed to upgrade to (note that this does not immediately imply upgrading to that format) + bool SetMaxVersion(int nVersion); + + // get the current wallet format (the oldest client version guaranteed to understand this wallet) + int GetVersion() { LOCK(cs_wallet); return nWalletVersion; } + + void FixSpentCoins(int& nMismatchSpent, int64_t& nBalanceInQuestion, bool fCheckOnly = false); + void DisableTransaction(const CTransaction &tx); + + /** Address book entry changed. + * @note called with lock cs_wallet held. + */ + boost::signals2::signal NotifyAddressBookChanged; + + /** Wallet transaction added, removed or updated. + * @note called with lock cs_wallet held. + */ + boost::signals2::signal NotifyTransactionChanged; +}; + +/** A key allocated from the key pool. */ +class CReserveKey +{ +protected: + CWallet* pwallet; + int64_t nIndex; + CPubKey vchPubKey; +public: + CReserveKey(CWallet* pwalletIn) + { + nIndex = -1; + pwallet = pwalletIn; + } + + ~CReserveKey() + { + if (!fShutdown) + ReturnKey(); + } + + void ReturnKey(); + bool GetReservedKey(CPubKey &pubkey); + void KeepKey(); +}; + + +typedef std::map mapValue_t; + + +static void ReadOrderPos(int64_t& nOrderPos, mapValue_t& mapValue) +{ + if (!mapValue.count("n")) + { + nOrderPos = -1; // TODO: calculate elsewhere + return; + } + nOrderPos = atoi64(mapValue["n"].c_str()); +} + + +static void WriteOrderPos(const int64_t& nOrderPos, mapValue_t& mapValue) +{ + if (nOrderPos == -1) + return; + mapValue["n"] = i64tostr(nOrderPos); +} + + +/** A transaction with a bunch of additional info that only the owner cares about. + * It includes any unrecorded transactions needed to link it back to the block chain. + */ +class CWalletTx : public CMerkleTx +{ +private: + const CWallet* pwallet; + +public: + std::vector vtxPrev; + mapValue_t mapValue; + std::vector > vOrderForm; + unsigned int fTimeReceivedIsTxTime; + unsigned int nTimeReceived; // time received by this node + unsigned int nTimeSmart; + char fFromMe; + std::string strFromAccount; + std::vector vfSpent; // which outputs are already spent + int64_t nOrderPos; // position in ordered transaction list + + // memory only + mutable bool fDebitCached; + mutable bool fCreditCached; + mutable bool fAvailableCreditCached; + mutable bool fChangeCached; + mutable int64_t nDebitCached; + mutable int64_t nCreditCached; + mutable int64_t nAvailableCreditCached; + mutable int64_t nChangeCached; + + CWalletTx() + { + Init(NULL); + } + + CWalletTx(const CWallet* pwalletIn) + { + Init(pwalletIn); + } + + CWalletTx(const CWallet* pwalletIn, const CMerkleTx& txIn) : CMerkleTx(txIn) + { + Init(pwalletIn); + } + + CWalletTx(const CWallet* pwalletIn, const CTransaction& txIn) : CMerkleTx(txIn) + { + Init(pwalletIn); + } + + void Init(const CWallet* pwalletIn) + { + pwallet = pwalletIn; + vtxPrev.clear(); + mapValue.clear(); + vOrderForm.clear(); + fTimeReceivedIsTxTime = false; + nTimeReceived = 0; + nTimeSmart = 0; + fFromMe = false; + strFromAccount.clear(); + vfSpent.clear(); + fDebitCached = false; + fCreditCached = false; + fAvailableCreditCached = false; + fChangeCached = false; + nDebitCached = 0; + nCreditCached = 0; + nAvailableCreditCached = 0; + nChangeCached = 0; + nOrderPos = -1; + } + + IMPLEMENT_SERIALIZE + ( + CWalletTx* pthis = const_cast(this); + if (fRead) + pthis->Init(NULL); + char fSpent = false; + + if (!fRead) + { + pthis->mapValue["fromaccount"] = pthis->strFromAccount; + + std::string str; + BOOST_FOREACH(char f, vfSpent) + { + str += (f ? '1' : '0'); + if (f) + fSpent = true; + } + pthis->mapValue["spent"] = str; + + WriteOrderPos(pthis->nOrderPos, pthis->mapValue); + + if (nTimeSmart) + pthis->mapValue["timesmart"] = strprintf("%u", nTimeSmart); + } + + nSerSize += SerReadWrite(s, *(CMerkleTx*)this, nType, nVersion,ser_action); + READWRITE(vtxPrev); + READWRITE(mapValue); + READWRITE(vOrderForm); + READWRITE(fTimeReceivedIsTxTime); + READWRITE(nTimeReceived); + READWRITE(fFromMe); + READWRITE(fSpent); + + if (fRead) + { + pthis->strFromAccount = pthis->mapValue["fromaccount"]; + + if (mapValue.count("spent")) + BOOST_FOREACH(char c, pthis->mapValue["spent"]) + pthis->vfSpent.push_back(c != '0'); + else + pthis->vfSpent.assign(vout.size(), fSpent); + + ReadOrderPos(pthis->nOrderPos, pthis->mapValue); + + pthis->nTimeSmart = mapValue.count("timesmart") ? (unsigned int)atoi64(pthis->mapValue["timesmart"]) : 0; + } + + pthis->mapValue.erase("fromaccount"); + pthis->mapValue.erase("version"); + pthis->mapValue.erase("spent"); + pthis->mapValue.erase("n"); + pthis->mapValue.erase("timesmart"); + ) + + // marks certain txout's as spent + // returns true if any update took place + bool UpdateSpent(const std::vector& vfNewSpent) + { + bool fReturn = false; + for (unsigned int i = 0; i < vfNewSpent.size(); i++) + { + if (i == vfSpent.size()) + break; + + if (vfNewSpent[i] && !vfSpent[i]) + { + vfSpent[i] = true; + fReturn = true; + fAvailableCreditCached = false; + } + } + return fReturn; + } + + // make sure balances are recalculated + void MarkDirty() + { + fCreditCached = false; + fAvailableCreditCached = false; + fDebitCached = false; + fChangeCached = false; + } + + void BindWallet(CWallet *pwalletIn) + { + pwallet = pwalletIn; + MarkDirty(); + } + + void MarkSpent(unsigned int nOut) + { + if (nOut >= vout.size()) + throw std::runtime_error("CWalletTx::MarkSpent() : nOut out of range"); + vfSpent.resize(vout.size()); + if (!vfSpent[nOut]) + { + vfSpent[nOut] = true; + fAvailableCreditCached = false; + } + } + + void MarkUnspent(unsigned int nOut) + { + if (nOut >= vout.size()) + throw std::runtime_error("CWalletTx::MarkUnspent() : nOut out of range"); + vfSpent.resize(vout.size()); + if (vfSpent[nOut]) + { + vfSpent[nOut] = false; + fAvailableCreditCached = false; + } + } + + bool IsSpent(unsigned int nOut) const + { + if (nOut >= vout.size()) + throw std::runtime_error("CWalletTx::IsSpent() : nOut out of range"); + if (nOut >= vfSpent.size()) + return false; + return (!!vfSpent[nOut]); + } + + int64_t GetDebit() const + { + if (vin.empty()) + return 0; + if (fDebitCached) + return nDebitCached; + nDebitCached = pwallet->GetDebit(*this); + fDebitCached = true; + return nDebitCached; + } + + int64_t GetCredit(bool fUseCache=true) const + { + // Must wait until coinbase is safely deep enough in the chain before valuing it + if ((IsCoinBase() || IsCoinStake()) && GetBlocksToMaturity() > 0) + return 0; + + // GetBalance can assume transactions in mapWallet won't change + if (fUseCache && fCreditCached) + return nCreditCached; + nCreditCached = pwallet->GetCredit(*this); + fCreditCached = true; + return nCreditCached; + } + + int64_t GetAvailableCredit(bool fUseCache=true) const + { + // Must wait until coinbase is safely deep enough in the chain before valuing it + if ((IsCoinBase() || IsCoinStake()) && GetBlocksToMaturity() > 0) + return 0; + + if (fUseCache && fAvailableCreditCached) + return nAvailableCreditCached; + + int64_t nCredit = 0; + for (unsigned int i = 0; i < vout.size(); i++) + { + if (!IsSpent(i)) + { + const CTxOut &txout = vout[i]; + nCredit += pwallet->GetCredit(txout); + if (!MoneyRange(nCredit)) + throw std::runtime_error("CWalletTx::GetAvailableCredit() : value out of range"); + } + } + + nAvailableCreditCached = nCredit; + fAvailableCreditCached = true; + return nCredit; + } + + + int64_t GetChange() const + { + if (fChangeCached) + return nChangeCached; + nChangeCached = pwallet->GetChange(*this); + fChangeCached = true; + return nChangeCached; + } + + void GetAmounts(std::list >& listReceived, + std::list >& listSent, int64_t& nFee, std::string& strSentAccount) const; + + void GetAccountAmounts(const std::string& strAccount, int64_t& nReceived, + int64_t& nSent, int64_t& nFee) const; + + bool IsFromMe() const + { + return (GetDebit() > 0); + } + + bool IsTrusted() const + { + // Quick answer in most cases + if (!IsFinalTx(*this)) + return false; + int nDepth = GetDepthInMainChain(); + if (nDepth >= 1) + return true; + if (nDepth < 0) + return false; + if (fConfChange || !IsFromMe()) // using wtx's cached debit + return false; + + // If no confirmations but it's from us, we can still + // consider it confirmed if all dependencies are confirmed + std::map mapPrev; + std::vector vWorkQueue; + vWorkQueue.reserve(vtxPrev.size()+1); + vWorkQueue.push_back(this); + for (unsigned int i = 0; i < vWorkQueue.size(); i++) + { + const CMerkleTx* ptx = vWorkQueue[i]; + + if (!IsFinalTx(*ptx)) + return false; + int nPDepth = ptx->GetDepthInMainChain(); + if (nPDepth >= 1) + continue; + if (nPDepth < 0) + return false; + if (!pwallet->IsFromMe(*ptx)) + return false; + + if (mapPrev.empty()) + { + BOOST_FOREACH(const CMerkleTx& tx, vtxPrev) + mapPrev[tx.GetHash()] = &tx; + } + + BOOST_FOREACH(const CTxIn& txin, ptx->vin) + { + if (!mapPrev.count(txin.prevout.hash)) + return false; + vWorkQueue.push_back(mapPrev[txin.prevout.hash]); + } + } + + return true; + } + + bool WriteToDisk(); + + int64_t GetTxTime() const; + int GetRequestCount() const; + + void AddSupportingTransactions(CTxDB& txdb); + + bool AcceptWalletTransaction(CTxDB& txdb); + bool AcceptWalletTransaction(); + + void RelayWalletTransaction(CTxDB& txdb); + void RelayWalletTransaction(); +}; + + + + +class COutput +{ +public: + const CWalletTx *tx; + int i; + int nDepth; + + COutput(const CWalletTx *txIn, int iIn, int nDepthIn) + { + tx = txIn; i = iIn; nDepth = nDepthIn; + } + + std::string ToString() const + { + return strprintf("COutput(%s, %d, %d) [%s]", tx->GetHash().ToString().substr(0,10).c_str(), i, nDepth, FormatMoney(tx->vout[i].nValue).c_str()); + } + + void print() const + { + printf("%s\n", ToString().c_str()); + } +}; + + + + +/** Private key that includes an expiration date in case it never gets used. */ +class CWalletKey +{ +public: + CPrivKey vchPrivKey; + int64_t nTimeCreated; + int64_t nTimeExpires; + std::string strComment; + //// todo: add something to note what created it (user, getnewaddress, change) + //// maybe should have a map property map + + CWalletKey(int64_t nExpires=0) + { + nTimeCreated = (nExpires ? GetTime() : 0); + nTimeExpires = nExpires; + } + + IMPLEMENT_SERIALIZE + ( + if (!(nType & SER_GETHASH)) + READWRITE(nVersion); + READWRITE(vchPrivKey); + READWRITE(nTimeCreated); + READWRITE(nTimeExpires); + READWRITE(strComment); + ) +}; + + + + + + +/** Account information. + * Stored in wallet with key "acc"+string account name. + */ +class CAccount +{ +public: + CPubKey vchPubKey; + + CAccount() + { + SetNull(); + } + + void SetNull() + { + vchPubKey = CPubKey(); + } + + IMPLEMENT_SERIALIZE + ( + if (!(nType & SER_GETHASH)) + READWRITE(nVersion); + READWRITE(vchPubKey); + ) +}; + + + +/** Internal transfers. + * Database key is acentry. + */ +class CAccountingEntry +{ +public: + std::string strAccount; + int64_t nCreditDebit; + int64_t nTime; + std::string strOtherAccount; + std::string strComment; + mapValue_t mapValue; + int64_t nOrderPos; // position in ordered transaction list + uint64_t nEntryNo; + + CAccountingEntry() + { + SetNull(); + } + + void SetNull() + { + nCreditDebit = 0; + nTime = 0; + strAccount.clear(); + strOtherAccount.clear(); + strComment.clear(); + nOrderPos = -1; + } + + IMPLEMENT_SERIALIZE + ( + CAccountingEntry& me = *const_cast(this); + if (!(nType & SER_GETHASH)) + READWRITE(nVersion); + // Note: strAccount is serialized as part of the key, not here. + READWRITE(nCreditDebit); + READWRITE(nTime); + READWRITE(strOtherAccount); + + if (!fRead) + { + WriteOrderPos(nOrderPos, me.mapValue); + + if (!(mapValue.empty() && _ssExtra.empty())) + { + CDataStream ss(nType, nVersion); + ss.insert(ss.begin(), '\0'); + ss << mapValue; + ss.insert(ss.end(), _ssExtra.begin(), _ssExtra.end()); + me.strComment.append(ss.str()); + } + } + + READWRITE(strComment); + + size_t nSepPos = strComment.find("\0", 0, 1); + if (fRead) + { + me.mapValue.clear(); + if (std::string::npos != nSepPos) + { + CDataStream ss(std::vector(strComment.begin() + nSepPos + 1, strComment.end()), nType, nVersion); + ss >> me.mapValue; + me._ssExtra = std::vector(ss.begin(), ss.end()); + } + ReadOrderPos(me.nOrderPos, me.mapValue); + } + if (std::string::npos != nSepPos) + me.strComment.erase(nSepPos); + + me.mapValue.erase("n"); + ) + +private: + std::vector _ssExtra; +}; + +bool GetWalletFile(CWallet* pwallet, std::string &strWalletFileOut); + +#endif diff --git a/src/walletdb.cpp b/src/walletdb.cpp new file mode 100644 index 0000000..adbee9e --- /dev/null +++ b/src/walletdb.cpp @@ -0,0 +1,719 @@ +// Copyright (c) 2009-2010 Satoshi Nakamoto +// Copyright (c) 2009-2012 The Bitcoin developers +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include "walletdb.h" +#include "wallet.h" +#include +#include + +using namespace std; +using namespace boost; + + +static uint64_t nAccountingEntryNumber = 0; +extern bool fWalletUnlockStakingOnly; + +// +// CWalletDB +// + +bool CWalletDB::WriteName(const string& strAddress, const string& strName) +{ + nWalletDBUpdated++; + return Write(make_pair(string("name"), strAddress), strName); +} + +bool CWalletDB::EraseName(const string& strAddress) +{ + // This should only be used for sending addresses, never for receiving addresses, + // receiving addresses must always have an address book entry if they're not change return. + nWalletDBUpdated++; + return Erase(make_pair(string("name"), strAddress)); +} + +bool CWalletDB::ReadAccount(const string& strAccount, CAccount& account) +{ + account.SetNull(); + return Read(make_pair(string("acc"), strAccount), account); +} + +bool CWalletDB::WriteAccount(const string& strAccount, const CAccount& account) +{ + return Write(make_pair(string("acc"), strAccount), account); +} + +bool CWalletDB::WriteAccountingEntry(const uint64_t nAccEntryNum, const CAccountingEntry& acentry) +{ + return Write(boost::make_tuple(string("acentry"), acentry.strAccount, nAccEntryNum), acentry); +} + +bool CWalletDB::WriteAccountingEntry(const CAccountingEntry& acentry) +{ + return WriteAccountingEntry(++nAccountingEntryNumber, acentry); +} + +int64_t CWalletDB::GetAccountCreditDebit(const string& strAccount) +{ + list entries; + ListAccountCreditDebit(strAccount, entries); + + int64_t nCreditDebit = 0; + BOOST_FOREACH (const CAccountingEntry& entry, entries) + nCreditDebit += entry.nCreditDebit; + + return nCreditDebit; +} + +void CWalletDB::ListAccountCreditDebit(const string& strAccount, list& entries) +{ + bool fAllAccounts = (strAccount == "*"); + + Dbc* pcursor = GetCursor(); + if (!pcursor) + throw runtime_error("CWalletDB::ListAccountCreditDebit() : cannot create DB cursor"); + unsigned int fFlags = DB_SET_RANGE; + while (true) + { + // Read next record + CDataStream ssKey(SER_DISK, CLIENT_VERSION); + if (fFlags == DB_SET_RANGE) + ssKey << boost::make_tuple(string("acentry"), (fAllAccounts? string("") : strAccount), uint64_t(0)); + CDataStream ssValue(SER_DISK, CLIENT_VERSION); + int ret = ReadAtCursor(pcursor, ssKey, ssValue, fFlags); + fFlags = DB_NEXT; + if (ret == DB_NOTFOUND) + break; + else if (ret != 0) + { + pcursor->close(); + throw runtime_error("CWalletDB::ListAccountCreditDebit() : error scanning DB"); + } + + // Unserialize + string strType; + ssKey >> strType; + if (strType != "acentry") + break; + CAccountingEntry acentry; + ssKey >> acentry.strAccount; + if (!fAllAccounts && acentry.strAccount != strAccount) + break; + + ssValue >> acentry; + ssKey >> acentry.nEntryNo; + entries.push_back(acentry); + } + + pcursor->close(); +} + + +DBErrors +CWalletDB::ReorderTransactions(CWallet* pwallet) +{ + LOCK(pwallet->cs_wallet); + // Old wallets didn't have any defined order for transactions + // Probably a bad idea to change the output of this + + // First: get all CWalletTx and CAccountingEntry into a sorted-by-time multimap. + typedef pair TxPair; + typedef multimap TxItems; + TxItems txByTime; + + for (map::iterator it = pwallet->mapWallet.begin(); it != pwallet->mapWallet.end(); ++it) + { + CWalletTx* wtx = &((*it).second); + txByTime.insert(make_pair(wtx->nTimeReceived, TxPair(wtx, (CAccountingEntry*)0))); + } + list acentries; + ListAccountCreditDebit("", acentries); + BOOST_FOREACH(CAccountingEntry& entry, acentries) + { + txByTime.insert(make_pair(entry.nTime, TxPair((CWalletTx*)0, &entry))); + } + + int64_t& nOrderPosNext = pwallet->nOrderPosNext; + nOrderPosNext = 0; + std::vector nOrderPosOffsets; + for (TxItems::iterator it = txByTime.begin(); it != txByTime.end(); ++it) + { + CWalletTx *const pwtx = (*it).second.first; + CAccountingEntry *const pacentry = (*it).second.second; + int64_t& nOrderPos = (pwtx != 0) ? pwtx->nOrderPos : pacentry->nOrderPos; + + if (nOrderPos == -1) + { + nOrderPos = nOrderPosNext++; + nOrderPosOffsets.push_back(nOrderPos); + + if (pacentry) + // Have to write accounting regardless, since we don't keep it in memory + if (!WriteAccountingEntry(pacentry->nEntryNo, *pacentry)) + return DB_LOAD_FAIL; + } + else + { + int64_t nOrderPosOff = 0; + BOOST_FOREACH(const int64_t& nOffsetStart, nOrderPosOffsets) + { + if (nOrderPos >= nOffsetStart) + ++nOrderPosOff; + } + nOrderPos += nOrderPosOff; + nOrderPosNext = std::max(nOrderPosNext, nOrderPos + 1); + + if (!nOrderPosOff) + continue; + + // Since we're changing the order, write it back + if (pwtx) + { + if (!WriteTx(pwtx->GetHash(), *pwtx)) + return DB_LOAD_FAIL; + } + else + if (!WriteAccountingEntry(pacentry->nEntryNo, *pacentry)) + return DB_LOAD_FAIL; + } + } + + return DB_LOAD_OK; +} + +class CWalletScanState { +public: + unsigned int nKeys; + unsigned int nCKeys; + unsigned int nKeyMeta; + bool fIsEncrypted; + bool fAnyUnordered; + int nFileVersion; + vector vWalletUpgrade; + + CWalletScanState() { + nKeys = nCKeys = nKeyMeta = 0; + fIsEncrypted = false; + fAnyUnordered = false; + nFileVersion = 0; + } +}; + +bool +ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue, + CWalletScanState &wss, string& strType, string& strErr) +{ + try { + // Unserialize + // Taking advantage of the fact that pair serialization + // is just the two items serialized one after the other + ssKey >> strType; + if (strType == "name") + { + string strAddress; + ssKey >> strAddress; + ssValue >> pwallet->mapAddressBook[CBitcoinAddress(strAddress).Get()]; + } + else if (strType == "tx") + { + uint256 hash; + ssKey >> hash; + CWalletTx& wtx = pwallet->mapWallet[hash]; + ssValue >> wtx; + if (wtx.CheckTransaction() && (wtx.GetHash() == hash)) + wtx.BindWallet(pwallet); + else + { + pwallet->mapWallet.erase(hash); + return false; + } + + // Undo serialize changes in 31600 + if (31404 <= wtx.fTimeReceivedIsTxTime && wtx.fTimeReceivedIsTxTime <= 31703) + { + if (!ssValue.empty()) + { + char fTmp; + char fUnused; + ssValue >> fTmp >> fUnused >> wtx.strFromAccount; + strErr = strprintf("LoadWallet() upgrading tx ver=%d %d '%s' %s", + wtx.fTimeReceivedIsTxTime, fTmp, wtx.strFromAccount.c_str(), hash.ToString().c_str()); + wtx.fTimeReceivedIsTxTime = fTmp; + } + else + { + strErr = strprintf("LoadWallet() repairing tx ver=%d %s", wtx.fTimeReceivedIsTxTime, hash.ToString().c_str()); + wtx.fTimeReceivedIsTxTime = 0; + } + wss.vWalletUpgrade.push_back(hash); + } + + if (wtx.nOrderPos == -1) + wss.fAnyUnordered = true; + + //// debug print + //printf("LoadWallet %s\n", wtx.GetHash().ToString().c_str()); + //printf(" %12" PRId64" %s %s %s\n", + // wtx.vout[0].nValue, + // DateTimeStrFormat("%x %H:%M:%S", wtx.GetBlockTime()).c_str(), + // wtx.hashBlock.ToString().substr(0,20).c_str(), + // wtx.mapValue["message"].c_str()); + } + else if (strType == "acentry") + { + string strAccount; + ssKey >> strAccount; + uint64_t nNumber; + ssKey >> nNumber; + if (nNumber > nAccountingEntryNumber) + nAccountingEntryNumber = nNumber; + + if (!wss.fAnyUnordered) + { + CAccountingEntry acentry; + ssValue >> acentry; + if (acentry.nOrderPos == -1) + wss.fAnyUnordered = true; + } + } + else if (strType == "key" || strType == "wkey") + { + vector vchPubKey; + ssKey >> vchPubKey; + CKey key; + if (strType == "key") + { + wss.nKeys++; + CPrivKey pkey; + ssValue >> pkey; + key.SetPubKey(vchPubKey); + if (!key.SetPrivKey(pkey)) + { + strErr = "Error reading wallet database: CPrivKey corrupt"; + return false; + } + if (key.GetPubKey() != vchPubKey) + { + strErr = "Error reading wallet database: CPrivKey pubkey inconsistency"; + return false; + } + if (!key.IsValid()) + { + strErr = "Error reading wallet database: invalid CPrivKey"; + return false; + } + } + else + { + CWalletKey wkey; + ssValue >> wkey; + key.SetPubKey(vchPubKey); + if (!key.SetPrivKey(wkey.vchPrivKey)) + { + strErr = "Error reading wallet database: CPrivKey corrupt"; + return false; + } + if (key.GetPubKey() != vchPubKey) + { + strErr = "Error reading wallet database: CWalletKey pubkey inconsistency"; + return false; + } + if (!key.IsValid()) + { + strErr = "Error reading wallet database: invalid CWalletKey"; + return false; + } + } + if (!pwallet->LoadKey(key)) + { + strErr = "Error reading wallet database: LoadKey failed"; + return false; + } + } + else if (strType == "mkey") + { + unsigned int nID; + ssKey >> nID; + CMasterKey kMasterKey; + ssValue >> kMasterKey; + if(pwallet->mapMasterKeys.count(nID) != 0) + { + strErr = strprintf("Error reading wallet database: duplicate CMasterKey id %u", nID); + return false; + } + pwallet->mapMasterKeys[nID] = kMasterKey; + if (pwallet->nMasterKeyMaxID < nID) + pwallet->nMasterKeyMaxID = nID; + } + else if (strType == "ckey") + { + wss.nCKeys++; + vector vchPubKey; + ssKey >> vchPubKey; + vector vchPrivKey; + ssValue >> vchPrivKey; + if (!pwallet->LoadCryptedKey(vchPubKey, vchPrivKey)) + { + strErr = "Error reading wallet database: LoadCryptedKey failed"; + return false; + } + wss.fIsEncrypted = true; + } + else if (strType == "keymeta") + { + CPubKey vchPubKey; + ssKey >> vchPubKey; + CKeyMetadata keyMeta; + ssValue >> keyMeta; + wss.nKeyMeta++; + + pwallet->LoadKeyMetadata(vchPubKey, keyMeta); + + // find earliest key creation time, as wallet birthday + if (!pwallet->nTimeFirstKey || + (keyMeta.nCreateTime < pwallet->nTimeFirstKey)) + pwallet->nTimeFirstKey = keyMeta.nCreateTime; + } + else if (strType == "defaultkey") + { + ssValue >> pwallet->vchDefaultKey; + } + else if (strType == "pool") + { + int64_t nIndex; + ssKey >> nIndex; + CKeyPool keypool; + ssValue >> keypool; + pwallet->setKeyPool.insert(nIndex); + + // If no metadata exists yet, create a default with the pool key's + // creation time. Note that this may be overwritten by actually + // stored metadata for that key later, which is fine. + CKeyID keyid = keypool.vchPubKey.GetID(); + if (pwallet->mapKeyMetadata.count(keyid) == 0) + pwallet->mapKeyMetadata[keyid] = CKeyMetadata(keypool.nTime); + + } + else if (strType == "version") + { + ssValue >> wss.nFileVersion; + if (wss.nFileVersion == 10300) + wss.nFileVersion = 300; + } + else if (strType == "cscript") + { + uint160 hash; + ssKey >> hash; + CScript script; + ssValue >> script; + if (!pwallet->LoadCScript(script)) + { + strErr = "Error reading wallet database: LoadCScript failed"; + return false; + } + } + else if (strType == "orderposnext") + { + ssValue >> pwallet->nOrderPosNext; + } + } catch (...) + { + return false; + } + return true; +} + +static bool IsKeyType(string strType) +{ + return (strType== "key" || strType == "wkey" || + strType == "mkey" || strType == "ckey"); +} + +DBErrors CWalletDB::LoadWallet(CWallet* pwallet) +{ + pwallet->vchDefaultKey = CPubKey(); + CWalletScanState wss; + bool fNoncriticalErrors = false; + DBErrors result = DB_LOAD_OK; + + try { + LOCK(pwallet->cs_wallet); + int nMinVersion = 0; + if (Read((string)"minversion", nMinVersion)) + { + if (nMinVersion > CLIENT_VERSION) + return DB_TOO_NEW; + pwallet->LoadMinVersion(nMinVersion); + } + + // Get cursor + Dbc* pcursor = GetCursor(); + if (!pcursor) + { + printf("Error getting wallet database cursor\n"); + return DB_CORRUPT; + } + + while (true) + { + // Read next record + CDataStream ssKey(SER_DISK, CLIENT_VERSION); + CDataStream ssValue(SER_DISK, CLIENT_VERSION); + int ret = ReadAtCursor(pcursor, ssKey, ssValue); + if (ret == DB_NOTFOUND) + break; + else if (ret != 0) + { + printf("Error reading next record from wallet database\n"); + return DB_CORRUPT; + } + + // Try to be tolerant of single corrupt records: + string strType, strErr; + if (!ReadKeyValue(pwallet, ssKey, ssValue, wss, strType, strErr)) + { + // losing keys is considered a catastrophic error, anything else + // we assume the user can live with: + if (IsKeyType(strType)) + result = DB_CORRUPT; + else + { + // Leave other errors alone, if we try to fix them we might make things worse. + fNoncriticalErrors = true; // ... but do warn the user there is something wrong. + if (strType == "tx") + // Rescan if there is a bad transaction record: + SoftSetBoolArg("-rescan", true); + } + } + if (!strErr.empty()) + printf("%s\n", strErr.c_str()); + } + pcursor->close(); + } + catch (...) + { + result = DB_CORRUPT; + } + + if (fNoncriticalErrors && result == DB_LOAD_OK) + result = DB_NONCRITICAL_ERROR; + + // Any wallet corruption at all: skip any rewriting or + // upgrading, we don't want to make it worse. + if (result != DB_LOAD_OK) + return result; + + printf("nFileVersion = %d\n", wss.nFileVersion); + + printf("Keys: %u plaintext, %u encrypted, %u w/ metadata, %u total\n", + wss.nKeys, wss.nCKeys, wss.nKeyMeta, wss.nKeys + wss.nCKeys); + + // nTimeFirstKey is only reliable if all keys have metadata + if ((wss.nKeys + wss.nCKeys) != wss.nKeyMeta) + pwallet->nTimeFirstKey = 1; // 0 would be considered 'no value' + + + BOOST_FOREACH(uint256 hash, wss.vWalletUpgrade) + WriteTx(hash, pwallet->mapWallet[hash]); + + // Rewrite encrypted wallets of versions 0.4.0 and 0.5.0rc: + if (wss.fIsEncrypted && (wss.nFileVersion == 40000 || wss.nFileVersion == 50000)) + return DB_NEED_REWRITE; + + if (wss.nFileVersion < CLIENT_VERSION) // Update + WriteVersion(CLIENT_VERSION); + + if (wss.fAnyUnordered) + result = ReorderTransactions(pwallet); + + return result; +} + +void ThreadFlushWalletDB(void* parg) +{ + // Make this thread recognisable as the wallet flushing thread + RenameThread("arepacoin-wallet"); + + const string& strFile = ((const string*)parg)[0]; + static bool fOneThread; + if (fOneThread) + return; + fOneThread = true; + if (!GetBoolArg("-flushwallet", true)) + return; + + unsigned int nLastSeen = nWalletDBUpdated; + unsigned int nLastFlushed = nWalletDBUpdated; + int64_t nLastWalletUpdate = GetTime(); + while (!fShutdown) + { + MilliSleep(500); + + if (nLastSeen != nWalletDBUpdated) + { + nLastSeen = nWalletDBUpdated; + nLastWalletUpdate = GetTime(); + } + + if (nLastFlushed != nWalletDBUpdated && GetTime() - nLastWalletUpdate >= 2) + { + TRY_LOCK(bitdb.cs_db,lockDb); + if (lockDb) + { + // Don't do this if any databases are in use + int nRefCount = 0; + map::iterator mi = bitdb.mapFileUseCount.begin(); + while (mi != bitdb.mapFileUseCount.end()) + { + nRefCount += (*mi).second; + mi++; + } + + if (nRefCount == 0 && !fShutdown) + { + map::iterator mi = bitdb.mapFileUseCount.find(strFile); + if (mi != bitdb.mapFileUseCount.end()) + { + printf("Flushing wallet.dat\n"); + nLastFlushed = nWalletDBUpdated; + int64_t nStart = GetTimeMillis(); + + // Flush wallet.dat so it's self contained + bitdb.CloseDb(strFile); + bitdb.CheckpointLSN(strFile); + + bitdb.mapFileUseCount.erase(mi++); + printf("Flushed wallet.dat %" PRId64"ms\n", GetTimeMillis() - nStart); + } + } + } + } + } +} + +bool BackupWallet(const CWallet& wallet, const string& strDest) +{ + if (!wallet.fFileBacked) + return false; + while (!fShutdown) + { + { + LOCK(bitdb.cs_db); + if (!bitdb.mapFileUseCount.count(wallet.strWalletFile) || bitdb.mapFileUseCount[wallet.strWalletFile] == 0) + { + // Flush log data to the dat file + bitdb.CloseDb(wallet.strWalletFile); + bitdb.CheckpointLSN(wallet.strWalletFile); + bitdb.mapFileUseCount.erase(wallet.strWalletFile); + + // Copy wallet.dat + filesystem::path pathSrc = GetDataDir() / wallet.strWalletFile; + filesystem::path pathDest(strDest); + if (filesystem::is_directory(pathDest)) + pathDest /= wallet.strWalletFile; + + try { +#if BOOST_VERSION >= 104000 + filesystem::copy_file(pathSrc, pathDest, filesystem::copy_option::overwrite_if_exists); +#else + filesystem::copy_file(pathSrc, pathDest); +#endif + printf("copied wallet.dat to %s\n", pathDest.string().c_str()); + return true; + } catch(const filesystem::filesystem_error &e) { + printf("error copying wallet.dat to %s - %s\n", pathDest.string().c_str(), e.what()); + return false; + } + } + } + MilliSleep(100); + } + return false; +} + +// +// Try to (very carefully!) recover wallet.dat if there is a problem. +// +bool CWalletDB::Recover(CDBEnv& dbenv, std::string filename, bool fOnlyKeys) +{ + // Recovery procedure: + // move wallet.dat to wallet.timestamp.bak + // Call Salvage with fAggressive=true to + // get as much data as possible. + // Rewrite salvaged data to wallet.dat + // Set -rescan so any missing transactions will be + // found. + int64_t now = GetTime(); + std::string newFilename = strprintf("wallet.%" PRId64".bak", now); + + int result = dbenv.dbenv.dbrename(NULL, filename.c_str(), NULL, + newFilename.c_str(), DB_AUTO_COMMIT); + if (result == 0) + printf("Renamed %s to %s\n", filename.c_str(), newFilename.c_str()); + else + { + printf("Failed to rename %s to %s\n", filename.c_str(), newFilename.c_str()); + return false; + } + + std::vector salvagedData; + bool allOK = dbenv.Salvage(newFilename, true, salvagedData); + if (salvagedData.empty()) + { + printf("Salvage(aggressive) found no records in %s.\n", newFilename.c_str()); + return false; + } + printf("Salvage(aggressive) found %" PRIszu" records\n", salvagedData.size()); + + bool fSuccess = allOK; + Db* pdbCopy = new Db(&dbenv.dbenv, 0); + int ret = pdbCopy->open(NULL, // Txn pointer + filename.c_str(), // Filename + "main", // Logical db name + DB_BTREE, // Database type + DB_CREATE, // Flags + 0); + if (ret > 0) + { + printf("Cannot create database file %s\n", filename.c_str()); + return false; + } + CWallet dummyWallet; + CWalletScanState wss; + + DbTxn* ptxn = dbenv.TxnBegin(); + BOOST_FOREACH(CDBEnv::KeyValPair& row, salvagedData) + { + if (fOnlyKeys) + { + CDataStream ssKey(row.first, SER_DISK, CLIENT_VERSION); + CDataStream ssValue(row.second, SER_DISK, CLIENT_VERSION); + string strType, strErr; + bool fReadOK = ReadKeyValue(&dummyWallet, ssKey, ssValue, + wss, strType, strErr); + if (!IsKeyType(strType)) + continue; + if (!fReadOK) + { + printf("WARNING: CWalletDB::Recover skipping %s: %s\n", strType.c_str(), strErr.c_str()); + continue; + } + } + Dbt datKey(&row.first[0], row.first.size()); + Dbt datValue(&row.second[0], row.second.size()); + int ret2 = pdbCopy->put(ptxn, &datKey, &datValue, DB_NOOVERWRITE); + if (ret2 > 0) + fSuccess = false; + } + ptxn->commit(0); + pdbCopy->close(0); + delete pdbCopy; + + return fSuccess; +} + +bool CWalletDB::Recover(CDBEnv& dbenv, std::string filename) +{ + return CWalletDB::Recover(dbenv, filename, false); +} diff --git a/src/walletdb.h b/src/walletdb.h new file mode 100644 index 0000000..9b54b35 --- /dev/null +++ b/src/walletdb.h @@ -0,0 +1,185 @@ +// Copyright (c) 2009-2010 Satoshi Nakamoto +// Copyright (c) 2009-2012 The Bitcoin developers +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. +#ifndef BITCOIN_WALLETDB_H +#define BITCOIN_WALLETDB_H + +#include "db.h" +#include "base58.h" + +class CKeyPool; +class CAccount; +class CAccountingEntry; + +/** Error statuses for the wallet database */ +enum DBErrors +{ + DB_LOAD_OK, + DB_CORRUPT, + DB_NONCRITICAL_ERROR, + DB_TOO_NEW, + DB_LOAD_FAIL, + DB_NEED_REWRITE +}; + +class CKeyMetadata +{ +public: + static const int CURRENT_VERSION=1; + int nVersion; + int64_t nCreateTime; // 0 means unknown + + CKeyMetadata() + { + SetNull(); + } + CKeyMetadata(int64_t nCreateTime_) + { + nVersion = CKeyMetadata::CURRENT_VERSION; + nCreateTime = nCreateTime_; + } + + IMPLEMENT_SERIALIZE + ( + READWRITE(this->nVersion); + nVersion = this->nVersion; + READWRITE(nCreateTime); + ) + + void SetNull() + { + nVersion = CKeyMetadata::CURRENT_VERSION; + nCreateTime = 0; + } +}; + + +/** Access to the wallet database (wallet.dat) */ +class CWalletDB : public CDB +{ +public: + CWalletDB(std::string strFilename, const char* pszMode="r+") : CDB(strFilename.c_str(), pszMode) + { + } +private: + CWalletDB(const CWalletDB&); + void operator=(const CWalletDB&); +public: + bool WriteName(const std::string& strAddress, const std::string& strName); + + bool EraseName(const std::string& strAddress); + + bool WriteTx(uint256 hash, const CWalletTx& wtx) + { + nWalletDBUpdated++; + return Write(std::make_pair(std::string("tx"), hash), wtx); + } + + bool EraseTx(uint256 hash) + { + nWalletDBUpdated++; + return Erase(std::make_pair(std::string("tx"), hash)); + } + + bool WriteKey(const CPubKey& vchPubKey, const CPrivKey& vchPrivKey, const CKeyMetadata &keyMeta) + { + nWalletDBUpdated++; + + if(!Write(std::make_pair(std::string("keymeta"), vchPubKey), keyMeta)) + return false; + + return Write(std::make_pair(std::string("key"), vchPubKey.Raw()), vchPrivKey, false); + } + + bool WriteCryptedKey(const CPubKey& vchPubKey, const std::vector& vchCryptedSecret, const CKeyMetadata &keyMeta) + { + nWalletDBUpdated++; + bool fEraseUnencryptedKey = true; + + if(!Write(std::make_pair(std::string("keymeta"), vchPubKey), keyMeta)) + return false; + + if (!Write(std::make_pair(std::string("ckey"), vchPubKey.Raw()), vchCryptedSecret, false)) + return false; + if (fEraseUnencryptedKey) + { + Erase(std::make_pair(std::string("key"), vchPubKey.Raw())); + Erase(std::make_pair(std::string("wkey"), vchPubKey.Raw())); + } + return true; + } + + bool WriteMasterKey(unsigned int nID, const CMasterKey& kMasterKey) + { + nWalletDBUpdated++; + return Write(std::make_pair(std::string("mkey"), nID), kMasterKey, true); + } + + bool WriteCScript(const uint160& hash, const CScript& redeemScript) + { + nWalletDBUpdated++; + return Write(std::make_pair(std::string("cscript"), hash), redeemScript, false); + } + + bool WriteBestBlock(const CBlockLocator& locator) + { + nWalletDBUpdated++; + return Write(std::string("bestblock"), locator); + } + + bool ReadBestBlock(CBlockLocator& locator) + { + return Read(std::string("bestblock"), locator); + } + + bool WriteOrderPosNext(int64_t nOrderPosNext) + { + nWalletDBUpdated++; + return Write(std::string("orderposnext"), nOrderPosNext); + } + + bool WriteDefaultKey(const CPubKey& vchPubKey) + { + nWalletDBUpdated++; + return Write(std::string("defaultkey"), vchPubKey.Raw()); + } + + bool ReadPool(int64_t nPool, CKeyPool& keypool) + { + return Read(std::make_pair(std::string("pool"), nPool), keypool); + } + + bool WritePool(int64_t nPool, const CKeyPool& keypool) + { + nWalletDBUpdated++; + return Write(std::make_pair(std::string("pool"), nPool), keypool); + } + + bool ErasePool(int64_t nPool) + { + nWalletDBUpdated++; + return Erase(std::make_pair(std::string("pool"), nPool)); + } + + bool WriteMinVersion(int nVersion) + { + return Write(std::string("minversion"), nVersion); + } + + bool ReadAccount(const std::string& strAccount, CAccount& account); + bool WriteAccount(const std::string& strAccount, const CAccount& account); +private: + bool WriteAccountingEntry(const uint64_t nAccEntryNum, const CAccountingEntry& acentry); +public: + bool WriteAccountingEntry(const CAccountingEntry& acentry); + int64_t GetAccountCreditDebit(const std::string& strAccount); + void ListAccountCreditDebit(const std::string& strAccount, std::list& acentries); + + DBErrors ReorderTransactions(CWallet*); + DBErrors LoadWallet(CWallet* pwallet); + static bool Recover(CDBEnv& dbenv, std::string filename, bool fOnlyKeys); + static bool Recover(CDBEnv& dbenv, std::string filename); +}; + +#endif // BITCOIN_WALLETDB_H diff --git a/src/zerocoin/Accumulator.cpp b/src/zerocoin/Accumulator.cpp new file mode 100644 index 0000000..e05f8ac --- /dev/null +++ b/src/zerocoin/Accumulator.cpp @@ -0,0 +1,106 @@ +/** + * @file Accumulator.cpp + * + * @brief Accumulator and AccumulatorWitness classes for the Zerocoin library. + * + * @author Ian Miers, Christina Garman and Matthew Green + * @date June 2013 + * + * @copyright Copyright 2013 Ian Miers, Christina Garman and Matthew Green + * @license This project is released under the MIT license. + **/ + +#include +#include "Zerocoin.h" + +namespace libzerocoin { + +//Accumulator class +Accumulator::Accumulator(const AccumulatorAndProofParams* p, const CoinDenomination d): params(p), denomination(d) { + if (!(params->initialized)) { + throw ZerocoinException("Invalid parameters for accumulator"); + } + + this->value = this->params->accumulatorBase; +} + +Accumulator::Accumulator(const Params* p, const CoinDenomination d) { + this->params = &(p->accumulatorParams); + this->denomination = d; + + if (!(params->initialized)) { + throw ZerocoinException("Invalid parameters for accumulator"); + } + + this->value = this->params->accumulatorBase; +} + +void Accumulator::accumulate(const PublicCoin& coin) { + // Make sure we're initialized + if(!(this->value)) { + throw ZerocoinException("Accumulator is not initialized"); + } + + if(this->denomination != coin.getDenomination()) { + //std::stringstream msg; + std::string msg; + msg = "Wrong denomination for coin. Expected coins of denomination: "; + msg += this->denomination; + msg += ". Instead, got a coin of denomination: "; + msg += coin.getDenomination(); + throw std::invalid_argument(msg); + } + + if(coin.validate()) { + // Compute new accumulator = "old accumulator"^{element} mod N + this->value = this->value.pow_mod(coin.getValue(), this->params->accumulatorModulus); + } else { + throw std::invalid_argument("Coin is not valid"); + } +} + +const CoinDenomination Accumulator::getDenomination() const { + return static_cast (this->denomination); +} + +const Bignum& Accumulator::getValue() const { + return this->value; +} + +Accumulator& Accumulator::operator += (const PublicCoin& c) { + this->accumulate(c); + return *this; +} + +bool Accumulator::operator == (const Accumulator rhs) const { + return this->value == rhs.value; +} + +//AccumulatorWitness class +AccumulatorWitness::AccumulatorWitness(const Params* p, + const Accumulator& checkpoint, const PublicCoin coin): params(p), witness(checkpoint), element(coin) { +} + +void AccumulatorWitness::AddElement(const PublicCoin& c) { + if(element != c) { + witness += c; + } +} + +const Bignum& AccumulatorWitness::getValue() const { + return this->witness.getValue(); +} + +bool AccumulatorWitness::VerifyWitness(const Accumulator& a, const PublicCoin &publicCoin) const { + Accumulator temp(witness); + temp += element; + return (temp == a && this->element == publicCoin); +} + +AccumulatorWitness& AccumulatorWitness::operator +=( + const PublicCoin& rhs) { + this->AddElement(rhs); + return *this; +} + +} /* namespace libzerocoin */ diff --git a/src/zerocoin/Accumulator.h b/src/zerocoin/Accumulator.h new file mode 100644 index 0000000..deed87b --- /dev/null +++ b/src/zerocoin/Accumulator.h @@ -0,0 +1,148 @@ +/** + * @file Accumulator.h + * + * @brief Accumulator and AccumulatorWitness classes for the Zerocoin library. + * + * @author Ian Miers, Christina Garman and Matthew Green + * @date June 2013 + * + * @copyright Copyright 2013 Ian Miers, Christina Garman and Matthew Green + * @license This project is released under the MIT license. + **/ +#ifndef ACCUMULATOR_H_ +#define ACCUMULATOR_H_ + +namespace libzerocoin { +/** + * \brief Implementation of the RSA-based accumulator. + **/ + +class Accumulator { +public: + + /** + * @brief Construct an Accumulator from a stream. + * @param p An AccumulatorAndProofParams object containing global parameters + * @param d the denomination of coins we are accumulating + * @throw Zerocoin exception in case of invalid parameters + **/ + template + Accumulator(const AccumulatorAndProofParams* p, Stream& strm): params(p) { + strm >> *this; + } + + template + Accumulator(const Params* p, Stream& strm) { + strm >> *this; + this->params = &(p->accumulatorParams); + } + + /** + * @brief Construct an Accumulator from a Params object. + * @param p A Params object containing global parameters + * @param d the denomination of coins we are accumulating + * @throw Zerocoin exception in case of invalid parameters + **/ + Accumulator(const AccumulatorAndProofParams* p, const CoinDenomination d = ZQ_PEDERSEN); + + Accumulator(const Params* p, const CoinDenomination d = ZQ_PEDERSEN); + + /** + * Accumulate a coin into the accumulator. Validates + * the coin prior to accumulation. + * + * @param coin A PublicCoin to accumulate. + * + * @throw Zerocoin exception if the coin is not valid. + * + **/ + void accumulate(const PublicCoin &coin); + + const CoinDenomination getDenomination() const; + /** Get the accumulator result + * + * @return a Bignum containing the result. + */ + const Bignum& getValue() const; + + + // /** + // * Used to set the accumulator value + // * + // * Use this to handle accumulator checkpoints + // * @param b the value to set the accumulator to. + // * @throw A ZerocoinException if the accumulator value is invalid. + // */ + // void setValue(Bignum &b); // shouldn't this be a constructor? + + /** Used to accumulate a coin + * + * @param c the coin to accumulate + * @return a refrence to the updated accumulator. + */ + Accumulator& operator +=(const PublicCoin& c); + bool operator==(const Accumulator rhs) const; + + IMPLEMENT_SERIALIZE + ( + READWRITE(value); + READWRITE(denomination); + ) +private: + const AccumulatorAndProofParams* params; + Bignum value; + // Denomination is stored as an INT because storing + // and enum raises amigiuities in the serialize code //FIXME if possible + int denomination; +}; + +/**A witness that a PublicCoin is in the accumulation of a set of coins + * + */ +class AccumulatorWitness { +public: + template + AccumulatorWitness(const Params* p, Stream& strm): params(p) { + strm >> *this; + } + + /** Construct's a witness. You must add all elements after the witness + * @param p pointer to params + * @param checkpoint the last known accumulator value before the element was added + * @param coin the coin we want a witness to + */ + AccumulatorWitness(const Params* p, const Accumulator& checkpoint, const PublicCoin coin); + + /** Adds element to the set whose's accumulation we are proving coin is a member of + * + * @param c the coin to add + */ + void AddElement(const PublicCoin& c); + + /** + * + * @return the value of the witness + */ + const Bignum& getValue() const; + + /** Checks that this is a witness to the accumulation of coin + * @param a the accumulator we are checking against. + * @param publicCoin the coin we're providing a witness for + * @return True if the witness computation validates + */ + bool VerifyWitness(const Accumulator& a, const PublicCoin &publicCoin) const; + + /** + * Adds rhs to the set whose's accumulation ware proving coin is a member of + * @param rhs the PublicCoin to add + * @return + */ + AccumulatorWitness& operator +=(const PublicCoin& rhs); +private: + const Params* params; + Accumulator witness; + const PublicCoin element; +}; + +} /* namespace libzerocoin */ +#endif /* ACCUMULATOR_H_ */ diff --git a/src/zerocoin/AccumulatorProofOfKnowledge.cpp b/src/zerocoin/AccumulatorProofOfKnowledge.cpp new file mode 100644 index 0000000..ed9ac91 --- /dev/null +++ b/src/zerocoin/AccumulatorProofOfKnowledge.cpp @@ -0,0 +1,143 @@ +/** + * @file AccumulatorProofOfKnowledge.cpp + * + * @brief AccumulatorProofOfKnowledge class for the Zerocoin library. + * + * @author Ian Miers, Christina Garman and Matthew Green + * @date June 2013 + * + * @copyright Copyright 2013 Ian Miers, Christina Garman and Matthew Green + * @license This project is released under the MIT license. + **/ + +#include "Zerocoin.h" + +namespace libzerocoin { + +AccumulatorProofOfKnowledge::AccumulatorProofOfKnowledge(const AccumulatorAndProofParams* p): params(p) {} + +AccumulatorProofOfKnowledge::AccumulatorProofOfKnowledge(const AccumulatorAndProofParams* p, + const Commitment& commitmentToCoin, const AccumulatorWitness& witness, + Accumulator& a): params(p) { + + Bignum sg = params->accumulatorPoKCommitmentGroup.g; + Bignum sh = params->accumulatorPoKCommitmentGroup.h; + + Bignum g_n = params->accumulatorQRNCommitmentGroup.g; + Bignum h_n = params->accumulatorQRNCommitmentGroup.h; + + Bignum e = commitmentToCoin.getContents(); + Bignum r = commitmentToCoin.getRandomness(); + + Bignum r_1 = Bignum::randBignum(params->accumulatorModulus/4); + Bignum r_2 = Bignum::randBignum(params->accumulatorModulus/4); + Bignum r_3 = Bignum::randBignum(params->accumulatorModulus/4); + + this->C_e = g_n.pow_mod(e, params->accumulatorModulus) * h_n.pow_mod(r_1, params->accumulatorModulus); + this->C_u = witness.getValue() * h_n.pow_mod(r_2, params->accumulatorModulus); + this->C_r = g_n.pow_mod(r_2, params->accumulatorModulus) * h_n.pow_mod(r_3, params->accumulatorModulus); + + Bignum r_alpha = Bignum::randBignum(params->maxCoinValue * Bignum(2).pow(params->k_prime + params->k_dprime)); + if(!(Bignum::randBignum(Bignum(3)) % 2)) { + r_alpha = 0-r_alpha; + } + + Bignum r_gamma = Bignum::randBignum(params->accumulatorPoKCommitmentGroup.modulus); + Bignum r_phi = Bignum::randBignum(params->accumulatorPoKCommitmentGroup.modulus); + Bignum r_psi = Bignum::randBignum(params->accumulatorPoKCommitmentGroup.modulus); + Bignum r_sigma = Bignum::randBignum(params->accumulatorPoKCommitmentGroup.modulus); + Bignum r_xi = Bignum::randBignum(params->accumulatorPoKCommitmentGroup.modulus); + + Bignum r_epsilon = Bignum::randBignum((params->accumulatorModulus/4) * Bignum(2).pow(params->k_prime + params->k_dprime)); + if(!(Bignum::randBignum(Bignum(3)) % 2)) { + r_epsilon = 0-r_epsilon; + } + Bignum r_eta = Bignum::randBignum((params->accumulatorModulus/4) * Bignum(2).pow(params->k_prime + params->k_dprime)); + if(!(Bignum::randBignum(Bignum(3)) % 2)) { + r_eta = 0-r_eta; + } + Bignum r_zeta = Bignum::randBignum((params->accumulatorModulus/4) * Bignum(2).pow(params->k_prime + params->k_dprime)); + if(!(Bignum::randBignum(Bignum(3)) % 2)) { + r_zeta = 0-r_zeta; + } + + Bignum r_beta = Bignum::randBignum((params->accumulatorModulus/4) * params->accumulatorPoKCommitmentGroup.modulus * Bignum(2).pow(params->k_prime + params->k_dprime)); + if(!(Bignum::randBignum(Bignum(3)) % 2)) { + r_beta = 0-r_beta; + } + Bignum r_delta = Bignum::randBignum((params->accumulatorModulus/4) * params->accumulatorPoKCommitmentGroup.modulus * Bignum(2).pow(params->k_prime + params->k_dprime)); + if(!(Bignum::randBignum(Bignum(3)) % 2)) { + r_delta = 0-r_delta; + } + + this->st_1 = (sg.pow_mod(r_alpha, params->accumulatorPoKCommitmentGroup.modulus) * sh.pow_mod(r_phi, params->accumulatorPoKCommitmentGroup.modulus)) % params->accumulatorPoKCommitmentGroup.modulus; + this->st_2 = (((commitmentToCoin.getCommitmentValue() * sg.inverse(params->accumulatorPoKCommitmentGroup.modulus)).pow_mod(r_gamma, params->accumulatorPoKCommitmentGroup.modulus)) * sh.pow_mod(r_psi, params->accumulatorPoKCommitmentGroup.modulus)) % params->accumulatorPoKCommitmentGroup.modulus; + this->st_3 = ((sg * commitmentToCoin.getCommitmentValue()).pow_mod(r_sigma, params->accumulatorPoKCommitmentGroup.modulus) * sh.pow_mod(r_xi, params->accumulatorPoKCommitmentGroup.modulus)) % params->accumulatorPoKCommitmentGroup.modulus; + + this->t_1 = (h_n.pow_mod(r_zeta, params->accumulatorModulus) * g_n.pow_mod(r_epsilon, params->accumulatorModulus)) % params->accumulatorModulus; + this->t_2 = (h_n.pow_mod(r_eta, params->accumulatorModulus) * g_n.pow_mod(r_alpha, params->accumulatorModulus)) % params->accumulatorModulus; + this->t_3 = (C_u.pow_mod(r_alpha, params->accumulatorModulus) * ((h_n.inverse(params->accumulatorModulus)).pow_mod(r_beta, params->accumulatorModulus))) % params->accumulatorModulus; + this->t_4 = (C_r.pow_mod(r_alpha, params->accumulatorModulus) * ((h_n.inverse(params->accumulatorModulus)).pow_mod(r_delta, params->accumulatorModulus)) * ((g_n.inverse(params->accumulatorModulus)).pow_mod(r_beta, params->accumulatorModulus))) % params->accumulatorModulus; + + CHashWriter hasher(0,0); + hasher << *params << sg << sh << g_n << h_n << commitmentToCoin.getCommitmentValue() << C_e << C_u << C_r << st_1 << st_2 << st_3 << t_1 << t_2 << t_3 << t_4; + + //According to the proof, this hash should be of length k_prime bits. It is currently greater than that, which should not be a problem, but we should check this. + Bignum c = Bignum(hasher.GetHash()); + + this->s_alpha = r_alpha - c*e; + this->s_beta = r_beta - c*r_2*e; + this->s_zeta = r_zeta - c*r_3; + this->s_sigma = r_sigma - c*((e+1).inverse(params->accumulatorPoKCommitmentGroup.groupOrder)); + this->s_eta = r_eta - c*r_1; + this->s_epsilon = r_epsilon - c*r_2; + this->s_delta = r_delta - c*r_3*e; + this->s_xi = r_xi + c*r*((e+1).inverse(params->accumulatorPoKCommitmentGroup.groupOrder)); + this->s_phi = (r_phi - c*r) % params->accumulatorPoKCommitmentGroup.groupOrder; + this->s_gamma = r_gamma - c*((e-1).inverse(params->accumulatorPoKCommitmentGroup.groupOrder)); + this->s_psi = r_psi + c*r*((e-1).inverse(params->accumulatorPoKCommitmentGroup.groupOrder)); +} + +/** Verifies that a commitment c is accumulated in accumulator a + */ +bool AccumulatorProofOfKnowledge:: Verify(const Accumulator& a, const Bignum& valueOfCommitmentToCoin) const { + Bignum sg = params->accumulatorPoKCommitmentGroup.g; + Bignum sh = params->accumulatorPoKCommitmentGroup.h; + + Bignum g_n = params->accumulatorQRNCommitmentGroup.g; + Bignum h_n = params->accumulatorQRNCommitmentGroup.h; + + //According to the proof, this hash should be of length k_prime bits. It is currently greater than that, which should not be a problem, but we should check this. + CHashWriter hasher(0,0); + hasher << *params << sg << sh << g_n << h_n << valueOfCommitmentToCoin << C_e << C_u << C_r << st_1 << st_2 << st_3 << t_1 << t_2 << t_3 << t_4; + + Bignum c = Bignum(hasher.GetHash()); //this hash should be of length k_prime bits + + Bignum st_1_prime = (valueOfCommitmentToCoin.pow_mod(c, params->accumulatorPoKCommitmentGroup.modulus) * sg.pow_mod(s_alpha, params->accumulatorPoKCommitmentGroup.modulus) * sh.pow_mod(s_phi, params->accumulatorPoKCommitmentGroup.modulus)) % params->accumulatorPoKCommitmentGroup.modulus; + Bignum st_2_prime = (sg.pow_mod(c, params->accumulatorPoKCommitmentGroup.modulus) * ((valueOfCommitmentToCoin * sg.inverse(params->accumulatorPoKCommitmentGroup.modulus)).pow_mod(s_gamma, params->accumulatorPoKCommitmentGroup.modulus)) * sh.pow_mod(s_psi, params->accumulatorPoKCommitmentGroup.modulus)) % params->accumulatorPoKCommitmentGroup.modulus; + Bignum st_3_prime = (sg.pow_mod(c, params->accumulatorPoKCommitmentGroup.modulus) * (sg * valueOfCommitmentToCoin).pow_mod(s_sigma, params->accumulatorPoKCommitmentGroup.modulus) * sh.pow_mod(s_xi, params->accumulatorPoKCommitmentGroup.modulus)) % params->accumulatorPoKCommitmentGroup.modulus; + + Bignum t_1_prime = (C_r.pow_mod(c, params->accumulatorModulus) * h_n.pow_mod(s_zeta, params->accumulatorModulus) * g_n.pow_mod(s_epsilon, params->accumulatorModulus)) % params->accumulatorModulus; + Bignum t_2_prime = (C_e.pow_mod(c, params->accumulatorModulus) * h_n.pow_mod(s_eta, params->accumulatorModulus) * g_n.pow_mod(s_alpha, params->accumulatorModulus)) % params->accumulatorModulus; + Bignum t_3_prime = ((a.getValue()).pow_mod(c, params->accumulatorModulus) * C_u.pow_mod(s_alpha, params->accumulatorModulus) * ((h_n.inverse(params->accumulatorModulus)).pow_mod(s_beta, params->accumulatorModulus))) % params->accumulatorModulus; + Bignum t_4_prime = (C_r.pow_mod(s_alpha, params->accumulatorModulus) * ((h_n.inverse(params->accumulatorModulus)).pow_mod(s_delta, params->accumulatorModulus)) * ((g_n.inverse(params->accumulatorModulus)).pow_mod(s_beta, params->accumulatorModulus))) % params->accumulatorModulus; + + bool result = false; + + bool result_st1 = (st_1 == st_1_prime); + bool result_st2 = (st_2 == st_2_prime); + bool result_st3 = (st_3 == st_3_prime); + + bool result_t1 = (t_1 == t_1_prime); + bool result_t2 = (t_2 == t_2_prime); + bool result_t3 = (t_3 == t_3_prime); + bool result_t4 = (t_4 == t_4_prime); + + bool result_range = ((s_alpha >= -(params->maxCoinValue * Bignum(2).pow(params->k_prime + params->k_dprime + 1))) && (s_alpha <= (params->maxCoinValue * Bignum(2).pow(params->k_prime + params->k_dprime + 1)))); + + result = result_st1 && result_st2 && result_st3 && result_t1 && result_t2 && result_t3 && result_t4 && result_range; + + return result; +} + +} /* namespace libzerocoin */ diff --git a/src/zerocoin/AccumulatorProofOfKnowledge.h b/src/zerocoin/AccumulatorProofOfKnowledge.h new file mode 100644 index 0000000..4078940 --- /dev/null +++ b/src/zerocoin/AccumulatorProofOfKnowledge.h @@ -0,0 +1,91 @@ +/** + * @file AccumulatorProofOfKnowledge.h + * + * @brief AccumulatorProofOfKnowledge class for the Zerocoin library. + * + * @author Ian Miers, Christina Garman and Matthew Green + * @date June 2013 + * + * @copyright Copyright 2013 Ian Miers, Christina Garman and Matthew Green + * @license This project is released under the MIT license. + **/ + +#ifndef ACCUMULATEPROOF_H_ +#define ACCUMULATEPROOF_H_ + +namespace libzerocoin { + +/**A prove that a value insde the commitment commitmentToCoin is in an accumulator a. + * + */ +class AccumulatorProofOfKnowledge { +public: + AccumulatorProofOfKnowledge(const AccumulatorAndProofParams* p); + + /** Generates a proof that a commitment to a coin c was accumulated + * @param p Cryptographic parameters + * @param commitmentToCoin commitment containing the coin we want to prove is accumulated + * @param witness The witness to the accumulation of the coin + * @param a + */ + AccumulatorProofOfKnowledge(const AccumulatorAndProofParams* p, const Commitment& commitmentToCoin, const AccumulatorWitness& witness, Accumulator& a); + /** Verifies that a commitment c is accumulated in accumulated a + */ + bool Verify(const Accumulator& a,const Bignum& valueOfCommitmentToCoin) const; + + IMPLEMENT_SERIALIZE + ( + READWRITE(C_e); + READWRITE(C_u); + READWRITE(C_r); + READWRITE(st_1); + READWRITE(st_2); + READWRITE(st_3); + READWRITE(t_1); + READWRITE(t_2); + READWRITE(t_3); + READWRITE(t_4); + READWRITE(s_alpha); + READWRITE(s_beta); + READWRITE(s_zeta); + READWRITE(s_sigma); + READWRITE(s_eta); + READWRITE(s_epsilon); + READWRITE(s_delta); + READWRITE(s_xi); + READWRITE(s_phi); + READWRITE(s_gamma); + READWRITE(s_psi); + ) +private: + const AccumulatorAndProofParams* params; + + /* Return values for proof */ + Bignum C_e; + Bignum C_u; + Bignum C_r; + + Bignum st_1; + Bignum st_2; + Bignum st_3; + + Bignum t_1; + Bignum t_2; + Bignum t_3; + Bignum t_4; + + Bignum s_alpha; + Bignum s_beta; + Bignum s_zeta; + Bignum s_sigma; + Bignum s_eta; + Bignum s_epsilon; + Bignum s_delta; + Bignum s_xi; + Bignum s_phi; + Bignum s_gamma; + Bignum s_psi; +}; + +} /* namespace libzerocoin */ +#endif /* ACCUMULATEPROOF_H_ */ diff --git a/src/zerocoin/Coin.cpp b/src/zerocoin/Coin.cpp new file mode 100644 index 0000000..c9aa9a5 --- /dev/null +++ b/src/zerocoin/Coin.cpp @@ -0,0 +1,167 @@ +/** + * @file Coin.cpp + * + * @brief PublicCoin and PrivateCoin classes for the Zerocoin library. + * + * @author Ian Miers, Christina Garman and Matthew Green + * @date June 2013 + * + * @copyright Copyright 2013 Ian Miers, Christina Garman and Matthew Green + * @license This project is released under the MIT license. + **/ + +#include +#include "Zerocoin.h" + +namespace libzerocoin { + +//PublicCoin class +PublicCoin::PublicCoin(const Params* p): + params(p), denomination(ZQ_PEDERSEN) { + if(this->params->initialized == false) { + throw std::invalid_argument("Params are not initialized"); + } +}; + +PublicCoin::PublicCoin(const Params* p, const Bignum& coin, const CoinDenomination d): + params(p), value(coin), denomination(d) { + if(this->params->initialized == false) { + throw std::invalid_argument("Params are not initialized"); + } +}; + +bool PublicCoin::operator==(const PublicCoin& rhs) const { + return this->value == rhs.value;// FIXME check param equality +} + +bool PublicCoin::operator!=(const PublicCoin& rhs) const { + return !(*this == rhs); +} + +const Bignum& PublicCoin::getValue() const { + return this->value; +} + +const CoinDenomination PublicCoin::getDenomination() const { + return static_cast(this->denomination); +} + +bool PublicCoin::validate() const { + return (this->params->accumulatorParams.minCoinValue < value) && (value < this->params->accumulatorParams.maxCoinValue) && value.isPrime(params->zkp_iterations); +} + +//PrivateCoin class +PrivateCoin::PrivateCoin(const Params* p, const CoinDenomination denomination): params(p), publicCoin(p) { + // Verify that the parameters are valid + if(this->params->initialized == false) { + throw std::invalid_argument("Params are not initialized"); + } + +#ifdef ZEROCOIN_FAST_MINT + // Mint a new coin with a random serial number using the fast process. + // This is more vulnerable to timing attacks so don't mint coins when + // somebody could be timing you. + this->mintCoinFast(denomination); +#else + // Mint a new coin with a random serial number using the standard process. + this->mintCoin(denomination); +#endif + +} + +/** + * + * @return the coins serial number + */ +const Bignum& PrivateCoin::getSerialNumber() const { + return this->serialNumber; +} + +const Bignum& PrivateCoin::getRandomness() const { + return this->randomness; +} + +void PrivateCoin::mintCoin(const CoinDenomination denomination) { + // Repeat this process up to MAX_COINMINT_ATTEMPTS times until + // we obtain a prime number + for(uint32_t attempt = 0; attempt < MAX_COINMINT_ATTEMPTS; attempt++) { + + // Generate a random serial number in the range 0...{q-1} where + // "q" is the order of the commitment group. + Bignum s = Bignum::randBignum(this->params->coinCommitmentGroup.groupOrder); + + // Generate a Pedersen commitment to the serial number "s" + Commitment coin(¶ms->coinCommitmentGroup, s); + + // Now verify that the commitment is a prime number + // in the appropriate range. If not, we'll throw this coin + // away and generate a new one. + if (coin.getCommitmentValue().isPrime(ZEROCOIN_MINT_PRIME_PARAM) && + coin.getCommitmentValue() >= params->accumulatorParams.minCoinValue && + coin.getCommitmentValue() <= params->accumulatorParams.maxCoinValue) { + // Found a valid coin. Store it. + this->serialNumber = s; + this->randomness = coin.getRandomness(); + this->publicCoin = PublicCoin(params,coin.getCommitmentValue(), denomination); + + // Success! We're done. + return; + } + } + + // We only get here if we did not find a coin within + // MAX_COINMINT_ATTEMPTS. Throw an exception. + throw ZerocoinException("Unable to mint a new Zerocoin (too many attempts)"); +} + +void PrivateCoin::mintCoinFast(const CoinDenomination denomination) { + + // Generate a random serial number in the range 0...{q-1} where + // "q" is the order of the commitment group. + Bignum s = Bignum::randBignum(this->params->coinCommitmentGroup.groupOrder); + + // Generate a random number "r" in the range 0...{q-1} + Bignum r = Bignum::randBignum(this->params->coinCommitmentGroup.groupOrder); + + // Manually compute a Pedersen commitment to the serial number "s" under randomness "r" + // C = g^s * h^r mod p + Bignum commitmentValue = this->params->coinCommitmentGroup.g.pow_mod(s, this->params->coinCommitmentGroup.modulus).mul_mod(this->params->coinCommitmentGroup.h.pow_mod(r, this->params->coinCommitmentGroup.modulus), this->params->coinCommitmentGroup.modulus); + + // Repeat this process up to MAX_COINMINT_ATTEMPTS times until + // we obtain a prime number + for (uint32_t attempt = 0; attempt < MAX_COINMINT_ATTEMPTS; attempt++) { + // First verify that the commitment is a prime number + // in the appropriate range. If not, we'll throw this coin + // away and generate a new one. + if (commitmentValue.isPrime(ZEROCOIN_MINT_PRIME_PARAM) && + commitmentValue >= params->accumulatorParams.minCoinValue && + commitmentValue <= params->accumulatorParams.maxCoinValue) { + // Found a valid coin. Store it. + this->serialNumber = s; + this->randomness = r; + this->publicCoin = PublicCoin(params, commitmentValue, denomination); + + // Success! We're done. + return; + } + + // Generate a new random "r_delta" in 0...{q-1} + Bignum r_delta = Bignum::randBignum(this->params->coinCommitmentGroup.groupOrder); + + // The commitment was not prime. Increment "r" and recalculate "C": + // r = r + r_delta mod q + // C = C * h mod p + r = (r + r_delta) % this->params->coinCommitmentGroup.groupOrder; + commitmentValue = commitmentValue.mul_mod(this->params->coinCommitmentGroup.h.pow_mod(r_delta, this->params->coinCommitmentGroup.modulus), this->params->coinCommitmentGroup.modulus); + } + + // We only get here if we did not find a coin within + // MAX_COINMINT_ATTEMPTS. Throw an exception. + throw ZerocoinException("Unable to mint a new Zerocoin (too many attempts)"); +} + +const PublicCoin& PrivateCoin::getPublicCoin() const { + return this->publicCoin; +} + +} /* namespace libzerocoin */ diff --git a/src/zerocoin/Coin.h b/src/zerocoin/Coin.h new file mode 100644 index 0000000..09e3caa --- /dev/null +++ b/src/zerocoin/Coin.h @@ -0,0 +1,139 @@ +/** + * @file Coin.h + * + * @brief PublicCoin and PrivateCoin classes for the Zerocoin library. + * + * @author Ian Miers, Christina Garman and Matthew Green + * @date June 2013 + * + * @copyright Copyright 2013 Ian Miers, Christina Garman and Matthew Green + * @license This project is released under the MIT license. + **/ + +#ifndef COIN_H_ +#define COIN_H_ +#include "../bignum.h" +#include "Params.h" +namespace libzerocoin { + +enum CoinDenomination { + ZQ_LOVELACE = 1, + ZQ_GOLDWASSER = 10, + ZQ_RACKOFF = 25, + ZQ_PEDERSEN = 50, + ZQ_WILLIAMSON = 100 // Malcolm J. Williamson, + // the scientist who actually invented + // Public key cryptography +}; + +/** A Public coin is the part of a coin that + * is published to the network and what is handled + * by other clients. It contains only the value + * of commitment to a serial number and the + * denomination of the coin. + */ +class PublicCoin { +public: + template + PublicCoin(const Params* p, Stream& strm): params(p) { + strm >> *this; + } + + PublicCoin( const Params* p); + + /**Generates a public coin + * + * @param p cryptographic paramters + * @param coin the value of the commitment. + * @param denomination The denomination of the coin. Defaults to ZQ_PEDERSEN + */ + PublicCoin( const Params* p, const Bignum& coin, const CoinDenomination d = ZQ_PEDERSEN); + const Bignum& getValue() const; + const CoinDenomination getDenomination() const; + bool operator==(const PublicCoin& rhs) const; + bool operator!=(const PublicCoin& rhs) const; + /** Checks that a coin prime + * and in the appropriate range + * given the parameters + * @return true if valid + */ + bool validate() const; + IMPLEMENT_SERIALIZE + ( + READWRITE(value); + READWRITE(denomination); + ) +private: + const Params* params; + Bignum value; + // Denomination is stored as an INT because storing + // and enum raises amigiuities in the serialize code //FIXME if possible + int denomination; +}; + +/** + * A private coin. As the name implies, the content + * of this should stay private except PublicCoin. + * + * Contains a coin's serial number, a commitment to it, + * and opening randomness for the commitment. + * + * @warning Failure to keep this secret(or safe), + * @warning will result in the theft of your coins + * @warning and a TOTAL loss of anonymity. + */ +class PrivateCoin { +public: + template + PrivateCoin(const Params* p, Stream& strm): params(p) { + strm >> *this; + } + PrivateCoin(const Params* p,const CoinDenomination denomination = ZQ_PEDERSEN); + const PublicCoin& getPublicCoin() const; + const Bignum& getSerialNumber() const; + const Bignum& getRandomness() const; + + IMPLEMENT_SERIALIZE + ( + READWRITE(publicCoin); + READWRITE(randomness); + READWRITE(serialNumber); + ) +private: + const Params* params; + PublicCoin publicCoin; + Bignum randomness; + Bignum serialNumber; + + /** + * @brief Mint a new coin. + * @param denomination the denomination of the coin to mint + * @throws ZerocoinException if the process takes too long + * + * Generates a new Zerocoin by (a) selecting a random serial + * number, (b) committing to this serial number and repeating until + * the resulting commitment is prime. Stores the + * resulting commitment (coin) and randomness (trapdoor). + **/ + void mintCoin(const CoinDenomination denomination); + + /** + * @brief Mint a new coin using a faster process. + * @param denomination the denomination of the coin to mint + * @throws ZerocoinException if the process takes too long + * + * Generates a new Zerocoin by (a) selecting a random serial + * number, (b) committing to this serial number and repeating until + * the resulting commitment is prime. Stores the + * resulting commitment (coin) and randomness (trapdoor). + * This routine is substantially faster than the + * mintCoin() routine, but could be more vulnerable + * to timing attacks. Don't use it if you think someone + * could be timing your coin minting. + **/ + void mintCoinFast(const CoinDenomination denomination); + +}; + +} /* namespace libzerocoin */ +#endif /* COIN_H_ */ diff --git a/src/zerocoin/CoinSpend.cpp b/src/zerocoin/CoinSpend.cpp new file mode 100644 index 0000000..c7890f5 --- /dev/null +++ b/src/zerocoin/CoinSpend.cpp @@ -0,0 +1,82 @@ +/** + * @file CoinSpend.cpp + * + * @brief CoinSpend class for the Zerocoin library. + * + * @author Ian Miers, Christina Garman and Matthew Green + * @date June 2013 + * + * @copyright Copyright 2013 Ian Miers, Christina Garman and Matthew Green + * @license This project is released under the MIT license. + **/ + +#include "Zerocoin.h" + +namespace libzerocoin { + +CoinSpend::CoinSpend(const Params* p, const PrivateCoin& coin, + Accumulator& a, const AccumulatorWitness& witness, const SpendMetaData& m): + params(p), + denomination(coin.getPublicCoin().getDenomination()), + coinSerialNumber((coin.getSerialNumber())), + accumulatorPoK(&p->accumulatorParams), + serialNumberSoK(p), + commitmentPoK(&p->serialNumberSoKCommitmentGroup, &p->accumulatorParams.accumulatorPoKCommitmentGroup) { + + // Sanity check: let's verify that the Witness is valid with respect to + // the coin and Accumulator provided. + if (!(witness.VerifyWitness(a, coin.getPublicCoin()))) { + throw std::invalid_argument("Accumulator witness does not verify"); + } + + // 1: Generate two separate commitments to the public coin (C), each under + // a different set of public parameters. We do this because the RSA accumulator + // has specific requirements for the commitment parameters that are not + // compatible with the group we use for the serial number proof. + // Specifically, our serial number proof requires the order of the commitment group + // to be the same as the modulus of the upper group. The Accumulator proof requires a + // group with a significantly larger order. + const Commitment fullCommitmentToCoinUnderSerialParams(&p->serialNumberSoKCommitmentGroup, coin.getPublicCoin().getValue()); + this->serialCommitmentToCoinValue = fullCommitmentToCoinUnderSerialParams.getCommitmentValue(); + + const Commitment fullCommitmentToCoinUnderAccParams(&p->accumulatorParams.accumulatorPoKCommitmentGroup, coin.getPublicCoin().getValue()); + this->accCommitmentToCoinValue = fullCommitmentToCoinUnderAccParams.getCommitmentValue(); + + // 2. Generate a ZK proof that the two commitments contain the same public coin. + this->commitmentPoK = CommitmentProofOfKnowledge(&p->serialNumberSoKCommitmentGroup, &p->accumulatorParams.accumulatorPoKCommitmentGroup, fullCommitmentToCoinUnderSerialParams, fullCommitmentToCoinUnderAccParams); + + // Now generate the two core ZK proofs: + // 3. Proves that the committed public coin is in the Accumulator (PoK of "witness") + this->accumulatorPoK = AccumulatorProofOfKnowledge(&p->accumulatorParams, fullCommitmentToCoinUnderAccParams, witness, a); + + // 4. Proves that the coin is correct w.r.t. serial number and hidden coin secret + // (This proof is bound to the coin 'metadata', i.e., transaction hash) + this->serialNumberSoK = SerialNumberSignatureOfKnowledge(p, coin, fullCommitmentToCoinUnderSerialParams, signatureHash(m)); +} + +const Bignum& +CoinSpend::getCoinSerialNumber() { + return this->coinSerialNumber; +} + +const CoinDenomination +CoinSpend::getDenomination() { + return static_cast(this->denomination); +} + +bool +CoinSpend::Verify(const Accumulator& a, const SpendMetaData &m) const { + // Verify both of the sub-proofs using the given meta-data + return (a.getDenomination() == this->denomination) + && commitmentPoK.Verify(serialCommitmentToCoinValue, accCommitmentToCoinValue) + && accumulatorPoK.Verify(a, accCommitmentToCoinValue) + && serialNumberSoK.Verify(coinSerialNumber, serialCommitmentToCoinValue, signatureHash(m)); +} + +const uint256 CoinSpend::signatureHash(const SpendMetaData &m) const { + CHashWriter h(0,0); + h << m << serialCommitmentToCoinValue << accCommitmentToCoinValue << commitmentPoK << accumulatorPoK; + return h.GetHash(); +} + +} /* namespace libzerocoin */ diff --git a/src/zerocoin/CoinSpend.h b/src/zerocoin/CoinSpend.h new file mode 100644 index 0000000..8bf6925 --- /dev/null +++ b/src/zerocoin/CoinSpend.h @@ -0,0 +1,107 @@ +/** + * @file CoinSpend.h + * + * @brief CoinSpend class for the Zerocoin library. + * + * @author Ian Miers, Christina Garman and Matthew Green + * @date June 2013 + * + * @copyright Copyright 2013 Ian Miers, Christina Garman and Matthew Green + * @license This project is released under the MIT license. + **/ + +#ifndef COINSPEND_H_ +#define COINSPEND_H_ + +#include "Params.h" +#include "Coin.h" +#include "Commitment.h" +#include "../bignum.h" +#include "Accumulator.h" +#include "AccumulatorProofOfKnowledge.h" +#include "SerialNumberSignatureOfKnowledge.h" +#include "SpendMetaData.h" +#include "../serialize.h" + +namespace libzerocoin { + +/** The complete proof needed to spend a zerocoin. + * Composes together a proof that a coin is accumulated + * and that it has a given serial number. + */ +class CoinSpend { +public: + template + CoinSpend(const Params* p, Stream& strm):denomination(ZQ_PEDERSEN), + accumulatorPoK(&p->accumulatorParams), + serialNumberSoK(p), + commitmentPoK(&p->serialNumberSoKCommitmentGroup, &p->accumulatorParams.accumulatorPoKCommitmentGroup) { + strm >> *this; + } + /**Generates a proof spending a zerocoin. + * + * To use this, provide an unspent PrivateCoin, the latest Accumulator + * (e.g from the most recent Bitcoin block) containing the public part + * of the coin, a witness to that, and whatever medeta data is needed. + * + * Once constructed, this proof can be serialized and sent. + * It is validated simply be calling validate. + * @warning Validation only checks that the proof is correct + * @warning for the specified values in this class. These values must be validated + * Clients ought to check that + * 1) params is the right params + * 2) the accumulator actually is in some block + * 3) that the serial number is unspent + * 4) that the transaction + * + * @param p cryptographic parameters + * @param coin The coin to be spend + * @param a The current accumulator containing the coin + * @param witness The witness showing that the accumulator contains the coin + * @param m arbitrary meta data related to the spend that might be needed by Bitcoin + * (i.e. the transaction hash) + * @throw ZerocoinException if the process fails + */ + CoinSpend(const Params* p, const PrivateCoin& coin, Accumulator& a, const AccumulatorWitness& witness, const SpendMetaData& m); + + /** Returns the serial number of the coin spend by this proof. + * + * @return the coin's serial number + */ + const Bignum& getCoinSerialNumber(); + + /**Gets the denomination of the coin spent in this proof. + * + * @return the denomination + */ + const CoinDenomination getDenomination(); + + bool Verify(const Accumulator& a, const SpendMetaData &metaData) const; + + IMPLEMENT_SERIALIZE + ( + READWRITE(denomination); + READWRITE(accCommitmentToCoinValue); + READWRITE(serialCommitmentToCoinValue); + READWRITE(coinSerialNumber); + READWRITE(accumulatorPoK); + READWRITE(serialNumberSoK); + READWRITE(commitmentPoK); + ) + +private: + const Params *params; + const uint256 signatureHash(const SpendMetaData &m) const; + // Denomination is stored as an INT because storing + // and enum raises amigiuities in the serialize code //FIXME if possible + int denomination; + Bignum accCommitmentToCoinValue; + Bignum serialCommitmentToCoinValue; + Bignum coinSerialNumber; + AccumulatorProofOfKnowledge accumulatorPoK; + SerialNumberSignatureOfKnowledge serialNumberSoK; + CommitmentProofOfKnowledge commitmentPoK; +}; + +} /* namespace libzerocoin */ +#endif /* COINSPEND_H_ */ diff --git a/src/zerocoin/Commitment.cpp b/src/zerocoin/Commitment.cpp new file mode 100644 index 0000000..50e7fcd --- /dev/null +++ b/src/zerocoin/Commitment.cpp @@ -0,0 +1,172 @@ +/** + * @file Commitment.cpp + * + * @brief Commitment and CommitmentProof classes for the Zerocoin library. + * + * @author Ian Miers, Christina Garman and Matthew Green + * @date June 2013 + * + * @copyright Copyright 2013 Ian Miers, Christina Garman and Matthew Green + * @license This project is released under the MIT license. + **/ + +#include +#include "Zerocoin.h" + +namespace libzerocoin { + +//Commitment class +Commitment::Commitment::Commitment(const IntegerGroupParams* p, + const Bignum& value): params(p), contents(value) { + this->randomness = Bignum::randBignum(params->groupOrder); + this->commitmentValue = (params->g.pow_mod(this->contents, params->modulus).mul_mod( + params->h.pow_mod(this->randomness, params->modulus), params->modulus)); +} + +const Bignum& Commitment::getCommitmentValue() const { + return this->commitmentValue; +} + +const Bignum& Commitment::getRandomness() const { + return this->randomness; +} + +const Bignum& Commitment::getContents() const { + return this->contents; +} + +//CommitmentProofOfKnowledge class +CommitmentProofOfKnowledge::CommitmentProofOfKnowledge(const IntegerGroupParams* ap, const IntegerGroupParams* bp): ap(ap), bp(bp) {} + +// TODO: get parameters from the commitment group +CommitmentProofOfKnowledge::CommitmentProofOfKnowledge(const IntegerGroupParams* aParams, + const IntegerGroupParams* bParams, const Commitment& a, const Commitment& b): + ap(aParams),bp(bParams) +{ + Bignum r1, r2, r3; + + // First: make sure that the two commitments have the + // same contents. + if (a.getContents() != b.getContents()) { + throw std::invalid_argument("Both commitments must contain the same value"); + } + + // Select three random values "r1, r2, r3" in the range 0 to (2^l)-1 where l is: + // length of challenge value + max(modulus 1, modulus 2, order 1, order 2) + margin. + // We set "margin" to be a relatively generous security parameter. + // + // We choose these large values to ensure statistical zero knowledge. + uint32_t randomSize = COMMITMENT_EQUALITY_CHALLENGE_SIZE + COMMITMENT_EQUALITY_SECMARGIN + + std::max(std::max(this->ap->modulus.bitSize(), this->bp->modulus.bitSize()), + std::max(this->ap->groupOrder.bitSize(), this->bp->groupOrder.bitSize())); + Bignum maxRange = (Bignum(2).pow(randomSize) - Bignum(1)); + + r1 = Bignum::randBignum(maxRange); + r2 = Bignum::randBignum(maxRange); + r3 = Bignum::randBignum(maxRange); + + // Generate two random, ephemeral commitments "T1, T2" + // of the form: + // T1 = g1^r1 * h1^r2 mod p1 + // T2 = g2^r1 * h2^r3 mod p2 + // + // Where (g1, h1, p1) are from "aParams" and (g2, h2, p2) are from "bParams". + Bignum T1 = this->ap->g.pow_mod(r1, this->ap->modulus).mul_mod((this->ap->h.pow_mod(r2, this->ap->modulus)), this->ap->modulus); + Bignum T2 = this->bp->g.pow_mod(r1, this->bp->modulus).mul_mod((this->bp->h.pow_mod(r3, this->bp->modulus)), this->bp->modulus); + + // Now hash commitment "A" with commitment "B" as well as the + // parameters and the two ephemeral commitments "T1, T2" we just generated + this->challenge = calculateChallenge(a.getCommitmentValue(), b.getCommitmentValue(), T1, T2); + + // Let "m" be the contents of the commitments "A, B". We have: + // A = g1^m * h1^x mod p1 + // B = g2^m * h2^y mod p2 + // T1 = g1^r1 * h1^r2 mod p1 + // T2 = g2^r1 * h2^r3 mod p2 + // + // Now compute: + // S1 = r1 + (m * challenge) -- note, not modular arithmetic + // S2 = r2 + (x * challenge) -- note, not modular arithmetic + // S3 = r3 + (y * challenge) -- note, not modular arithmetic + this->S1 = r1 + (a.getContents() * this->challenge); + this->S2 = r2 + (a.getRandomness() * this->challenge); + this->S3 = r3 + (b.getRandomness() * this->challenge); + + // We're done. The proof is S1, S2, S3 and "challenge", all of which + // are stored in member variables. +} + +bool CommitmentProofOfKnowledge::Verify(const Bignum& A, const Bignum& B) const +{ + // Compute the maximum range of S1, S2, S3 and verify that the given values are + // in a correct range. This might be an unnecessary check. + uint32_t maxSize = 64 * (COMMITMENT_EQUALITY_CHALLENGE_SIZE + COMMITMENT_EQUALITY_SECMARGIN + + std::max(std::max(this->ap->modulus.bitSize(), this->bp->modulus.bitSize()), + std::max(this->ap->groupOrder.bitSize(), this->bp->groupOrder.bitSize()))); + + if ((uint32_t)this->S1.bitSize() > maxSize || + (uint32_t)this->S2.bitSize() > maxSize || + (uint32_t)this->S3.bitSize() > maxSize || + this->S1 < Bignum(0) || + this->S2 < Bignum(0) || + this->S3 < Bignum(0) || + this->challenge < Bignum(0) || + this->challenge > (Bignum(2).pow(COMMITMENT_EQUALITY_CHALLENGE_SIZE) - Bignum(1))) { + // Invalid inputs. Reject. + return false; + } + + // Compute T1 = g1^S1 * h1^S2 * inverse(A^{challenge}) mod p1 + Bignum T1 = A.pow_mod(this->challenge, ap->modulus).inverse(ap->modulus).mul_mod( + (ap->g.pow_mod(S1, ap->modulus).mul_mod(ap->h.pow_mod(S2, ap->modulus), ap->modulus)), + ap->modulus); + + // Compute T2 = g2^S1 * h2^S3 * inverse(B^{challenge}) mod p2 + Bignum T2 = B.pow_mod(this->challenge, bp->modulus).inverse(bp->modulus).mul_mod( + (bp->g.pow_mod(S1, bp->modulus).mul_mod(bp->h.pow_mod(S3, bp->modulus), bp->modulus)), + bp->modulus); + + // Hash T1 and T2 along with all of the public parameters + Bignum computedChallenge = calculateChallenge(A, B, T1, T2); + + // Return success if the computed challenge matches the incoming challenge + if(computedChallenge == this->challenge) { + return true; + } + + // Otherwise return failure + return false; +} + +const Bignum CommitmentProofOfKnowledge::calculateChallenge(const Bignum& a, const Bignum& b, const Bignum &commitOne, const Bignum &commitTwo) const { + CHashWriter hasher(0,0); + + // Hash together the following elements: + // * A string identifying the proof + // * Commitment A + // * Commitment B + // * Ephemeral commitment T1 + // * Ephemeral commitment T2 + // * A serialized instance of the commitment A parameters + // * A serialized instance of the commitment B parameters + + hasher << std::string(ZEROCOIN_COMMITMENT_EQUALITY_PROOF); + hasher << commitOne; + hasher << std::string("||"); + hasher << commitTwo; + hasher << std::string("||"); + hasher << a; + hasher << std::string("||"); + hasher << b; + hasher << std::string("||"); + hasher << *(this->ap); + hasher << std::string("||"); + hasher << *(this->bp); + + // Convert the SHA256 result into a Bignum + // Note that if we ever change the size of the hash function we will have + // to update COMMITMENT_EQUALITY_CHALLENGE_SIZE appropriately! + return Bignum(hasher.GetHash()); +} + +} /* namespace libzerocoin */ diff --git a/src/zerocoin/Commitment.h b/src/zerocoin/Commitment.h new file mode 100644 index 0000000..d8630a3 --- /dev/null +++ b/src/zerocoin/Commitment.h @@ -0,0 +1,105 @@ +/** + * @file Commitment.h + * + * @brief Commitment and CommitmentProof classes for the Zerocoin library. + * + * @author Ian Miers, Christina Garman and Matthew Green + * @date June 2013 + * + * @copyright Copyright 2013 Ian Miers, Christina Garman and Matthew Green + * @license This project is released under the MIT license. + **/ + +#ifndef COMMITMENT_H_ +#define COMMITMENT_H_ + +#include "Params.h" +#include "../serialize.h" + +// We use a SHA256 hash for our PoK challenges. Update the following +// if we ever change hash functions. +#define COMMITMENT_EQUALITY_CHALLENGE_SIZE 256 + +// A 512-bit security parameter for the statistical ZK PoK. +#define COMMITMENT_EQUALITY_SECMARGIN 512 + +namespace libzerocoin { + +/** + * A commitment, complete with contents and opening randomness. + * These should remain secret. Publish only the commitment value. + */ +class Commitment { +public: + /**Generates a Pedersen commitment to the given value. + * + * @param p the group parameters for the coin + * @param value the value to commit to + */ + Commitment(const IntegerGroupParams* p, const Bignum& value); + const Bignum& getCommitmentValue() const; + const Bignum& getRandomness() const; + const Bignum& getContents() const; +private: + const IntegerGroupParams *params; + Bignum commitmentValue; + Bignum randomness; + const Bignum contents; + IMPLEMENT_SERIALIZE + ( + READWRITE(commitmentValue); + READWRITE(randomness); + READWRITE(contents); + ) +}; + +/**Proof that two commitments open to the same value. + * + */ +class CommitmentProofOfKnowledge { +public: + CommitmentProofOfKnowledge(const IntegerGroupParams* ap, const IntegerGroupParams* bp); + /** Generates a proof that two commitments, a and b, open to the same value. + * + * @param ap the IntegerGroup for commitment a + * @param bp the IntegerGroup for commitment b + * @param a the first commitment + * @param b the second commitment + */ + CommitmentProofOfKnowledge(const IntegerGroupParams* aParams, const IntegerGroupParams* bParams, const Commitment& a, const Commitment& b); + //FIXME: is it best practice that this is here? + template + CommitmentProofOfKnowledge(const IntegerGroupParams* aParams, + const IntegerGroupParams* bParams, Stream& strm): ap(aParams), bp(bParams) + { + strm >> *this; + } + + const Bignum calculateChallenge(const Bignum& a, const Bignum& b, const Bignum &commitOne, const Bignum &commitTwo) const; + + /**Verifies the proof + * + * @return true if the proof is valid. + */ + /**Verifies the proof of equality of the two commitments + * + * @param A value of commitment one + * @param B value of commitment two + * @return + */ + bool Verify(const Bignum& A, const Bignum& B) const; + IMPLEMENT_SERIALIZE + ( + READWRITE(S1); + READWRITE(S2); + READWRITE(S3); + READWRITE(challenge); + ) +private: + const IntegerGroupParams *ap, *bp; + + Bignum S1, S2, S3, challenge; +}; + +} /* namespace libzerocoin */ +#endif /* COMMITMENT_H_ */ diff --git a/src/zerocoin/ParamGeneration.cpp b/src/zerocoin/ParamGeneration.cpp new file mode 100644 index 0000000..d5bd36b --- /dev/null +++ b/src/zerocoin/ParamGeneration.cpp @@ -0,0 +1,654 @@ +/// \file ParamGeneration.cpp +/// +/// \brief Parameter manipulation routines for the Zerocoin cryptographic +/// components. +/// +/// \author Ian Miers, Christina Garman and Matthew Green +/// \date June 2013 +/// +/// \copyright Copyright 2013 Ian Miers, Christina Garman and Matthew Green +/// \license This project is released under the MIT license. + +#include +#include "Zerocoin.h" + +using namespace std; + +namespace libzerocoin { + +/// \brief Fill in a set of Zerocoin parameters from a modulus "N". +/// \param N A trusted RSA modulus +/// \param aux An optional auxiliary string used in derivation +/// \param securityLevel A security level +/// +/// \throws ZerocoinException if the process fails +/// +/// Fills in a ZC_Params data structure deterministically from +/// a trustworthy RSA modulus "N", which is provided as a Bignum. +/// +/// Note: this routine makes the fundamental assumption that "N" +/// encodes a valid RSA-style modulus of the form "e1*e2" for some +/// unknown safe primes "e1" and "e2". These factors must not +/// be known to any party, or the security of Zerocoin is +/// compromised. The integer "N" must be a MINIMUM of 1023 +/// in length, and 3072 bits is strongly recommended. +/// + +void +CalculateParams(Params ¶ms, Bignum N, string aux, uint32_t securityLevel) +{ + params.initialized = false; + params.accumulatorParams.initialized = false; + + // Verify that |N| is > 1023 bits. + uint32_t NLen = N.bitSize(); + if (NLen < 1023) { + throw ZerocoinException("Modulus must be at least 1023 bits"); + } + + // Verify that "securityLevel" is at least 80 bits (minimum). + if (securityLevel < 80) { + throw ZerocoinException("Security level must be at least 80 bits."); + } + + // Set the accumulator modulus to "N". + params.accumulatorParams.accumulatorModulus = N; + + // Calculate the required size of the field "F_p" into which + // we're embedding the coin commitment group. This may throw an + // exception if the securityLevel is too large to be supported + // by the current modulus. + uint32_t pLen = 0; + uint32_t qLen = 0; + calculateGroupParamLengths(NLen - 2, securityLevel, &pLen, &qLen); + + // Calculate candidate parameters ("p", "q") for the coin commitment group + // using a deterministic process based on "N", the "aux" string, and + // the dedicated string "COMMITMENTGROUP". + params.coinCommitmentGroup = deriveIntegerGroupParams(calculateSeed(N, aux, securityLevel, STRING_COMMIT_GROUP), + pLen, qLen); + + // Next, we derive parameters for a second Accumulated Value commitment group. + // This is a Schnorr group with the specific property that the order of the group + // must be exactly equal to "q" from the commitment group. We set + // the modulus of the new group equal to "2q+1" and test to see if this is prime. + params.serialNumberSoKCommitmentGroup = deriveIntegerGroupFromOrder(params.coinCommitmentGroup.modulus); + + // Calculate the parameters for the internal commitment + // using the same process. + params.accumulatorParams.accumulatorPoKCommitmentGroup = deriveIntegerGroupParams(calculateSeed(N, aux, securityLevel, STRING_AIC_GROUP), + qLen + 300, qLen + 1); + + // Calculate the parameters for the accumulator QRN commitment generators. This isn't really + // a whole group, just a pair of random generators in QR_N. + uint32_t resultCtr; + params.accumulatorParams.accumulatorQRNCommitmentGroup.g = generateIntegerFromSeed(NLen - 1, + calculateSeed(N, aux, securityLevel, STRING_QRNCOMMIT_GROUPG), + &resultCtr).pow_mod(Bignum(2), N); + params.accumulatorParams.accumulatorQRNCommitmentGroup.h = generateIntegerFromSeed(NLen - 1, + calculateSeed(N, aux, securityLevel, STRING_QRNCOMMIT_GROUPG), + &resultCtr).pow_mod(Bignum(2), N); + + // Calculate the accumulator base, which we calculate as "u = C**2 mod N" + // where C is an arbitrary value. In the unlikely case that "u = 1" we increment + // "C" and repeat. + Bignum constant(ACCUMULATOR_BASE_CONSTANT); + params.accumulatorParams.accumulatorBase = Bignum(1); + for (uint32_t count = 0; count < MAX_ACCUMGEN_ATTEMPTS && params.accumulatorParams.accumulatorBase.isOne(); count++) { + params.accumulatorParams.accumulatorBase = constant.pow_mod(Bignum(2), params.accumulatorParams.accumulatorModulus); + } + + // Compute the accumulator range. The upper range is the largest possible coin commitment value. + // The lower range is sqrt(upper range) + 1. Since OpenSSL doesn't have + // a square root function we use a slightly higher approximation. + params.accumulatorParams.maxCoinValue = params.coinCommitmentGroup.modulus; + params.accumulatorParams.minCoinValue = Bignum(2).pow((params.coinCommitmentGroup.modulus.bitSize() / 2) + 3); + + // If all went well, mark params as successfully initialized. + params.accumulatorParams.initialized = true; + + // If all went well, mark params as successfully initialized. + params.initialized = true; +} + +/// \brief Format a seed string by hashing several values. +/// \param N A Bignum +/// \param aux An auxiliary string +/// \param securityLevel The security level in bits +/// \param groupName A group description string +/// \throws ZerocoinException if the process fails +/// +/// Returns the hash of the value. + +uint256 +calculateGeneratorSeed(uint256 seed, uint256 pSeed, uint256 qSeed, string label, uint32_t index, uint32_t count) +{ + CHashWriter hasher(0,0); + uint256 hash; + + // Compute the hash of: + // ||||||groupName + hasher << seed; + hasher << string("||"); + hasher << pSeed; + hasher << string("||"); + hasher << qSeed; + hasher << string("||"); + hasher << label; + hasher << string("||"); + hasher << index; + hasher << string("||"); + hasher << count; + + return hasher.GetHash(); +} + +/// \brief Format a seed string by hashing several values. +/// \param N A Bignum +/// \param aux An auxiliary string +/// \param securityLevel The security level in bits +/// \param groupName A group description string +/// \throws ZerocoinException if the process fails +/// +/// Returns the hash of the value. + +uint256 +calculateSeed(Bignum modulus, string auxString, uint32_t securityLevel, string groupName) +{ + CHashWriter hasher(0,0); + uint256 hash; + + // Compute the hash of: + // ||||||groupName + hasher << modulus; + hasher << string("||"); + hasher << securityLevel; + hasher << string("||"); + hasher << auxString; + hasher << string("||"); + hasher << groupName; + + return hasher.GetHash(); +} + +uint256 +calculateHash(uint256 input) +{ + CHashWriter hasher(0,0); + + // Compute the hash of "input" + hasher << input; + + return hasher.GetHash(); +} + +/// \brief Calculate field/group parameter sizes based on a security level. +/// \param maxPLen Maximum size of the field (modulus "p") in bits. +/// \param securityLevel Required security level in bits (at least 80) +/// \param pLen Result: length of "p" in bits +/// \param qLen Result: length of "q" in bits +/// \throws ZerocoinException if the process fails +/// +/// Calculates the appropriate sizes of "p" and "q" for a prime-order +/// subgroup of order "q" embedded within a field "F_p". The sizes +/// are based on a 'securityLevel' provided in symmetric-equivalent +/// bits. Our choices slightly exceed the specs in FIPS 186-3: +/// +/// securityLevel = 80: pLen = 1024, qLen = 256 +/// securityLevel = 112: pLen = 2048, qLen = 256 +/// securityLevel = 128: qLen = 3072, qLen = 320 +/// +/// If the length of "p" exceeds the length provided in "maxPLen", or +/// if "securityLevel < 80" this routine throws an exception. + +void +calculateGroupParamLengths(uint32_t maxPLen, uint32_t securityLevel, + uint32_t *pLen, uint32_t *qLen) +{ + *pLen = *qLen = 0; + + if (securityLevel < 80) { + throw ZerocoinException("Security level must be at least 80 bits."); + } else if (securityLevel == 80) { + *qLen = 256; + *pLen = 1024; + } else if (securityLevel <= 112) { + *qLen = 256; + *pLen = 2048; + } else if (securityLevel <= 128) { + *qLen = 320; + *pLen = 3072; + } else { + throw ZerocoinException("Security level not supported."); + } + + if (*pLen > maxPLen) { + throw ZerocoinException("Modulus size is too small for this security level."); + } +} + +/// \brief Deterministically compute a set of group parameters using NIST procedures. +/// \param seedStr A byte string seeding the process. +/// \param pLen The desired length of the modulus "p" in bits +/// \param qLen The desired length of the order "q" in bits +/// \return An IntegerGroupParams object +/// +/// Calculates the description of a group G of prime order "q" embedded within +/// a field "F_p". The input to this routine is in arbitrary seed. It uses the +/// algorithms described in FIPS 186-3 Appendix A.1.2 to calculate +/// primes "p" and "q". It uses the procedure in Appendix A.2.3 to +/// derive two generators "g", "h". + +IntegerGroupParams +deriveIntegerGroupParams(uint256 seed, uint32_t pLen, uint32_t qLen) +{ + IntegerGroupParams result; + Bignum p; + Bignum q; + uint256 pSeed, qSeed; + + // Calculate "p" and "q" and "domain_parameter_seed" from the + // "seed" buffer above, using the procedure described in NIST + // FIPS 186-3, Appendix A.1.2. + calculateGroupModulusAndOrder(seed, pLen, qLen, &(result.modulus), + &(result.groupOrder), &pSeed, &qSeed); + + // Calculate the generators "g", "h" using the process described in + // NIST FIPS 186-3, Appendix A.2.3. This algorithm takes ("p", "q", + // "domain_parameter_seed", "index"). We use "index" value 1 + // to generate "g" and "index" value 2 to generate "h". + result.g = calculateGroupGenerator(seed, pSeed, qSeed, result.modulus, result.groupOrder, 1); + result.h = calculateGroupGenerator(seed, pSeed, qSeed, result.modulus, result.groupOrder, 2); + + // Perform some basic tests to make sure we have good parameters + if ((uint32_t)(result.modulus.bitSize()) < pLen || // modulus is pLen bits long + (uint32_t)(result.groupOrder.bitSize()) < qLen || // order is qLen bits long + !(result.modulus.isPrime()) || // modulus is prime + !(result.groupOrder.isPrime()) || // order is prime + !((result.g.pow_mod(result.groupOrder, result.modulus)).isOne()) || // g^order mod modulus = 1 + !((result.h.pow_mod(result.groupOrder, result.modulus)).isOne()) || // h^order mod modulus = 1 + ((result.g.pow_mod(Bignum(100), result.modulus)).isOne()) || // g^100 mod modulus != 1 + ((result.h.pow_mod(Bignum(100), result.modulus)).isOne()) || // h^100 mod modulus != 1 + result.g == result.h || // g != h + result.g.isOne()) { // g != 1 + // If any of the above tests fail, throw an exception + throw ZerocoinException("Group parameters are not valid"); + } + + return result; +} + +/// \brief Deterministically compute a set of group parameters with a specified order. +/// \param groupOrder The order of the group +/// \return An IntegerGroupParams object +/// +/// Given "q" calculates the description of a group G of prime order "q" embedded within +/// a field "F_p". + +IntegerGroupParams +deriveIntegerGroupFromOrder(Bignum &groupOrder) +{ + IntegerGroupParams result; + + // Set the order to "groupOrder" + result.groupOrder = groupOrder; + + // Try possible values for "modulus" of the form "groupOrder * 2 * i" where + // "p" is prime and i is a counter starting at 1. + for (uint32_t i = 1; i < NUM_SCHNORRGEN_ATTEMPTS; i++) { + // Set modulus equal to "groupOrder * 2 * i" + result.modulus = (result.groupOrder * Bignum(i*2)) + Bignum(1); + + // Test the result for primality + // TODO: This is a probabilistic routine and thus not the right choice + if (result.modulus.isPrime(256)) { + + // Success. + // + // Calculate the generators "g", "h" using the process described in + // NIST FIPS 186-3, Appendix A.2.3. This algorithm takes ("p", "q", + // "domain_parameter_seed", "index"). We use "index" value 1 + // to generate "g" and "index" value 2 to generate "h". + uint256 seed = calculateSeed(groupOrder, "", 128, ""); + uint256 pSeed = calculateHash(seed); + uint256 qSeed = calculateHash(pSeed); + result.g = calculateGroupGenerator(seed, pSeed, qSeed, result.modulus, result.groupOrder, 1); + result.h = calculateGroupGenerator(seed, pSeed, qSeed, result.modulus, result.groupOrder, 2); + + // Perform some basic tests to make sure we have good parameters + if (!(result.modulus.isPrime()) || // modulus is prime + !(result.groupOrder.isPrime()) || // order is prime + !((result.g.pow_mod(result.groupOrder, result.modulus)).isOne()) || // g^order mod modulus = 1 + !((result.h.pow_mod(result.groupOrder, result.modulus)).isOne()) || // h^order mod modulus = 1 + ((result.g.pow_mod(Bignum(100), result.modulus)).isOne()) || // g^100 mod modulus != 1 + ((result.h.pow_mod(Bignum(100), result.modulus)).isOne()) || // h^100 mod modulus != 1 + result.g == result.h || // g != h + result.g.isOne()) { // g != 1 + // If any of the above tests fail, throw an exception + throw ZerocoinException("Group parameters are not valid"); + } + + return result; + } + } + + // If we reached this point group generation has failed. Throw an exception. + throw ZerocoinException("Too many attempts to generate Schnorr group."); +} + +/// \brief Deterministically compute a group description using NIST procedures. +/// \param seed A byte string seeding the process. +/// \param pLen The desired length of the modulus "p" in bits +/// \param qLen The desired length of the order "q" in bits +/// \param resultModulus A value "p" describing a finite field "F_p" +/// \param resultGroupOrder A value "q" describing the order of a subgroup +/// \param resultDomainParameterSeed A resulting seed for use in later calculations. +/// +/// Calculates the description of a group G of prime order "q" embedded within +/// a field "F_p". The input to this routine is in arbitrary seed. It uses the +/// algorithms described in FIPS 186-3 Appendix A.1.2 to calculate +/// primes "p" and "q". + +void +calculateGroupModulusAndOrder(uint256 seed, uint32_t pLen, uint32_t qLen, + Bignum *resultModulus, Bignum *resultGroupOrder, + uint256 *resultPseed, uint256 *resultQseed) +{ + // Verify that the seed length is >= qLen + if (qLen > (sizeof(seed)) * 8) { + // TODO: The use of 256-bit seeds limits us to 256-bit group orders. We should probably change this. + // throw ZerocoinException("Seed is too short to support the required security level."); + } + +#ifdef ZEROCOIN_DEBUG + cout << "calculateGroupModulusAndOrder: pLen = " << pLen << endl; +#endif + + // Generate a random prime for the group order. + // This may throw an exception, which we'll pass upwards. + // Result is the value "resultGroupOrder", "qseed" and "qgen_counter". + uint256 qseed; + uint32_t qgen_counter; + *resultGroupOrder = generateRandomPrime(qLen, seed, &qseed, &qgen_counter); + + // Using ⎡pLen / 2 + 1⎤ as the length and qseed as the input_seed, use the random prime + // routine to obtain p0 , pseed, and pgen_counter. We pass exceptions upward. + uint32_t p0len = ceil((pLen / 2.0) + 1); + uint256 pseed; + uint32_t pgen_counter; + Bignum p0 = generateRandomPrime(p0len, qseed, &pseed, &pgen_counter); + + // Set x = 0, old_counter = pgen_counter + uint32_t old_counter = pgen_counter; + + // Generate a random integer "x" of pLen bits + uint32_t iterations; + Bignum x = generateIntegerFromSeed(pLen, pseed, &iterations); + pseed += (iterations + 1); + + // Set x = 2^{pLen−1} + (x mod 2^{pLen–1}). + Bignum powerOfTwo = Bignum(2).pow(pLen-1); + x = powerOfTwo + (x % powerOfTwo); + + // t = ⎡x / (2 * resultGroupOrder * p0)⎤. + // TODO: we don't have a ceiling function + Bignum t = x / (Bignum(2) * (*resultGroupOrder) * p0); + + // Now loop until we find a valid prime "p" or we fail due to + // pgen_counter exceeding ((4*pLen) + old_counter). + for ( ; pgen_counter <= ((4*pLen) + old_counter) ; pgen_counter++) { + // If (2 * t * resultGroupOrder * p0 + 1) > 2^{pLen}, then + // t = ⎡2^{pLen−1} / (2 * resultGroupOrder * p0)⎤. + powerOfTwo = Bignum(2).pow(pLen); + Bignum prod = (Bignum(2) * t * (*resultGroupOrder) * p0) + Bignum(1); + if (prod > powerOfTwo) { + // TODO: implement a ceil function + t = Bignum(2).pow(pLen-1) / (Bignum(2) * (*resultGroupOrder) * p0); + } + + // Compute a candidate prime resultModulus = 2tqp0 + 1. + *resultModulus = (Bignum(2) * t * (*resultGroupOrder) * p0) + Bignum(1); + + // Verify that resultModulus is prime. First generate a pseudorandom integer "a". + Bignum a = generateIntegerFromSeed(pLen, pseed, &iterations); + pseed += iterations + 1; + + // Set a = 2 + (a mod (resultModulus–3)). + a = Bignum(2) + (a % ((*resultModulus) - Bignum(3))); + + // Set z = a^{2 * t * resultGroupOrder} mod resultModulus + Bignum z = a.pow_mod(Bignum(2) * t * (*resultGroupOrder), (*resultModulus)); + + // If GCD(z–1, resultModulus) == 1 AND (z^{p0} mod resultModulus == 1) + // then we have found our result. Return. + if ((resultModulus->gcd(z - Bignum(1))).isOne() && + (z.pow_mod(p0, (*resultModulus))).isOne()) { + // Success! Return the seeds and primes. + *resultPseed = pseed; + *resultQseed = qseed; + return; + } + + // This prime did not work out. Increment "t" and try again. + t = t + Bignum(1); + } // loop continues until pgen_counter exceeds a limit + + // We reach this point only if we exceeded our maximum iteration count. + // Throw an exception. + throw ZerocoinException("Unable to generate a prime modulus for the group"); +} + +/// \brief Deterministically compute a generator for a given group. +/// \param seed A first seed for the process. +/// \param pSeed A second seed for the process. +/// \param qSeed A third seed for the process. +/// \param modulus Proposed prime modulus for the field. +/// \param groupOrder Proposed order of the group. +/// \param index Index value, selects which generator you're building. +/// \return The resulting generator. +/// \throws A ZerocoinException if error. +/// +/// Generates a random group generator deterministically as a function of (seed,pSeed,qSeed) +/// Uses the algorithm described in FIPS 186-3 Appendix A.2.3. + +Bignum +calculateGroupGenerator(uint256 seed, uint256 pSeed, uint256 qSeed, Bignum modulus, Bignum groupOrder, uint32_t index) +{ + Bignum result; + + // Verify that 0 <= index < 256 + if (index > 255) { + throw ZerocoinException("Invalid index for group generation"); + } + + // Compute e = (modulus - 1) / groupOrder + Bignum e = (modulus - Bignum(1)) / groupOrder; + + // Loop until we find a generator + for (uint32_t count = 1; count < MAX_GENERATOR_ATTEMPTS; count++) { + // hash = Hash(seed || pSeed || qSeed || “ggen” || index || count + uint256 hash = calculateGeneratorSeed(seed, pSeed, qSeed, "ggen", index, count); + Bignum W(hash); + + // Compute result = W^e mod p + result = W.pow_mod(e, modulus); + + // If result > 1, we have a generator + if (result > 1) { + return result; + } + } + + // We only get here if we failed to find a generator + throw ZerocoinException("Unable to find a generator, too many attempts"); +} + +/// \brief Deterministically compute a random prime number. +/// \param primeBitLen Desired bit length of the prime. +/// \param in_seed Input seed for the process. +/// \param out_seed Result: output seed from the process. +/// \param prime_gen_counter Result: number of iterations required. +/// \return The resulting prime number. +/// \throws A ZerocoinException if error. +/// +/// Generates a random prime number of primeBitLen bits from a given input +/// seed. Uses the Shawe-Taylor algorithm as described in FIPS 186-3 +/// Appendix C.6. This is a recursive function. + +Bignum +generateRandomPrime(uint32_t primeBitLen, uint256 in_seed, uint256 *out_seed, + uint32_t *prime_gen_counter) +{ + // Verify that primeBitLen is not too small + if (primeBitLen < 2) { + throw ZerocoinException("Prime length is too short"); + } + + // If primeBitLen < 33 bits, perform the base case. + if (primeBitLen < 33) { + Bignum result(0); + + // Set prime_seed = in_seed, prime_gen_counter = 0. + uint256 prime_seed = in_seed; + (*prime_gen_counter) = 0; + + // Loop up to "4 * primeBitLen" iterations. + while ((*prime_gen_counter) < (4 * primeBitLen)) { + + // Generate a pseudorandom integer "c" of length primeBitLength bits + uint32_t iteration_count; + Bignum c = generateIntegerFromSeed(primeBitLen, prime_seed, &iteration_count); +#ifdef ZEROCOIN_DEBUG + cout << "generateRandomPrime: primeBitLen = " << primeBitLen << endl; + cout << "Generated c = " << c << endl; +#endif + + prime_seed += (iteration_count + 1); + (*prime_gen_counter)++; + + // Set "intc" to be the least odd integer >= "c" we just generated + uint32_t intc = c.getulong(); + intc = (2 * floor(intc / 2.0)) + 1; +#ifdef ZEROCOIN_DEBUG + cout << "Should be odd. c = " << intc << endl; + cout << "The big num is: c = " << c << endl; +#endif + + // Perform trial division on this (relatively small) integer to determine if "intc" + // is prime. If so, return success. + if (primalityTestByTrialDivision(intc)) { + // Return "intc" converted back into a Bignum and "prime_seed". We also updated + // the variable "prime_gen_counter" in previous statements. + result = intc; + *out_seed = prime_seed; + + // Success + return result; + } + } // while() + + // If we reached this point there was an error finding a candidate prime + // so throw an exception. + throw ZerocoinException("Unable to find prime in Shawe-Taylor algorithm"); + + // END OF BASE CASE + } + // If primeBitLen >= 33 bits, perform the recursive case. + else { + // Recurse to find a new random prime of roughly half the size + uint32_t newLength = ceil((double)primeBitLen / 2.0) + 1; + Bignum c0 = generateRandomPrime(newLength, in_seed, out_seed, prime_gen_counter); + + // Generate a random integer "x" of primeBitLen bits using the output + // of the previous call. + uint32_t numIterations; + Bignum x = generateIntegerFromSeed(primeBitLen, *out_seed, &numIterations); + (*out_seed) += numIterations + 1; + + // Compute "t" = ⎡x / (2 * c0⎤ + // TODO no Ceiling call + Bignum t = x / (Bignum(2) * c0); + + // Repeat the following procedure until we find a prime (or time out) + for (uint32_t testNum = 0; testNum < MAX_PRIMEGEN_ATTEMPTS; testNum++) { + + // If ((2 * t * c0) + 1 > 2^{primeBitLen}), + // then t = ⎡2^{primeBitLen} – 1 / (2 * c0)⎤. + if ((Bignum(2) * t * c0) > (Bignum(2).pow(Bignum(primeBitLen)))) { + t = ((Bignum(2).pow(Bignum(primeBitLen))) - Bignum(1)) / (Bignum(2) * c0); + } + + // Set c = (2 * t * c0) + 1 + Bignum c = (Bignum(2) * t * c0) + Bignum(1); + + // Increment prime_gen_counter + (*prime_gen_counter)++; + + // Test "c" for primality as follows: + // 1. First pick an integer "a" in between 2 and (c - 2) + Bignum a = generateIntegerFromSeed(c.bitSize(), (*out_seed), &numIterations); + a = Bignum(2) + (a % (c - Bignum(3))); + (*out_seed) += (numIterations + 1); + + // 2. Compute "z" = a^{2*t} mod c + Bignum z = a.pow_mod(Bignum(2) * t, c); + + // 3. Check if "c" is prime. + // Specifically, verify that gcd((z-1), c) == 1 AND (z^c0 mod c) == 1 + // If so we return "c" as our result. + if (c.gcd(z - Bignum(1)).isOne() && z.pow_mod(c0, c).isOne()) { + // Return "c", out_seed and prime_gen_counter + // (the latter two of which were already updated) + return c; + } + + // 4. If the test did not succeed, increment "t" and loop + t = t + Bignum(1); + } // end of test loop + } + + // We only reach this point if the test loop has iterated MAX_PRIMEGEN_ATTEMPTS + // and failed to identify a valid prime. Throw an exception. + throw ZerocoinException("Unable to generate random prime (too many tests)"); +} + +Bignum +generateIntegerFromSeed(uint32_t numBits, uint256 seed, uint32_t *numIterations) +{ + Bignum result(0); + uint32_t iterations = ceil((double)numBits / (double)HASH_OUTPUT_BITS); + +#ifdef ZEROCOIN_DEBUG + cout << "numBits = " << numBits << endl; + cout << "iterations = " << iterations << endl; +#endif + + // Loop "iterations" times filling up the value "result" with random bits + for (uint32_t count = 0; count < iterations; count++) { + // result += ( H(pseed + count) * 2^{count * p0len} ) + result += Bignum(calculateHash(seed + count)) * Bignum(2).pow(count * HASH_OUTPUT_BITS); + } + + result = Bignum(2).pow(numBits - 1) + (result % (Bignum(2).pow(numBits - 1))); + + // Return the number of iterations and the result + *numIterations = iterations; + return result; +} + +/// \brief Determines whether a uint32_t is a prime through trial division. +/// \param candidate Candidate to test. +/// \return true if the value is prime, false otherwise +/// +/// Performs trial division to determine whether a uint32_t is prime. + +bool +primalityTestByTrialDivision(uint32_t candidate) +{ + // TODO: HACK HACK WRONG WRONG + Bignum canBignum(candidate); + + return canBignum.isPrime(); +} + +} // namespace libzerocoin diff --git a/src/zerocoin/ParamGeneration.h b/src/zerocoin/ParamGeneration.h new file mode 100644 index 0000000..de2d452 --- /dev/null +++ b/src/zerocoin/ParamGeneration.h @@ -0,0 +1,53 @@ +/// \file ParamGeneration.h +/// +/// \brief Parameter generation routines for Zerocoin. +/// +/// \author Ian Miers, Christina Garman and Matthew Green +/// \date June 2013 +/// +/// \copyright Copyright 2013 Ian Miers, Christina Garman and Matthew Green +/// \license This project is released under the MIT license. + +#ifndef PARAMGENERATION_H_ +#define PARAMGENERATION_H_ + +namespace libzerocoin { + +void CalculateParams(Params ¶ms, Bignum N, std::string aux, uint32_t securityLevel); +void calculateGroupParamLengths(uint32_t maxPLen, uint32_t securityLevel, + uint32_t *pLen, uint32_t *qLen); + +// Constants +#define STRING_COMMIT_GROUP "COIN_COMMITMENT_GROUP" +#define STRING_AVC_GROUP "ACCUMULATED_VALUE_COMMITMENT_GROUP" +#define STRING_AVC_ORDER "ACCUMULATED_VALUE_COMMITMENT_ORDER" +#define STRING_AIC_GROUP "ACCUMULATOR_INTERNAL_COMMITMENT_GROUP" +#define STRING_QRNCOMMIT_GROUPG "ACCUMULATOR_QRN_COMMITMENT_GROUPG" +#define STRING_QRNCOMMIT_GROUPH "ACCUMULATOR_QRN_COMMITMENT_GROUPH" +#define ACCUMULATOR_BASE_CONSTANT 31 +#define MAX_PRIMEGEN_ATTEMPTS 10000 +#define MAX_ACCUMGEN_ATTEMPTS 10000 +#define MAX_GENERATOR_ATTEMPTS 10000 +#define NUM_SCHNORRGEN_ATTEMPTS 10000 + +// Prototypes +bool primalityTestByTrialDivision(uint32_t candidate); +uint256 calculateSeed(Bignum modulus, std::string auxString, uint32_t securityLevel, std::string groupName); +uint256 calculateGeneratorSeed(uint256 seed, uint256 pSeed, uint256 qSeed, std::string label, uint32_t index, uint32_t count); + +uint256 calculateHash(uint256 input); +IntegerGroupParams deriveIntegerGroupParams(uint256 seed, uint32_t pLen, uint32_t qLen); +IntegerGroupParams deriveIntegerGroupFromOrder(Bignum &groupOrder); +void calculateGroupModulusAndOrder(uint256 seed, uint32_t pLen, uint32_t qLen, + Bignum *resultModulus, Bignum *resultGroupOrder, + uint256 *resultPseed, uint256 *resultQseed); +Bignum calculateGroupGenerator(uint256 seed, uint256 pSeed, uint256 qSeed, Bignum modulus, + Bignum groupOrder, uint32_t index); +Bignum generateRandomPrime(uint32_t primeBitLen, uint256 in_seed, uint256 *out_seed, + uint32_t *prime_gen_counter); +Bignum generateIntegerFromSeed(uint32_t numBits, uint256 seed, uint32_t *numIterations); +bool primalityTestByTrialDivision(uint32_t candidate); + +}/* namespace libzerocoin */ + +#endif /* PARAMGENERATION_H_ */ diff --git a/src/zerocoin/Params.cpp b/src/zerocoin/Params.cpp new file mode 100644 index 0000000..c275044 --- /dev/null +++ b/src/zerocoin/Params.cpp @@ -0,0 +1,45 @@ +/** +* @file Params.cpp +* +* @brief Parameter class for Zerocoin. +* +* @author Ian Miers, Christina Garman and Matthew Green +* @date June 2013 +* +* @copyright Copyright 2013 Ian Miers, Christina Garman and Matthew Green +* @license This project is released under the MIT license. +**/ +#include "Zerocoin.h" + +namespace libzerocoin { + +Params::Params(Bignum N, uint32_t securityLevel) { + this->zkp_hash_len = securityLevel; + this->zkp_iterations = securityLevel; + + this->accumulatorParams.k_prime = ACCPROOF_KPRIME; + this->accumulatorParams.k_dprime = ACCPROOF_KDPRIME; + + // Generate the parameters + CalculateParams(*this, N, ZEROCOIN_PROTOCOL_VERSION, securityLevel); + + this->accumulatorParams.initialized = true; + this->initialized = true; +} + +AccumulatorAndProofParams::AccumulatorAndProofParams() { + this->initialized = false; +} + +IntegerGroupParams::IntegerGroupParams() { + this->initialized = false; +} + +Bignum IntegerGroupParams::randomElement() const { + // The generator of the group raised + // to a random number less than the order of the group + // provides us with a uniformly distributed random number. + return this->g.pow_mod(Bignum::randBignum(this->groupOrder),this->modulus); +} + +} /* namespace libzerocoin */ diff --git a/src/zerocoin/Params.h b/src/zerocoin/Params.h new file mode 100644 index 0000000..60a5af4 --- /dev/null +++ b/src/zerocoin/Params.h @@ -0,0 +1,216 @@ +/** +* @file Params.h +* +* @brief Parameter classes for Zerocoin. +* +* @author Ian Miers, Christina Garman and Matthew Green +* @date June 2013 +* +* @copyright Copyright 2013 Ian Miers, Christina Garman and Matthew Green +* @license This project is released under the MIT license. +**/ +#ifndef PARAMS_H_ +#define PARAMS_H_ + +namespace libzerocoin { + +class IntegerGroupParams { +public: + /** @brief Integer group class, default constructor + * + * Allocates an empty (uninitialized) set of parameters. + **/ + IntegerGroupParams(); + + /** + * Generates a random group element + * @return a random element in the group. + */ + Bignum randomElement() const; + bool initialized; + + /** + * A generator for the group. + */ + Bignum g; + + /** + * A second generator for the group. + * Note log_g(h) and log_h(g) must + * be unknown. + */ + Bignum h; + + /** + * The modulus for the group. + */ + Bignum modulus; + + /** + * The order of the group + */ + Bignum groupOrder; + + IMPLEMENT_SERIALIZE + ( + READWRITE(initialized); + READWRITE(g); + READWRITE(h); + READWRITE(modulus); + READWRITE(groupOrder); + ) +}; + +class AccumulatorAndProofParams { +public: + /** @brief Construct a set of Zerocoin parameters from a modulus "N". + * @param N A trusted RSA modulus + * @param securityLevel A security level expressed in symmetric bits (default 80) + * + * Allocates and derives a set of Zerocoin parameters from + * a trustworthy RSA modulus "N". This routine calculates all + * of the remaining parameters (group descriptions etc.) from N + * using a verifiable, deterministic procedure. + * + * Note: this constructor makes the fundamental assumption that "N" + * encodes a valid RSA-style modulus of the form "e1 * e2" where + * "e1" and "e2" are safe primes. The factors "e1", "e2" MUST NOT + * be known to any party, or the security of Zerocoin is + * compromised. The integer "N" must be a MINIMUM of 1024 + * in length. 3072 bits is strongly recommended. + **/ + AccumulatorAndProofParams(); + + //AccumulatorAndProofParams(Bignum accumulatorModulus); + + bool initialized; + + /** + * Modulus used for the accumulator. + * Product of two safe primes who's factorization is unknown. + */ + Bignum accumulatorModulus; + + /** + * The initial value for the accumulator + * A random Quadratic residue mod n thats not 1 + */ + Bignum accumulatorBase; + + /** + * Lower bound on the value for committed coin. + * Required by the accumulator proof. + */ + Bignum minCoinValue; + + /** + * Upper bound on the value for a comitted coin. + * Required by the accumulator proof. + */ + Bignum maxCoinValue; + + /** + * The second of two groups used to form a commitment to + * a coin (which it self is a commitment to a serial number). + * This one differs from serialNumberSokCommitment due to + * restrictions from Camenisch and Lysyanskaya's paper. + */ + IntegerGroupParams accumulatorPoKCommitmentGroup; + + /** + * Hidden order quadratic residue group mod N. + * Used in the accumulator proof. + */ + IntegerGroupParams accumulatorQRNCommitmentGroup; + + /** + * Security parameter. + * Bit length of the challenges used in the accumulator proof. + */ + uint32_t k_prime; + + /** + * Security parameter. + * The statistical zero-knowledgeness of the accumulator proof. + */ + uint32_t k_dprime; + + IMPLEMENT_SERIALIZE + ( + READWRITE(initialized); + READWRITE(accumulatorModulus); + READWRITE(accumulatorBase); + READWRITE(accumulatorPoKCommitmentGroup); + READWRITE(accumulatorQRNCommitmentGroup); + READWRITE(minCoinValue); + READWRITE(maxCoinValue); + READWRITE(k_prime); + READWRITE(k_dprime); + ) +}; + +class Params { +public: + /** @brief Construct a set of Zerocoin parameters from a modulus "N". + * @param N A trusted RSA modulus + * @param securityLevel A security level expressed in symmetric bits (default 80) + * + * Allocates and derives a set of Zerocoin parameters from + * a trustworthy RSA modulus "N". This routine calculates all + * of the remaining parameters (group descriptions etc.) from N + * using a verifiable, deterministic procedure. + * + * Note: this constructor makes the fundamental assumption that "N" + * encodes a valid RSA-style modulus of the form "e1 * e2" where + * "e1" and "e2" are safe primes. The factors "e1", "e2" MUST NOT + * be known to any party, or the security of Zerocoin is + * compromised. The integer "N" must be a MINIMUM of 1024 + * in length. 3072 bits is strongly recommended. + **/ + Params(Bignum accumulatorModulus, + uint32_t securityLevel = ZEROCOIN_DEFAULT_SECURITYLEVEL); + + bool initialized; + + AccumulatorAndProofParams accumulatorParams; + + /** + * The Quadratic Residue group from which we form + * a coin as a commitment to a serial number. + */ + IntegerGroupParams coinCommitmentGroup; + + /** + * One of two groups used to form a commitment to + * a coin (which it self is a commitment to a serial number). + * This is the one used in the serial number poof. + * It's order must be equal to the modulus of coinCommitmentGroup. + */ + IntegerGroupParams serialNumberSoKCommitmentGroup; + + /** + * The number of iterations to use in the serial + * number proof. + */ + uint32_t zkp_iterations; + + /** + * The amount of the hash function we use for + * proofs. + */ + uint32_t zkp_hash_len; + + IMPLEMENT_SERIALIZE + ( + READWRITE(initialized); + READWRITE(accumulatorParams); + READWRITE(coinCommitmentGroup); + READWRITE(serialNumberSoKCommitmentGroup); + READWRITE(zkp_iterations); + READWRITE(zkp_hash_len); + ) +}; + +} /* namespace libzerocoin */ + +#endif /* PARAMS_H_ */ diff --git a/src/zerocoin/SerialNumberSignatureOfKnowledge.cpp b/src/zerocoin/SerialNumberSignatureOfKnowledge.cpp new file mode 100644 index 0000000..1654c50 --- /dev/null +++ b/src/zerocoin/SerialNumberSignatureOfKnowledge.cpp @@ -0,0 +1,139 @@ +/** +* @file SerialNumberSignatureOfKnowledge.cpp +* +* @brief SerialNumberSignatureOfKnowledge class for the Zerocoin library. +* +* @author Ian Miers, Christina Garman and Matthew Green +* @date June 2013 +* +* @copyright Copyright 2013 Ian Miers, Christina Garman and Matthew Green +* @license This project is released under the MIT license. +**/ + +#include "Zerocoin.h" + +namespace libzerocoin { + +SerialNumberSignatureOfKnowledge::SerialNumberSignatureOfKnowledge(const Params* p): params(p) { } + +SerialNumberSignatureOfKnowledge::SerialNumberSignatureOfKnowledge(const + Params* p, const PrivateCoin& coin, const Commitment& commitmentToCoin, + uint256 msghash):params(p), + s_notprime(p->zkp_iterations), + sprime(p->zkp_iterations) { + + // Sanity check: verify that the order of the "accumulatedValueCommitmentGroup" is + // equal to the modulus of "coinCommitmentGroup". Otherwise we will produce invalid + // proofs. + if (params->coinCommitmentGroup.modulus != params->serialNumberSoKCommitmentGroup.groupOrder) { + throw ZerocoinException("Groups are not structured correctly."); + } + + Bignum a = params->coinCommitmentGroup.g; + Bignum b = params->coinCommitmentGroup.h; + Bignum g = params->serialNumberSoKCommitmentGroup.g; + Bignum h = params->serialNumberSoKCommitmentGroup.h; + + CHashWriter hasher(0,0); + hasher << *params << commitmentToCoin.getCommitmentValue() << coin.getSerialNumber(); + + vector r(params->zkp_iterations); + vector v(params->zkp_iterations); + vector c(params->zkp_iterations); + + + for(uint32_t i=0; i < params->zkp_iterations; i++) { + //FIXME we really ought to use one BN_CTX for all of these + // operations for performance reasons, not the one that + // is created individually by the wrapper + r[i] = Bignum::randBignum(params->coinCommitmentGroup.groupOrder); + v[i] = Bignum::randBignum(params->serialNumberSoKCommitmentGroup.groupOrder); + } + + // Openssl's rng is not thread safe, so we don't call it in a parallel loop, + // instead we generate the random values beforehand and run the calculations + // based on those values in parallel. +#ifdef ZEROCOIN_THREADING + #pragma omp parallel for +#endif + for(uint32_t i=0; i < params->zkp_iterations; i++) { + // compute g^{ {a^x b^r} h^v} mod p2 + c[i] = challengeCalculation(coin.getSerialNumber(), r[i], v[i]); + } + + // We can't hash data in parallel either + // because OPENMP cannot not guarantee loops + // execute in order. + for(uint32_t i=0; i < params->zkp_iterations; i++) { + hasher << c[i]; + } + this->hash = hasher.GetHash(); + unsigned char *hashbytes = (unsigned char*) &hash; + +#ifdef ZEROCOIN_THREADING + #pragma omp parallel for +#endif + for(uint32_t i = 0; i < params->zkp_iterations; i++) { + int bit = i % 8; + int byte = i / 8; + + bool challenge_bit = ((hashbytes[byte] >> bit) & 0x01); + if (challenge_bit) { + s_notprime[i] = r[i]; + sprime[i] = v[i]; + } else { + s_notprime[i] = r[i] - coin.getRandomness(); + sprime[i] = v[i] - (commitmentToCoin.getRandomness() * + b.pow_mod(r[i] - coin.getRandomness(), params->serialNumberSoKCommitmentGroup.groupOrder)); + } + } +} + +inline Bignum SerialNumberSignatureOfKnowledge::challengeCalculation(const Bignum& a_exp,const Bignum& b_exp, + const Bignum& h_exp) const { + + Bignum a = params->coinCommitmentGroup.g; + Bignum b = params->coinCommitmentGroup.h; + Bignum g = params->serialNumberSoKCommitmentGroup.g; + Bignum h = params->serialNumberSoKCommitmentGroup.h; + + Bignum exponent = (a.pow_mod(a_exp, params->serialNumberSoKCommitmentGroup.groupOrder) + * b.pow_mod(b_exp, params->serialNumberSoKCommitmentGroup.groupOrder)) % params->serialNumberSoKCommitmentGroup.groupOrder; + + return (g.pow_mod(exponent, params->serialNumberSoKCommitmentGroup.modulus) * h.pow_mod(h_exp, params->serialNumberSoKCommitmentGroup.modulus)) % params->serialNumberSoKCommitmentGroup.modulus; +} + +bool SerialNumberSignatureOfKnowledge::Verify(const Bignum& coinSerialNumber, const Bignum& valueOfCommitmentToCoin, + const uint256 msghash) const { + Bignum a = params->coinCommitmentGroup.g; + Bignum b = params->coinCommitmentGroup.h; + Bignum g = params->serialNumberSoKCommitmentGroup.g; + Bignum h = params->serialNumberSoKCommitmentGroup.h; + CHashWriter hasher(0,0); + hasher << *params << valueOfCommitmentToCoin < tprime(params->zkp_iterations); + unsigned char *hashbytes = (unsigned char*) &this->hash; +#ifdef ZEROCOIN_THREADING + #pragma omp parallel for +#endif + for(uint32_t i = 0; i < params->zkp_iterations; i++) { + int bit = i % 8; + int byte = i / 8; + bool challenge_bit = ((hashbytes[byte] >> bit) & 0x01); + if(challenge_bit) { + tprime[i] = challengeCalculation(coinSerialNumber, s_notprime[i], sprime[i]); + } else { + Bignum exp = b.pow_mod(s_notprime[i], params->serialNumberSoKCommitmentGroup.groupOrder); + tprime[i] = ((valueOfCommitmentToCoin.pow_mod(exp, params->serialNumberSoKCommitmentGroup.modulus) % params->serialNumberSoKCommitmentGroup.modulus) * + (h.pow_mod(sprime[i], params->serialNumberSoKCommitmentGroup.modulus) % params->serialNumberSoKCommitmentGroup.modulus)) % + params->serialNumberSoKCommitmentGroup.modulus; + } + } + for(uint32_t i = 0; i < params->zkp_iterations; i++) { + hasher << tprime[i]; + } + return hasher.GetHash() == hash; +} + +} /* namespace libzerocoin */ diff --git a/src/zerocoin/SerialNumberSignatureOfKnowledge.h b/src/zerocoin/SerialNumberSignatureOfKnowledge.h new file mode 100644 index 0000000..3177618 --- /dev/null +++ b/src/zerocoin/SerialNumberSignatureOfKnowledge.h @@ -0,0 +1,75 @@ +/** +* @file SerialNumberSignatureOfKnowledge.h +* +* @brief SerialNumberSignatureOfKnowledge class for the Zerocoin library. +* +* @author Ian Miers, Christina Garman and Matthew Green +* @date June 2013 +* +* @copyright Copyright 2013 Ian Miers, Christina Garman and Matthew Green +* @license This project is released under the MIT license. +**/ + +#ifndef SERIALNUMBERPROOF_H_ +#define SERIALNUMBERPROOF_H_ + +#include +#include +#include +#include "Params.h" +#include "Coin.h" +#include "Commitment.h" +#include "../bignum.h" +#include "../serialize.h" +#include "Accumulator.h" +#include "../util.h" + +using namespace std; +namespace libzerocoin { + +/**A Signature of knowledge on the hash of metadata attesting that the signer knows the values + * necessary to open a commitment which contains a coin(which it self is of course a commitment) + * with a given serial number. + */ +class SerialNumberSignatureOfKnowledge { +public: + SerialNumberSignatureOfKnowledge(const Params* p); + /** Creates a Signature of knowledge object that a commitment to a coin contains a coin with serial number x + * + * @param p params + * @param coin the coin we are going to prove the serial number of. + * @param commitmentToCoin the commitment to the coin + * @param msghash hash of meta data to create a signature of knowledge on. + */ + SerialNumberSignatureOfKnowledge(const Params* p, const PrivateCoin& coin, const Commitment& commitmentToCoin, uint256 msghash); + + /** Verifies the Signature of knowledge. + * + * @param msghash hash of meta data to create a signature of knowledge on. + * @return + */ + bool Verify(const Bignum& coinSerialNumber, const Bignum& valueOfCommitmentToCoin,const uint256 msghash) const; + + IMPLEMENT_SERIALIZE + ( + READWRITE(s_notprime); + READWRITE(sprime); + READWRITE(hash); + ) +private: + const Params* params; + // challenge hash + uint256 hash; //TODO For efficiency, should this be a bitset where Templates define params? + + // challenge response values + // this is s_notprime instead of s + // because the serialization macros + // define something named s and it conflicts + vector s_notprime; + vector sprime; + inline Bignum challengeCalculation(const Bignum& a_exp, const Bignum& b_exp, + const Bignum& h_exp) const; +}; + +} /* namespace libzerocoin */ +#endif /* SERIALNUMBERPROOF_H_ */ diff --git a/src/zerocoin/SpendMetaData.cpp b/src/zerocoin/SpendMetaData.cpp new file mode 100644 index 0000000..83d5619 --- /dev/null +++ b/src/zerocoin/SpendMetaData.cpp @@ -0,0 +1,19 @@ +/** +* @file SpendMetaData.cpp +* +* @brief SpendMetaData class for the Zerocoin library. +* +* @author Ian Miers, Christina Garman and Matthew Green +* @date June 2013 +* +* @copyright Copyright 2013 Ian Miers, Christina Garman and Matthew Green +* @license This project is released under the MIT license. +**/ + +#include "Zerocoin.h" + +namespace libzerocoin { + +SpendMetaData::SpendMetaData(uint256 accumulatorId, uint256 txHash): accumulatorId(accumulatorId), txHash(txHash) {} + +} /* namespace libzerocoin */ diff --git a/src/zerocoin/SpendMetaData.h b/src/zerocoin/SpendMetaData.h new file mode 100644 index 0000000..855d8f9 --- /dev/null +++ b/src/zerocoin/SpendMetaData.h @@ -0,0 +1,52 @@ +/** +* @file SpendMetaData.h +* +* @brief SpendMetaData class for the Zerocoin library. +* +* @author Ian Miers, Christina Garman and Matthew Green +* @date June 2013 +* +* @copyright Copyright 2013 Ian Miers, Christina Garman and Matthew Green +* @license This project is released under the MIT license. +**/ + +#ifndef SPENDMETADATA_H_ +#define SPENDMETADATA_H_ + +#include "../uint256.h" +#include "../serialize.h" + +using namespace std; +namespace libzerocoin { + +/** Any meta data needed for actual bitcoin integration. + * Can extended provided the getHash() function is updated + */ +class SpendMetaData { +public: + /** + * Creates meta data associated with a coin spend + * @param accumulatorId hash of block containing accumulator + * @param txHash hash of transaction + */ + SpendMetaData(uint256 accumulatorId, uint256 txHash); + + /** + * The hash of the block containing the accumulator CoinSpend + * proves membership in. + */ + uint256 accumulatorId; // The block the accumulator is in + /**Contains the hash of the rest of transaction + * spending a zerocoin (excluding the coinspend proof) + */ + uint256 txHash; // The Hash of the rest of the transaction the spend proof is n. + // Allows us to sign the transaction. + IMPLEMENT_SERIALIZE + ( + READWRITE(accumulatorId); + READWRITE(txHash); + ) +}; + +} /* namespace libzerocoin */ +#endif /* SPENDMETADATA_H_ */ diff --git a/src/zerocoin/ZeroTest.cpp b/src/zerocoin/ZeroTest.cpp new file mode 100644 index 0000000..f00f0c5 --- /dev/null +++ b/src/zerocoin/ZeroTest.cpp @@ -0,0 +1,421 @@ +/** +* @file Tests.cpp +* +* @brief Test routines for Zerocoin. +* +* @author Ian Miers, Christina Garman and Matthew Green +* @date June 2013 +* +* @copyright Copyright 2013 Ian Miers, Christina Garman and Matthew Green +* @license This project is released under the MIT license. +**/ + +using namespace std; + +#include +#include +#include +#include +#include "Zerocoin.h" +#include "../util.h" + +using namespace libzerocoin; +extern Params* ZCParams; + + +#define TESTS_COINS_TO_ACCUMULATE 10 + +// Global test counters +uint32_t gNumTests = 0; +uint32_t gSuccessfulTests = 0; + +// Proof size +uint32_t gProofSize = 0; +uint32_t gCoinSize = 0; +uint32_t gSerialNumberSize = 0; + +// Global coin array +PrivateCoin *gCoins[TESTS_COINS_TO_ACCUMULATE]; + +// Global params +Params *g_Params; + +////////// +// Utility routines +////////// + +void +LogTestResult(string testName, bool (*testPtr)()) +{ + printf("Testing if %s ...\n", testName.c_str()); + + bool testResult = testPtr(); + + if (testResult == true) { + printf("\t[PASS]\n"); + gSuccessfulTests++; + } else { + printf("\t[FAIL]\n"); + } + + gNumTests++; +} + +Bignum +GetTestModulus() +{ + static Bignum testModulus(0); + + // TODO: should use a hard-coded RSA modulus for testing + if (!testModulus) { + Bignum p, q; + + // Note: we are NOT using safe primes for testing because + // they take too long to generate. Don't do this in real + // usage. See the paramgen utility for better code. + p = Bignum::generatePrime(1024, false); + q = Bignum::generatePrime(1024, false); + testModulus = p * q; + } + + return testModulus; +} + +////////// +// Test routines +////////// + +bool +Test_GenRSAModulus() +{ + Bignum result = GetTestModulus(); + + if (!result) { + return false; + } + else { + return true; + } +} + +bool +Test_CalcParamSizes() +{ + bool result = true; +#if 0 + + uint32_t pLen, qLen; + + try { + calculateGroupParamLengths(4000, 80, &pLen, &qLen); + if (pLen < 1024 || qLen < 256) { + result = false; + } + calculateGroupParamLengths(4000, 96, &pLen, &qLen); + if (pLen < 2048 || qLen < 256) { + result = false; + } + calculateGroupParamLengths(4000, 112, &pLen, &qLen); + if (pLen < 3072 || qLen < 320) { + result = false; + } + calculateGroupParamLengths(4000, 120, &pLen, &qLen); + if (pLen < 3072 || qLen < 320) { + result = false; + } + calculateGroupParamLengths(4000, 128, &pLen, &qLen); + if (pLen < 3072 || qLen < 320) { + result = false; + } + } catch (exception &e) { + result = false; + } +#endif + + return result; +} + +bool +Test_GenerateGroupParams() +{ + int32_t pLen = 1024, qLen = 256, count; + IntegerGroupParams group; + + for (count = 0; count < 1; count++) { + + try { + group = deriveIntegerGroupParams(calculateSeed(GetTestModulus(), "test", ZEROCOIN_DEFAULT_SECURITYLEVEL, "TEST GROUP"), pLen, qLen); + } catch (std::runtime_error e) { + printf("Caught exception %s\n", e.what()); + return false; + } + + // Now perform some simple tests on the resulting parameters + if (group.groupOrder.bitSize() < qLen || group.modulus.bitSize() < pLen) { + return false; + } + + Bignum c = group.g.pow_mod(group.groupOrder, group.modulus); + if (!(c.isOne())) return false; + + // Try at multiple parameter sizes + pLen = pLen * 1.5; + qLen = qLen * 1.5; + } + + return true; +} + +bool +Test_ParamGen() +{ + bool result = true; + + try { + // Instantiating testParams runs the parameter generation code + Params testParams(GetTestModulus(),ZEROCOIN_DEFAULT_SECURITYLEVEL); + } catch (runtime_error e) { + printf("ParamGen exception %s\n", e.what()); + result = false; + } + + return result; +} + +bool +Test_Accumulator() +{ + // This test assumes a list of coins were generated during + // the Test_MintCoin() test. + if (gCoins[0] == NULL) { + return false; + } + try { + // Accumulate the coin list from first to last into one accumulator + Accumulator accOne(&g_Params->accumulatorParams); + Accumulator accTwo(&g_Params->accumulatorParams); + Accumulator accThree(&g_Params->accumulatorParams); + Accumulator accFour(&g_Params->accumulatorParams); + AccumulatorWitness wThree(g_Params, accThree, gCoins[0]->getPublicCoin()); + + for (uint32_t i = 0; i < TESTS_COINS_TO_ACCUMULATE; i++) { + accOne += gCoins[i]->getPublicCoin(); + accTwo += gCoins[TESTS_COINS_TO_ACCUMULATE - (i+1)]->getPublicCoin(); + accThree += gCoins[i]->getPublicCoin(); + wThree += gCoins[i]->getPublicCoin(); + if(i != 0) { + accFour += gCoins[i]->getPublicCoin(); + } + } + + // Compare the accumulated results + if (accOne.getValue() != accTwo.getValue() || accOne.getValue() != accThree.getValue()) { + printf("Accumulators don't match\n"); + return false; + } + + if(accFour.getValue() != wThree.getValue()) { + printf("Witness math not working,\n"); + return false; + } + + // Verify that the witness is correct + if (!wThree.VerifyWitness(accThree, gCoins[0]->getPublicCoin()) ) { + printf("Witness not valid\n"); + return false; + } + + // Serialization test: see if we can serialize the accumulator + CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); + ss << accOne; + + // Deserialize it into a new object + Accumulator newAcc(g_Params, ss); + + // Compare the results + if (accOne.getValue() != newAcc.getValue()) { + return false; + } + + } catch (runtime_error e) { + return false; + } + + return true; +} + +bool +Test_EqualityPoK() +{ + // Run this test 10 times + for (uint32_t i = 0; i < 10; i++) { + try { + // Generate a random integer "val" + Bignum val = Bignum::randBignum(g_Params->coinCommitmentGroup.groupOrder); + + // Manufacture two commitments to "val", both + // under different sets of parameters + Commitment one(&g_Params->accumulatorParams.accumulatorPoKCommitmentGroup, val); + + Commitment two(&g_Params->serialNumberSoKCommitmentGroup, val); + + // Now generate a proof of knowledge that "one" and "two" are + // both commitments to the same value + CommitmentProofOfKnowledge pok(&g_Params->accumulatorParams.accumulatorPoKCommitmentGroup, + &g_Params->serialNumberSoKCommitmentGroup, + one, two); + + // Serialize the proof into a stream + CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); + ss << pok; + + // Deserialize back into a PoK object + CommitmentProofOfKnowledge newPok(&g_Params->accumulatorParams.accumulatorPoKCommitmentGroup, + &g_Params->serialNumberSoKCommitmentGroup, + ss); + + if (newPok.Verify(one.getCommitmentValue(), two.getCommitmentValue()) != true) { + return false; + } + + // Just for fun, deserialize the proof a second time + CDataStream ss2(SER_NETWORK, PROTOCOL_VERSION); + ss2 << pok; + + // This time tamper with it, then deserialize it back into a PoK + ss2[15] = 0; + CommitmentProofOfKnowledge newPok2(&g_Params->accumulatorParams.accumulatorPoKCommitmentGroup, + &g_Params->serialNumberSoKCommitmentGroup, + ss2); + + // If the tampered proof verifies, that's a failure! + if (newPok2.Verify(one.getCommitmentValue(), two.getCommitmentValue()) == true) { + return false; + } + + } catch (runtime_error &e) { + return false; + } + } + + return true; +} + +bool +Test_MintCoin() +{ + gCoinSize = 0; + + try { + // Generate a list of coins + for (uint32_t i = 0; i < TESTS_COINS_TO_ACCUMULATE; i++) { + gCoins[i] = new PrivateCoin(g_Params); + + PublicCoin pc = gCoins[i]->getPublicCoin(); + CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); + ss << pc; + gCoinSize += ss.size(); + } + + gCoinSize /= TESTS_COINS_TO_ACCUMULATE; + + } catch (exception &e) { + return false; + } + + return true; +} + +bool +Test_MintAndSpend() +{ + try { + // This test assumes a list of coins were generated in Test_MintCoin() + if (gCoins[0] == NULL) + { + // No coins: mint some. + Test_MintCoin(); + if (gCoins[0] == NULL) { + return false; + } + } + + // Accumulate the list of generated coins into a fresh accumulator. + // The first one gets marked as accumulated for a witness, the + // others just get accumulated normally. + Accumulator acc(&g_Params->accumulatorParams); + AccumulatorWitness wAcc(g_Params, acc, gCoins[0]->getPublicCoin()); + + for (uint32_t i = 0; i < TESTS_COINS_TO_ACCUMULATE; i++) { + acc += gCoins[i]->getPublicCoin(); + wAcc +=gCoins[i]->getPublicCoin(); + } + + // Now spend the coin + SpendMetaData m(1,1); + + CoinSpend spend(g_Params, *(gCoins[0]), acc, wAcc, m); + + // Serialize the proof and deserialize into newSpend + CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); + ss << spend; + gProofSize = ss.size(); + CoinSpend newSpend(g_Params, ss); + + // See if we can verify the deserialized proof (return our result) + bool ret = newSpend.Verify(acc, m); + + // Extract the serial number + Bignum serialNumber = newSpend.getCoinSerialNumber(); + gSerialNumberSize = ceil((double)serialNumber.bitSize() / 8.0); + + return ret; + } catch (runtime_error &e) { + printf("MintAndSpend exception %s\n", e.what()); + return false; + } + + return false; +} + +void +Test_RunAllTests() +{ + printf("ZeroCoin v%s self-test routine\n", ZEROCOIN_VERSION_STRING); + + // Make a new set of parameters from a random RSA modulus + //g_Params = new Params(GetTestModulus()); + g_Params = ZCParams; + + gNumTests = gSuccessfulTests = gProofSize = 0; + for (uint32_t i = 0; i < TESTS_COINS_TO_ACCUMULATE; i++) { + gCoins[i] = NULL; + } + + // Run through all of the Zerocoin tests + LogTestResult("an RSA modulus can be generated", Test_GenRSAModulus); + LogTestResult("parameter sizes are correct", Test_CalcParamSizes); + LogTestResult("group/field parameters can be generated", Test_GenerateGroupParams); + LogTestResult("parameter generation is correct", Test_ParamGen); + LogTestResult("coins can be minted", Test_MintCoin); + LogTestResult("the accumulator works", Test_Accumulator); + LogTestResult("the commitment equality PoK works", Test_EqualityPoK); + LogTestResult("a minted coin can be spent", Test_MintAndSpend); + + printf("\nAverage coin size is %d bytes.\n", gCoinSize); + printf("Serial number size is %d bytes.\n", gSerialNumberSize); + printf("Spend proof size is %d bytes.\n", gProofSize); + + // Summarize test results + if (gSuccessfulTests < gNumTests) { + printf("\nERROR: SOME TESTS FAILED\n"); + } + + // Clear any generated coins + for (uint32_t i = 0; i < TESTS_COINS_TO_ACCUMULATE; i++) { + delete gCoins[i]; + } + + printf("\n%d out of %d tests passed.\n\n", gSuccessfulTests, gNumTests); + delete g_Params; +} diff --git a/src/zerocoin/ZeroTest.h b/src/zerocoin/ZeroTest.h new file mode 100644 index 0000000..36ab6b7 --- /dev/null +++ b/src/zerocoin/ZeroTest.h @@ -0,0 +1,6 @@ +#ifndef ZEROTEST_H_ +#define ZEROTEST_H_ + +void Test_RunAllTests(); + +#endif diff --git a/src/zerocoin/Zerocoin.h b/src/zerocoin/Zerocoin.h new file mode 100644 index 0000000..7672750 --- /dev/null +++ b/src/zerocoin/Zerocoin.h @@ -0,0 +1,61 @@ +/** +* @file Zerocoin.h +* +* @brief Exceptions and constants for Zerocoin +* +* @author Ian Miers, Christina Garman and Matthew Green +* @date June 2013 +* +* @copyright Copyright 2013 Ian Miers, Christina Garman and Matthew Green +* @license This project is released under the MIT license. +**/ + +#ifndef ZEROCOIN_H_ +#define ZEROCOIN_H_ + +#include + +#define ZEROCOIN_DEFAULT_SECURITYLEVEL 80 +#define ZEROCOIN_MIN_SECURITY_LEVEL 80 +#define ZEROCOIN_MAX_SECURITY_LEVEL 80 +#define ACCPROOF_KPRIME 160 +#define ACCPROOF_KDPRIME 128 +#define MAX_COINMINT_ATTEMPTS 10000 +#define ZEROCOIN_MINT_PRIME_PARAM 20 +#define ZEROCOIN_VERSION_STRING "0.11" +#define ZEROCOIN_VERSION_INT 11 +#define ZEROCOIN_PROTOCOL_VERSION "1" +#define HASH_OUTPUT_BITS 256 +#define ZEROCOIN_COMMITMENT_EQUALITY_PROOF "COMMITMENT_EQUALITY_PROOF" +#define ZEROCOIN_ACCUMULATOR_PROOF "ACCUMULATOR_PROOF" +#define ZEROCOIN_SERIALNUMBER_PROOF "SERIALNUMBER_PROOF" + +// Activate multithreaded mode for proof verification + +//#define ZEROCOIN_THREADING 1 + +// Uses a fast technique for coin generation. Could be more vulnerable +// to timing attacks. Turn off if an attacker can measure coin minting time. +#define ZEROCOIN_FAST_MINT 1 + +// Errors thrown by the Zerocoin library + +class ZerocoinException : public std::runtime_error +{ +public: + explicit ZerocoinException(const std::string& str) : std::runtime_error(str) {} +}; + +#include "../serialize.h" +#include "../bignum.h" +#include "../util.h" +#include "Params.h" +#include "Coin.h" +#include "Commitment.h" +#include "Accumulator.h" +#include "AccumulatorProofOfKnowledge.h" +#include "CoinSpend.h" +#include "SerialNumberSignatureOfKnowledge.h" +#include "ParamGeneration.h" + +#endif /* ZEROCOIN_H_ */