# Path: parser/stpcommands.py
# def blockCharacteristic(stpfile, characteristic, wordsize):
# def setupQuery(stpfile):
# def setupVariables(stpfile, variables, wordsize):
# def assertVariableValue(stpfile, a, b):
# def getStringForVariables(variables, wordsize):
# def assertNonZero(stpfile, variables, wordsize):
# def getStringForNonZero(variables, wordsize):
# def limitWeight(stpfile, weight, p, wordsize, ignoreMSBs=0):
# def setupWeightComputationSum(stpfile, weight, p, wordsize, ignoreMSBs=0):
# def setupWeightComputation(stpfile, weight, p, wordsize, ignoreMSBs=0):
# def getWeightString(variables, wordsize, ignoreMSBs=0, weightVariable="weight"):
# def getStringEq(a, b, c):
# def getStringAdd(a, b, c, wordsize):
# def getStringForAndDifferential(a, b, c):
# def getStringLeftRotate(value, rotation, wordsize):
# def getStringRightRotate(value, rotation, wordsize):
# def add4bitSbox(sbox, variables):
#     DDT = [[0]*16 for i in range(16)]
# 
# Path: ciphers/cipher.py
# class AbstractCipher(object, metaclass=ABCMeta):
#     """
#     Abstract Class for Ciphers
#     """
# 
#     @abstractmethod
#     def createSTP(self, filename, cipherParameters):
#         """
#         Each cipher need to define how it creates an instance for the
#         SMT solver.
#         """
#         pass
# 
#     @abstractmethod
#     def getFormatString(self):
#         """
#         Each cipher needs to specify the format it should be printed.
#         """
#         pass
# 
# Path: parser/stpcommands.py
# def getStringLeftRotate(value, rotation, wordsize):
#     if rotation % wordsize == 0:
#         return "{0}".format(value)
#     command = "((({0} << {1})[{2}:0]) | (({0} >> {3})[{2}:0]))".format(
#         value, (rotation % wordsize), wordsize - 1, (wordsize - rotation) % wordsize)
# 
#     return command
# 
# Path: parser/stpcommands.py
# def getStringRightRotate(value, rotation, wordsize):
#     if rotation % wordsize == 0:
#         return "{0}".format(value)
#     command = "((({0} >> {1})[{2}:0]) | (({0} << {3})[{2}:0]))".format(
#         value, (rotation % wordsize), wordsize - 1, (wordsize - rotation) % wordsize)
#     return command


