Пример #1
0
 def verify_header(self, header, prev_hash, bits, target):
     height = header.get('block_height')
     if prev_hash != header.get('prev_block_hash'):
         raise Exception("prev hash mismatch: %s vs %s" %
                         (prev_hash, header.get('prev_block_hash')))
     # DGWv3 PastBlocksMax = 24 Because checkpoint don't have preblock data.
     if height % 2016 != 0 and height // 2016 < len(
             self.checkpoints) or height >= len(
                 self.checkpoints) * 2016 and height <= len(
                     self.checkpoints) * 2016 + 24:
         return
     if constants.net.TESTNET:
         return
     if bits != header.get('bits'):
         raise Exception("bits mismatch: %s vs %s" %
                         (bits, header.get('bits')))
     if height < 450000:
         _powhash = rev_hex(
             bh2u(scryptGetHash(bfh(serialize_header(header)))))
     else:
         _powhash = rev_hex(
             bh2u(lyra2re2_hash.getPoWHash(bfh(serialize_header(header)))))
     if int('0x' + _powhash, 16) > target:
         raise Exception("insufficient proof of work: %s vs target %s" %
                         (int('0x' + _powhash, 16), target))
Пример #2
0
 def verify_header(cls,
                   header: dict,
                   prev_hash: str,
                   target: int,
                   expected_header_hash: str = None) -> None:
     height = header.get('block_height')
     _hash = hash_header(header)
     if expected_header_hash and expected_header_hash != _hash:
         raise Exception("hash mismatches with expected: {} vs {}".format(
             expected_header_hash, _hash))
     if prev_hash != header.get('prev_block_hash'):
         raise Exception("prev hash mismatch: %s vs %s" %
                         (prev_hash, header.get('prev_block_hash')))
     # DGWv3 PastBlocksMax = 24 Because checkpoint don't have preblock data.
     if height // 2016 < len(constants.net.CHECKPOINTS) and height % 2016 != 2015 or \
             height >= len(constants.net.CHECKPOINTS)*2016 and height <= len(constants.net.CHECKPOINTS)*2016 + 24:
         return
     if constants.net.TESTNET:
         return
     bits = cls.target_to_bits(target)
     if bits != header.get('bits'):
         raise Exception("bits mismatch: %s vs %s" %
                         (bits, header.get('bits')))
     if height < 450000:
         _powhash = rev_hex(
             bh2u(scryptGetHash(bfh(serialize_header(header)))))
     else:
         _powhash = rev_hex(
             bh2u(lyra2re2_hash.getPoWHash(bfh(serialize_header(header)))))
     if int('0x' + _powhash, 16) > target:
         raise Exception("insufficient proof of work: %s vs target %s" %
                         (int('0x' + _powhash, 16), target))
Пример #3
0
 def pow_hash_header(self, header):
     height = header.get('block_height')
     if height >= 347000:
         return rev_hex(lyra2re2_hash.getPoWHash(self.serialize_header(header).decode('hex')).encode('hex'))
     elif height >= 208301:
         return rev_hex(lyra2re_hash.getPoWHash(self.serialize_header(header).decode('hex')).encode('hex'))
     else:
         return rev_hex(vtc_scrypt.getPoWHash(self.serialize_header(header).decode('hex')).encode('hex'))
Пример #4
0
 def header_hash(cls, header):
     '''
     Given a header return the hash for Kreds.
     Need to download `lyra2re2_hash` module
     Source code: https://github.com/metalicjames/lyra2re-hash-python
     '''
     import lyra2re2_hash
     return lyra2re2_hash.getPoWHash(header)
Пример #5
0
def pow_hash_header(header):
    height = header.get('block_height')
    header_bytes = bfh(serialize_header(header))
    if height >= 347000:
        return hash_encode(lyra2re2_hash.getPoWHash(header_bytes))
    elif height >= 208301:
        return hash_encode(lyra2re_hash.getPoWHash(header_bytes))
    else:
        return hash_encode(vtc_scrypt_new.getPoWHash(header_bytes))
Пример #6
0
 def calc_sha256(self):
     if self.sha256 is None:
         r = b""
         r += struct.pack("<i", self.nVersion)
         r += ser_uint256(self.hashPrevBlock)
         r += ser_uint256(self.hashMerkleRoot)
         r += struct.pack("<I", self.nTime)
         r += struct.pack("<I", self.nBits)
         r += struct.pack("<I", self.nNonce)
         self.sha256 = uint256_from_str(hash256(r))
         self.hash = encode(hash256(r)[::-1], 'hex_codec').decode('ascii')
         self.lyra2re2Hash = uint256_from_str(lyra2re2_hash.getPoWHash(r))
         self.lyra2rec0banHash = uint256_from_str(
             lyra2rec0ban_hash.getPoWHash(r))
