So here is the diff so far:
diff --git a/ArmoryQt.py b/ArmoryQt.py
index de98353..54afbe0 100644
--- a/ArmoryQt.py
+++ b/ArmoryQt.py
@@ -96,6 +96,18 @@ class ArmoryMainWindow(QMainWindow):
self.lblLogoIcon.setPixmap(QPixmap(':/armory_logo_green_h56.png'))
if Colors.isDarkBkgd:
self.lblLogoIcon.setPixmap(QPixmap(':/armory_logo_white_text_green_h56.png'))
+ elif USE_NAMECOIN:
+ self.setWindowTitle('Armory - Namecoin Wallet Management')
+ self.iconfile = ':/armory_icon_32x32.png'
+ self.lblLogoIcon.setPixmap(QPixmap(':/armory_logo_h44.png'))
+ if Colors.isDarkBkgd:
+ self.lblLogoIcon.setPixmap(QPixmap(':/armory_logo_white_text_h65.png'))
+ elif USE_NAMECOIN_TESTNET:
+ self.setWindowTitle('Armory - Namecoin Wallet Management [TESTNET]')
+ self.iconfile = ':/armory_icon_green_32x32.png'
+ self.lblLogoIcon.setPixmap(QPixmap(':/armory_logo_green_h56.png'))
+ if Colors.isDarkBkgd:
+ self.lblLogoIcon.setPixmap(QPixmap(':/armory_logo_white_text_green_h56.png'))
else:
self.setWindowTitle('Armory - Bitcoin Wallet Management')
self.iconfile = ':/armory_icon_32x32.png'
@@ -110,7 +122,7 @@ class ArmoryMainWindow(QMainWindow):
self.setWindowIcon(QIcon(self.iconfile))
else:
self.notifCtr = ArmoryMac.MacNotificationHandler.None
- if USE_TESTNET:
+ if USE_TESTNET or USE_NAMECOIN_TESTNET:
self.iconfile = ':/armory_icon_green_fullres.png'
ArmoryMac.MacDockIconHandler.instance().setMainWindow(self)
ArmoryMac.MacDockIconHandler.instance().setIcon(QIcon(self.iconfile))
@@ -533,7 +545,7 @@ class ArmoryMainWindow(QMainWindow):
self.mainDisplayTabs.addTab(self.tabAnnounce, 'Announcements')
##########################################################################
- if USE_TESTNET and not CLI_OPTIONS.disableModules:
+ if (USE_TESTNET or USE_NAMECOIN_TESTNET) and not CLI_OPTIONS.disableModules:
self.loadArmoryModules()
##########################################################################
@@ -958,7 +970,7 @@ class ArmoryMainWindow(QMainWindow):
LOGWARN('Sig on "%s" is valid: %s' % (name, str(isSignedByATI)))
- if not isSignedByATI and not USE_TESTNET:
+ if not isSignedByATI and not (USE_TESTNET or USE_NAMECOIN_TESTNET):
reply = QMessageBox.warning(self, tr("UNSIGNED Module"), tr("""
Armory detected the following module which is
unsigned and may be dangerous:
@@ -1321,7 +1333,7 @@ class ArmoryMainWindow(QMainWindow):
self.sysTray = QSystemTrayIcon(self)
self.sysTray.setIcon( QIcon(self.iconfile) )
self.sysTray.setVisible(True)
- self.sysTray.setToolTip('Armory' + (' [Testnet]' if USE_TESTNET else ''))
+ self.sysTray.setToolTip('Armory' + (' [Testnet]' if USE_TESTNET or USE_NAMECOIN_TESTNET else ''))
self.connect(self.sysTray, SIGNAL('messageClicked()'), self.bringArmoryToFront)
self.connect(self.sysTray, SIGNAL('activated(QSystemTrayIcon::ActivationReason)'), \
self.sysTrayActivated)
@@ -1421,7 +1433,7 @@ class ArmoryMainWindow(QMainWindow):
"""
LOGINFO('setupUriRegistration')
- if USE_TESTNET:
+ if USE_TESTNET or USE_NAMECOIN or USE_NAMECOIN_TESTNET:
return
if OS_LINUX:
@@ -5081,8 +5093,12 @@ class ArmoryMainWindow(QMainWindow):
lastBlkTime = info['toptime']
# Use a reference point if we are starting from scratch
- refBlock = max(290746, lastBlkNum)
- refTime = max(1394922889, lastBlkTime)
+ if COIN == 'Namecoin':
+ refBlock = max(204428, lastBlkNum)
+ refTime = max(1415390883, lastBlkTime)
+ else:
+ refBlock = max(290746, lastBlkNum)
+ refTime = max(1394922889, lastBlkTime)
# Ten min/block is pretty accurate, even from genesis (about 1% slow)
@@ -6929,7 +6945,7 @@ def checkForAlreadyOpenError():
armoryExists.append(proc.pid)
if bexe in proc.name:
LOGINFO('Found bitcoind PID: %d', proc.pid)
- if ('testnet' in proc.name) == USE_TESTNET:
+ if ('testnet' in proc.name) == USE_TESTNET or USE_NAMECOIN_TESTNET:
bitcoindExists.append(proc.pid)
if len(armoryExists)>0:
@@ -6956,7 +6972,7 @@ if 1:
checkForAlreadyOpen()
pixLogo = QPixmap(':/splashlogo.png')
- if USE_TESTNET:
+ if USE_TESTNET or USE_NAMECOIN_TESTNET:
pixLogo = QPixmap(':/splashlogo_testnet.png')
SPLASH = QSplashScreen(pixLogo)
SPLASH.setMask(pixLogo.mask())
diff --git a/SDM.py b/SDM.py
index 3b80b55..238b5d2 100644
--- a/SDM.py
+++ b/SDM.py
@@ -20,7 +20,7 @@ from armoryengine.ArmoryUtils import BITCOIN_PORT, LOGERROR, hex_to_binary, \
launchProcess, killProcessTree, killProcess, LOGWARN, RightNow, HOUR, \
PyBackgroundThread, touchFile, DISABLE_TORRENTDL, secondsToHumanTime, \
bytesToHumanSize, MAGIC_BYTES, deleteBitcoindDBs, TheTDM, satoshiIsAvailable,\
- MEGABYTE, ARMORY_HOME_DIR, CLI_OPTIONS
+ MEGABYTE, ARMORY_HOME_DIR, CLI_OPTIONS, COIN, USE_NAMECOIN_TESTNET
from bitcoinrpc_jsonrpc import authproxy
@@ -277,7 +277,10 @@ class SatoshiDaemonManager(object):
LOGINFO('Total size of files in %s is %s' % (blockDir, sizeStr))
# If they have only a small portion of the blockchain, do it
- szThresh = 100*MEGABYTE if USE_TESTNET else 6*GIGABYTE
+ if USE_TESTNET or USE_NAMECOIN_TESTNET:
+ szThresh = 100*MEGABYTE
+ else:
+ szThresh = 6*GIGABYTE
if blockDirSize < szThresh:
return True
@@ -308,7 +311,7 @@ class SatoshiDaemonManager(object):
self.failedFindHome = False
# If we are supplied a path, then ignore the extra exe search paths
if pathToBitcoindExe==None:
- pathToBitcoindExe = self.findBitcoind(extraExeSearch)
+ pathToBitcoindExe = self.findDaemon(extraExeSearch)
if len(pathToBitcoindExe)==0:
LOGDEBUG('Failed to find bitcoind')
self.failedFindExe = True
@@ -374,7 +377,7 @@ class SatoshiDaemonManager(object):
#############################################################################
- def findBitcoind(self, extraSearchPaths=[]):
+ def findDaemon(self, extraSearchPaths=[]):
self.foundExe = []
searchPaths = list(extraSearchPaths) # create a copy
@@ -382,7 +385,7 @@ class SatoshiDaemonManager(object):
if OS_WINDOWS:
# Making sure the search path argument comes with /daemon and /Bitcoin on Windows
- searchPaths.extend([os.path.join(sp, 'Bitcoin') for sp in searchPaths])
+ searchPaths.extend([os.path.join(sp, COIN) for sp in searchPaths])
searchPaths.extend([os.path.join(sp, 'daemon') for sp in searchPaths])
possBaseDir = []
@@ -407,7 +410,7 @@ class SatoshiDaemonManager(object):
shell = win32com.client.Dispatch('WScript.Shell')
targ = shell.CreateShortCut(path).Targetpath
targDir = os.path.dirname(targ)
- LOGINFO('Found Bitcoin-Qt link on desktop: %s', targDir)
+ LOGINFO('Found %s-Qt link on desktop: %s', COIN, targDir)
possBaseDir.append( targDir )
# Also look in default place in ProgramFiles dirs
@@ -417,12 +420,12 @@ class SatoshiDaemonManager(object):
# Now look at a few subdirs of the
searchPaths.extend(possBaseDir)
- searchPaths.extend([os.path.join(p, 'Bitcoin', 'daemon') for p in possBaseDir])
+ searchPaths.extend([os.path.join(p, COIN, 'daemon') for p in possBaseDir])
searchPaths.extend([os.path.join(p, 'daemon') for p in possBaseDir])
- searchPaths.extend([os.path.join(p, 'Bitcoin') for p in possBaseDir])
+ searchPaths.extend([os.path.join(p, COIN) for p in possBaseDir])
for p in searchPaths:
- testPath = os.path.join(p, 'bitcoind.exe')
+ testPath = os.path.join(p, COIN.lower() + '.exe')
if os.path.exists(testPath):
self.foundExe.append(testPath)
@@ -433,18 +436,18 @@ class SatoshiDaemonManager(object):
else:
searchPaths.extend([os.path.join(p, 'bin/32') for p in extraSearchPaths])
- searchPaths.extend(['/usr/lib/bitcoin/'])
+ searchPaths.extend(['/usr/lib/' + COIN.lower() + '/'])
searchPaths.extend(os.getenv("PATH").split(':'))
for p in searchPaths:
- testPath = os.path.join(p, 'bitcoind')
+ testPath = os.path.join(p, COIN.lower() + 'd')
if os.path.exists(testPath):
self.foundExe.append(testPath)
try:
- locs = subprocess_check_output(['whereis','bitcoind']).split()
+ locs = subprocess_check_output(['whereis',COIN.lower() + 'd']).split()
if len(locs)>1:
- locs = filter(lambda x: os.path.basename(x)=='bitcoind', locs)
+ locs = filter(lambda x: os.path.basename(x)==COIN.lower() + 'd', locs)
LOGINFO('"whereis" returned: %s', str(locs))
self.foundExe.extend(locs)
except:
@@ -461,10 +464,10 @@ class SatoshiDaemonManager(object):
foundIt=True
if not foundIt:
- LOGERROR('Bitcoind could not be found in the specified installation:')
+ LOGERROR(COIN + 'd could not be found in the specified installation:')
for p in extraSearchPaths:
LOGERROR(' %s', p)
- LOGERROR('Bitcoind is being started from:')
+ LOGERROR(COIN + 'd is being started from:')
LOGERROR(' %s', self.foundExe[0])
return self.foundExe
@@ -607,12 +610,16 @@ class SatoshiDaemonManager(object):
pargs = [self.executable]
- if USE_TESTNET:
+ if USE_TESTNET or USE_NAMECOIN_TESTNET:
testhome = self.satoshiHome[:]
if self.satoshiHome.endswith('/testnet3/'):
pargs.append('-datadir=%s' % self.satoshiHome[:-10])
elif self.satoshiHome.endswith('/testnet3'):
pargs.append('-datadir=%s' % self.satoshiHome[:-9])
+ elif self.satoshiHome.endswith('/testnet/'):
+ pargs.append('-datadir=%s' % self.satoshiHome[:-9])
+ elif self.satoshiHome.endswith('/testnet'):
+ pargs.append('-datadir=%s' % self.satoshiHome[:-8])
pargs.append('-testnet')
else:
pargs.append('-datadir=%s' % self.satoshiHome)
diff --git a/armoryd.py b/armoryd.py
index 0198b8b..3d36f36 100644
--- a/armoryd.py
+++ b/armoryd.py
@@ -1495,7 +1495,8 @@ class Armory_Json_Rpc_Server(jsonrpc.JSONRPC):
#'proxy': '',
'difficulty': TheBDM.getTopBlockDifficulty() \
if isReady else -1,
- 'testnet': USE_TESTNET,
+ 'testnet': USE_TESTNET or USE_NAMECOIN_TESTNET,
+ 'chain': COIN
'keypoolsize': self.curWlt.addrPoolSize
}
diff --git a/armoryengine/ArmoryUtils.py b/armoryengine/ArmoryUtils.py
index ed61fa8..103872f 100644
--- a/armoryengine/ArmoryUtils.py
+++ b/armoryengine/ArmoryUtils.py
@@ -62,6 +62,7 @@ ARMORY_INFO_SIGN_ADDR = '1NWvhByxfTXPYNT4zMBmEY3VL8QJQtQoei'
ARMORY_INFO_SIGN_PUBLICKEY = ('04'
'af4abc4b24ef57547dd13a1110e331645f2ad2b99dfe1189abb40a5b24e4ebd8'
'de0c1c372cc46bbee0ce3d1d49312e416a1fa9c7bb3e32a7eb3867d1c6d1f715')
+# We can leave SATOSHI_PUBLIC_KEY here, since it is the same for both Bitcoin and Namecoin
SATOSHI_PUBLIC_KEY = ( '04'
'fc9702847840aaf195de8442ebecedf5b095cdbb9bc716bda9110971b28a49e0'
'ead8564ff0db22209e0374782c093bb899692d524e9d6a6956e7c5ecbcd68284')
@@ -80,6 +81,8 @@ parser.add_option("--satoshi-rpcport", dest="satoshiRpcport",default='DEFAULT',t
parser.add_option("--dbdir", dest="leveldbDir", default='DEFAULT', type='str', help="Location to store blocks database (defaults to --datadir)")
parser.add_option("--rpcport", dest="rpcport", default='DEFAULT', type="str", help="RPC port for running armoryd.py")
parser.add_option("--testnet", dest="testnet", default=False, action="store_true", help="Use the testnet protocol")
+parser.add_option("--namecoin", dest="namecoin", default=False, action="store_true", help="Use Namecoin instead of Bitcoin protocol")
+parser.add_option("--namecoin-testnet", dest="namecoinTestnet", default=False, action="store_true", help="Use Namecoin testnet protocol")
parser.add_option("--offline", dest="offline", default=False, action="store_true", help="Force Armory to run in offline mode")
parser.add_option("--nettimeout", dest="nettimeout", default=2, type="int", help="Timeout for detecting internet connection at startup")
parser.add_option("--interport", dest="interport", default=-1, type="int", help="Port for inter-process communication between Armory instances")
@@ -240,6 +243,18 @@ for opt,val in CLI_OPTIONS.__dict__.iteritems():
USE_TESTNET = CLI_OPTIONS.testnet
#USE_TESTNET = True
+# Use CLI args to determine namecoin or not
+USE_NAMECOIN = CLI_OPTIONS.namecoin
+
+# Use CLI args to determine namecoin testnet or not
+USE_NAMECOIN_TESTNET = CLI_OPTIONS.namecoinTestnet
+
+COIN = 'Bitcoin'
+if USE_NAMECOIN or USE_NAMECOIN_TESTNET:
+ MIN_TX_FEE = 500000
+ MIN_RELAY_TX_FEE = 100000
+ COIN = 'Namecoin'
+
# Set default port for inter-process communication
if CLI_OPTIONS.interport < 0:
CLI_OPTIONS.interport = 8223 + (1 if USE_TESTNET else 0)
@@ -257,7 +272,14 @@ USER_HOME_DIR = ''
BTC_HOME_DIR = ''
ARMORY_HOME_DIR = ''
LEVELDB_DIR = ''
-SUBDIR = 'testnet3' if USE_TESTNET else ''
+if USE_TESTNET:
+ SUBDIR = 'testnet3'
+elif USE_NAMECOIN:
+ SUBDIR = ''
+elif USE_NAMECOIN_TESTNET:
+ SUBDIR = 'testnet'
+else:
+ SUBDIR = ''
if OS_WINDOWS:
OS_NAME = 'Windows'
OS_VARIANT = platform.win32_ver()
@@ -267,27 +289,51 @@ if OS_WINDOWS:
rt = ctypes.windll.shell32.SHGetFolderPathW(0, 26, 0, 0, ctypes.byref(buffer))
USER_HOME_DIR = unicode(buffer.value)
- BTC_HOME_DIR = os.path.join(USER_HOME_DIR, 'Bitcoin', SUBDIR)
+ BTC_HOME_DIR = os.path.join(USER_HOME_DIR, COIN, SUBDIR)
+ if COIN == 'Namecoin':
+ if USE_NAMECOIN:
+ SUBDIR = 'namecoin'
+ elif USE_NAMECOIN_TESTNET:
+ SUBDIR = 'namecoin_testnet'
+ BLKFILE_DIR = BTC_HOME_DIR
+ else:
+ BLKFILE_DIR = os.path.join(BTC_HOME_DIR, 'blocks')
ARMORY_HOME_DIR = os.path.join(USER_HOME_DIR, 'Armory', SUBDIR)
- BLKFILE_DIR = os.path.join(BTC_HOME_DIR, 'blocks')
- BLKFILE_1stFILE = os.path.join(BLKFILE_DIR, 'blk00000.dat')
+ BLKFILE_1stFILE = os.path.join(BLKFILE_DIR,
+ 'blk0001.dat' if COIN == 'Namecoin' else 'blk00000.dat')
elif OS_LINUX:
OS_NAME = 'Linux'
OS_VARIANT = platform.linux_distribution()
USER_HOME_DIR = os.getenv('HOME')
- BTC_HOME_DIR = os.path.join(USER_HOME_DIR, '.bitcoin', SUBDIR)
+ BTC_HOME_DIR = os.path.join(USER_HOME_DIR, '.' + COIN.lower(), SUBDIR)
+ if COIN == 'Namecoin':
+ if USE_NAMECOIN:
+ SUBDIR = 'namecoin'
+ elif USE_NAMECOIN_TESTNET:
+ SUBDIR = 'namecoin_testnet'
+ BLKFILE_DIR = BTC_HOME_DIR
+ else:
+ BLKFILE_DIR = os.path.join(BTC_HOME_DIR, 'blocks')
ARMORY_HOME_DIR = os.path.join(USER_HOME_DIR, '.armory', SUBDIR)
- BLKFILE_DIR = os.path.join(BTC_HOME_DIR, 'blocks')
- BLKFILE_1stFILE = os.path.join(BLKFILE_DIR, 'blk00000.dat')
+ BLKFILE_1stFILE = os.path.join(BLKFILE_DIR,
+ 'blk0001.dat' if COIN == 'Namecoin' else 'blk00000.dat')
elif OS_MACOSX:
platform.mac_ver()
OS_NAME = 'MacOSX'
OS_VARIANT = platform.mac_ver()
USER_HOME_DIR = os.path.expanduser('~/Library/Application Support')
- BTC_HOME_DIR = os.path.join(USER_HOME_DIR, 'Bitcoin', SUBDIR)
+ BTC_HOME_DIR = os.path.join(USER_HOME_DIR, COIN, SUBDIR)
+ if COIN == 'Namecoin':
+ if USE_NAMECOIN:
+ SUBDIR = 'namecoin'
+ elif USE_NAMECOIN_TESTNET:
+ SUBDIR = 'namecoin_testnet'
+ BLKFILE_DIR = BTC_HOME_DIR
+ else:
+ BLKFILE_DIR = os.path.join(BTC_HOME_DIR, 'blocks')
ARMORY_HOME_DIR = os.path.join(USER_HOME_DIR, 'Armory', SUBDIR)
- BLKFILE_DIR = os.path.join(BTC_HOME_DIR, 'blocks')
- BLKFILE_1stFILE = os.path.join(BLKFILE_DIR, 'blk00000.dat')
+ BLKFILE_1stFILE = os.path.join(BLKFILE_DIR,
+ 'blk0001.dat' if COIN == 'Namecoin' else 'blk00000.dat')
else:
print '***Unknown operating system!'
print '***Cannot determine default directory locations'
@@ -302,6 +348,8 @@ BLOCKCHAINS = {}
BLOCKCHAINS['\xf9\xbe\xb4\xd9'] = "Main Network"
BLOCKCHAINS['\xfa\xbf\xb5\xda'] = "Old Test Network"
BLOCKCHAINS['\x0b\x11\x09\x07'] = "Test Network (testnet3)"
+BLOCKCHAINS['\xf9\xbe\xb4\xfe'] = "Namecoin Network"
+BLOCKCHAINS['\xfa\xbf\xb5\xfe'] = "Namecoin Test Network"
NETWORKS = {}
NETWORKS['\x00'] = "Main Network"
@@ -354,6 +402,11 @@ if not CLI_OPTIONS.satoshiHome.lower()=='default':
testnetTry = os.path.join(CLI_OPTIONS.satoshiHome, 'testnet3')
if os.path.exists(testnetTry):
CLI_OPTIONS.satoshiHome = testnetTry
+ if USE_NAMECOIN_TESTNET:
+ namecoinTestnetTry = os.path.join(CLI_OPTIONS.satoshiHome,
+ 'testnet')
+ if os.path.exists(namecoinTestnetTry):
+ CLI_OPTIONS.satoshiHome = namecoinTestnetTry
if not os.path.exists(CLI_OPTIONS.satoshiHome):
print 'Directory "%s" does not exist! Using default!' % \
@@ -432,7 +485,58 @@ if not os.path.exists(LEVELDB_DIR):
##### MAIN NETWORK IS DEFAULT #####
-if not USE_TESTNET:
+if USE_TESTNET:
+ BITCOIN_PORT = 18333
+ BITCOIN_RPC_PORT = 18332
+ ARMORY_RPC_PORT = 18225
+ MAGIC_BYTES = '\x0b\x11\x09\x07'
+ GENESIS_BLOCK_HASH_HEX = '43497fd7f826957108f4a30fd9cec3aeba79972084e90ead01ea330900000000'
+ GENESIS_BLOCK_HASH = 'CI\x7f\xd7\xf8&\x95q\x08\xf4\xa3\x0f\xd9\xce\xc3\xae\xbay\x97 \x84\xe9\x0e\xad\x01\xea3\t\x00\x00\x00\x00'
+ GENESIS_TX_HASH_HEX = '3ba3edfd7a7b12b27ac72c3e67768f617fc81bc3888a51323a9fb8aa4b1e5e4a'
+ GENESIS_TX_HASH = ';\xa3\xed\xfdz{\x12\xb2z\xc7,>gv\x8fa\x7f\xc8\x1b\xc3\x88\x8aQ2:\x9f\xb8\xaaK\x1e^J'
+ ADDRBYTE = '\x6f'
+ P2SHBYTE = '\xc4'
+ PRIVKEYBYTE = '\xef'
+
+ #
+ BLOCKEXPLORE_NAME = 'blockexplorer.com'
+ BLOCKEXPLORE_URL_TX = 'http://blockexplorer.com/testnet/tx/%s'
+ BLOCKEXPLORE_URL_ADDR = 'http://blockexplorer.com/testnet/address/%s'
+elif USE_NAMECOIN:
+ BITCOIN_PORT = 8334
+ BITCOIN_RPC_PORT = 8336
+ ARMORY_RPC_PORT = 8228
+ MAGIC_BYTES = '\xf9\xbe\xb4\xfe'
+ GENESIS_BLOCK_HASH_HEX = '70c7a9f0a2fb3d48e635a70d5b157c807e58c8fb45eb2c5e2cb7620000000000'
+ GENESIS_BLOCK_HASH = 'p\xc7\xa9\xf0\xa2\xfb=H\xe65\xa7\r[\x15|\x80~X\xc8\xfbE\xeb,^,\xb7b\x00\x00\x00\x00\x00'
+ GENESIS_TX_HASH_HEX = '0dcbd3e6f061215bf3b3383c8ce2ec201bc65acde32595449ac86890bd2dc641'
+ GENESIS_TX_HASH = '\r\xcb\xd3\xe6\xf0a![\xf3\xb38<\x8c\xe2\xec \x1b\xc6Z\xcd\xe3%\x95D\x9a\xc8h\x90\xbd-\xc6A'
+ ADDRBYTE = '\x34'
+ P2SHBYTE = ''
+ PRIVKEYBYTE = '\xb4'
+
+ #
+ BLOCKEXPLORE_NAME = 'https://bitinfocharts.com/namecoin/'
+ BLOCKEXPLORE_URL_TX = 'https://bitinfocharts.com/namecoin/tx/%s'
+ BLOCKEXPLORE_URL_ADDR = 'https://bitinfocharts.com/namecoin/address/%s'
+elif USE_NAMECOIN_TESTNET:
+ BITCOIN_PORT = 18334
+ BITCOIN_RPC_PORT = 18336
+ ARMORY_RPC_PORT = 18228
+ MAGIC_BYTES = '\xfa\xbf\xb5\xfe'
+ GENESIS_BLOCK_HASH_HEX = '08b067b31dc139ee8e7a76a4f2cfcca477c4c06e1ef89f4ae308951907000000'
+ GENESIS_BLOCK_HASH = '\x08\xb0g\xb3\x1d\xc19\xee\x8ezv\xa4\xf2\xcf\xcc\xa4w\xc4\xc0n\x1e\xf8\x9fJ\xe3\x08\x95\x19\x07\x00\x00\x00'
+ GENESIS_TX_HASH_HEX = '3ba3edfd7a7b12b27ac72c3e67768f617fc81bc3888a51323a9fb8aa4b1e5e4a'
+ GENESIS_TX_HASH = ';\xa3\xed\xfdz{\x12\xb2z\xc7,>gv\x8fa\x7f\xc8\x1b\xc3\x88\x8aQ2:\x9f\xb8\xaaK\x1e^J'
+ ADDRBYTE = '\x6f'
+ P2SHBYTE = ''
+ PRIVKEYBYTE = '\xef'
+
+ #
+ BLOCKEXPLORE_NAME = 'http://testnet.explorer.namecoin.info/'
+ BLOCKEXPLORE_URL_TX = 'http://testnet.explorer.namecoin.info/tx/%s'
+ BLOCKEXPLORE_URL_ADDR = 'http://testnet.explorer.namecoin.info/a/%s'
+else:
# TODO: The testnet genesis tx hash can't be the same...?
BITCOIN_PORT = 8333
BITCOIN_RPC_PORT = 8332
@@ -450,23 +554,6 @@ if not USE_TESTNET:
BLOCKEXPLORE_NAME = 'blockchain.info'
BLOCKEXPLORE_URL_TX = 'https://blockchain.info/tx/%s'
BLOCKEXPLORE_URL_ADDR = 'https://blockchain.info/address/%s'
-else:
- BITCOIN_PORT = 18333
- BITCOIN_RPC_PORT = 18332
- ARMORY_RPC_PORT = 18225
- MAGIC_BYTES = '\x0b\x11\x09\x07'
- GENESIS_BLOCK_HASH_HEX = '43497fd7f826957108f4a30fd9cec3aeba79972084e90ead01ea330900000000'
- GENESIS_BLOCK_HASH = 'CI\x7f\xd7\xf8&\x95q\x08\xf4\xa3\x0f\xd9\xce\xc3\xae\xbay\x97 \x84\xe9\x0e\xad\x01\xea3\t\x00\x00\x00\x00'
- GENESIS_TX_HASH_HEX = '3ba3edfd7a7b12b27ac72c3e67768f617fc81bc3888a51323a9fb8aa4b1e5e4a'
- GENESIS_TX_HASH = ';\xa3\xed\xfdz{\x12\xb2z\xc7,>gv\x8fa\x7f\xc8\x1b\xc3\x88\x8aQ2:\x9f\xb8\xaaK\x1e^J'
- ADDRBYTE = '\x6f'
- P2SHBYTE = '\xc4'
- PRIVKEYBYTE = '\xef'
-
- #
- BLOCKEXPLORE_NAME = 'blockexplorer.com'
- BLOCKEXPLORE_URL_TX = 'http://blockexplorer.com/testnet/tx/%s'
- BLOCKEXPLORE_URL_ADDR = 'http://blockexplorer.com/testnet/address/%s'
# These are the same regardless of network
# They are the way data is stored in the database which is network agnostic
@@ -3706,4 +3793,4 @@ def isInternetAvailable():
def onlineModeIsPossible(btcdir=BTC_HOME_DIR):
return (CLI_OPTIONS.forceOnline or isInternetAvailable()) and \
satoshiIsAvailable() and \
- os.path.exists(os.path.join(btcdir, 'blocks'))
+ (os.path.exists(os.path.join(btcdir, 'blocks')) if COIN == 'Bitcoin' else 1)
diff --git a/armoryengine/BDM.py b/armoryengine/BDM.py
index 01b13a0..4e9695a 100644
--- a/armoryengine/BDM.py
+++ b/armoryengine/BDM.py
@@ -294,16 +294,21 @@ class BlockDataManager(object):
blkdir = ""
+ blk1st = ""
if forInit == False:
# Check for the existence of the Bitcoin-Qt directory
if not os.path.exists(self.btcdir):
raise FileExistsError, ('Directory does not exist: %s' % self.btcdir)
- blkdir = os.path.join(self.btcdir, 'blocks')
- blk1st = os.path.join(blkdir, 'blk00000.dat')
+ if COIN == 'Namecoin':
+ blkdir = self.btcdir
+ blk1st = os.path.join(blkdir, 'blk0001.dat')
+ else:
+ blkdir = os.path.join(self.btcdir, 'blocks')
+ blk1st = os.path.join(blkdir, 'blk00000.dat')
- # ... and its blk000X.dat files
+ # ... and its blk000X.dat or blk0000x.dat files
if not os.path.exists(blk1st):
LOGERROR('Blockchain data not available: %s', blk1st)
raise FileExistsError, ('Blockchain data not available: %s' % blk1st)
@@ -327,6 +332,7 @@ class BlockDataManager(object):
bdmConfig.homeDirLocation = armoryHomeDir
bdmConfig.blkFileLocation = blockdir
bdmConfig.levelDBLocation = leveldbdir
+ bdmConfig.chain = COIN
bdmConfig.setGenesisBlockHash(GENESIS_BLOCK_HASH)
bdmConfig.setGenesisTxHash(GENESIS_TX_HASH)
bdmConfig.setMagicBytes(MAGIC_BYTES)
diff --git a/armoryengine/PyBtcWallet.py b/armoryengine/PyBtcWallet.py
index b27c9dc..79acda3 100644
--- a/armoryengine/PyBtcWallet.py
+++ b/armoryengine/PyBtcWallet.py
@@ -198,7 +198,7 @@ class PyBtcWallet(object):
self.linearAddr160List = []
self.chainIndexMap = {}
self.txAddrMap = {} # cache for getting tx-labels based on addr search
- if USE_TESTNET:
+ if USE_TESTNET or USE_NAMECOIN_TESTNET:
self.addrPoolSize = 10 # this makes debugging so much easier!
else:
self.addrPoolSize = CLI_OPTIONS.keypool
diff --git a/cppForSwig/BlockDataManagerConfig.h b/cppForSwig/BlockDataManagerConfig.h
index ff15423..5e27530 100644
--- a/cppForSwig/BlockDataManagerConfig.h
+++ b/cppForSwig/BlockDataManagerConfig.h
@@ -29,6 +29,7 @@ struct BlockDataManagerConfig
string homeDirLocation;
string blkFileLocation;
string levelDBLocation;
+ string chain;
BinaryData genesisBlockHash;
BinaryData genesisTxHash;
diff --git a/cppForSwig/BlockObj.cpp b/cppForSwig/BlockObj.cpp
index 03e12a5..a1f4bd5 100644
--- a/cppForSwig/BlockObj.cpp
+++ b/cppForSwig/BlockObj.cpp
@@ -507,7 +507,8 @@ void TxOut::pprint(ostream & os, int nIndent, bool pBigendian)
/////////////////////////////////////////////////////////////////////////////
void Tx::unserialize(uint8_t const * ptr, size_t size)
{
- uint32_t nBytes = BtcUtils::TxCalcLength(ptr, size, &offsetsTxIn_, &offsetsTxOut_);
+ uint32_t nBytes = BtcUtils::TxCalcLength(ptr, size, getBlockHeight(), &offsetsTxIn_,
+ &offsetsTxOut_);
if (nBytes > size)
throw BlockDeserializingException();
diff --git a/cppForSwig/BlockUtils.cpp b/cppForSwig/BlockUtils.cpp
index 44c1bad..305c4b3 100644
--- a/cppForSwig/BlockUtils.cpp
+++ b/cppForSwig/BlockUtils.cpp
@@ -81,7 +81,8 @@ public:
}
while(numBlkFiles < UINT16_MAX)
{
- string path = BtcUtils::getBlkFilename(blkFileLocation_, numBlkFiles);
+ string chain = "Namecoin";//config().chain;
+ string path = BtcUtils::getBlkFilename(chain, blkFileLocation_, numBlkFiles);
uint64_t filesize = BtcUtils::GetFileSize(path);
if(filesize == FILE_DOES_NOT_EXIST)
break;
diff --git a/cppForSwig/BtcUtils.h b/cppForSwig/BtcUtils.h
index 2f77baa..dab0591 100644
--- a/cppForSwig/BtcUtils.h
+++ b/cppForSwig/BtcUtils.h
@@ -67,6 +67,10 @@ class LedgerEntry;
#define MAINNET_GENESIS_HASH_HEX "6fe28c0ab6f1b372c1a6a246ae63f74f931e8365e15a089c68d6190000000000"
#define MAINNET_GENESIS_TX_HASH_HEX "3ba3edfd7a7b12b27ac72c3e67768f617fc81bc3888a51323a9fb8aa4b1e5e4a"
+#define NAMECOIN_MAGIC_BYTES "f9beb4fe"
+
+#define NAMECOIN_TESTNET_MAGIC_BYTES "fabfb5fe"
+
#define BITMASK(X) (2**X - 1)
#define HASH160PREFIX WRITE_UINT8_LE((uint8_t)SCRIPT_PREFIX_HASH160)
@@ -756,9 +760,16 @@ public:
/////////////////////////////////////////////////////////////////////////////
static size_t TxCalcLength(uint8_t const * ptr,
size_t size,
+ uint32_t nBlk,
vector * offsetsIn=NULL,
vector * offsetsOut=NULL)
{
+ /*if(nBlk >= 19200) {
+ // Check for merge mined blocks and increment ptr???
+ // Problem is that nBlk isn't currently the block height.
+ // getBlockHeight() returns uint32_max!
+ }*/
+
BinaryRefReader brr(ptr, size);
if (brr.getSizeRemaining() < 4)
@@ -1342,13 +1353,18 @@ public:
// This got more complicated when Bitcoin-Qt 0.8 switched from
// blk0001.dat to blocks/blk00000.dat
- static string getBlkFilename(string dir, uint32_t fblkNum)
+ static string getBlkFilename(string chain, string dir, uint32_t fblkNum)
{
/// Update: It's been enough time since the hardfork that just about
// everyone must've upgraded to 0.8+ by now... remove pre-0.8
// compatibility.
char* fname = new char[1024];
- sprintf(fname, "%s/blk%05d.dat", dir.c_str(), fblkNum);
+ if(chain == "Namecoin") {
+ sprintf(fname, "%s/blk%04d.dat", dir.c_str(), fblkNum+1);
+ }
+ else {
+ sprintf(fname, "%s/blk%05d.dat", dir.c_str(), fblkNum);
+ }
string strName(fname);
delete[] fname;
return strName;
diff --git a/cppForSwig/gtest/CppBlockUtilsTests.cpp b/cppForSwig/gtest/CppBlockUtilsTests.cpp
index 50be814..e4a76af 100644
--- a/cppForSwig/gtest/CppBlockUtilsTests.cpp
+++ b/cppForSwig/gtest/CppBlockUtilsTests.cpp
@@ -4749,6 +4749,7 @@ protected:
config_.armoryDbType = ARMORY_DB_FULL;
config_.pruneType = DB_PRUNE_NONE;
config_.levelDBLocation = string("ldbtestdir");
+ config_.chain = "Bitcoin"
config_.genesisBlockHash = ghash_;
config_.genesisTxHash = gentx_;
@@ -6486,7 +6487,7 @@ protected:
mkdir(homedir_);
// Put the first 5 blocks into the blkdir
- blk0dat_ = BtcUtils::getBlkFilename(blkdir_, 0);
+ blk0dat_ = BtcUtils::getBlkFilename(config_.chain, blkdir_, 0);
BtcUtils::copyFile("../reorgTest/blk_0_to_4.dat", blk0dat_);
config.armoryDbType = ARMORY_DB_BARE;
@@ -6613,7 +6614,7 @@ protected:
mkdir(blkdir_);
mkdir(homedir_);
- blk0dat_ = BtcUtils::getBlkFilename(blkdir_, 0);
+ blk0dat_ = BtcUtils::getBlkFilename(config_.chain, blkdir_, 0);
}
/////////////////////////////////////////////////////////////////////////////
@@ -8022,7 +8023,7 @@ protected:
mkdir(homedir_);
// Put the first 5 blocks into the blkdir
- blk0dat_ = BtcUtils::getBlkFilename(blkdir_, 0);
+ blk0dat_ = BtcUtils::getBlkFilename(config_.chain, blkdir_, 0);
BtcUtils::copyFile("../reorgTest/blk_0_to_4.dat", blk0dat_);
BlockDataManagerConfig config;
@@ -8168,14 +8169,14 @@ TEST_F(BlockUtilsSuper, HeadersOnly_Reorg)
EXPECT_EQ(iface_->getTopBlockHeight(HEADERS), 4);
EXPECT_EQ(iface_->getTopBlockHash(HEADERS), blkHash4);
- BtcUtils::copyFile("../reorgTest/blk_3A.dat", BtcUtils::getBlkFilename(blkdir_, 1));
+ BtcUtils::copyFile("../reorgTest/blk_3A.dat", BtcUtils::getBlkFilename(config_.chain, blkdir_, 1));
TheBDM.readBlkFileUpdate();
EXPECT_EQ(iface_->getTopBlockHeight(HEADERS), 4);
EXPECT_EQ(iface_->getTopBlockHash(HEADERS), blkHash4);
EXPECT_FALSE(TheBDM.blockchain().getHeaderByHash(blkHash3A).isMainBranch());
EXPECT_TRUE( TheBDM.blockchain().getHeaderByHash(blkHash3 ).isMainBranch());
- BtcUtils::copyFile("../reorgTest/blk_4A.dat", BtcUtils::getBlkFilename(blkdir_, 2));
+ BtcUtils::copyFile("../reorgTest/blk_4A.dat", BtcUtils::getBlkFilename(config_.chain, blkdir_, 2));
TheBDM.readBlkFileUpdate();
EXPECT_EQ(iface_->getTopBlockHeight(HEADERS), 4);
EXPECT_EQ(iface_->getTopBlockHash(HEADERS), blkHash4);
@@ -8184,7 +8185,7 @@ TEST_F(BlockUtilsSuper, HeadersOnly_Reorg)
EXPECT_FALSE(TheBDM.blockchain().getHeaderByHash(blkHash4A).isMainBranch());
EXPECT_TRUE( TheBDM.blockchain().getHeaderByHash(blkHash4 ).isMainBranch());
- BtcUtils::copyFile("../reorgTest/blk_5A.dat", BtcUtils::getBlkFilename(blkdir_, 3));
+ BtcUtils::copyFile("../reorgTest/blk_5A.dat", BtcUtils::getBlkFilename(config_.chain, blkdir_, 3));
TheBDM.readBlkFileUpdate();
EXPECT_EQ(iface_->getTopBlockHeight(HEADERS), 5);
EXPECT_EQ(iface_->getTopBlockHeight(HEADERS), 5);
@@ -8467,7 +8468,7 @@ protected:
mkdir(homedir_);
// Put the first 5 blocks into the blkdir
- blk0dat_ = BtcUtils::getBlkFilename(blkdir_, 0);
+ blk0dat_ = BtcUtils::getBlkFilename(config_.chain, blkdir_, 0);
BtcUtils::copyFile("../reorgTest/blk_0_to_4.dat", blk0dat_);
BlockDataManagerConfig config;
diff --git a/qtdefines.py b/qtdefines.py
index aff2f1f..9a15fe2 100644
--- a/qtdefines.py
+++ b/qtdefines.py
@@ -746,6 +746,12 @@ class ArmoryDialog(QDialog):
if USE_TESTNET:
self.setWindowTitle('Armory - Bitcoin Wallet Management [TESTNET]')
self.setWindowIcon(QIcon(':/armory_icon_green_32x32.png'))
+ elif USE_NAMECOIN:
+ self.setWindowTitle('Armory - Namecoin Wallet Management')
+ self.setWindowIcon(QIcon(':/armory_icon_32x32.png'))
+ elif USE_NAMECOIN_TESTNET:
+ self.setWindowTitle('Armory - Namecoin Wallet Management [TESTNET]')
+ self.setWindowIcon(QIcon(':/armory_icon_green_32x32.png'))
else:
self.setWindowTitle('Armory - Bitcoin Wallet Management')
self.setWindowIcon(QIcon(':/armory_icon_32x32.png'))
diff --git a/qtdialogs.py b/qtdialogs.py
index 82ad491..97dfe84 100644
--- a/qtdialogs.py
+++ b/qtdialogs.py
@@ -7353,7 +7353,7 @@ class DlgPrintBackup(ArmoryDialog):
doMask = self.chkSecurePrint.isChecked()
- if USE_TESTNET:
+ if USE_TESTNET or USE_NAMECOIN_TESTNET:
self.scene.drawPixmapFile(':/armory_logo_green_h56.png')
else:
self.scene.drawPixmapFile(':/armory_logo_h36.png')
diff --git a/ui/MultiSigDialogs.py b/ui/MultiSigDialogs.py
index e180c43..c74dc06 100644
--- a/ui/MultiSigDialogs.py
+++ b/ui/MultiSigDialogs.py
@@ -1346,6 +1346,13 @@ class DlgLockboxManager(ArmoryDialog):
if USE_TESTNET:
blkExploreTitle = 'View on blockexplorer.com'
blkExploreURL = 'http://blockexplorer.com/testnet/tx/%s' % txHash
+ elif USE_NAMECOIN:
+ blkExploreTitle = 'View on bitinfocharts.com'
+ blkExploreURL = 'https://bitinfocharts.com/namecoin/tx/%s' % txHash
+ elif USE_NAMECOIN_TESTNET:
+ # TODO: Find an explorer that is up-to-date
+ blkExploreTitle = 'View on namecoin.info'
+ blkExploreURL = 'http://testnet.explorer.namecoin.info/tx/%s' % txHash
else:
blkExploreTitle = 'View on blockchain.info'
blkExploreURL = 'https://blockchain.info/tx/%s' % txHash
diff --git a/ui/TxFrames.py b/ui/TxFrames.py
index caf4192..7608b30 100644
--- a/ui/TxFrames.py
+++ b/ui/TxFrames.py
@@ -153,7 +153,7 @@ class SendBitcoinsFrame(ArmoryFrame):
Click this button to copy a "bitcoin:" link directly into Armory."""))
self.connect(btnEnterURI, SIGNAL("clicked()"), self.clickEnterURI)
fromFrameList = [self.frmSelectedWlt]
- if not USE_TESTNET:
+ if not(USE_TESTNET or USE_NAMECOIN or USE_NAMECOIN_TESTNET):
btnDonate = QPushButton("Donate to Armory Developers!")
ttipDonate = self.main.createToolTipWidget(\
'Making this software was a lot of work. You can give back '
@@ -262,7 +262,9 @@ class SendBitcoinsFrame(ArmoryFrame):
loadCount % donateFreq == (donateFreq-1) and \
not loadCount == lastPestering and \
not dnaaDonate and \
- not USE_TESTNET:
+ not USE_TESTNET and \
+ not USE_NAMECOIN and \
+ not USE_NAMECOIN_TESTNET:
result = MsgBoxWithDNAA(MSGBOX.Question, 'Please donate!', tr("""
Armory is the result of thousands of hours of development
by very talented coders. Yet, this software
diff --git a/ui/Wizards.py b/ui/Wizards.py
index e37e57d..965e083 100644
--- a/ui/Wizards.py
+++ b/ui/Wizards.py
@@ -8,7 +8,7 @@
from PyQt4.Qt import * #@UnusedWildImport
from PyQt4.QtGui import * #@UnusedWildImport
-from armoryengine.ArmoryUtils import USE_TESTNET
+from armoryengine.ArmoryUtils import USE_TESTNET, USE_NAMECOIN, USE_NAMECOIN_TESTNET
from ui.WalletFrames import NewWalletFrame, SetPassphraseFrame, VerifyPassphraseFrame,\
WalletBackupFrame, WizardCreateWatchingOnlyWalletFrame
from ui.TxFrames import SendBitcoinsFrame, SignBroadcastOfflineTxFrame,\
@@ -35,6 +35,12 @@ class ArmoryWizard(QWizard):
if USE_TESTNET:
self.setWindowTitle('Armory - Bitcoin Wallet Management [TESTNET]')
self.setWindowIcon(QIcon(':/armory_icon_green_32x32.png'))
+ elif USE_NAMECOIN:
+ self.setWindowTitle('Armory - Namecoin Wallet Management')
+ self.setWindowIcon(QIcon(':/armory_icon_32x32.png'))
+ elif USE_NAMECOIN_TESTNET:
+ self.setWindowTitle('Armory - Namecoin Wallet Management [TESTNET]')
+ self.setWindowIcon(QIcon(':/armory_icon_green_32x32.png'))
else:
self.setWindowTitle('Armory - Bitcoin Wallet Management')
self.setWindowIcon(QIcon(':/armory_icon_32x32.png'))
Let me know if you want it as a file uploaded somewhere.
Some notes:
The fee calculation logic may need to be changed for Namecoin. I did change the MIN_TX_FEE and MIN_RELAY_TX_FEE, but not the fee calculation logic.
P2SH and multisig will need to be disabled until the new version of Namecoin that is rebased against Bitcoin Core is released.
BlockDataManagerConfig.h has a string chain, which is set in the Python code to either 'Bitcoin' or 'Namecoin' depending on which is being used. The variable chain isn't actually being used right now, because I couldn't figure out how to use it. I have 'Namecoin' hardcoded in BlockUtils.cpp (and that part is working correctly to read the correct block files). If you want to switch between Namecoin and Bitcoin, you need to recompile.
I think TxCalcLength needs to be modified in BtcUtils.h, so that Armory knows that the transaction part of the block starts after the merged mining data. A couple of posts ago I posted helpful information I found on the wiki about merged mining. The difficult part is that the merge mined data is not a constant size. And a block may not necessarily be merge mined even though it is at height 19200 or greater.
Namecoin currently has the donate to ATI button hidden, because I don't know of a Namecoin donation address.
I tested this, but at this stage all I could test was that the correct addresses were being generated and that the correct block files were detected.
And finally, I did not change all the instances of the word Bitcoin to Namecoin, so that still needs to be done. I figured it would just make the diff harder to read at this point.