Beispiel #1
0
def test_rectangles_to_draw():
    """
    Tests the rectangles to draw method.
    """
    # Compute the rectangles for this hard-coded example.
    # Convert to a set, since no particular rectangle order was required.
    block = Block(0, children=[
        Block(1, children=[
            Block(2, COLOUR_LIST[2]),
            Block(2, COLOUR_LIST[1]),
            Block(2, COLOUR_LIST[2]),
            Block(2, COLOUR_LIST[0])
        ]),
        Block(1, children=[
            Block(2, COLOUR_LIST[0]),
            Block(2, COLOUR_LIST[1]),
            Block(2, COLOUR_LIST[1]),
            Block(2, COLOUR_LIST[2])
        ]),
        Block(1, children=[
            Block(2, COLOUR_LIST[2]),
            Block(2, COLOUR_LIST[1]),
            Block(2, COLOUR_LIST[1]),
            Block(2, COLOUR_LIST[0])
        ]),
        Block(1, children=[
            Block(2, COLOUR_LIST[0]),
            Block(2, COLOUR_LIST[2]),
            Block(2, COLOUR_LIST[1]),
            Block(2, COLOUR_LIST[2])
        ])
    ])
    block.update_block_locations((0, 0), 50)
    actual_set = set(block.rectangles_to_draw())

    # Define the correct set of rectangles, again as a set.
    correct_rectangles = [((138, 151, 71), (37, 0), (12, 12), 0),
                          ((0, 0, 0), (37, 0), (12, 12), 3),
                          ((199, 44, 58), (25, 0), (12, 12), 0),
                          ((0, 0, 0), (25, 0), (12, 12), 3),
                          ((138, 151, 71), (25, 12), (12, 12), 0),
                          ((0, 0, 0), (25, 12), (12, 12), 3),
                          ((1, 128, 181), (37, 12), (12, 12), 0),
                          ((0, 0, 0), (37, 12), (12, 12), 3),
                          ((1, 128, 181), (12, 0), (12, 12), 0),
                          ((0, 0, 0), (12, 0), (12, 12), 3),
                          ((199, 44, 58), (0, 0), (12, 12), 0),
                          ((0, 0, 0), (0, 0), (12, 12), 3),
                          ((199, 44, 58), (0, 12), (12, 12), 0),
                          ((0, 0, 0), (0, 12), (12, 12), 3),
                          ((138, 151, 71), (12, 12), (12, 12), 0),
                          ((0, 0, 0), (12, 12), (12, 12), 3),
                          ((138, 151, 71), (12, 25), (12, 12), 0),
                          ((0, 0, 0), (12, 25), (12, 12), 3),
                          ((199, 44, 58), (0, 25), (12, 12), 0),
                          ((0, 0, 0), (0, 25), (12, 12), 3),
                          ((199, 44, 58), (0, 37), (12, 12), 0),
                          ((0, 0, 0), (0, 37), (12, 12), 3),
                          ((1, 128, 181), (12, 37), (12, 12), 0),
                          ((0, 0, 0), (12, 37), (12, 12), 3),
                          ((1, 128, 181), (37, 25), (12, 12), 0),
                          ((0, 0, 0), (37, 25), (12, 12), 3),
                          ((138, 151, 71), (25, 25), (12, 12), 0),
                          ((0, 0, 0), (25, 25), (12, 12), 3),
                          ((199, 44, 58), (25, 37), (12, 12), 0),
                          ((0, 0, 0), (25, 37), (12, 12), 3),
                          ((138, 151, 71), (37, 37), (12, 12), 0),
                          ((0, 0, 0), (37, 37), (12, 12), 3)]
    correct_set = set(correct_rectangles)

    # There must be no difference between the actual set and the correct set!
    assert actual_set.difference(correct_set) == set()
    assert correct_set.difference(actual_set) == set()
