示例#1
0
def signElement(elem: Element) -> Signature:
    if isinstance(elem, Verification):
        verif: SignedVerification = SignedVerification(elem.hash, elem.holder)
        verif.sign(elem.holder, PrivateKey(elem.holder))
        return verif.signature

    if isinstance(elem, SignedMeritRemovalVerificationPacket):
        return elem.signature

    if isinstance(elem, SendDifficulty):
        sendDiff: SignedSendDifficulty = SignedSendDifficulty(
            elem.difficulty, elem.nonce)
        sendDiff.sign(elem.holder, PrivateKey(elem.holder))
        return sendDiff.signature

    if isinstance(elem, DataDifficulty):
        dataDiff: SignedDataDifficulty = SignedDataDifficulty(
            elem.difficulty, elem.nonce)
        dataDiff.sign(elem.holder, PrivateKey(elem.holder))
        return dataDiff.signature

    if isinstance(elem, MeritRemoval):
        result: Signature = signElement(elem.e2)
        if not elem.partial:
            result = Signature.aggregate([result, signElement(elem.e1)])
        return result

    raise GenerationError(
        "Tried to sign an Element in a Block we didn't recognize the type of.")
示例#2
0
  def voteAndVerify() ->  None:
    #Check the difficulties for a holder who has yet to vote.
    try:
      rpc.call("consensus", "getSendDifficulty", {"holder": 0}, False)
      raise TestError("")
    except TestError as e:
      if str(e) != "-2 Holder doesn't have a SendDifficulty.":
        raise TestError("getSendDifficulty didn't raise when asked about a holder who has yet to vote.")
    try:
      rpc.call("consensus", "getDataDifficulty", {"holder": 0}, False)
      raise TestError("")
    except TestError as e:
      if str(e) != "-2 Holder doesn't have a DataDifficulty.":
        raise TestError("getDataDifficulty didn't raise when asked about a holder who has yet to vote.")

    #Create the votes.
    sendDiff: SignedSendDifficulty = SignedSendDifficulty(6, 0)
    sendDiff.sign(0, PrivateKey(0))

    dataDiff: SignedDataDifficulty = SignedDataDifficulty(10, 1)
    dataDiff.sign(0, PrivateKey(0))

    #Send them.
    rpc.meros.signedElement(sendDiff)
    rpc.meros.signedElement(dataDiff)
    rpc.meros.live.recv()
    rpc.meros.live.recv()

    #Check them.
    if rpc.call("consensus", "getSendDifficulty", {"holder": 0}, False) != 6:
      raise TestError("getSendDifficulty didn't reply with the holder's current difficulty.")
    if rpc.call("consensus", "getDataDifficulty", {"holder": 0}, False) != 10:
      raise TestError("getDataDifficulty didn't reply with the holder's current difficulty.")
示例#3
0
def mineBlock(rpc: RPC, nick: int = 0) -> None:
    privKey: PrivateKey = PrivateKey(nick)
    template: Dict[str, Any] = rpc.call(
        "merit", "getBlockTemplate",
        {"miner": privKey.toPublicKey().serialize().hex()})
    header: bytes = bytes.fromhex(template["header"])[:-4]
    header += (rpc.call(
        "merit", "getBlock",
        {"block": rpc.call("merit", "getHeight") - 1})["header"]["time"] +
               1200).to_bytes(4, "little")

    proof: int = -1
    tempHash: bytes = bytes()
    signature: bytes = bytes()
    while ((proof == -1)
           or ((int.from_bytes(tempHash, "little") * template["difficulty"]) >
               int.from_bytes(bytes.fromhex("FF" * 32), "little"))):
        proof += 1
        tempHash = RandomX(header + proof.to_bytes(4, "little"))
        signature = privKey.sign(tempHash).serialize()
        tempHash = RandomX(tempHash + signature)

    rpc.call(
        "merit", "publishBlock", {
            "id":
            template["id"],
            "header":
            header.hex() + proof.to_bytes(4, "little").hex() + signature.hex()
        })
    if rpc.meros.live.recv() != (MessageType.BlockHeader.toByte() + header +
                                 proof.to_bytes(4, "little") + signature):
        raise TestError("Meros didn't broadcast back the BlockHeader.")
示例#4
0
 def sign(
   self,
   holder: int,
   privKey: PrivateKey
 ) -> None:
   self.holder = holder
   self.signature = privKey.sign(self.signatureSerialize())
def HundredSixSignedElementsTest(rpc: RPC) -> None:
    #Solely used to get the genesis Block hash.
    blockchain: Blockchain = Blockchain()

    blsPrivKey: PrivateKey = PrivateKey(0)
    sig: Signature = blsPrivKey.sign(bytes())

    #Create a Data.
    #This is required so the Verification isn't terminated early for having an unknown hash.
    data: bytes = bytes.fromhex(rpc.call("personal", "data", ["AA"]))

    #Create a signed Verification, SendDifficulty, and DataDifficulty.
    elements: List[SignedElement] = [
        SignedVerification(data, 1, sig),
        SignedSendDifficulty(0, 0, 1, sig),
        SignedDataDifficulty(0, 0, 1, sig)
    ]

    for elem in elements:
        #Handshake with the node.
        rpc.meros.liveConnect(blockchain.blocks[0].header.hash)

        #Send the Element.
        rpc.meros.signedElement(elem)

        #Sleep for thirty seconds to make sure Meros realizes our connection is dead.
        sleep(30)

        #Verify the node didn't crash.
        try:
            if rpc.call("merit", "getHeight") != 1:
                raise Exception()
        except Exception:
            raise TestError(
                "Node crashed after being sent a malformed Element.")
示例#6
0
    def add(self,
            nick: int = 0,
            packets: List[VerificationPacket] = [],
            elements: List[Element] = []) -> None:
        #Determine if this is a new miner or not.
        miner: Union[PrivateKey, int]
        self.miners.append(self.miners[-1])
        if nick > self.miners[-1]:
            raise GenerationError(
                "Told to mine a Block with a miner nick which doesn't exist.")
        if nick == self.miners[-1]:
            miner = PrivateKey(nick)
            self.miners[-1] += 1
        else:
            miner = nick

        timeBase: int
        if len(self.blocks) == 0:
            timeBase = Blockchain().blocks[0].header.time
        else:
            timeBase = self.blocks[-1].time

        #Create and add the PrototypeBlock.
        self.blocks.append(
            PrototypeBlock(
                timeBase + self.timeOffset,
                #Create copies of the lists used as arguments to ensure we don't mutate the arguments.
                list(packets),
                list(elements),
                miner))