from parser import stpcommands
from ciphers.cipher import AbstractCipher
from parser.stpcommands import getStringLeftRotate as rotl
from parser.stpcommands import getStringRightRotate as rotr
                            5, "0"*4))

            weight_sum += ("0b{0}@(BVPLUS({1}, {2}[0:0], {2}[1:1], "
                "{2}[2:2],{2}[3:3], {2}[4:4])),".format("0"*11, 5, "0b0000@" +
                                                        tmp[z + 5*wordsize*rnd]))

        command += "ASSERT({}=BVPLUS({},{}));\n".format(w[rnd], 16, 
                                                        weight_sum[:-1])

        # Linear after S-box
        command += "ASSERT({} = BVXOR({}, {}));\n".format(c[0 + 5*rnd],
                                                          b[0 + 5*rnd],
                                                          b[4 + 5*rnd])
        command += "ASSERT({} = BVXOR({}, {}));\n".format(c[1 + 5*rnd],
                                                          b[0 + 5*rnd],
                                                          b[1 + 5*rnd])
        command += "ASSERT({} = {});\n".format(c[2 + 5*rnd], b[2 + 5*rnd])
        command += "ASSERT({} = BVXOR({}, {}));\n".format(c[3 + 5*rnd],
                                                          b[2 + 5*rnd],
                                                          b[3 + 5*rnd])
        command += "ASSERT({} = {});\n".format(c[4 + 5*rnd], b[4 + 5*rnd])


        # Linear functions
        rot_constants = [[19, 28], [61, 39], [1, 6], [10, 17], [7, 41]]
        for row in range(5):
            command += "ASSERT({} = BVXOR({}, BVXOR({}, {})));\n".format(
                s[row + 5 * (rnd + 1)],
                c[row + 5*rnd],
                rotr(c[row + 5*rnd], rot_constants[row][0], wordsize),

# Path: parser/stpcommands.py
# def blockCharacteristic(stpfile, characteristic, wordsize):
# def setupQuery(stpfile):
# def setupVariables(stpfile, variables, wordsize):
# def assertVariableValue(stpfile, a, b):
# def getStringForVariables(variables, wordsize):
# def assertNonZero(stpfile, variables, wordsize):
# def getStringForNonZero(variables, wordsize):
# def limitWeight(stpfile, weight, p, wordsize, ignoreMSBs=0):
# def setupWeightComputationSum(stpfile, weight, p, wordsize, ignoreMSBs=0):
# def setupWeightComputation(stpfile, weight, p, wordsize, ignoreMSBs=0):
# def getWeightString(variables, wordsize, ignoreMSBs=0, weightVariable="weight"):
# def getStringEq(a, b, c):
# def getStringAdd(a, b, c, wordsize):
# def getStringForAndDifferential(a, b, c):
# def getStringLeftRotate(value, rotation, wordsize):
# def getStringRightRotate(value, rotation, wordsize):
# def add4bitSbox(sbox, variables):
#     DDT = [[0]*16 for i in range(16)]
# 
# Path: ciphers/cipher.py
# class AbstractCipher(object, metaclass=ABCMeta):
#     """
#     Abstract Class for Ciphers
#     """
# 
#     @abstractmethod
#     def createSTP(self, filename, cipherParameters):
#         """
#         Each cipher need to define how it creates an instance for the
#         SMT solver.
#         """
#         pass
# 
#     @abstractmethod
#     def getFormatString(self):
#         """
#         Each cipher needs to specify the format it should be printed.
#         """
#         pass
# 
# Path: parser/stpcommands.py
# def getStringLeftRotate(value, rotation, wordsize):
#     if rotation % wordsize == 0:
#         return "{0}".format(value)
#     command = "((({0} << {1})[{2}:0]) | (({0} >> {3})[{2}:0]))".format(
#         value, (rotation % wordsize), wordsize - 1, (wordsize - rotation) % wordsize)
# 
#     return command
# 
# Path: parser/stpcommands.py
# def getStringRightRotate(value, rotation, wordsize):
#     if rotation % wordsize == 0:
#         return "{0}".format(value)
#     command = "((({0} >> {1})[{2}:0]) | (({0} << {3})[{2}:0]))".format(
#         value, (rotation % wordsize), wordsize - 1, (wordsize - rotation) % wordsize)
#     return command


# Path: ciphers/ascon.py
from parser import stpcommands
from ciphers.cipher import AbstractCipher
from parser.stpcommands import getStringLeftRotate as rotl
from parser.stpcommands import getStringRightRotate as rotr

                            5, "0"*4))

            weight_sum += ("0b{0}@(BVPLUS({1}, {2}[0:0], {2}[1:1], "
                "{2}[2:2],{2}[3:3], {2}[4:4])),".format("0"*11, 5, "0b0000@" +
                                                        tmp[z + 5*wordsize*rnd]))

        command += "ASSERT({}=BVPLUS({},{}));\n".format(w[rnd], 16, 
                                                        weight_sum[:-1])

        # Linear after S-box
        command += "ASSERT({} = BVXOR({}, {}));\n".format(c[0 + 5*rnd],
                                                          b[0 + 5*rnd],
                                                          b[4 + 5*rnd])
        command += "ASSERT({} = BVXOR({}, {}));\n".format(c[1 + 5*rnd],
                                                          b[0 + 5*rnd],
                                                          b[1 + 5*rnd])
        command += "ASSERT({} = {});\n".format(c[2 + 5*rnd], b[2 + 5*rnd])
        command += "ASSERT({} = BVXOR({}, {}));\n".format(c[3 + 5*rnd],
                                                          b[2 + 5*rnd],
                                                          b[3 + 5*rnd])
        command += "ASSERT({} = {});\n".format(c[4 + 5*rnd], b[4 + 5*rnd])


        # Linear functions
        rot_constants = [[19, 28], [61, 39], [1, 6], [10, 17], [7, 41]]
        for row in range(5):
            command += "ASSERT({} = BVXOR({}, BVXOR({}, {})));\n".format(
                s[row + 5 * (rnd + 1)],
                c[row + 5*rnd],
                rotr(c[row + 5*rnd], rot_constants[row][0], wordsize),

                rotr(c[row + 5*rnd], rot_constants[row][1], wordsize),