Пример #7
0
 def verify_header(self, header, prev_header, bits, target):
     prev_hash = hash_header(prev_header)
     if prev_hash != header.get('prev_block_hash'):
         raise BaseException("prev hash mismatch: %s vs %s" % (prev_hash, header.get('prev_block_hash')))
     if bitcoin.NetworkConstants.TESTNET:
         return
     height = header.get('block_height')
     if height < 450000 :
         _powhash = rev_hex(bh2u(scryptGetHash(bfh(serialize_header(header)))))
     else:
         _powhash = rev_hex(bh2u(lyra2re2_hash.getPoWHash(bfh(serialize_header(header)))))
     if bits != header.get('bits'):
         raise BaseException("bits mismatch: %s vs %s" % (bits, header.get('bits')))
     if int('0x' + _powhash, 16) > target:
         raise BaseException("insufficient proof of work: %s vs target %s" % (int('0x' + _powhash, 16), target))
Пример #8
0
def pow_hash_header(header):
    if header['version'] & (15 << 11) == (4 << 11):
        blake_state = cblake()
        blake_state.update(bfh(serialize_header(header)))
        return hash_encode(blake_state.final())
    if header['version'] & (15 << 11) == (2 << 11):
        return hash_encode(
            groestl_hash.getPoWHash(bfh(serialize_header(header))))
    if header['version'] & (15 << 11) == (10 << 11):
        return hash_encode(
            lyra2re2_hash.getPoWHash(bfh(serialize_header(header))))
    if header['version'] & (15 << 11) == (3 << 11):
        return hash_encode(x17_hash.x17_gethash(bfh(serialize_header(header))))
    if header['version'] & (15 << 11) == (11 << 11):
        return hash_encode(
            shield_x16s_hash.getPoWHash(bfh(serialize_header(header))))
    return hash_encode(getPoWHash(bfh(serialize_header(header))))
Пример #9
0
 def header_hash(cls, header):
     '''Given a header return the hash.'''
     import lyra2re2_hash
     return lyra2re2_hash.getPoWHash(header)
Пример #10
0
    def submit_share(self, job_id, worker_name, extranonce1_bin, extranonce2, ntime, nonce,
                     difficulty):
        '''Check parameters and finalize block template. If it leads
           to valid block candidate, asynchronously submits the block
           back to the bitcoin network.

            - extranonce1_bin is binary. No checks performed, it should be from session data
            - job_id, extranonce2, ntime, nonce - in hex form sent by the client
            - difficulty - decimal number from session, again no checks performed
            - submitblock_callback - reference to method which receive result of submitblock()
        '''

        # Check if extranonce2 looks correctly. extranonce2 is in hex form...
        if len(extranonce2) != self.extranonce2_size * 2:
            raise SubmitException("Incorrect size of extranonce2. Expected %d chars" % (self.extranonce2_size*2))

        # Check for job
        job = self.get_job(job_id)
        if job == None:
            raise SubmitException("Job '%s' not found" % job_id)

        # Check if ntime looks correct
        if len(ntime) != 8:
            raise SubmitException("Incorrect size of ntime. Expected 8 chars")

        if not job.check_ntime(int(ntime, 16)):
            raise SubmitException("Ntime out of range")

        # Check nonce
        if len(nonce) != 8:
            raise SubmitException("Incorrect size of nonce. Expected 8 chars")

        # Convert from hex to binary
        extranonce2_bin = binascii.unhexlify(extranonce2)
        ntime_bin = binascii.unhexlify(ntime)
        nonce_bin = binascii.unhexlify(nonce)

        # Check for duplicated submit
        if not job.register_submit(extranonce1_bin, extranonce2_bin, ntime_bin, nonce_bin):
            log.info("Duplicate from %s, (%s %s %s %s)" % \
                    (worker_name, binascii.hexlify(extranonce1_bin), extranonce2, ntime, nonce))
            raise SubmitException("Duplicate share")

        # Now let's do the hard work!
        # ---------------------------

        # 1. Build coinbase
        coinbase_bin = job.serialize_coinbase(extranonce1_bin, extranonce2_bin)
        coinbase_hash = util.doublesha(coinbase_bin)

        # 2. Calculate merkle root
        merkle_root_bin = job.merkletree.withFirst(coinbase_hash)
        merkle_root_int = util.uint256_from_str(merkle_root_bin)

        # 3. Serialize header with given merkle, ntime and nonce
        header_bin = job.serialize_header(merkle_root_int, ntime_bin, nonce_bin)

        # 4. Reverse header and compare it with target of the user
        hash_bin = lyra2re2_hash.getPoWHash(''.join([ header_bin[i*4:i*4+4][::-1] for i in range(0, 20) ]))
        hash_int = util.uint256_from_str(hash_bin)
        block_hash_hex = "%064x" % hash_int
        header_hex = binascii.hexlify(header_bin)

        target_user = self.diff_to_target(difficulty)
        if hash_int > target_user:
            raise SubmitException("Share is above target")

        # Mostly for debugging purposes
        target_info = self.diff_to_target(100000)
        if hash_int <= target_info:
            log.info("Yay, share with diff above 100000")

        # 5. Compare hash with target of the network
        if hash_int <= job.target:
            # Yay! It is block candidate!
            log.info("We found a block candidate! %s" % block_hash_hex)

            # 6. Finalize and serialize block object
            job.finalize(merkle_root_int, extranonce1_bin, extranonce2_bin, int(ntime, 16), int(nonce, 16))

            if not job.is_valid():
                # Should not happen
                log.error("Final job validation failed!")

            # 7. Submit block to the network
            serialized = binascii.hexlify(job.serialize())
            on_submit = self.bitcoin_rpc.submitblock(serialized)

            return (header_hex, block_hash_hex, on_submit)

        return (header_hex, block_hash_hex, None)