示例#7
0
def createSend(rpc: RPC, last: Union[Claim, Send], toAddress: str) -> Send:
    funded: Ristretto.SigningKey = Ristretto.SigningKey(b'\0' * 32)
    if isinstance(last, Claim):
        send: Send = Send([(last.hash, 0)],
                          [(decodeAddress(toAddress), 1),
                           (funded.get_verifying_key(), last.amount - 1)])
    else:
        send: Send = Send(
            [(last.hash, 1)],
            [(decodeAddress(toAddress), 1),
             (funded.get_verifying_key(), last.outputs[1][1] - 1)])

    send.sign(funded)
    send.beat(SpamFilter(3))
    sleep(65)
    rpc.meros.liveConnect(Blockchain().blocks[0].header.hash)
    if rpc.meros.liveTransaction(send) != rpc.meros.live.recv():
        raise TestError("Meros didn't broadcast back a Send.")

    sv: SignedVerification = SignedVerification(send.hash)
    sv.sign(0, PrivateKey(0))
    if rpc.meros.signedElement(sv) != rpc.meros.live.recv():
        raise TestError("Meros didn't broadcast back a Verification.")

    return send
示例#8
0
def VUnknownSignedTest(rpc: RPC) -> None:
    file: IO[Any] = open("e2e/Vectors/Merit/BlankBlocks.json", "r")
    chain: Blockchain = Blockchain.fromJSON(json.loads(file.read()))
    file.close()

    #Send a single block so we have a miner.
    rpc.meros.liveConnect(chain.blocks[0].header.hash)
    rpc.meros.syncConnect(chain.blocks[0].header.hash)
    header: bytes = rpc.meros.liveBlockHeader(chain.blocks[1].header)
    if MessageType(rpc.meros.sync.recv()[0]) != MessageType.BlockBodyRequest:
        raise TestError("Meros didn't ask for the body.")
    rpc.meros.blockBody(chain.blocks[1])
    if rpc.meros.live.recv() != header:
        raise TestError("Meros didn't broadcast the header.")

    #Create a valid Data.
    #Uneccessary at this time, but good preparation for the future.
    privKey: ed25519.SigningKey = ed25519.SigningKey(b'\0' * 32)
    data: Data = Data(bytes(32), privKey.get_verifying_key().to_bytes())
    data.sign(privKey)
    data.beat(SpamFilter(5))

    #Sign the Data.
    verif: SignedVerification = SignedVerification(data.hash)
    verif.sign(0, PrivateKey(0))

    #Run twice. The first shouldn't send the Transaction. The second should.
    for i in range(2):
        rpc.meros.signedElement(verif)
        if MessageType(
                rpc.meros.sync.recv()[0]) != MessageType.TransactionRequest:
            raise TestError("Meros didn't request the transaction.")

        if i == 0:
            #When we send DataMissing, we should be disconnected within a few seconds.
            rpc.meros.dataMissing()
            start: int = int(time())
            try:
                rpc.meros.sync.recv()
            except Exception:
                #More than a few seconds is allowed as Meros's own SyncRequest must timeout.
                if int(time()) - start > 10:
                    raise TestError(
                        "Meros didn't disconnect us for sending a Verification of a non-existent Transaction."
                    )
            #Clear our invalid connections.
            rpc.meros.live.connection.close()
            rpc.meros.sync.connection.close()
            sleep(65)
            #Init new ones.
            rpc.meros.liveConnect(chain.blocks[0].header.hash)
            rpc.meros.syncConnect(chain.blocks[0].header.hash)

        else:
            rpc.meros.syncTransaction(data)
            sleep(2)
            if not rpc.call("consensus", "getStatus",
                            [data.hash.hex()])["verifiers"]:
                raise TestError("Meros didn't add the Verification.")
示例#9
0
def BLSTest() -> None:
    key: PrivateKey = PrivateKey(0)
    if not key.sign(b"abc").verify(AggregationInfo(key.toPublicKey(), b"abc")):
        raise TestError(
            "Couldn't sign and verify a BLS signature from Python.")
    if key.sign(b"abc").verify(AggregationInfo(key.toPublicKey(), b"def")):
        raise TestError(
            "Could verify a BLS signature with anything in Python.")
示例#10
0
def signElement(elem: Element) -> Signature:
    if isinstance(elem, Verification):
        verif: SignedVerification = SignedVerification(elem.hash, elem.holder)
        verif.sign(elem.holder, PrivateKey(elem.holder))
        return verif.signature
    if isinstance(elem, SendDifficulty):
        sendDiff: SignedSendDifficulty = SignedSendDifficulty(
            elem.difficulty, elem.nonce)
        sendDiff.sign(elem.holder, PrivateKey(elem.holder))
        return sendDiff.signature
    if isinstance(elem, DataDifficulty):
        dataDiff: SignedDataDifficulty = SignedDataDifficulty(
            elem.difficulty, elem.nonce)
        dataDiff.sign(elem.holder, PrivateKey(elem.holder))
        return dataDiff.signature

    raise GenerationError(
        "Tried to sign an Element in a Block we didn't recognize the type of.")
示例#11
0
 def mine(self, privKey: PrivateKey, difficulty: int) -> None:
     self.proof = -1
     while ((self.proof == -1)
            or ((int.from_bytes(self.hash, "little") * difficulty) >
                int.from_bytes(bytes.fromhex("FF" * 32), "little"))):
         self.proof += 1
         self.hash = RandomX(self.serializeHash())
         self.signature = privKey.sign(self.hash).serialize()
         self.hash = RandomX(self.hash + self.signature)
