Exemplo n.º 1
0
 def explorer_post(self, endpoint, data):
     """
     Put explorer data onto the stub client for the specified endpoint.
     """
     hash_template = re.compile(r'^.*/transactionpool/transactions$')
     match = hash_template.match(endpoint)
     if match:
         transactionid = Hash(value=jscrypto.random(Hash.SIZE)).__str__()
         transaction = tftransactions.from_json(data)
         # ensure all coin outputs and block stake outputs have identifiers set
         for idx, co in enumerate(transaction.coin_outputs):
             co.id = transaction.coin_outputid_new(idx)
         for idx, bso in enumerate(transaction.blockstake_outputs):
             bso.id = transaction.blockstake_outputid_new(idx)
         self._posted_transactions[transactionid] = transaction
         return jsstr.sprintf('{"transactionid":"%s"}',
                              transactionid.__str__())
     raise Exception("invalid endpoint {}".format(endpoint))
class UnlockHash(BaseDataTypeClass):
    """
    An UnlockHash is a specially constructed hash of the UnlockConditions type,
    with a fixed binary length of 33 and a fixed string length of 78 (string version includes a checksum).
    """
    def __init__(self, uhtype=None, uhhash=None):
        self._type = UnlockHashType.NIL
        self.uhtype = uhtype
        self._hash = Hash()
        self.hash = uhhash

    @classmethod
    def from_str(cls, obj):
        if not isinstance(obj, str):
            raise TypeError(
                "UnlockHash is expected to be a str, not {}".format(type(obj)))
        obj = jsstr.strip(obj)
        if len(obj) != UnlockHash._TOTAL_SIZE_HEX:
            raise ValueError(
                "UnlockHash is expexcted to be of length {} when stringified, not of length {}, invalid: {} ({})"
                .format(UnlockHash._TOTAL_SIZE_HEX, len(obj), obj, type(obj)))

        t = UnlockHashType(
            int(jsarr.slice_array(obj, 0, UnlockHash._TYPE_SIZE_HEX)))
        h = Hash(
            value=obj[UnlockHash._TYPE_SIZE_HEX:UnlockHash._TYPE_SIZE_HEX +
                      UnlockHash._HASH_SIZE_HEX])
        uh = cls(uhtype=t, uhhash=h)

        if t.__eq__(UnlockHashType.NIL):
            expectedNH = jshex.bytes_to_hex(
                bytes(jsarr.new_array(UnlockHash._HASH_SIZE)))
            nh = jshex.bytes_to_hex(h.value)
            if nh != expectedNH:
                raise ValueError("unexpected nil hash {}".format(nh))
        else:
            expected_checksum = jshex.bytes_to_hex(
                jsarr.slice_array(uh._checksum(), 0,
                                  UnlockHash._CHECKSUM_SIZE))
            checksum = jsarr.slice_array(
                obj,
                UnlockHash._TOTAL_SIZE_HEX - UnlockHash._CHECKSUM_SIZE_HEX)
            if expected_checksum != checksum:
                raise ValueError("unexpected checksum {}, expected {}".format(
                    checksum, expected_checksum))

        return uh

    @classmethod
    def from_json(cls, obj):
        return UnlockHash.from_str(obj)

    @property
    def uhtype(self):
        return self._type

    @uhtype.setter
    def uhtype(self, value):
        if value == None:
            value = UnlockHashType.NIL
        elif not isinstance(value, UnlockHashType):
            raise TypeError(
                "UnlockHash's type has to be of type UnlockHashType, not {}".
                format(type(value)))
        self._type = value

    @property
    def hash(self):
        return self._hash

    @hash.setter
    def hash(self, value):
        self._hash.value = value

    def __str__(self):
        checksum = jshex.bytes_to_hex(
            jsarr.slice_array(self._checksum(), 0, UnlockHash._CHECKSUM_SIZE))
        return "{}{}{}".format(
            jshex.bytes_to_hex(bytes([self._type.__int__()])),
            self._hash.__str__(), checksum)

    def _checksum(self):
        if self._type.__eq__(UnlockHashType.NIL):
            return bytes(jsarr.new_array(UnlockHash._CHECKSUM_SIZE))
        e = RivineBinaryEncoder()
        e.add_int8(self._type.value)
        e.add(self._hash)
        return jscrypto.blake2b(e.data)

    def __repr__(self):
        return self.__str__()

    def json(self):
        return self.__str__()

    def __eq__(self, other):
        other = UnlockHash._op_other_as_unlockhash(other)
        return self.uhtype.__eq__(other.uhtype) and self.hash.__eq__(
            other.hash)

    def __ne__(self, other):
        other = UnlockHash._op_other_as_unlockhash(other)
        return self.uhtype.__ne__(other.uhtype) or self.hash.__ne__(other.hash)

    def __hash__(self):
        return hash(self.__str__())

    @staticmethod
    def _op_other_as_unlockhash(other):
        if isinstance(other, str):
            other = UnlockHash.from_json(other)
        elif not isinstance(other, UnlockHash):
            raise TypeError("UnlockHash of type {} is not supported".format(
                type(other)))
        return other

    def sia_binary_encode(self, encoder):
        """
        Encode this unlock hash according to the Sia Binary Encoding format.
        """
        encoder.add_byte(self._type.__int__())
        encoder.add(self._hash)

    def rivine_binary_encode(self, encoder):
        """
        Encode this unlock hash according to the Rivine Binary Encoding format.
        """
        encoder.add_int8(self._type.__int__())
        encoder.add(self._hash)