Beispiel #2
0
def child_block() -> Block:
    """Create a reference child block with a size of 750 and a max_depth of 0.
    """
    return Block((0, 0), 750, COLOUR_LIST[0], 0, 0)
Beispiel #3
0
def test_JEN_score_blob_goal() -> None:
    block1 = Block((0, 0), 16, None, 0, 2)
    c1 = Block((8, 0), 8, (1, 128, 181), 1, 2)
    c2 = Block((0, 0), 8, (199, 44, 58), 1, 2)
    c3 = Block((0, 8), 8, None, 1, 2)
    c4 = Block((8, 8), 8, None, 1, 2)
    block1.children = [c1, c2, c3, c4]
    b31 = Block((4, 8), 4, (1, 128, 181), 2, 2)
    b32 = Block((0, 8), 4, (199, 44, 58), 2, 2)
    b33 = Block((0, 12), 4, (255, 211, 92), 2, 2)
    b34 = Block((4, 12), 4, (199, 44, 58), 2, 2)
    c3.children = [b31, b32, b33, b34]
    b41 = Block((12, 8), 4, (255, 211, 92), 2, 2)
    b42 = Block((8, 8), 4, (199, 44, 58), 2, 2)
    b43 = Block((8, 12), 4, (255, 211, 92), 2, 2)
    b44 = Block((12, 12), 4, (199, 44, 58), 2, 2)
    c4.children = [b41, b42, b43, b44]
    block2 = Block((0, 0), 16, None, 0, 2)
    c1 = Block((8, 0), 8, (1, 128, 181), 1, 2)
    c2 = Block((0, 0), 8, (199, 44, 58), 1, 2)
    c3 = Block((0, 8), 8, (255, 211, 92), 1, 2)
    c4 = Block((8, 8), 8, (1, 128, 181), 1, 2)
    block2.children = [c1, c2, c3, c4]
    block3 = Block((0, 0), 16, None, 0, 2)
    c1 = Block((8, 0), 8, (1, 128, 181), 1, 2)
    c2 = Block((0, 0), 8, (199, 44, 58), 1, 2)
    c3 = Block((0, 8), 8, None, 1, 2)
    c4 = Block((8, 8), 8, (199, 44, 58), 1, 2)
    block3.children = [c1, c2, c3, c4]
    b31 = Block((4, 8), 4, (1, 128, 181), 2, 2)
    b32 = Block((0, 8), 4, (199, 44, 58), 2, 2)
    b33 = Block((0, 12), 4, (255, 211, 92), 2, 2)
    b34 = Block((4, 12), 4, (0, 0, 0), 2, 2)
    c3.children = [b31, b32, b33, b34]
    b41 = Block((12, 8), 4, (255, 211, 92), 2, 2)
    b42 = Block((8, 8), 4, (199, 44, 58), 2, 2)
    b43 = Block((8, 12), 4, (0, 0, 0), 2, 2)
    b44 = Block((12, 12), 4, (199, 44, 58), 2, 2)
    c4.children = [b41, b42, b43, b44]
    goal1 = BlobGoal((199, 44, 58))
    goal2 = BlobGoal((255, 211, 92))
    goal3 = BlobGoal((0, 0, 0))
    block4 = Block((0, 0), 16, None, 0, 2)
    c1 = Block((8, 0), 8, (1, 128, 181), 1, 2)
    c2 = Block((0, 0), 8, (199, 44, 58), 1, 2)
    c3 = Block((0, 8), 8, None, 1, 2)
    c4 = Block((8, 8), 8, None, 1, 2)
    block4.children = [c1, c2, c3, c4]
    b31 = Block((4, 8), 4, (1, 128, 181), 2, 2)
    b32 = Block((0, 8), 4, (199, 44, 58), 2, 2)
    b33 = Block((0, 12), 4, (199, 44, 58), 2, 2)
    b34 = Block((4, 12), 4, (199, 44, 58), 2, 2)
    c3.children = [b31, b32, b33, b34]
    b41 = Block((12, 8), 4, (255, 211, 92), 2, 2)
    b42 = Block((8, 8), 4, (199, 44, 58), 2, 2)
    b43 = Block((8, 12), 4, (199, 44, 58), 2, 2)
    b44 = Block((12, 12), 4, (199, 44, 58), 2, 2)
    c4.children = [b41, b42, b43, b44]
    assert goal1.score(block1) == 5
    assert goal1.score(block4) == 10
    assert goal2.score(block1) == 1
    assert goal2.score(block2) == 4
    assert goal3.score(block3) == 2
    assert goal3.score(block1) == 0