示例#12
0
def verify(rpc: RPC, txHash: bytes, nick: int = 0, mr: bool = False) -> None:
    sv: SignedVerification = SignedVerification(txHash)
    sv.sign(nick, PrivateKey(nick))
    temp: bytes = rpc.meros.signedElement(sv)
    if mr:
        if MessageType(
                rpc.meros.live.recv()[0]) != MessageType.SignedMeritRemoval:
            raise TestError("Meros didn't create a MeritRemoval.")
    elif temp != rpc.meros.live.recv():
        raise TestError("Meros didn't broadcast back a Verification.")
示例#13
0
def HundredSixSignedElementsTest(
  rpc: RPC
) -> None:
  #Solely used to get the genesis Block hash.
  blockchain: Blockchain = Blockchain()

  edPrivKey: Ristretto.SigningKey = Ristretto.SigningKey(b'\0' * 32)
  blsPrivKey: PrivateKey = PrivateKey(0)
  sig: Signature = blsPrivKey.sign(bytes())

  #Create a Data for the Verification.
  data: Data = Data(bytes(32), edPrivKey.get_verifying_key())
  data.sign(edPrivKey)
  data.beat(SpamFilter(5))

  #Create a signed Verification, SendDifficulty, and DataDifficulty.
  elements: List[SignedElement] = [
    SignedVerification(data.hash, 1, sig),
    SignedSendDifficulty(0, 0, 1, sig),
    SignedDataDifficulty(0, 0, 1, sig)
  ]

  dataSent: bool = False
  for elem in elements:
    #Handshake with the node.
    rpc.meros.liveConnect(blockchain.blocks[0].header.hash)

    #Send the Data if we have yet to.
    if not dataSent:
      if rpc.meros.liveTransaction(data) != rpc.meros.live.recv():
        raise TestError("Data wasn't rebroadcasted.")
      dataSent = True

    #Send the Element.
    rpc.meros.signedElement(elem)

    #Sleep for thirty seconds to make sure Meros realizes our connection is dead.
    sleep(30)

    #Verify the node didn't crash.
    try:
      if rpc.call("merit", "getHeight") != 1:
        raise Exception()
    except Exception:
      raise TestError("Node crashed after being sent a malformed Element.")
