diff --git a/src/avalanche/proof.h b/src/avalanche/proof.h --- a/src/avalanche/proof.h +++ b/src/avalanche/proof.h @@ -81,20 +81,22 @@ CPubKey master; std::vector stakes; + LimitedProofId limitedProofId; ProofId proofid; - ProofId computeProofId() const; + void computeProofId(); public: Proof() : sequence(0), expirationTime(0), master(), stakes(), proofid() {} Proof(uint64_t sequence_, int64_t expirationTime_, CPubKey master_, std::vector stakes_) : sequence(sequence_), expirationTime(expirationTime_), - master(std::move(master_)), stakes(std::move(stakes_)), - proofid(computeProofId()) {} + master(std::move(master_)), stakes(std::move(stakes_)) { + computeProofId(); + } SERIALIZE_METHODS(Proof, obj) { READWRITE(obj.sequence, obj.expirationTime, obj.master, obj.stakes); - SER_READ(obj, obj.proofid = obj.computeProofId()); + SER_READ(obj, obj.computeProofId()); } static bool FromHex(Proof &proof, const std::string &hexProof, @@ -106,6 +108,7 @@ const std::vector &getStakes() const { return stakes; } const ProofId &getId() const { return proofid; } + const LimitedProofId &getLimitedId() const { return limitedProofId; } uint32_t getScore() const; bool verify(ProofValidationState &state) const; diff --git a/src/avalanche/proof.cpp b/src/avalanche/proof.cpp --- a/src/avalanche/proof.cpp +++ b/src/avalanche/proof.cpp @@ -47,7 +47,7 @@ return true; } -ProofId Proof::computeProofId() const { +void Proof::computeProofId() { CHashWriter ss(SER_GETHASH, 0); ss << sequence; ss << expirationTime; @@ -57,11 +57,13 @@ ss << s.getStake(); } + limitedProofId = LimitedProofId(ss.GetHash()); + CHashWriter ss2(SER_GETHASH, 0); - ss2 << ss.GetHash(); + ss2 << limitedProofId; ss2 << master; - return ProofId(ss2.GetHash()); + proofid = ProofId(ss2.GetHash()); } uint32_t Proof::getScore() const { diff --git a/src/avalanche/proofid.h b/src/avalanche/proofid.h --- a/src/avalanche/proofid.h +++ b/src/avalanche/proofid.h @@ -12,6 +12,17 @@ namespace avalanche { +struct LimitedProofId : public uint256 { + explicit LimitedProofId() : uint256() {} + explicit LimitedProofId(const uint256 &b) : uint256(b) {} + + static LimitedProofId fromHex(const std::string &str) { + LimitedProofId r; + r.SetHex(str); + return r; + } +}; + struct ProofId : public uint256 { explicit ProofId() : uint256() {} explicit ProofId(const uint256 &b) : uint256(b) {} diff --git a/src/rpc/avalanche.cpp b/src/rpc/avalanche.cpp --- a/src/rpc/avalanche.cpp +++ b/src/rpc/avalanche.cpp @@ -226,8 +226,10 @@ {RPCResult::Type::NUM, "expiration", "A timestamp indicating when the proof expires"}, {RPCResult::Type::STR_HEX, "master", "The master public key"}, + {RPCResult::Type::STR_HEX, "limitedid", + "A hash of the proof data excluding the master key."}, {RPCResult::Type::STR_HEX, "proofid", - "The proof's unique identifier"}, + "A hash of the limitedid and master key."}, {RPCResult::Type::ARR, "stakes", "", @@ -270,6 +272,7 @@ result.pushKV("sequence", proof.getSequence()); result.pushKV("expiration", proof.getExpirationTime()); result.pushKV("master", HexStr(proof.getMaster())); + result.pushKV("limitedid", proof.getLimitedId().ToString()); result.pushKV("proofid", proof.getId().ToString()); UniValue stakes(UniValue::VARR); diff --git a/test/functional/abc_rpc_avalancheproof.py b/test/functional/abc_rpc_avalancheproof.py --- a/test/functional/abc_rpc_avalancheproof.py +++ b/test/functional/abc_rpc_avalancheproof.py @@ -79,6 +79,9 @@ assert_equal(decodedproof["expiration"], proof_expiration) assert_equal(decodedproof["master"], proof_master) assert_equal(decodedproof["proofid"], f"{proofobj.proofid:0{64}x}") + assert_equal( + decodedproof["limitedid"], + f"{proofobj.limited_proofid:0{64}x}") assert_equal(decodedproof["stakes"][0]["txid"], stakes[0]["txid"]) assert_equal(decodedproof["stakes"][0]["vout"], stakes[0]["vout"]) assert_equal(decodedproof["stakes"][0]["height"], stakes[0]["height"]) diff --git a/test/functional/test_framework/messages.py b/test/functional/test_framework/messages.py --- a/test/functional/test_framework/messages.py +++ b/test/functional/test_framework/messages.py @@ -896,7 +896,13 @@ class AvalancheProof: - __slots__ = ("sequence", "expiration", "master", "stakes", "proofid") + __slots__ = ( + "sequence", + "expiration", + "master", + "stakes", + "limited_proofid", + "proofid") def __init__(self, sequence=0, expiration=0, master=b"", signed_stakes=None): @@ -906,12 +912,14 @@ self.stakes: List[AvalancheSignedStake] = signed_stakes or [ AvalancheSignedStake()] - self.proofid: int = self.compute_proof_id() - def compute_proof_id(self) -> int: - """Return Bitcoin's 256-bit hash (double SHA-256) of the + self.limited_proofid: int = None + self.proofid: int = None + self.compute_proof_id() + + def compute_proof_id(self): + """Compute Bitcoin's 256-bit hash (double SHA-256) of the serialized proof data. - :return: bytes of length 32 """ ss = struct.pack("