Beispiel #4
0
 def get_block_object_from_block_data(block_data):
     return Block(block_data['num_bloc'], block_data['id_contributeur'],
                  block_data['nonce'], block_data['preuve'],
                  block_data['previous_hash'], block_data['transactions'])
Beispiel #5
0
def test_JEN_block_to_squares() -> None:
    block1 = Block((0, 0), 16, None, 0, 2)
    c1 = Block((8, 0), 8, (1, 128, 181), 1, 2)
    c2 = Block((0, 0), 8, (199, 44, 58), 1, 2)
    c3 = Block((0, 8), 8, None, 1, 2)
    c4 = Block((8, 8), 8, None, 1, 2)
    block1.children = [c1, c2, c3, c4]
    b31 = Block((4, 8), 4, (1, 128, 181), 2, 2)
    b32 = Block((0, 8), 4, (199, 44, 58), 2, 2)
    b33 = Block((0, 12), 4, (255, 211, 92), 2, 2)
    b34 = Block((4, 12), 4, (199, 44, 58), 2, 2)
    c3.children = [b31, b32, b33, b34]
    b41 = Block((12, 8), 4, (255, 211, 92), 2, 2)
    b42 = Block((8, 8), 4, (199, 44, 58), 2, 2)
    b43 = Block((8, 12), 4, (255, 211, 92), 2, 2)
    b44 = Block((12, 12), 4, (199, 44, 58), 2, 2)
    c4.children = [b41, b42, b43, b44]
    lst = _block_to_squares(block1)
    assert ((1, 128, 181), (4, 8), 4) in lst
 def add_block(self, data): 
     self.chain.append(Block(data))
Beispiel #7
0
server_sockets = {}

# stores all operations not added to blockchain yet
queue = []
# stores key values
kv_store = {}
# blockchain contains dicts with operation, nonce, hash
blockchain = Blockchain()
# simulates failed link between src (current process) and process in set
failed_links = set()
# leader
leader = None

ballot_num = list()
accept_num = [-1, -1, -1]
accept_val = Block()

majority_accept = threading.Event()

DELAY = 2

def writeToFile(pid):
    with open("blockchain_{}.json".format(pid), "w") as f:
        arr = []
        for block in blockchain.chain:
            print(block.operation)
            arr.append(block.to_dict())
        json.dump(arr, f, indent=4)

def readFromFile(pid):
    with open("blockchain_{}.json".format(pid), "r") as f:
Beispiel #8
0
 def getBlockWithData(self, *args):
     """Get block with data (x,y,z) => Block"""
     ans = self.conn.sendReceive("world.getBlockWithData", intFloor(args))
     return Block(*map(int, ans.split(",")))
Beispiel #9
0
def get_chain():
    chain_snapshot = blockchain.chain
    #serializable_chain = [Block(bl_el.index, bl_el.previous_hash, [tx.__dict__ for tx in bl_el.transactions], bl_el.proof, bl_el.timestamp) for bl_el in chain_snapshot]
    #dict_chain = [block.__dict__ for block in serializable_chain]
    dict_chain = [block.__dict__.copy() for block in [Block(bl_el.index, bl_el.previous_hash, [tx.__dict__ for tx in bl_el.transactions], bl_el.proof, bl_el.timestamp) for bl_el in chain_snapshot]]
    return jsonify(dict_chain), 200