Пример #11
0
# 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.
import os
import threading

from . import util
from . import bitcoin
from .bitcoin import *

try:
    import lyra2re2_hash
    getPoWHash = lambda x: lyra2re2_hash.getPoWHash(x)
except ImportError as e:
    exit("Please run 'sudo pip3 install https://github.com/straks/lyra2re-hash-python/archive/master.zip'")

class VerifyError(Exception):
    '''Exception used for blockchain verification errors.'''

MAX_TARGET = 0x00000fffff000000000000000000000000000000000000000000000000000000

def bits_to_work(bits):
    return (1 << 256) // (bits_to_target(bits) + 1)

def bits_to_target(bits):
    bitsN = (bits >> 24) & 0xff
    if not (bitsN >= 0x03 and bitsN <= 0x1e):
        raise BaseException("First part of bits should be in [0x03, 0x1e]")
Пример #12
0
import lyra2re2_hash
import weakref
import binascii
import StringIO

from binascii import unhexlify, hexlify

teststart = '700000005d385ba114d079971b29a9418fd0549e7d68a95c7f168621a314201000000000578586d149fd07b22f3a8a347c516de7052f034d2b76ff68e0d6ecff9b77a45489e3fd511732011df0731000'
testbin = unhexlify(teststart)
hash_bin = lyra2re2_hash.getPoWHash(testbin)

print hexlify(hash_bin)
Пример #13
0
        x += (harr[i + 1] + harr[i])

    return x


def little_endian(value):
    return hexlify(pack("L", value))[0:8]


# STRAKS BLOCK 10
header_hex = (
    little_endian(536870912) + swap_order(
        "00000491760a7e6cf8fb72ef96626eae4b10242b2999c629336175252582e33a") +
    swap_order(
        "15b4d0b16c968c98a7f61ac344925398a7a1466620271e0abd28e823d547c9f6") +
    little_endian(1510792864) + little_endian(504122572) +
    little_endian(53233))

print "header_hex:", header_hex

header_bin = unhexlify(header_hex)
hash_bin = lyra2re2_hash.getPoWHash(header_bin)

unswapped_hhash = hexlify(hash_bin)
header_hash = swap_order(hexlify(hash_bin))

print unswapped_hhash
print header_hash

print ">> matches target hash:", header_hash == "0000025f19e1714fd575bfe9e18e137625e731036da615f416d79f7edbdc1e81"
def powhash(header):
    return rev_hex(bh2u(lyra2re2_hash.getPoWHash(bfh(header))))
Пример #15
0
import lyra2re2_hash
import weakref
import binascii
import StringIO

from binascii import unhexlify, hexlify

teststart = '700000005d385ba114d079971b29a9418fd0549e7d68a95c7f168621a314201000000000578586d149fd07b22f3a8a347c516de7052f034d2b76ff68e0d6ecff9b77a45489e3fd511732011df0731000';
testbin = unhexlify(teststart)
hash_bin = lyra2re2_hash.getPoWHash(testbin)

