This is an automated email from the ASF dual-hosted git repository. cmorris pushed a commit to branch qredo-plugin in repository https://gitbox.apache.org/repos/asf/incubator-milagro-dta.git
commit c8dab8c507da4d5de7e2e51046c0ff9f7bd32d1d Author: Christopher Morris <[email protected]> AuthorDate: Wed Aug 28 14:43:28 2019 +0100 Qredo Plugin --- pkg/qredoplugin/coin.go | 176 +++++++++++++++++++++++++++++++ pkg/qredoplugin/coin_test.go | 52 ++++++++++ pkg/qredoplugin/helpers.go | 225 ++++++++++++++++++++++++++++++++++++++++ pkg/qredoplugin/helpers_test.go | 47 +++++++++ pkg/qredoplugin/service.go | 103 ++++++++++++++++++ plugins/qredoplugin.go | 9 ++ 6 files changed, 612 insertions(+) diff --git a/pkg/qredoplugin/coin.go b/pkg/qredoplugin/coin.go new file mode 100644 index 0000000..c2a6cfa --- /dev/null +++ b/pkg/qredoplugin/coin.go @@ -0,0 +1,176 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +package qredoplugin + +/* +The coin constans are defined here +https://github.com/satoshilabs/slips/blob/master/slip-0044.md +https://www.thepolyglotdeveloper.com/2018/02/generate-cryptocurrency-private-keys-public-addresses-golang/ +https://godoc.org/bitbucket.org/dchapes/ripple/crypto/rkey#example-package--Address + +*/ + +import ( + "encoding/hex" + "fmt" + "strings" + + "github.com/btcsuite/btcd/btcec" + "github.com/btcsuite/btcd/chaincfg" + "github.com/btcsuite/btcutil" + ethcrypto "github.com/ethereum/go-ethereum/crypto" + "github.com/pkg/errors" +) + +var ( + errUnsupportedCoin = errors.New("unsupported coin") +) + +//Network list of Cryptocurrency networks +type Network struct { + name string + symbol string + xpubkey byte + xprivatekey byte +} + +var network = map[string]Network{ + "rdd": {name: "reddcoin", symbol: "rdd", xpubkey: 0x3d, xprivatekey: 0xbd}, + "dgb": {name: "digibyte", symbol: "dgb", xpubkey: 0x1e, xprivatekey: 0x80}, + "doge": {name: "dogecoin", symbol: "doge", xpubkey: 0x1e, xprivatekey: 0x9e}, + "via": {name: "viacoin", symbol: "via", xpubkey: 0x47, xprivatekey: 0xc7}, + "btc": {name: "bitcoin", symbol: "btc", xpubkey: 0x00, xprivatekey: 0x80}, + "testbtc": {name: "bitcoin testnet", symbol: "btc", xpubkey: 0x6f, xprivatekey: 0xef}, + "ltc": {name: "litecoin", symbol: "ltc", xpubkey: 0x30, xprivatekey: 0xb0}, +} + +func addressForPublicKey(publicKey string, coinType int) (string, error) { + pubK, _ := hex.DecodeString(publicKey) + pubKeyBytes := []byte(pubK) + + switch coinType { + case 0: //Bitcoin + return network["btc"].pubkeyToAddress(pubKeyBytes, false) + case 1: //Bitcoin Testnet + return network["testbtc"].pubkeyToAddress(pubKeyBytes, false) + case 2: //litecoin + return network["ltc"].pubkeyToAddress(pubKeyBytes, false) + case 3: //Dogecoin + return network["doge"].pubkeyToAddress(pubKeyBytes, false) + case 60: //Ethereum + compByte, err := hex.DecodeString(publicKey) + pubKey, err := btcec.ParsePubKey([]byte(compByte), btcec.S256()) + if err != nil { + return "", errors.Wrap(err, "Failed to generate Ethereum Address") + } + pubECDSA := pubKey.ToECDSA() + address1 := ethcrypto.PubkeyToAddress(*pubECDSA) + retAddress := fmt.Sprintf("%x", address1) + return retAddress, nil + // case 128: //Monero + // case 144: //Ripple + // case 145: //Bitcoin Cash + // case 148: //Stellar + // case 1815: //Cardano + } + return "", errUnsupportedCoin +} + +func addressForPrivateKey(privateKey []byte, coinType int) (string, error) { + switch coinType { + case 0: //Bitcoin + return network["btc"].privkeyToAddress(privateKey, false) + case 1: //Bitcoin Testnet + return network["testbtc"].privkeyToAddress(privateKey, false) + case 2: //litecoin + return network["ltc"].privkeyToAddress(privateKey, false) + case 3: //Dogecoin + return network["doge"].privkeyToAddress(privateKey, false) + case 60: //Ethereum + _, cpub1 := btcec.PrivKeyFromBytes(btcec.S256(), privateKey) + pubKey := cpub1.SerializeUncompressed() + address := ethcrypto.Keccak256(pubKey[1:])[12:] + addRet := strings.ToLower(fmt.Sprintf("%x", address)) + return addRet, nil + // case 128: //Monero + // case 144: //Ripple + // case 145: //Bitcoin Cash + // case 148: //Stellar + // case 1815: //Cardano + } + return "", errUnsupportedCoin +} + +func (network Network) privkeyToAddress(privateKey []byte, compressed bool) (string, error) { + wif, _ := network.createPrivateKeyFromBytes(privateKey) + address, _ := network.getAddress(wif) + if compressed == true { + address.SetFormat(btcutil.PKFCompressed) + } else { + address.SetFormat(btcutil.PKFUncompressed) + } + return address.EncodeAddress(), nil +} + +func (network Network) pubkeyToAddress(publicKey []byte, compressed bool) (string, error) { + mainNetAddr, err := btcutil.NewAddressPubKey(publicKey, network.getNetworkParams()) + if err != nil { + return "", errors.Wrap(err, "Failed to decode Public Key") + } + if compressed == true { + mainNetAddr.SetFormat(btcutil.PKFCompressed) + } else { + mainNetAddr.SetFormat(btcutil.PKFUncompressed) + } + return mainNetAddr.EncodeAddress(), nil +} + +func (network Network) getNetworkParams() *chaincfg.Params { + networkParams := &chaincfg.MainNetParams + networkParams.PubKeyHashAddrID = network.xpubkey + networkParams.PrivateKeyID = network.xprivatekey + return networkParams +} + +func (network Network) createPrivateKeyFromBytes(privateKey []byte) (*btcutil.WIF, error) { + secret, _ := btcec.PrivKeyFromBytes(btcec.S256(), privateKey) + return btcutil.NewWIF(secret, network.getNetworkParams(), true) +} + +func (network Network) createPrivateKey() (*btcutil.WIF, error) { + secret, err := btcec.NewPrivateKey(btcec.S256()) + if err != nil { + return nil, err + } + return btcutil.NewWIF(secret, network.getNetworkParams(), true) +} + +func (network Network) importWIF(wifStr string) (*btcutil.WIF, error) { + wif, err := btcutil.DecodeWIF(wifStr) + if err != nil { + return nil, err + } + if !wif.IsForNet(network.getNetworkParams()) { + return nil, errors.New("The WIF string is not valid for the `" + network.name + "` network") + } + return wif, nil +} + +func (network Network) getAddress(wif *btcutil.WIF) (*btcutil.AddressPubKey, error) { + return btcutil.NewAddressPubKey(wif.PrivKey.PubKey().SerializeUncompressed(), network.getNetworkParams()) +} diff --git a/pkg/qredoplugin/coin_test.go b/pkg/qredoplugin/coin_test.go new file mode 100644 index 0000000..9d9cff6 --- /dev/null +++ b/pkg/qredoplugin/coin_test.go @@ -0,0 +1,52 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +package qredoplugin + +import ( + "encoding/hex" + "testing" + + "github.com/stretchr/testify/assert" +) + +func Test_AddressForPublicKey(t *testing.T) { + pubKey := "0487DBF8D88A860270AB7D689EB44C2DFFF768D2F7851A753FACF356978B82CE4ACB5C9B061FC884668D9BB46B83D6BF180A2099F397142785D2E03DACCEF03D01" + btcAddress, err := addressForPublicKey(pubKey, 0) + assert.Nil(t, err, "Error should be nil") + assert.Equal(t, "1MwiNcg3v19BLeawNJKL8L18m4Tzmtua5T", btcAddress) + + btcTestNetAddress, err := addressForPublicKey(pubKey, 1) + assert.Nil(t, err, "Error should be nil") + assert.Equal(t, "n2Tfffm2j2aS7m4Z5sHhxFDTd44hfnDhPz", btcTestNetAddress) + + _, err = addressForPublicKey(pubKey, 9999999999) + assert.EqualError(t, err, "unsupported coin") +} +func Test_AddressForPrivateKey(t *testing.T) { + privKey, _ := hex.DecodeString("EB354D4B18E0B4AC6E63369F33D0CFFE7F3C09101D29678877A6CE8879D7E152") + btcAddress, err := addressForPrivateKey(privKey, 0) + assert.Nil(t, err, "Error should be nil") + assert.Equal(t, "1MwiNcg3v19BLeawNJKL8L18m4Tzmtua5T", btcAddress) + + btcTestNetAddress, err := addressForPrivateKey(privKey, 1) + assert.Nil(t, err, "Error should be nil") + assert.Equal(t, "n2Tfffm2j2aS7m4Z5sHhxFDTd44hfnDhPz", btcTestNetAddress) + + _, err = addressForPrivateKey(privKey, 9999999999) + assert.EqualError(t, err, "unsupported coin") +} diff --git a/pkg/qredoplugin/helpers.go b/pkg/qredoplugin/helpers.go new file mode 100644 index 0000000..9295106 --- /dev/null +++ b/pkg/qredoplugin/helpers.go @@ -0,0 +1,225 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +package qredoplugin + +import ( + "crypto/sha256" + "encoding/hex" + "fmt" + "math/big" + + "github.com/apache/incubator-milagro-dta/libs/cryptowallet" + "github.com/apache/incubator-milagro-dta/libs/documents" + "github.com/apache/incubator-milagro-dta/pkg/common" + "github.com/btcsuite/btcd/btcec" + "github.com/pkg/errors" +) + +func deriveFinalPrivateKey(s *Service, order documents.OrderDoc, beneficiariesSikeSK []byte, beneficiariesSeed []byte, beneficiaryIDDocumentCID string, nodeID string, signingBlsPK []byte) (string, error) { + if beneficiaryIDDocumentCID != "" { + //we are using the beneficiary specified in order Part 3 + beneficiaryBlob := order.OrderPart3.BeneficiaryEncryptedData + + //Decrypt the Envelope intented for the Beneficiary + privateKeyPart1of1, err := adhocEncryptedEnvelopeDecode(s, beneficiariesSikeSK, beneficiaryBlob, beneficiaryIDDocumentCID, signingBlsPK) + if err != nil { + return "", err + } + //Calculate the final private key by Eliptical Key addition of both parts + privateKeyPart2of2 := order.OrderDocument.OrderPart4.Secret + + finalPrivateKey, err := addPrivateKeys(privateKeyPart1of1, privateKeyPart2of2) + + if err != nil { + return "", err + } + return finalPrivateKey, err + } + + //we are using the beneficiary specified in the order part 1 + privateKeyPart2of2 := order.OrderDocument.OrderPart4.Secret + if order.OrderDocument.BeneficiaryCID != nodeID { + //need to forward this data to the beneficiary to complete redemption + return "", errors.New("Currently beneficiary must be the same as the Principal") + } + //restore the Seed + _, _, ecAddPrivateKey, err := cryptowallet.Bip44Address(beneficiariesSeed, cryptowallet.CoinTypeBitcoinMain, 0, 0, 0) + if err != nil { + return "", err + } + privateKeyPart1of1 := hex.EncodeToString(ecAddPrivateKey.Serialize()) + finalPrivateKey, err := addPrivateKeys(privateKeyPart1of1, privateKeyPart2of2) + if err != nil { + return "", err + } + return finalPrivateKey, err + +} + +func adhocEncryptedEnvelopeEncode(s *Service, nodeID string, beneficiaryIDDocumentCID string, order documents.OrderDoc, blsSK []byte) ([]byte, error) { + //Regenerate the original Princaipal Priv Key based on Order + if beneficiaryIDDocumentCID == "" { + //beneficiaryIDDocumentCID is empty when it was passed in the Inital Deposit Order + return nil, nil + } + seedHex, err := common.RetrieveSeed(s.Store, order.Reference) + if err != nil { + return nil, err + } + seedOrderModifier := order.OrderDocument.OrderPart2.PreviousOrderCID + seed, err := hex.DecodeString(seedHex) + if err != nil { + return nil, err + } + concatenatedSeeds := append(seed, seedOrderModifier...) + finalSeed := sha256.Sum256(concatenatedSeeds) + finalSeedHex := hex.EncodeToString(finalSeed[:]) + privateKeyPart1of2, err := cryptowallet.RedeemSecret(finalSeedHex) + if err != nil { + return nil, err + } + beneficiaryIDDocument, err := common.RetrieveIDDocFromIPFS(s.Ipfs, beneficiaryIDDocumentCID) + if err != nil { + return nil, err + } + secretBody := &documents.SimpleString{Content: privateKeyPart1of2} + header := &documents.Header{} + recipients := map[string]documents.IDDoc{ + beneficiaryIDDocumentCID: beneficiaryIDDocument, + } + docEnv, err := documents.Encode(nodeID, nil, secretBody, header, blsSK, recipients) + if err != nil { + return nil, err + } + return docEnv, err +} + +func adhocEncryptedEnvelopeDecode(s *Service, sikeSK []byte, beneficiaryBlob []byte, beneficiaryIDDocumentCID string, signingBlsPK []byte) (string, error) { + //Regenerate the original Principal Priv Key based on Order + secretBody := &documents.SimpleString{} + _, err := documents.Decode(beneficiaryBlob, "INTERNAL", sikeSK, beneficiaryIDDocumentCID, nil, secretBody, signingBlsPK) + if err != nil { + return "", err + } + return secretBody.Content, err +} + +func generateFinalPubKey(s *Service, pubKeyPart2of2 string, order documents.OrderDoc) (string, string, error) { + beneficiaryIDDocumentCID := order.OrderDocument.BeneficiaryCID + coinType := order.Coin + var pubKeyPart1of2 string + + if beneficiaryIDDocumentCID == "" { + //There is no beneficiary ID so we do it all locally based on + //Retrieve the Local Seed + seedHex, err := common.RetrieveSeed(s.Store, order.Reference) + if err != nil { + return "", "", err + } + seedOrderModifier := order.OrderDocument.OrderPart2.PreviousOrderCID + seed, err := hex.DecodeString(seedHex) + if err != nil { + return "", "", err + } + concatenatedSeeds := append(seed, seedOrderModifier...) + finalSeed := sha256.Sum256(concatenatedSeeds) + finalSeedHex := hex.EncodeToString(finalSeed[:]) + //Use HD Wallet to obtain the local Public Key + pubKeyPart1of2, err = cryptowallet.RedeemPublicKey(finalSeedHex) + + if err != nil { + return "", "", err + } + } + + if beneficiaryIDDocumentCID != "" { + //There is a BeneficiaryID use it to generate the key + //Get beneficiary's identity out of IPFS + id := &documents.IDDoc{} + rawDocI, err := s.Ipfs.Get(beneficiaryIDDocumentCID) + if err != nil { + return "", "", errors.Wrapf(err, "Read identity Doc") + } + err = documents.DecodeIDDocument(rawDocI, beneficiaryIDDocumentCID, id) + if err != nil { + return "", "", err + } + pubKeyPart1of2 = hex.EncodeToString(id.BeneficiaryECPublicKey) + } + + finalPublicKey, err := addPublicKeys(pubKeyPart2of2, pubKeyPart1of2) + + if err != nil { + return "", "", err + } + addressForPublicKey, err := addressForPublicKey(finalPublicKey, int(coinType)) + if err != nil { + return "", "", err + } + return finalPublicKey, addressForPublicKey, nil + +} + +//AddPrivateKeys Perform eliptical key additon on 2 privates keys +func addPrivateKeys(key1 string, key2 string) (string, error) { + curveOrder := new(big.Int) + curveOrder.SetString("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141", 16) + priv1 := new(big.Int) + priv2 := new(big.Int) + priv3 := new(big.Int) + priv1.SetString(key1, 16) + priv2.SetString(key2, 16) + priv3.Add(priv1, priv2) + if curveOrder.Cmp(priv3) == -1 { + priv3.Sub(priv3, curveOrder) + } + priv4 := fmt.Sprintf("%064x", priv3) + return priv4, nil +} + +//AddPublicKeys Perform eliptical key addition on 2 public keys +func addPublicKeys(key1 string, key2 string) (string, error) { + pub1Hex, err := hex.DecodeString(key1) + if err != nil { + return "", errors.Wrap(err, "Failed to hex decode String") + } + dpub1, err := btcec.ParsePubKey(pub1Hex, btcec.S256()) + if err != nil { + return "", errors.Wrap(err, "Failed to Parse Public Key") + } + pub2Hex, err := hex.DecodeString(key2) + if err != nil { + return "", errors.Wrap(err, "Failed to hex decode String") + } + dpub2, err := btcec.ParsePubKey(pub2Hex, btcec.S256()) + if err != nil { + return "", errors.Wrap(err, "Failed to Parse Public Key") + } + x, y := btcec.S256().Add(dpub1.X, dpub1.Y, dpub2.X, dpub2.Y) + comp := fmt.Sprintf("04%064X%064X", x, y) + compByte, err := hex.DecodeString(comp) + if err != nil { + return "", err + } + pubKey, err := btcec.ParsePubKey([]byte(compByte), btcec.S256()) + if err != nil { + return "", err + } + pubKeyString := hex.EncodeToString(pubKey.SerializeCompressed()) + return pubKeyString, nil +} diff --git a/pkg/qredoplugin/helpers_test.go b/pkg/qredoplugin/helpers_test.go new file mode 100644 index 0000000..857e2fa --- /dev/null +++ b/pkg/qredoplugin/helpers_test.go @@ -0,0 +1,47 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +package qredoplugin + +import ( + "encoding/hex" + "testing" + + "github.com/btcsuite/btcd/btcec" + "github.com/stretchr/testify/assert" +) + +func Test_AddKeys(t *testing.T) { + privKey1, _ := btcec.NewPrivateKey(btcec.S256()) + privKey2, _ := btcec.NewPrivateKey(btcec.S256()) + privKey1Str := hex.EncodeToString(privKey1.Serialize()) + privKey2Str := hex.EncodeToString(privKey2.Serialize()) + + pubKey1 := btcec.PublicKey(privKey1.ToECDSA().PublicKey) + pubKey2 := btcec.PublicKey(privKey2.ToECDSA().PublicKey) + pubKey1Str := hex.EncodeToString(pubKey1.SerializeUncompressed()) + pubKey2Str := hex.EncodeToString(pubKey2.SerializeUncompressed()) + + //run Additions + privAdd, _ := addPrivateKeys(privKey1Str, privKey2Str) + pubAdd, _ := addPublicKeys(pubKey1Str, pubKey2Str) + + privAddBytes, _ := hex.DecodeString(privAdd) + _, pubKeyFromPrivate := btcec.PrivKeyFromBytes(btcec.S256(), privAddBytes) + pubKeyFromPrivateString := hex.EncodeToString(pubKeyFromPrivate.SerializeCompressed()) + assert.Equal(t, pubKeyFromPrivateString, pubAdd, "Addition failed") +} diff --git a/pkg/qredoplugin/service.go b/pkg/qredoplugin/service.go new file mode 100644 index 0000000..855b2fe --- /dev/null +++ b/pkg/qredoplugin/service.go @@ -0,0 +1,103 @@ +package qredoplugin + +import ( + "strconv" + + "github.com/apache/incubator-milagro-dta/libs/cryptowallet" + "github.com/apache/incubator-milagro-dta/libs/documents" + "github.com/apache/incubator-milagro-dta/pkg/api" + "github.com/apache/incubator-milagro-dta/pkg/common" + "github.com/apache/incubator-milagro-dta/pkg/defaultservice" + + "github.com/pkg/errors" +) + +var ( + extensionVendor = "Qredo" + pluginName = "qredoplugin" +) + +// Service is the Qredo Plugin service +type Service struct { + defaultservice.Service +} + +// NewService returns a Milagro implementation of Service +func NewService() *Service { + return &Service{} +} + +// Name of the plugin +func (s *Service) Name() string { + return pluginName +} + +// Vendor of the plugin +func (s *Service) Vendor() string { + return extensionVendor +} + +// ValidateOrderRequest checks if the Coin type is valid +func (s *Service) ValidateOrderRequest(req *api.OrderRequest) error { + if _, err := strconv.ParseInt(req.Extension["coin"], 10, 64); err != nil { + return errors.Wrap(err, "Failed to Parse Coin Type") + } + + return nil +} + +// PrepareOrderPart1 adds the coin type to the order +func (s *Service) PrepareOrderPart1(order *documents.OrderDoc, reqExtension map[string]string) (fulfillExtension map[string]string, err error) { + coin, err := strconv.ParseInt(reqExtension["coin"], 10, 64) + if err != nil { + return nil, errors.Wrap(err, "Failed to Parse Coin Type") + } + + order.Coin = coin + return nil, nil +} + +// PrepareOrderResponse gets the updated order and returns the commitment and extension +func (s *Service) PrepareOrderResponse(orderPart2 *documents.OrderDoc, reqExtension, fulfillExtension map[string]string) (commitment string, extension map[string]string, err error) { + pubKeyPart2of2 := orderPart2.OrderPart2.CommitmentPublicKey + finalPublicKey, cryptoAddress, err := generateFinalPubKey(s, pubKeyPart2of2, *orderPart2) + + return finalPublicKey, map[string]string{"address": cryptoAddress}, nil +} + +// ProduceBeneficiaryEncryptedData - +func (s *Service) ProduceBeneficiaryEncryptedData(blsSK []byte, order *documents.OrderDoc, req *api.OrderSecretRequest) (encrypted []byte, extension map[string]string, err error) { + //There is no beneficiary supplided in either the Deposit or Redemption + if order.BeneficiaryCID == "" && req.BeneficiaryIDDocumentCID == "" { + return nil, nil, errors.New("Beneficiary must be supplied") + } + + enc, err := adhocEncryptedEnvelopeEncode(s, s.NodeID(), req.BeneficiaryIDDocumentCID, *order, blsSK) + return enc, nil, err +} + +// ProduceFinalSecret - +func (s *Service) ProduceFinalSecret(seed, sikeSK []byte, order, orderPart4 *documents.OrderDoc, req *api.OrderSecretRequest, fulfillSecretRespomse *api.FulfillOrderSecretResponse) (secret, commitment string, extension map[string]string, err error) { + //retrieve principal IDDoc + principalDocID, err := common.RetrieveIDDocFromIPFS(s.Ipfs, order.PrincipalCID) + if err != nil { + return "", "", nil, err + } + + finalPrivateKey, err := deriveFinalPrivateKey(s, *orderPart4, sikeSK, seed, req.BeneficiaryIDDocumentCID, s.NodeID(), principalDocID.BLSPublicKey) + if err != nil { + return "", "", nil, err + } + //Generate Public key & derive crypto address + finalPublicKey, finalPublicKeyCompressed, err := cryptowallet.PublicKeyFromPrivate(finalPrivateKey) + if err != nil { + return "", "", nil, err + } + + addressForPublicKey, err := addressForPublicKey(finalPublicKey, int(order.Coin)) + if err != nil { + return "", "", nil, err + } + + return finalPrivateKey, finalPublicKeyCompressed, map[string]string{"address": addressForPublicKey}, nil +} diff --git a/plugins/qredoplugin.go b/plugins/qredoplugin.go new file mode 100644 index 0000000..68bf54d --- /dev/null +++ b/plugins/qredoplugin.go @@ -0,0 +1,9 @@ +package plugins + +import ( + "github.com/apache/incubator-milagro-dta/pkg/qredoplugin" +) + +func init() { + registerPlugin(qredoplugin.NewService()) +}