Beispiel #10
0
 def add_block(self, transaction):
     previous_hash = self.chain[len(self.chain) - 1].hash
     new_block = Block(transaction, previous_hash)
     new_block.generate_hash()
     proof = self.proof_of_work(new_block)
     self.chain.append(new_block)
Beispiel #11
0
 def genesis_block(self):
     transaction = []
     previous_hash = '0'
     genesis_block = Block(transaction, previous_hash)
     genesis_block.generate_hash()
     self.chain.append(genesis_block)
Beispiel #12
0
 def genesis_block(self):
     """Initialise the blockchain with a unique block."""
     self.chain.append(Block([], "0"))
Beispiel #13
0
    def first(self):
        """Generate beginning of the chain."""

        block = Block(0, "First block", "0")  # with hash = 0
        self.data.append(block)
        return block
Beispiel #14
0
    def next(self, previous, data):
        """Compute the next block using the previous one."""

        block = Block(previous.index + 1, data, previous.hash)
        self.data.append(block)
        return block
Beispiel #15
0
 def __init__(self):
     print("创建一个新区块链\n")
     self.chain = []
     genesis_block = Block('创世区块')
     self.chain.append(genesis_block)
Beispiel #16
0
 def create_block(self):
     return Block(index=0,
                  data_dict={'token': random.randint(0, 1000)},
                  previous_hash='')
Beispiel #17
0
from transaction_manager import TransactionManager

# flask init
app = Flask(__name__)
app.secret_key = 'super secret key'

# objects init
mutex = Lock()
s = Serializer()
block_chain = BlockChain()
transaction_manager = TransactionManager()

# create genesis block
genesis_block = Block(index=0,
                      timestamp=timer(),
                      transactions=transaction_manager.get_transactions(),
                      previous_hash="genesis_block",
                      difficulty=block_chain.get_difficulty())
block_chain.set_working_block(genesis_block)


@app.route('/', methods=['GET'])
def main():
    return block_chain.to_html()


@app.route('/get_block', methods=['GET'])
def get_block():
    return s.serialize(block_chain.get_working_block())

Beispiel #18
0
    def add_transaction(self, transaction):
        if not self.next_block:
            self.next_block = Block(prev_hash=self.best_block_hash)

        self.state = self.state.apply(transaction)
        self.next_block.transactions.append(transaction)
Beispiel #19
0
 def generate_block(self, x, y):
     """Create a new Block object at the given x,y and return it"""
     new_block = Block(self.settings, self.screen, self.block_image)
     new_block.rect.top = y
     new_block.rect.left = x
     return new_block
Beispiel #20
0
def read_block(block):
    # Reads a block from a dictionary
    return Block(read_header(block['header']),
                 [read_transaction(item) for item in block['transactions']])
