protocol: Validate CLTV block values
This commit is contained in:
		
							parent
							
								
									46d1856f71
								
							
						
					
					
						commit
						ef0f5ea1ea
					
				@ -2415,21 +2415,9 @@ class BasicSwap(BaseApp):
 | 
			
		||||
            initiate_tx_block_time = int(self.callcoinrpc(coin_from, 'getblock', [initiate_tx_block_hash, ])['time'])
 | 
			
		||||
            if offer.lock_type == TxLockTypes.ABS_LOCK_BLOCKS:
 | 
			
		||||
                # Walk the coin_to chain back until block time matches
 | 
			
		||||
                blockchaininfo = self.callcoinrpc(coin_to, 'getblockchaininfo')
 | 
			
		||||
                cblock_hash = blockchaininfo['bestblockhash']
 | 
			
		||||
                cblock_height = blockchaininfo['blocks']
 | 
			
		||||
                max_tries = 1000
 | 
			
		||||
                for i in range(max_tries):
 | 
			
		||||
                    prev_block = self.callcoinrpc(coin_to, 'getblock', [cblock_hash, ])
 | 
			
		||||
                    self.log.debug('prev_block %s', str(prev_block))
 | 
			
		||||
 | 
			
		||||
                    if prev_block['time'] <= initiate_tx_block_time:
 | 
			
		||||
                        break
 | 
			
		||||
                    # cblock_hash and height are out of step unless loop breaks
 | 
			
		||||
                    cblock_hash = prev_block['previousblockhash']
 | 
			
		||||
                    cblock_height = prev_block['height']
 | 
			
		||||
 | 
			
		||||
                ensure(prev_block['time'] <= initiate_tx_block_time, 'Block not found for lock height')
 | 
			
		||||
                block_header_at = ci_to.getBlockHeaderAt(initiate_tx_block_time, block_after=True)
 | 
			
		||||
                cblock_hash = block_header_at['hash']
 | 
			
		||||
                cblock_height = block_header_at['height']
 | 
			
		||||
 | 
			
		||||
                self.log.debug('Setting lock value from height of block %s %s', coin_to, cblock_hash)
 | 
			
		||||
                contract_lock_value = cblock_height + lock_value
 | 
			
		||||
@ -4084,7 +4072,10 @@ class BasicSwap(BaseApp):
 | 
			
		||||
            ensure(script_lock_value == expect_sequence, 'sequence mismatch')
 | 
			
		||||
        else:
 | 
			
		||||
            if offer.lock_type == TxLockTypes.ABS_LOCK_BLOCKS:
 | 
			
		||||
                self.log.warning('TODO: validate absolute lock values')
 | 
			
		||||
                block_header_from = ci_from.getBlockHeaderAt(bid.created_at)
 | 
			
		||||
                chain_height_at_bid_creation = block_header_from['height']
 | 
			
		||||
                ensure(script_lock_value <= chain_height_at_bid_creation + offer.lock_value + atomic_swap_1.ABS_LOCK_BLOCKS_LEEWAY, 'script lock height too high')
 | 
			
		||||
                ensure(script_lock_value >= chain_height_at_bid_creation + offer.lock_value - atomic_swap_1.ABS_LOCK_BLOCKS_LEEWAY, 'script lock height too low')
 | 
			
		||||
            else:
 | 
			
		||||
                ensure(script_lock_value <= bid.created_at + offer.lock_value + atomic_swap_1.INITIATE_TX_TIMEOUT, 'script lock time too high')
 | 
			
		||||
                ensure(script_lock_value >= bid.created_at + offer.lock_value, 'script lock time too low')
 | 
			
		||||
 | 
			
		||||
@ -243,6 +243,19 @@ class BTCInterface(CoinInterface):
 | 
			
		||||
    def getBlockHeader(self, block_hash):
 | 
			
		||||
        return self.rpc_callback('getblockheader', [block_hash])
 | 
			
		||||
 | 
			
		||||
    def getBlockHeaderAt(self, time, block_after=False):
 | 
			
		||||
        blockchaininfo = self.rpc_callback('getblockchaininfo')
 | 
			
		||||
        last_block_header = self.rpc_callback('getblockheader', [blockchaininfo['bestblockhash']])
 | 
			
		||||
 | 
			
		||||
        max_tries = 5000
 | 
			
		||||
        for i in range(max_tries):
 | 
			
		||||
            prev_block_header = self.rpc_callback('getblock', [last_block_header['previousblockhash']])
 | 
			
		||||
            if prev_block_header['time'] <= time:
 | 
			
		||||
                return last_block_header if block_after else prev_block_header
 | 
			
		||||
 | 
			
		||||
            last_block_header = prev_block_header
 | 
			
		||||
        raise ValueError(f'Block header not found at time: {time}')
 | 
			
		||||
 | 
			
		||||
    def initialiseWallet(self, key_bytes):
 | 
			
		||||
        key_wif = self.encodeKey(key_bytes)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -12,6 +12,7 @@ from basicswap.script import (
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
INITIATE_TX_TIMEOUT = 40 * 60  # TODO: make variable per coin
 | 
			
		||||
ABS_LOCK_BLOCKS_LEEWAY = 5
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def buildContractScript(lock_val, secret_hash, pkh_redeem, pkh_refund, op_lock=OpCodes.OP_CHECKSEQUENCEVERIFY):
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user