]> Git Repo - VerusCoin.git/blobdiff - src/pubkey.cpp
Init speedup test
[VerusCoin.git] / src / pubkey.cpp
index a4c046bff53806f05e5d81b8be78731dda0d90cc..0b87bb526e68270ac055a80d4fa7f67d1562d027 100644 (file)
 // Copyright (c) 2009-2014 The Bitcoin Core developers
+// Copyright (c) 2017 The Zcash developers
 // Distributed under the MIT software license, see the accompanying
 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
 
 #include "pubkey.h"
 
-#include "eccryptoverify.h"
+#include <secp256k1.h>
+#include <secp256k1_recovery.h>
+
+namespace
+{
+/* Global secp256k1_context object used for verification. */
+secp256k1_context* secp256k1_context_verify = NULL;
+}
 
-#include "ecwrapper.h"
 
 bool CPubKey::Verify(const uint256 &hash, const std::vector<unsigned char>& vchSig) const {
     if (!IsValid())
         return false;
-    CECKey key;
-    if (!key.SetPubKey(begin(), size()))
+    secp256k1_pubkey pubkey;
+    secp256k1_ecdsa_signature sig;
+    if (!secp256k1_ec_pubkey_parse(secp256k1_context_verify, &pubkey, &(*this)[0], size())) {
         return false;
-    if (!key.Verify(hash, vchSig))
+    }
+    if (vchSig.size() == 0) {
         return false;
-    return true;
+    }
+    /* Zcash, unlike Bitcoin, has always enforced strict DER signatures. */
+    if (!secp256k1_ecdsa_signature_parse_der(secp256k1_context_verify, &sig, &vchSig[0], vchSig.size())) {
+        return false;
+    }
+    /* libsecp256k1's ECDSA verification requires lower-S signatures, which have
+     * not historically been enforced in Bitcoin or Zcash, so normalize them first. */
+    secp256k1_ecdsa_signature_normalize(secp256k1_context_verify, &sig, &sig);
+    return secp256k1_ecdsa_verify(secp256k1_context_verify, &sig, hash.begin(), &pubkey);
 }
 
 bool CPubKey::RecoverCompact(const uint256 &hash, const std::vector<unsigned char>& vchSig) {
-    if (vchSig.size() != 65)
+    if (vchSig.size() != COMPACT_SIGNATURE_SIZE)
         return false;
     int recid = (vchSig[0] - 27) & 3;
     bool fComp = ((vchSig[0] - 27) & 4) != 0;
-    CECKey key;
-    if (!key.Recover(hash, &vchSig[1], recid))
+    secp256k1_pubkey pubkey;
+    secp256k1_ecdsa_recoverable_signature sig;
+    if (!secp256k1_ecdsa_recoverable_signature_parse_compact(secp256k1_context_verify, &sig, &vchSig[1], recid)) {
+        return false;
+    }
+    if (!secp256k1_ecdsa_recover(secp256k1_context_verify, &pubkey, &sig, hash.begin())) {
         return false;
-    std::vector<unsigned char> pubkey;
-    key.GetPubKey(pubkey, fComp);
-    Set(pubkey.begin(), pubkey.end());
+    }
+    unsigned char pub[PUBLIC_KEY_SIZE];
+    size_t publen = PUBLIC_KEY_SIZE;
+    secp256k1_ec_pubkey_serialize(secp256k1_context_verify, pub, &publen, &pubkey, fComp ? SECP256K1_EC_COMPRESSED : SECP256K1_EC_UNCOMPRESSED);
+    Set(pub, pub + publen);
     return true;
 }
 
 bool CPubKey::IsFullyValid() const {
     if (!IsValid())
         return false;
-    CECKey key;
-    if (!key.SetPubKey(begin(), size()))
-        return false;
-    return true;
+    secp256k1_pubkey pubkey;
+    return secp256k1_ec_pubkey_parse(secp256k1_context_verify, &pubkey, &(*this)[0], size());
 }
 
 bool CPubKey::Decompress() {
     if (!IsValid())
         return false;
-    CECKey key;
-    if (!key.SetPubKey(begin(), size()))
+    secp256k1_pubkey pubkey;
+    if (!secp256k1_ec_pubkey_parse(secp256k1_context_verify, &pubkey, &(*this)[0], size())) {
         return false;
-    std::vector<unsigned char> pubkey;
-    key.GetPubKey(pubkey, false);
-    Set(pubkey.begin(), pubkey.end());
+    }
+    unsigned char pub[PUBLIC_KEY_SIZE];
+    size_t publen = PUBLIC_KEY_SIZE;
+    secp256k1_ec_pubkey_serialize(secp256k1_context_verify, pub, &publen, &pubkey, SECP256K1_EC_UNCOMPRESSED);
+    Set(pub, pub + publen);
     return true;
 }
 