Beispiel #21
0
      def mine_block( self ):
      
            print('In mine block, Resolve Conflicts =====>>> ' , self.resolve_conflicts )
            if self.resolve_conflicts:
                  return Error.get_error_object( '409', 'Resolved conflict before you mine a new Block !')

            if self.hosting_node_id == None:
                  print( 'Cannot mine the block for invalid sender, Did you generated Wallet? ' )

                  error = Error()
                  error.message= 'Cannot mine the block for invalid sender, Did you generated Wallet?'
                  error.code= 'MINE_MISSING_WALLET'
                  return error


            last_block = self.__chain[-1]
            hashed_block = hash_block( last_block )

            # Calculate proof of work/nonce before you add reward tranasction
            proof = self.proof_of_work()

            copied_transactions = self.__open_transactions[:]

            # Verify for the signature mismatch before you mine the block.
            for tx in copied_transactions:
                  if not Wallet.verify_signature( tx ):
                        print( 'ERRPR:::Cannot mine the block as Signature is not matching...!!!' )
                        
                        error = Error()
                        error.message= 'Cannot mine the block as Signature is not matching...!!!'
                        error.code= 'MINE_MISSING_SIGNATURE'
                        return error


            reward_transaction = Transaction( 'MINNER', self.hosting_node_id, MINING_REWARDS, '' )
            copied_transactions.append( reward_transaction )

            block = Block( len( self.__chain ), hashed_block, copied_transactions, proof )
            
            self.__chain.append( block )
            self.__open_transactions = []
            # Save data in a file.
            self.save_data()

            print('In mine block data has been saved successfully, Starting broadcast now !!! ')

            # Let's inform other nodes for this mining using broadcasting a block
            for node in self.__peer_nodes:
                  try:
                        url = 'http://{}/broadcast_block'.format( node )
                        converted_block = block.__dict__.copy()
                        converted_block['transactions'] = [ tx.__dict__ for tx in converted_block['transactions'] ]
                        
                        print('Bradcasting mined block on ===>>> ' , url )
                        input = {
                              'block' : converted_block
                        }
                        response = requests.post( url, json={'block': converted_block} )

                        if response.status_code == 400 or response.status_code == 500:
                              print( 'Error:::Error in mine block for borading casting is ', response )
                        if response.status_code == 201:
                              print( '*** Mined Block broadcasted successfully ***' )  
                        
                        if response.status_code == 409:
                              print( '*** We need to resolve config which might caused due to earlier node network block missmatch...' )
                              self.resolve_conflicts = True


                  except ConnectionError:
                        print('Error connection a node server ', node )

            print('Mine Block Broadcasting completed....')

            return block
Beispiel #22
0
import json
import time
from transaction import Transaction
from block import Block
from key import BitcoinAccount

wallet = BitcoinAccount()

difficulty = 4

first_block = Block(0, "")

first_block.add_transaction("mohamed", "justine", 50, time.time())
first_block.mine(difficulty, wallet)

print("First block is: ")

print(first_block)

last_hash = first_block.hash_val

second_block = Block(1, last_hash)

second_block.mine(difficulty, wallet)

print("Second block is: ")

print(second_block)

print(json.dumps(second_block.to_dict()))
Beispiel #23
0
 def __init__(self):
     self.blockchain = Block()
     # by default it is Roulette contract
     self.contract = self.blockchain.deploy_contract()
     self.owner_account = self.blockchain.eth.defaultAccount
     self.accounts = self.blockchain.eth.accounts
Beispiel #24
0
properties = {"blocks": {}, "items": {}}
for name in os.listdir("data/properties/blocks/"):
    file = open("data/properties/blocks/" + name, "r")
    properties["blocks"].update({name[:-5]: json.loads(file.read())})
    file.close()
for name in os.listdir("data/properties/items/"):
    file = open("data/properties/items/" + name, "r")
    properties["items"].update({name[:-5]: json.loads(file.read())})
    file.close()

#generating map
gameMap = []
for y in range(WORLD_HEIGHT):
    gameMap.append([])
    for x in range(WORLD_WIDTH):
        gameMap[y].append(Block("air"))