print hexlify(hash_bin)
Пример #16
0
    def submit(self, connection_ref, _id, _params):
        # TODO: Job ID Check 구현해야함
        # TODO: Diff Check 해서 그냥 Share 기록 or Submit 구별 해야함
        # TODO: Share Result를 Database에 기록 해야함 - Database 는 Redis가 될듯
        session_id = connection_ref.get_session()

        _worker_name = _params[0]
        _split_worker_name = _worker_name.strip().split('.')
        username = _split_worker_name[0]
        if len(_split_worker_name) == 2:
            worker = _split_worker_name[1]
        else:
            worker = None
        _job_id = _params[1]

        _nonce_1 = self.job_manager.get_nonce_from_session_id(session_id)
        _block_template = self.job_manager.get_block_template(_job_id)

        if _block_template is None:
            logger.info('rejected share, worker : %s, reason : job not found' %
                        _worker_name)
            return {'id': _id, 'result': False, 'error': [21, 'job not found']}

        if os.getenv("COIN_TYPE") == 'bitcoin':
            _nonce_2 = _params[2]
            _time = _params[3]
            _time_reverse = hash_util.hex_to_reverse_hex(_time)
            _nonce = _params[4]
            _nonce_reverse = hash_util.hex_to_reverse_hex(_nonce)

            if len(_nonce) != 8:
                logger.info(
                    'rejected share, worker : %s, reason : incorrect size of nonce'
                    % _worker_name)
                return {
                    'id': _id,
                    'result': False,
                    'error': [20, 'incorrect size of nonce']
                }

            coinbase = binascii.hexlify(_block_template.coinbase_tx).split(
                _block_template.extranonce_placeholder)
            serialized_coinbase = binascii.unhexlify(coinbase[0] + _nonce_1 +
                                                     _nonce_2.encode() +
                                                     coinbase[1])

            if os.getenv("COIN_ALGORITHM") == 'keccak':
                coinbase_hash = binascii.hexlify(
                    hash_util.reverse_bytes(
                        hash_util.sha(serialized_coinbase)))
            else:
                coinbase_hash = hash_util.bytes_to_reverse_hash(
                    serialized_coinbase)

            tx_hashes = [coinbase_hash
                         ] + [h['hash'] for h in _block_template.transactions]
            merkle_root_reverse_hex = hash_util.hex_to_reverse_hex(
                hash_util.merkle_root(tx_hashes))

            # Header POW 종류별 구별 해야댐
            header = _block_template.serialize_block_header(
                _time_reverse, _nonce_reverse,
                merkle_root_reverse_hex)  # 80 bytes
            block_hex = _block_template.serialize_block(
                header, None, serialized_coinbase)
            if os.getenv("COIN_ALGORITHM") == 'lyra2rev2':
                import lyra2re2_hash
                header_hash = lyra2re2_hash.getPoWHash(header)
            elif os.getenv("COIN_ALGORITHM") == 'lyra2rev3':
                import lyra2re3_hash
                header_hash = lyra2re3_hash.getPoWHash(header)
            elif os.getenv("COIN_ALGORITHM") == 'keccak' or os.getenv(
                    "COIN_ALGORITHM") == 'keccakc':
                import sha3
                header_hash = sha3.keccak_256(header).digest()
            elif os.getenv("COIN_ALGORITHM") == 'x13-bcd':
                import x13bcd_hash
                header_hash = x13bcd_hash.getPoWHash(header)
            elif os.getenv("COIN_ALGORITHM") == 'neoscrypt':
                import neoscrypt
                header_hash = neoscrypt.getPoWHash(header)
            elif os.getenv("COIN_ALGORITHM") == 'yescrypt':
                import yescrypt_hash
                header_hash = yescrypt_hash.getHash(header, len(header))
            elif os.getenv("COIN_ALGORITHM") == 'xevan':
                import xevan_hash
                header_hash = xevan_hash.getPoWHash(header)
            elif os.getenv("COIN_ALGORITHM") == 'phi2':
                import phi2_hash
                header_hash = phi2_hash.getPoWHash(header)
            elif os.getenv("COIN_ALGORITHM") == 'x16r':
                import x16r_hash
                header_hash = x16r_hash.getPoWHash(header)
            elif os.getenv("COIN_ALGORITHM") == 'x16s':
                import x16s_hash
                header_hash = x16s_hash.getPoWHash(header)
            elif os.getenv("COIN_ALGORITHM") == 'timetravel10':
                import timetravel10_hash
                header_hash = timetravel10_hash.getPoWHash(header)
            else:
                header_hash = double_sha(header)

        elif os.getenv("COIN_TYPE") == 'zcash':
            _time = _params[2]
            _nonce_2 = _params[3]
            _soln = _params[4]

            _nonce = _nonce_1 + _nonce_2.encode()

            if len(_nonce) != 64:
                return {
                    'id': _id,
                    'result': False,
                    'error': [20, 'incorrect size of nonce']
                }

            if os.getenv("COIN_ALGORITHM") == 'zhash' and len(_soln) != 202:
                return {
                    'id': _id,
                    'result': False,
                    'error': [20, 'incorrect size of solution']
                }
            elif os.getenv("COIN_ALGORITHM") != 'zhash' and len(_soln) != 2694:
                return {
                    'id': _id,
                    'result': False,
                    'error': [20, 'incorrect size of solution']
                }

            n_time_int = int(_time, 16)
            curtime_int = int(_block_template.curtime, 16)

            if n_time_int < curtime_int:
                return {
                    'id': _id,
                    'result': False,
                    'error': [20, 'ntime out of range']
                }

            header = _block_template.serialize_block_header(
                _time.encode(), _nonce)  # 140 bytes

            header_soln = header + binascii.unhexlify(_soln)
            header_hash = double_sha(header_soln)

            block_hex = _block_template.serialize_block(
                header, binascii.unhexlify(_soln), None)
        else:
            raise Exception('invalid coin type')

        header_bignum = uint256_from_str(header_hash)

        share_diff = os.getenv("POW_LIMIT") / header_bignum
        logger.debug('share diff : {0:.8f}'.format(share_diff))

        diff = self.user_diffs[connection_ref.username]

        if share_diff < diff:
            # logger.debug('low difficulty share of %s' % share_diff)
            logger.info(
                'rejected share, worker : %s, reason : low difficulty share' %
                _worker_name)
            self.database_ref.insert_accepted_share(
                username, worker, False, False, _block_template.block_height,
                share_diff, _block_template.pool_reward, diff)
            return {
                'id': _id,
                'result': None,
                'error': [23, 'low difficulty share of %s' % share_diff]
            }

        if not self.job_manager.register_submit(_nonce_1, _nonce_2, _nonce,
                                                _time):
            logger.info(
                'rejected share, worker : %s, reason : duplicate share' %
                _worker_name)
            return {
                'id': _id,
                'result': None,
                'error': [22, 'duplicate share']
            }

        if share_diff >= _block_template.difficulty * 0.99:
            block_hash = binascii.hexlify(
                hash_util.reverse_bytes(header_hash)).decode()
            if os.getenv("COIN") in [
                    'monacoin', 'feathercoin', 'phoenixcoin', 'vertcoin',
                    'shield'
            ]:
                temp_hash = double_sha(header)
                block_hash = binascii.hexlify(
                    hash_util.reverse_bytes(temp_hash)).decode()

            logger.info('Try new block share, worker : %s, share diff : %s' %
                        (_worker_name, share_diff))
            share_result = self.coin_rpc.submit_block(
                binascii.hexlify(block_hex).decode())

            if share_result is None:
                logger.info('Found Block, result : %s, block hash : %s' %
                            (share_result, block_hash))
                result_hash = Interfaces.block_updater.update_block(
                    repeat=False, block_hash=block_hash)
                if result_hash is not None:
                    block_hash = result_hash
                self.database_ref.insert_accepted_share(
                    username, worker, True, True, _block_template.block_height,
                    share_diff, _block_template.pool_reward, diff, block_hash)
            else:
                logger.error(
                    'undefined share_result %s, block hash %s, coinbase tx %s'
                    % (share_result, block_hash,
                       binascii.hexlify(_block_template.coinbase_tx)))
                self.database_ref.insert_accepted_share(
                    username, worker, False, False,
                    _block_template.block_height, share_diff,
                    _block_template.pool_reward, diff)

                if os.getenv("COIN_TYPE") == 'bitcoin':
                    logger.error('Header : %s' %
                                 binascii.hexlify(header).decode())
                else:
                    logger.error('Header : %s' %
                                 binascii.hexlify(header_soln).decode())
                return {
                    'id': _id,
                    'result': None,
                    'error': [20, 'invalid solution']
                }
        else:
            logger.info('accepted share, worker : %s, share diff : %s' %
                        (_worker_name, '{0:.8f}'.format(share_diff)))
            self.database_ref.insert_accepted_share(
                username, worker, True, False, _block_template.block_height,
                share_diff, _block_template.pool_reward, diff)

        return {'id': _id, 'result': True, 'error': None}