-bool CPubKey::Derive(CPubKey& pubkeyChild, unsigned char ccChild[32], unsigned int nChild, const unsigned char cc[32]) const {
+bool CPubKey::Derive(CPubKey& pubkeyChild, ChainCode &ccChild, unsigned int nChild, const ChainCode& cc) const {
     assert(IsValid());
     assert((nChild >> 31) == 0);
-    assert(begin() + 33 == end());
+    assert(size() == COMPRESSED_PUBLIC_KEY_SIZE);
     unsigned char out[64];
     BIP32Hash(cc, nChild, *begin(), begin()+1, out);
-    memcpy(ccChild, out+32, 32);
-    CECKey key;
-    bool ret = key.SetPubKey(begin(), size());
-    ret &= key.TweakPublic(out);
-    std::vector<unsigned char> pubkey;
-    key.GetPubKey(pubkey, true);
-    pubkeyChild.Set(pubkey.begin(), pubkey.end());
-    return ret;
+    memcpy(ccChild.begin(), out+32, 32);
+    secp256k1_pubkey pubkey;
+    if (!secp256k1_ec_pubkey_parse(secp256k1_context_verify, &pubkey, &(*this)[0], size())) {
+        return false;
+    }
+    if (!secp256k1_ec_pubkey_tweak_add(secp256k1_context_verify, &pubkey, out)) {
+        return false;
+    }
+    unsigned char pub[COMPRESSED_PUBLIC_KEY_SIZE];
+    size_t publen = COMPRESSED_PUBLIC_KEY_SIZE;
+    secp256k1_ec_pubkey_serialize(secp256k1_context_verify, pub, &publen, &pubkey, SECP256K1_EC_COMPRESSED);
+    pubkeyChild.Set(pub, pub + publen);
+    return true;
 }
 
 void CExtPubKey::Encode(unsigned char code[74]) const {
@@ -75,16 +103,16 @@ void CExtPubKey::Encode(unsigned char code[74]) const {
     memcpy(code+1, vchFingerprint, 4);
     code[5] = (nChild >> 24) & 0xFF; code[6] = (nChild >> 16) & 0xFF;
     code[7] = (nChild >>  8) & 0xFF; code[8] = (nChild >>  0) & 0xFF;
-    memcpy(code+9, vchChainCode, 32);
-    assert(pubkey.size() == 33);
-    memcpy(code+41, pubkey.begin(), 33);
+    memcpy(code+9, chaincode.begin(), 32);
+    assert(pubkey.size() == CPubKey::COMPRESSED_PUBLIC_KEY_SIZE);
+    memcpy(code+41, pubkey.begin(), CPubKey::COMPRESSED_PUBLIC_KEY_SIZE);
 }
 
 void CExtPubKey::Decode(const unsigned char code[74]) {
     nDepth = code[0];
     memcpy(vchFingerprint, code+1, 4);
     nChild = (code[5] << 24) | (code[6] << 16) | (code[7] << 8) | code[8];
-    memcpy(vchChainCode, code+9, 32);
+    memcpy(chaincode.begin(), code+9, 32);
     pubkey.Set(code+41, code+74);
 }
 
@@ -93,5 +121,37 @@ bool CExtPubKey::Derive(CExtPubKey &out, unsigned int nChild) const {
     CKeyID id = pubkey.GetID();
     memcpy(&out.vchFingerprint[0], &id, 4);
     out.nChild = nChild;
-    return pubkey.Derive(out.pubkey, out.vchChainCode, nChild, vchChainCode);
+    return pubkey.Derive(out.pubkey, out.chaincode, nChild, chaincode);
+}
+
+/* static */ bool CPubKey::CheckLowS(const std::vector<unsigned char>& vchSig) {
+    secp256k1_ecdsa_signature sig;
+
+    /* Zcash, unlike Bitcoin, has always enforced strict DER signatures. */
+    if (!secp256k1_ecdsa_signature_parse_der(secp256k1_context_verify, &sig, &vchSig[0], vchSig.size())) {
+        return false;
+    }
+    return (!secp256k1_ecdsa_signature_normalize(secp256k1_context_verify, NULL, &sig));
+}
+
+/* static */ int ECCVerifyHandle::refcount = 0;
+
+ECCVerifyHandle::ECCVerifyHandle()
+{
+    if (refcount == 0) {
+        assert(secp256k1_context_verify == NULL);
+        secp256k1_context_verify = secp256k1_context_create(SECP256K1_CONTEXT_VERIFY);
+        assert(secp256k1_context_verify != NULL);
+    }
+    refcount++;
+}
+
+ECCVerifyHandle::~ECCVerifyHandle()
+{
+    refcount--;
+    if (refcount == 0) {
+        assert(secp256k1_context_verify != NULL);
+        secp256k1_context_destroy(secp256k1_context_verify);
+        secp256k1_context_verify = NULL;
+    }
 }
This page took 0.028728 seconds and 4 git commands to generate.