lastEnd = HEIGHT_DEFAULT
for i in range(WORLD_WIDTH // GENERATION_STEP):
    thisEnd = random.randint(HEIGHT_DEFAULT - HEIGHT_DISPERSION,
                             HEIGHT_DEFAULT + HEIGHT_DISPERSION)
    gameMap[lastEnd][i * GENERATION_STEP] = Block("grass")
    for x in range(1, GENERATION_STEP):
        gameMap[int(lastEnd - (lastEnd - thisEnd) / GENERATION_STEP *
                    x)][i * GENERATION_STEP + x] = Block("grass")
    lastEnd = thisEnd

for y in range(WORLD_HEIGHT):
    for blockX in range(len(gameMap[y])):
        if gameMap[y][blockX].name == "grass":
            gameMap[y - 1][blockX] = Block("dirt")
Beispiel #25
0
def test_JEN_combine() -> None:
    block = Block((0, 0), 16, (1, 128, 181), 0, 2)
    b1 = Block((8, 0), 8, (1, 128, 181), 1, 2)
    b2 = Block((0, 0), 8, (199, 44, 58), 1, 2)
    b3 = Block((0, 8), 8, (1, 128, 181), 1, 2)
    b4 = Block((8, 8), 8, (255, 211, 92), 1, 2)
    block.children = [b1, b2, b3, b4]
    b31 = Block((4, 8), 4, (1, 128, 181), 2, 2)
    b32 = Block((0, 8), 4, (199, 44, 58), 2, 2)
    b33 = Block((0, 12), 4, (255, 211, 92), 2, 2)
    b34 = Block((4, 12), 4, (199, 44, 58), 2, 2)
    b3.children = [b31, b32, b33, b34]
    b41 = Block((12, 8), 4, (255, 211, 92), 2, 2)
    b42 = Block((8, 8), 4, (199, 44, 58), 2, 2)
    b43 = Block((8, 12), 4, (255, 211, 92), 2, 2)
    b44 = Block((12, 12), 4, (199, 44, 58), 2, 2)
    b4.children = [b41, b42, b43, b44]
    assert b34.combine() is False
    assert block.combine() is False
    assert b3.combine()
    assert b4.combine() is False
    assert block.combine
    assert block.combine() is False
Beispiel #26
0
def create_genesis_block():

    return Block(0, date.datetime.now(), "Genesis Block", "0")
Beispiel #27
0
def test_JEN_flatten() -> None:
    blocky = Block((0, 0), 16, (1, 128, 181), 0, 0)
    assert _flatten(blocky) == [[(1, 128, 181)]]
    block = Block((0, 0), 16, None, 0, 1)
    b1 = Block((8, 0), 8, (1, 128, 181), 1, 1)
    b2 = Block((0, 0), 8, (199, 44, 58), 1, 1)
    b3 = Block((0, 8), 8, (1, 128, 181), 1, 1)
    b4 = Block((8, 8), 8, (255, 211, 92), 1, 1)
    block.children = [b1, b2, b3, b4]
    assert _flatten(block) == [[(199, 44, 58), (1, 128, 181)], [(1, 128, 181),
                                                                (255, 211, 92)]]
    block1 = Block((0, 0), 16, None, 0, 2)
    c1 = Block((8, 0), 8, (1, 128, 181), 1, 2)
    c2 = Block((0, 0), 8, (199, 44, 58), 1, 2)
    c3 = Block((0, 8), 8, None, 1, 2)
    c4 = Block((8, 8), 8, None, 1, 2)
    block1.children = [c1, c2, c3, c4]
    b31 = Block((4, 8), 4, (1, 128, 181), 2, 2)
    b32 = Block((0, 8), 4, (199, 44, 58), 2, 2)
    b33 = Block((0, 12), 4, (255, 211, 92), 2, 2)
    b34 = Block((4, 12), 4, (199, 44, 58), 2, 2)
    c3.children = [b31, b32, b33, b34]
    b41 = Block((12, 8), 4, (255, 211, 92), 2, 2)
    b42 = Block((8, 8), 4, (199, 44, 58), 2, 2)
    b43 = Block((8, 12), 4, (255, 211, 92), 2, 2)
    b44 = Block((12, 12), 4, (199, 44, 58), 2, 2)
    c4.children = [b41, b42, b43, b44]
    block2 = Block((0, 0), 16, None, 0, 2)
    c1 = Block((8, 0), 8, (1, 128, 181), 1, 2)
    c2 = Block((0, 0), 8, (199, 44, 58), 1, 2)
    c3 = Block((0, 8), 8, (255, 211, 92), 1, 2)
    c4 = Block((8, 8), 8, (1, 128, 181), 1, 2)
    block2.children = [c1, c2, c3, c4]
    assert len(_flatten(block1)) == len(_flatten(block2))
    assert _flatten(block1) == [[(199, 44, 58), (199, 44, 58), (199, 44, 58),
                                 (255, 211, 92)], [(199, 44, 58), (199, 44, 58),
                                                   (1, 128, 181), (199, 44, 58)],
                                [(1, 128, 181), (1, 128, 181), (199, 44, 58),
                                 (255, 211, 92)], [(1, 128, 181), (1, 128, 181),
                                                   (255, 211, 92), (199, 44, 58)]]
    assert _flatten(block2) == [[(199, 44, 58), (199, 44, 58), (255, 211, 92), (255, 211, 92)],
                                [(199, 44, 58), (199, 44, 58), (255, 211, 92), (255, 211, 92)],
                                [(1, 128, 181), (1, 128, 181), (1, 128, 181), (1, 128, 181)],
                                [(1, 128, 181), (1, 128, 181), (1, 128, 181), (1, 128, 181)]]
Beispiel #28
0
 def add_block(self, data):
     new_block = Block(data, self.chain[-1].hash())  #上一个区块链的prevBlockHash
     self.chain.append(new_block)
Beispiel #29
0
 def create_genesis_block():
     return Block(0, date.datetime.now(), 'Genesis Block', '0')
Beispiel #30
0
    def __init__(self):
        # Domain is (0,3)x(0,3)X(0,3) length unit
        x_min, y_min, z_min = 1, 1, 1
        x_max, y_max, z_max = 4, 4, 4

        # Single block with 4x4x4 sites, 1 length unit apart
        self.size_in_blocks = (1, 1, 1)
        self.sites_along_block = 6
        self.space_step = 1

        sites = []
        # Requirement: Sites are striped with the z coordinate changing most frequently, i.e. the z coordinate represents the least significant part of the site index within the block.
        for index in np.ndindex(3 * (self.sites_along_block, )):
            x_index, y_index, z_index = index
            if ((x_index < x_min or x_index > x_max)
                    or (y_index < y_min or y_index > y_max)
                    or (z_index < z_min or z_index > z_max)):
                # This site is solid
                sites.append(Site(Site.solid_site, [], None))
            else:
                links = []
                for direction in self.lattice_directions:
                    link_type = Link.no_boundary

                    # Assign an iolet id (the first iolet in the config xml file)
                    iolet_index = 0

                    # In this example, links that cross both wall and inlet/outlet (like the 8 corners of the cube) will be considered non-wall because of the ordering of the if statements below
                    if x_index == x_min and direction[0] == -1:
                        link_type = Link.wall
                    if x_index == x_max and direction[0] == 1:
                        link_type = Link.wall
                    if y_index == y_min and direction[1] == -1:
                        link_type = Link.wall
                    if y_index == y_max and direction[1] == 1:
                        link_type = Link.wall
                    if z_index == z_min and direction[2] == -1:
                        link_type = Link.inlet
                    if z_index == z_max and direction[2] == 1:
                        link_type = Link.outlet

                    # Assume walls are half a lattice away
                    wall_distance = 0.5

                    # iolet_index and wall_distance will be ignored when meaningless
                    links.append(Link(link_type, wall_distance, iolet_index))

                # For sites at the intersection of two cube faces considered wall (i.e. perpendicular to the x or y
                # axes), we arbitrarily choose the normal to lie along the y axis. The logic below must be consistent
                # with Code/unittests/FourCubeLatticeData.h
                normal = None
                if x_index == x_min:
                    normal = np.array([-1, 0, 0])
                if x_index == x_max:
                    normal = np.array([1, 0, 0])
                if y_index == y_min:
                    normal = np.array([0, -1, 0])
                if y_index == y_max:
                    normal = np.array([0, 1, 0])

                sites.append(Site(Site.fluid_site, links, normal))

        # Requirement: Blocks are striped with the z coordinate changing most frequently (i.e. the z coordinate represents the least significant part of the block index) then y and x slowest.
        # This geometry is made of a single block with the sites defined above
        self.blocks = [Block(sites)]

        # Let the parent class do the rest
        super(FourCube, self).__init__()