示例#14
0
    def syncUnknown() -> None:
        claim: Claim = Claim([(merit.mints[0], 0)], pubKey.to_bytes())
        claim.sign(PrivateKey(0))

        #Create a series of Sends, forming a diamond.
        #Cross sendB and sendC to actually force this to work in an ordered fashion to pass.
        sendA: Send = Send([(claim.hash, 0)],
                           [(pubKey.to_bytes(), claim.amount // 2),
                            (pubKey.to_bytes(), claim.amount // 2)])
        sendB: Send = Send([(sendA.hash, 0)],
                           [(pubKey.to_bytes(), sendA.outputs[0][1] // 2),
                            (pubKey.to_bytes(), sendA.outputs[0][1] // 2)])
        sendC: Send = Send(
            [(sendA.hash, 1), (sendB.hash, 1)],
            [(pubKey.to_bytes(), sendA.outputs[1][1] + sendB.outputs[1][1])])
        sendD: Send = Send([(sendB.hash, 0), (sendC.hash, 0)],
                           [(pubKey.to_bytes(), claim.amount)])
        for send in [sendA, sendB, sendC, sendD]:
            send.sign(privKey)
            send.beat(sendFilter)

        #Send the tail of the diamond, which should cause an ordered top-down sync.
        sent: bytes = rpc.meros.liveTransaction(sendD)
        for tx in [
                sendC, sendB, sendA, claim, sendA, claim, sendB, sendA, claim
        ]:
            if rpc.meros.sync.recv() != (
                    MessageType.TransactionRequest.toByte() + tx.hash):
                raise TestError("Meros didn't request one of the inputs.")
            rpc.meros.syncTransaction(tx)
        if rpc.meros.live.recv() != sent:
            raise TestError("Meros didn't broadcast the Send.")

        #Do the same for a few Data Transactions.
        datas: List[Data] = [Data(bytes(32), pubKey.to_bytes())]
        datas.append(Data(datas[-1].hash, bytes(1)))
        datas.append(Data(datas[-1].hash, bytes(1)))
        for data in datas:
            data.sign(privKey)
            data.beat(dataFilter)
示例#15
0
import json

from e2e.Libs.BLS import PrivateKey

from e2e.Classes.Merit.Merit import Merit

from e2e.Vectors.Generation.PrototypeChain import PrototypeBlock, PrototypeChain

proto: PrototypeChain = PrototypeChain(1, False)
merit: Merit = Merit.fromJSON(proto.finish().toJSON())

#Use up all of our Blocks with Merit, except the last one.
for i in range(98):
    merit.add(
        PrototypeBlock(merit.blockchain.blocks[-1].header.time + 1200,
                       minerID=(PrivateKey(1) if i == 0 else 1)).finish(
                           0, merit))

#Right before the end, move to pending.
merit.add(
    PrototypeBlock(merit.blockchain.blocks[-1].header.time + 1200,
                   minerID=1).finish(1, merit))

#Have our Merit die.
merit.add(
    PrototypeBlock(merit.blockchain.blocks[-1].header.time + 1200,
                   minerID=1).finish(0, merit))

#Regain Merit.
merit.add(
    PrototypeBlock(merit.blockchain.blocks[-1].header.time + 1200,
示例#16
0
from e2e.Vectors.Generation.PrototypeChain import PrototypeBlock, PrototypeChain

edPrivKey: ed25519.SigningKey = ed25519.SigningKey(b'\0' * 32)
edPubKey: bytes = edPrivKey.get_verifying_key().to_bytes()

transactions: Transactions = Transactions()
sendFilter: SpamFilter = SpamFilter(3)

proto: PrototypeChain = PrototypeChain(40, keepUnlocked=True)
proto.add(1)
merit: Merit = Merit.fromJSON(proto.toJSON())

#Create a Claim.
claim: Claim = Claim([(merit.mints[-1], 0)], edPubKey)
claim.sign(PrivateKey(0))
transactions.add(claim)

merit.add(
    PrototypeBlock(merit.blockchain.blocks[-1].header.time + 1200,
                   packets=[VerificationPacket(claim.hash, list(range(2)))
                            ]).finish(0, merit))

sends: List[Send] = [
    #Transaction which will win.
    Send([(claim.hash, 0)], [(bytes(32), claim.amount)]),
    #Transaction which will be beaten.
    Send([(claim.hash, 0)], [(edPubKey, claim.amount // 2),
                             (edPubKey, claim.amount // 2)])
]
#Children. One which will have a Verification, one which won't.
示例#17
0
def PartialArchiveTest(rpc: RPC) -> None:
    vectors: Dict[str, Any]
    with open("e2e/Vectors/Consensus/Verification/PartialArchive.json",
              "r") as file:
        vectors = json.loads(file.read())

    data: Data = Data.fromJSON(vectors["data"])
    svs: List[SignedVerification] = [
        SignedVerification.fromSignedJSON(vectors["verifs"][0]),
        SignedVerification.fromSignedJSON(vectors["verifs"][1])
    ]

    key: PrivateKey = PrivateKey(
        bytes.fromhex(rpc.call("personal", "getMiner")))

    def sendDataAndVerifications() -> None:
        if rpc.meros.liveTransaction(data) != rpc.meros.live.recv():
            raise TestError(
                "Meros didn't rebroadcast a Transaction we sent it.")
        for sv in svs:
            if rpc.meros.signedElement(sv) != rpc.meros.live.recv():
                raise TestError(
                    "Meros didn't rebroadcast a SignedVerification we sent it."
                )

        #As we don't have a quality RPC route for this, we need to use getTemplate.
        if bytes.fromhex(
                rpc.call("merit", "getBlockTemplate",
                         [key.toPublicKey().serialize().hex()
                          ])["header"])[36:68] != BlockHeader.createContents(
                              [VerificationPacket(data.hash, [0, 1])]):
            raise TestError(
                "New Block template doesn't have a properly created packet.")

    def verifyRecreation() -> None:
        template: Dict[str,
                       Any] = rpc.call("merit", "getBlockTemplate",
                                       [key.toPublicKey().serialize().hex()])
        if bytes.fromhex(
                template["header"])[36:68] != BlockHeader.createContents(
                    [VerificationPacket(data.hash, [1])]):
            raise TestError(
                "New Block template doesn't have a properly recreated packet.")

        #Mining it further verifies the internal state.
        header: bytes = bytes.fromhex(template["header"])
        proof: int = 0
        sig: bytes
        while True:
            initial: bytes = RandomX(header +
                                     proof.to_bytes(4, byteorder="little"))
            sig = key.sign(initial).serialize()
            final: bytes = RandomX(initial + sig)
            if (int.from_bytes(final, "little") *
                    template["difficulty"]) < int.from_bytes(
                        bytes.fromhex("FF" * 32), "little"):
                break
            proof += 1

        rpc.call("merit", "publishBlock", [
            template["id"],
            (header + proof.to_bytes(4, byteorder="little") + sig).hex()
        ])

        raise SuccessError(
            "Stop Liver from trying to verify the vector chain which doesn't have this Block."
        )

    #We may not want to use Liver here.
    #There's a very small Block count and we can't let it terminate (hence the SE).
    with raises(SuccessError):
        Liver(rpc,
              vectors["blockchain"],
              callbacks={
                  2: sendDataAndVerifications,
                  3: verifyRecreation
              }).live()
示例#18
0
    def finish(self, keepUnlocked: int, existing: Merit) -> Block:
        genesis: bytes = existing.blockchain.genesis
        prev: BlockHeader = existing.blockchain.blocks[-1].header
        diff: int = existing.blockchain.difficulty()

        #Create the signatures for every packet/element.
        signatures: List[Signature] = []
        for packet in self.packets:
            for holder in packet.holders:
                verif: SignedVerification = SignedVerification(
                    packet.hash, holder)
                verif.sign(holder, PrivateKey(holder))
                signatures.append(verif.signature)
        for element in self.elements:
            signatures.append(signElement(element))

        #Only add the Data Verification if:
        #1) We're supposed to make sure Merit Holders are always Unlocked
        #2) The last Block created a Data
        #3) The Merit Holder has Merit.
        if (keepUnlocked != 0) and (prev.last != genesis):
            #Create the Data from the last Block.
            blockData: Data = Data(genesis, prev.hash)

            #Create Verifications for said Data with every Private Key.
            #Ensures no one has their Merit locked.
            #pylint: disable=unnecessary-comprehension
            self.packets.append(VerificationPacket(blockData.hash, []))
            for i in range(keepUnlocked):
                if (
                        #Miners who are just being created don't have Merit.
                    ((i == (keepUnlocked - 1)) and
                     (isinstance(self.minerID, PrivateKey)))
                        or (existing.state.balances[i] == 0)):
                    continue

                self.packets[-1].holders.append(i)
                verif: SignedVerification = SignedVerification(
                    blockData.hash, i)
                verif.sign(i, PrivateKey(i))
                signatures.append(verif.signature)

            #Remove this packet if there's no holders.
            if not self.packets[-1].holders:
                del self.packets[-1]

        #Set the aggregate.
        aggregate = Signature.aggregate(signatures)

        #Create the actual Block.
        minerID: Union[bytes, int] = 0
        if isinstance(self.minerID, int):
            minerID = self.minerID
        else:
            minerID = self.minerID.toPublicKey().serialize()

        result: Block = Block(
            BlockHeader(
                0, prev.hash,
                BlockHeader.createContents(self.packets, self.elements),
                len(self.packets), bytes(4),
                BlockHeader.createSketchCheck(bytes(4), self.packets), minerID,
                self.time), BlockBody(self.packets, self.elements, aggregate))
        if isinstance(self.minerID, int):
            result.mine(PrivateKey(self.minerID), diff)
        else:
            result.mine(self.minerID, diff)
        return result
示例#19
0
def TwoHundredThirtyFiveTest(rpc: RPC) -> None:
    blockchain: Blockchain = Blockchain()
    dataFilter: SpamFilter = SpamFilter(5)

    edPrivKey: ed25519.SigningKey = ed25519.SigningKey(b'\0' * 32)
    edPubKey: ed25519.VerifyingKey = edPrivKey.get_verifying_key()

    #Mine one Block to the node.
    blsPrivKey: PrivateKey = PrivateKey(
        bytes.fromhex(rpc.call("personal", "getMiner")))
    blsPubKey: bytes = blsPrivKey.toPublicKey().serialize()

    #Call getBlockTemplate just to get an ID.
    #Skips the need to write a sync loop for the BlockBody.
    template: Dict[str, Any] = rpc.call("merit", "getBlockTemplate",
                                        [blsPubKey.hex()])

    #Mine a Block.
    block = Block(
        BlockHeader(0, blockchain.blocks[0].header.hash, bytes(32), 1,
                    bytes(4), bytes(32), blsPubKey,
                    blockchain.blocks[0].header.time + 1200, 0), BlockBody())
    block.mine(blsPrivKey, blockchain.difficulty())
    blockchain.add(block)

    rpc.call("merit", "publishBlock",
             [template["id"], block.serialize().hex()])

    #Send Meros a Data and receive its Verification to make sure it's verifying Transactions in the first place.
    data: Data = Data(bytes(32), edPubKey.to_bytes())
    data.sign(edPrivKey)
    data.beat(dataFilter)

    rpc.meros.liveConnect(blockchain.blocks[0].header.hash)
    if rpc.meros.liveTransaction(data) != rpc.meros.live.recv():
        raise TestError("Meros didn't send back the Data.")
    if MessageType(rpc.meros.live.recv()[0]) != MessageType.SignedVerification:
        raise TestError("Meros didn't send us its SignedVerification.")

    #Close our connection and mine 8 Blocks so its Merit is locked.
    rpc.meros.live.connection.close()
    for _ in range(8):
        block = Block(
            BlockHeader(0, blockchain.blocks[-1].header.hash, bytes(32), 1,
                        bytes(4), bytes(32), 0,
                        blockchain.blocks[-1].header.time + 1200, 0),
            BlockBody())
        #Reusing its key is fine as mining doesn't count as participation.
        block.mine(blsPrivKey, blockchain.difficulty())
        blockchain.add(block)

    #Sleep 30 seconds to make sure Meros noted we disconnected, and then reconnect.
    sleep(30)
    rpc.meros.liveConnect(blockchain.blocks[0].header.hash)
    rpc.meros.syncConnect(blockchain.blocks[0].header.hash)

    #Sync the Blocks.
    for b in range(8):
        header: bytes = rpc.meros.liveBlockHeader(blockchain.blocks[b +
                                                                    2].header)
        if rpc.meros.sync.recv() != (MessageType.BlockBodyRequest.toByte() +
                                     blockchain.blocks[b + 2].header.hash):
            raise TestError("Meros didn't request the BlockBody.")
        rpc.meros.blockBody(blockchain.blocks[b + 2])
        if rpc.meros.live.recv() != header:
            raise TestError("Meros didn't send back the header.")
        if MessageType(
                rpc.meros.live.recv()[0]) != MessageType.SignedVerification:
            raise TestError("Meros didn't verify this Block's data.")

    #Verify its Merit is locked.
    #Theoretically, all code after this check is unecessary.
    #Meros verifies a Block's Data after updating its State.
    #Therefore, if the above last Block had its Data verified, this issue should be closed.
    #That said, the timing is a bit too tight for comfort.
    #Better safe than sorry. Hence why the code after this check exists.
    if rpc.call("merit", "getMerit", [0])["status"] != "Locked":
        raise TestError("Merit wasn't locked when it was supposed to be.")

    #Send it a Transaction and make sure Meros verifies it, despite having its Merit locked.
    data = Data(data.hash, edPubKey.to_bytes())
    data.sign(edPrivKey)
    data.beat(dataFilter)

    if rpc.meros.liveTransaction(data) != rpc.meros.live.recv():
        raise TestError("Meros didn't send back the Data.")
    if MessageType(rpc.meros.live.recv()[0]) != MessageType.SignedVerification:
        raise TestError("Meros didn't send us its SignedVerification.")
示例#20
0
#Transactions.
transactions: Transactions = Transactions()
#Merit.
merit: Merit = Merit()

#SpamFilter.
dataFilter: SpamFilter = SpamFilter(5)

#Ed25519 keys.
edPrivKey: ed25519.SigningKey = ed25519.SigningKey(b'\0' * 32)
edPubKey: ed25519.VerifyingKey = edPrivKey.get_verifying_key()

#BLS keys.
blsPrivKeys: List[PrivateKey] = [
    PrivateKey(blake2b(b'\0', digest_size=32).digest()),
    PrivateKey(blake2b(b'\1', digest_size=32).digest())
]
blsPubKeys: List[PublicKey] = [
    blsPrivKeys[0].toPublicKey(), blsPrivKeys[1].toPublicKey()
]

#Add 4 Blank Blocks.
for i in range(4):
    merit.add(Block.fromJSON(blankBlocks[i]))

#Add a 5th Block to another verifier.
block: Block = Block(
    BlockHeader(0, merit.blockchain.last(), bytes(32), 1, bytes(4), bytes(32),
                blsPubKeys[1].serialize(),
                merit.blockchain.blocks[-1].header.time + 1200), BlockBody())
示例#21
0
from typing import Dict, List, IO, Any
import json

from e2e.Libs.BLS import PrivateKey, PublicKey

from e2e.Classes.Consensus.DataDifficulty import SignedDataDifficulty
from e2e.Classes.Consensus.MeritRemoval import SignedMeritRemoval

from e2e.Vectors.Generation.PrototypeChain import PrototypeChain

blsPrivKey: PrivateKey = PrivateKey(0)
blsPubKey: PublicKey = blsPrivKey.toPublicKey()

proto: PrototypeChain = PrototypeChain(1, False)

#Create conflicting Data Difficulties.
dataDiffs: List[SignedDataDifficulty] = [
    SignedDataDifficulty(3, 0),
    SignedDataDifficulty(4, 0)
]
dataDiffs[0].sign(0, blsPrivKey)
dataDiffs[1].sign(0, blsPrivKey)

#Create a MeritRemoval out of the conflicting Data Difficulties.
mr: SignedMeritRemoval = SignedMeritRemoval(dataDiffs[0], dataDiffs[1])
proto.add(elements=[mr])

#Create a MeritRemoval with the Elements swapped.
swapped: SignedMeritRemoval = SignedMeritRemoval(dataDiffs[1], dataDiffs[0])
proto.add(elements=[swapped])
示例#22
0
def verify(rpc: RPC, tx: bytes) -> None:
    sv: SignedVerification = SignedVerification(tx)
    sv.sign(0, PrivateKey(0))
    if rpc.meros.signedElement(sv) != rpc.meros.live.recv():
        raise TestError("Meros didn't send back a Verification.")
示例#23
0
    def test() -> None:
        #Send to the first address from outside the Wallet. First address is now funded.
        sendHash: bytes = createSend(
            rpc, claims[0], decodeAddress(rpc.call("personal", "getAddress")))

        #Send to the second address with all of the funds. Second address is now funded.
        #Tests send's minimal case (single input, no change).
        nextAddr: str = rpc.call("personal", "getAddress")
        sends: List[str] = [
            rpc.call(
                "personal", "send", {
                    "outputs": [{
                        "address": nextAddr,
                        "amount": str(claims[0].amount)
                    }]
                })
        ]
        checkSend(
            rpc, sends[-1], {
                "inputs": [{
                    "hash": sendHash.hex().upper(),
                    "nonce": 0
                }],
                "outputs": [{
                    "key": decodeAddress(nextAddr).hex().upper(),
                    "amount": str(claims[0].amount)
                }]
            })
        verify(rpc, bytes.fromhex(sends[-1]))

        #Send to the third address with some of the funds. Third and change addresses are now funded.
        #Tests send's capability to create a change output.
        mnemonic: str = rpc.call("personal", "getMnemonic")
        nextAddr = rpc.call("personal", "getAddress")
        sends.append(
            rpc.call(
                "personal", "send", {
                    "outputs": [{
                        "address": nextAddr,
                        "amount": str(claims[0].amount - 1)
                    }]
                }))
        checkSend(
            rpc, sends[-1], {
                "inputs": [{
                    "hash": sends[-2],
                    "nonce": 0
                }],
                "outputs":
                [{
                    "key": decodeAddress(nextAddr).hex().upper(),
                    "amount": str(claims[0].amount - 1)
                }, {
                    "key": getChangePublicKey(mnemonic, "", 0).hex().upper(),
                    "amount": "1"
                }]
            })
        verify(rpc, bytes.fromhex(sends[-1]))

        #Send all funds out of Wallet.
        #Tests MuSig signing and change UTXO detection.
        privKey: Ristretto.SigningKey = Ristretto.SigningKey(b'\0' * 32)
        pubKey: bytes = privKey.get_verifying_key()
        sends.append(
            rpc.call(
                "personal", "send", {
                    "outputs": [{
                        "address":
                        bech32_encode("mr",
                                      convertbits(bytes([0]) + pubKey, 8, 5)),
                        "amount":
                        str(claims[0].amount)
                    }]
                }))
        checkSend(
            rpc, sends[-1], {
                "inputs": [{
                    "hash": sends[-2],
                    "nonce": 0
                }, {
                    "hash": sends[-2],
                    "nonce": 1
                }],
                "outputs": [{
                    "key": pubKey.hex().upper(),
                    "amount": str(claims[0].amount)
                }]
            })
        verify(rpc, bytes.fromhex(sends[-1]))

        #Clear Wallet. Set a password this time around to make sure the password is properly carried.
        #Send two instances of funds to the first address.
        rpc.call("personal", "setWallet", {"password": "******"})
        mnemonic = rpc.call("personal", "getMnemonic")
        nodeKey: bytes = decodeAddress(rpc.call("personal", "getAddress"))
        send: Send = Send([(bytes.fromhex(sends[-1]), 0)],
                          [(nodeKey, claims[0].amount // 2),
                           (nodeKey, claims[0].amount // 2)])
        send.sign(Ristretto.SigningKey(b'\0' * 32))
        send.beat(SpamFilter(3))
        if rpc.meros.liveTransaction(send) != rpc.meros.live.recv():
            raise TestError("Meros didn't send back a Send.")
        verify(rpc, send.hash)
        sends = [send.hash.hex().upper()]

        #Send to self.
        #Tests send's capability to handle multiple UTXOs per key/lack of aggregation when all keys are the same/multiple output Sends.
        nextAddr = rpc.call("personal", "getAddress")
        changeKey: bytes = getChangePublicKey(mnemonic, "test", 0)
        sends.append(
            rpc.call(
                "personal", "send", {
                    "outputs": [{
                        "address": nextAddr,
                        "amount": str(claims[0].amount - 1)
                    }],
                    "password":
                    "******"
                }))
        checkSend(
            rpc, sends[-1], {
                "inputs": [{
                    "hash": sends[-2],
                    "nonce": 0
                }, {
                    "hash": sends[-2],
                    "nonce": 1
                }],
                "outputs": [{
                    "key": decodeAddress(nextAddr).hex().upper(),
                    "amount": str(claims[0].amount - 1)
                }, {
                    "key": changeKey.hex().upper(),
                    "amount": "1"
                }]
            })
        verify(rpc, bytes.fromhex(sends[-1]))

        #Externally send to the second/change address.
        #Enables entering multiple instances of each key into MuSig, which is significant as we originally only used the unique keys.
        sends.append(
            createSend(rpc, claims[1], decodeAddress(nextAddr)).hex().upper())
        sends.append(createSend(rpc, claims[2], changeKey).hex().upper())

        #Check personal_getUTXOs.
        utxos: List[Dict[str, Any]] = [{
            "hash": sends[-3],
            "nonce": 0,
            "address": nextAddr
        }, {
            "hash":
            sends[-3],
            "nonce":
            1,
            "address":
            bech32_encode("mr", convertbits(bytes([0]) + changeKey, 8, 5))
        }, {
            "hash": sends[-2],
            "nonce": 0,
            "address": nextAddr
        }, {
            "hash":
            sends[-1],
            "nonce":
            0,
            "address":
            bech32_encode("mr", convertbits(bytes([0]) + changeKey, 8, 5))
        }]
        if sortUTXOs(rpc.call("personal", "getUTXOs")) != sortUTXOs(utxos):
            raise TestError("personal_getUTXOs was incorrect.")
        for utxo in utxos:
            del utxo["address"]

        #Send to any address with all funds minus one.
        #Test MuSig signing, multiple inputs per key on account chains, change output creation to the next change key...
        sends.append(
            rpc.call(
                "personal", "send", {
                    "outputs": [{
                        "address":
                        nextAddr,
                        "amount":
                        str(claims[0].amount + claims[1].amount +
                            claims[2].amount - 1)
                    }],
                    "password":
                    "******"
                }))
        checkSend(
            rpc, sends[-1], {
                "inputs":
                utxos,
                "outputs": [{
                    "key":
                    decodeAddress(nextAddr).hex().upper(),
                    "amount":
                    str(claims[0].amount + claims[1].amount +
                        claims[2].amount - 1)
                }, {
                    "key":
                    getChangePublicKey(mnemonic, "test", 1).hex().upper(),
                    "amount":
                    "1"
                }]
            })
        verify(rpc, bytes.fromhex(sends[-1]))

        #Mine a Block so we can reboot the node without losing data.
        blsPrivKey: PrivateKey = PrivateKey(
            bytes.fromhex(rpc.call("personal", "getMeritHolderKey")))
        for _ in range(6):
            template: Dict[str, Any] = rpc.call(
                "merit", "getBlockTemplate",
                {"miner": blsPrivKey.toPublicKey().serialize().hex()})
            proof: int = -1
            tempHash: bytes = bytes()
            tempSignature: bytes = bytes()
            while ((proof == -1) or (
                (int.from_bytes(tempHash, "little") * template["difficulty"]) >
                    int.from_bytes(bytes.fromhex("FF" * 32), "little"))):
                proof += 1
                tempHash = RandomX(
                    bytes.fromhex(template["header"]) +
                    proof.to_bytes(4, "little"))
                tempSignature = blsPrivKey.sign(tempHash).serialize()
                tempHash = RandomX(tempHash + tempSignature)

            rpc.call(
                "merit", "publishBlock", {
                    "id":
                    template["id"],
                    "header":
                    template["header"] + proof.to_bytes(4, "little").hex() +
                    tempSignature.hex()
                })

        #Reboot the node and verify it still tracks the same change address.
        #Also reload the Wallet and verify it still tracks the same change address.
        #Really should be part of address discovery; we just have the opportunity right here.
        #Due to the timing of how the codebase was developed, and a personal frustration for how long this has taken...
        rpc.quit()
        sleep(3)
        rpc.meros = Meros(rpc.meros.db, rpc.meros.tcp, rpc.meros.rpc)
        if rpc.call("personal", "getTransactionTemplate",
                    {"outputs": [{
                        "address": nextAddr,
                        "amount": "1"
                    }]})["outputs"][1]["key"] != getChangePublicKey(
                        mnemonic, "test", 2).hex().upper():
            raise TestError(
                "Rebooting the node caused the WalletDB to stop tracking the next change address."
            )
        rpc.call("personal", "setAccount", rpc.call("personal", "getAccount"))
        if rpc.call("personal", "getTransactionTemplate",
                    {"outputs": [{
                        "address": nextAddr,
                        "amount": "1"
                    }]})["outputs"][1]["key"] != getChangePublicKey(
                        mnemonic, "test", 2).hex().upper():
            raise TestError(
                "Reloading the Wallet caused the WalletDB to stop tracking the next change address."
            )

        raise SuccessError()
示例#24
0
merit: Merit = PrototypeChain.withMint()
transactions: Transactions = Transactions()

sendFilter: SpamFilter = SpamFilter(3)

edPrivKey: ed25519.SigningKey = ed25519.SigningKey(b'\0' * 32)
edPubKeys: List[ed25519.VerifyingKey] = [
    edPrivKey.get_verifying_key(),
    ed25519.SigningKey(b'\1' * 32).get_verifying_key()
]

#Create the Claim.
claim: Claim = Claim([(merit.mints[-1].hash, 0)], edPubKeys[0].to_bytes())
claim.amount = merit.mints[-1].outputs[0][1]
claim.sign(PrivateKey(0))
transactions.add(claim)
merit.add(
    PrototypeBlock(merit.blockchain.blocks[-1].header.time + 1200,
                   packets=[VerificationPacket(claim.hash,
                                               [0])]).finish(0, merit))

#Give the second key pair Merit.
merit.add(
    PrototypeBlock(merit.blockchain.blocks[-1].header.time + 1200,
                   minerID=PrivateKey(1)).finish(0, merit))

#Create two competing Sends.
packets: List[VerificationPacket] = []
for i in range(2):
    send: Send = Send(
示例#25
0
edPrivKey: Ristretto.SigningKey = Ristretto.SigningKey(b'\0' * 32)
edPubKey: bytes = edPrivKey.get_verifying_key()

proto: PrototypeChain = PrototypeChain(40, keepUnlocked=True)
proto.add(1)

datas: List[Data] = [Data(bytes(32), edPubKey)]
for d in range(2):
  datas.append(Data(datas[0].hash, d.to_bytes(1, "little")))
for data in datas:
  data.sign(edPrivKey)
  data.beat(dataFilter)

verif: SignedVerification = SignedVerification(datas[1].hash)
verif.sign(0, PrivateKey(0))
proto.add(
  packets=[
    VerificationPacket(datas[0].hash, [0]),
    VerificationPacket(datas[2].hash, [1])
  ]
)

for _ in range(5):
  proto.add()

with open("e2e/Vectors/Consensus/Families/UnmentionedBeatMentioned.json", "w") as vectors:
  vectors.write(json.dumps({
    "blockchain": proto.toJSON(),
    "datas": [data.toJSON() for data in datas],
    "verification": verif.toSignedJSON()
示例#26
0
edPrivKey: Ristretto.SigningKey = Ristretto.SigningKey(b'\0' * 32)
edPubKey: bytes = edPrivKey.get_verifying_key()

transactions: Transactions = Transactions()
spamFilter: SpamFilter = SpamFilter(5)

proto = PrototypeChain(1, False)
proto.add(1)

data: Data = Data(bytes(32), edPubKey)
data.sign(edPrivKey)
data.beat(spamFilter)
transactions.add(data)

verif: SignedVerification = SignedVerification(data.hash)
verif.sign(1, PrivateKey(1))

proto.add(1, packets=[VerificationPacket(data.hash, [0])])
for _ in range(5):
    proto.add(1)

with open("e2e/Vectors/Consensus/Verification/HundredFortyTwo.json",
          "w") as vectors:
    vectors.write(
        json.dumps({
            "blockchain": proto.toJSON(),
            "transactions": transactions.toJSON(),
            "verification": verif.toSignedJSON(),
            "transaction": data.hash.hex().upper()
        }))
示例#27
0
文件: Claim.py 项目: Vyryn/Meros
 def sign(self, privKey: PrivateKey) -> None:
     self.signature = privKey.sign(self.hash).serialize()
示例#28
0
def StringBasedTypesTest(
  rpc: RPC
) -> None:
  edPrivKey: Ristretto.SigningKey = Ristretto.SigningKey(b'\0' * 32)
  edPubKey: bytes = edPrivKey.get_verifying_key()
  blsPubKey: PublicKey = PrivateKey(0).toPublicKey()

  #hex.
  #Test 0x-prefixed and no-0x both work without issue.
  data: Data = Data(bytes(32), edPubKey)
  data.sign(edPrivKey)
  rpc.call("transactions", "publishTransactionWithoutWork", {"type": "Data", "transaction": "0x" + data.serialize()[:-4].hex()})

  data = Data(data.hash, b"abc")
  data.sign(edPrivKey)
  rpc.call("transactions", "publishTransactionWithoutWork", {"type": "Data", "transaction": data.serialize()[:-4].hex()})

  #Test non-hex data is properly handled.
  try:
    rpc.call("transactions", "publishTransactionWithoutWork", {"type": "Data", "transaction": "az"})
    raise TestError()
  except Exception as e:
    if str(e) != "-32602 Invalid params.":
      raise TestError("Meros accepted non-hex data for a hex argument.")

  #Hash.
  rpc.call("transactions", "getTransaction", {"hash": data.hash.hex()})
  rpc.call("transactions", "getTransaction", {"hash": "0x" + data.hash.hex()})

  #Also call the upper form, supplementing the above hex tests (as Hash routes through hex).
  rpc.call("transactions", "getTransaction", {"hash": data.hash.hex().upper()})
  rpc.call("transactions", "getTransaction", {"hash": "0x" + data.hash.hex().upper()})

  #Improper length.
  try:
    rpc.call("transactions", "getTransaction", {"hash": data.hash.hex().upper()[:-2]})
    raise TestError()
  except Exception as e:
    if str(e) != "-32602 Invalid params.":
      raise TestError("Meros accepted a hex string with an improper length as a Hash.")

  #BLSPublicKey.
  try:
    rpc.call("merit", "getNickname", {"key": blsPubKey.serialize().hex()})
    raise TestError()
  except Exception as e:
    if str(e) != "-2 Key doesn't have a nickname assigned.":
      raise TestError("Meros didn't accept a valid BLSPublicKey.")
  try:
    rpc.call("merit", "getNickname", {"key": blsPubKey.serialize().hex()[:-2]})
    raise TestError()
  except Exception as e:
    if str(e) != "-32602 Invalid params.":
      raise TestError("Meros accepted a hex string with an improper length as a BLSPublicKey.")

  #Missing flags.
  try:
    rpc.call("merit", "getNickname", {"key": "0" + blsPubKey.serialize().hex()[1]})
    raise TestError()
  except Exception as e:
    if str(e) != "-32602 Invalid params.":
      raise TestError("Meros accepted an invalid BLSPublicKey as a BLSPublicKey.")

  #EdPublicKey.
  rpc.call("personal", "setAccount", {"key": edPubKey.hex(), "chainCode": bytes(32).hex()})
  try:
    rpc.call("personal", "setAccount", {"key": edPubKey[:-2].hex(), "chainCode": bytes(32).hex()})
    raise TestError()
  except Exception as e:
    if str(e) != "-32602 Invalid params.":
      raise TestError("Meros accepted a hex string with an improper length as an EdPublicKey.")
示例#29
0
bbFile.close()

#Transactions.
transactions: Transactions = Transactions()
#Merit.
merit: Merit = Merit()

#SpamFilter.
dataFilter: SpamFilter = SpamFilter(5)

#Ed25519 keys.
edPrivKey: ed25519.SigningKey = ed25519.SigningKey(b'\0' * 32)
edPubKey: ed25519.VerifyingKey = edPrivKey.get_verifying_key()

#BLS keys.
blsPrivKey: PrivateKey = PrivateKey(blake2b(b'\0', digest_size=32).digest())
blsPubKey: PublicKey = blsPrivKey.toPublicKey()

#Add 1 Blank Block.
for i in range(1):
  merit.add(Block.fromJSON(blankBlocks[i]))

#Create the Data and a successor.
first: Data = Data(bytes(32), edPubKey.to_bytes())
first.sign(edPrivKey)
first.beat(dataFilter)
transactions.add(first)

second: Data = Data(first.hash, bytes(1))
second.sign(edPrivKey)
second.beat(dataFilter)
示例#30
0
from e2e.Classes.Merit.Merit import Merit

from e2e.Vectors.Generation.PrototypeChain import PrototypeBlock, PrototypeChain

edPubKey: bytes = ed25519.SigningKey(b'\0' * 32).get_verifying_key().to_bytes()

proto: PrototypeChain = PrototypeChain(49, keepUnlocked=True)
merit: Merit = Merit.fromJSON(proto.toJSON())

transactions: Transactions = Transactions()

#Create the Claims.
for m in range(3):
    claim: Claim = Claim([(merit.mints[m], 0)], edPubKey)
    claim.sign(PrivateKey(0))
    transactions.add(claim)

merit.add(
    PrototypeBlock(merit.blockchain.blocks[-1].header.time + 1200,
                   packets=[
                       VerificationPacket(tx.hash, [0])
                       for tx in transactions.txs.values()
                   ]).finish(0, merit))

with open("e2e/Vectors/RPC/Personal/WatchWallet.json", "w") as vectors:
    vectors.write(
        json.dumps({
            "blockchain": merit.toJSON(),
            "transactions": transactions.toJSON()
        }))