OSDN Git Service

add pegin address for contract
authormars <mars@bytom.io>
Tue, 27 Nov 2018 13:24:48 +0000 (21:24 +0800)
committermars <mars@bytom.io>
Tue, 27 Nov 2018 13:24:48 +0000 (21:24 +0800)
account/accounts.go
api/api.go
api/receivers.go
node/node.go

index 503939b..eb6474a 100644 (file)
@@ -2,7 +2,10 @@
 package account
 
 import (
+       "crypto/hmac"
+       "crypto/sha256"
        "encoding/json"
+       "fmt"
        "reflect"
        "sort"
        "strings"
@@ -18,8 +21,11 @@ import (
        "github.com/vapor/consensus"
        "github.com/vapor/consensus/segwit"
        "github.com/vapor/crypto"
+       "github.com/vapor/crypto/ed25519"
        "github.com/vapor/crypto/ed25519/chainkd"
        "github.com/vapor/crypto/sha3pool"
+       chainjson "github.com/vapor/encoding/json"
+       "github.com/vapor/equity/compiler"
        "github.com/vapor/errors"
        "github.com/vapor/protocol"
        "github.com/vapor/protocol/bc"
@@ -808,7 +814,64 @@ func (m *Manager) GetPeginControlPrograms(claimScript []byte) (string, []byte) {
        federationRedeemScript := vmutil.CalculateContract(consensus.ActiveNetParams.FedpegXPubs, claimScript)
        scriptHash := crypto.Sha256(federationRedeemScript)
 
-       address, err := common.NewAddressWitnessScriptHash(scriptHash, &consensus.ActiveNetParams)
+       address, err := common.NewPeginAddressWitnessScriptHash(scriptHash, &consensus.ActiveNetParams)
+       if err != nil {
+               return "", nil
+       }
+
+       redeemContract := address.ScriptAddress()
+
+       program := []byte{}
+       program, err = vmutil.P2WSHProgram(redeemContract)
+       if err != nil {
+               return "", nil
+       }
+
+       return address.EncodeAddress(), program
+}
+
+var lockWith2of3KeysFmt = `
+contract LockWith3Keys(%s) locks amount of asset {
+  clause unlockWith2Sigs(%s) {
+    verify checkTxMultiSig(%s)
+    unlock amount of asset
+  }
+}
+`
+
+func (m *Manager) CreatePeginContractAddress(accountID string, change bool) (string, []byte, error) {
+       // 通过配置获取
+       claimCtrlProg, err := m.CreateAddress(accountID, change)
+       if err != nil {
+               return "", nil, err
+       }
+       claimScript := claimCtrlProg.ControlProgram
+
+       peginContractPrograms, err := m.getPeginContractPrograms(claimScript)
+       if err != nil {
+               return "", nil, err
+       }
+
+       scriptHash := crypto.Sha256(peginContractPrograms)
+
+       address, err := common.NewPeginAddressWitnessScriptHash(scriptHash, &consensus.ActiveNetParams)
+       if err != nil {
+               return "", nil, err
+       }
+
+       return address.EncodeAddress(), claimScript, nil
+
+}
+
+func (m *Manager) GetPeginContractControlPrograms(claimScript []byte) (string, []byte) {
+
+       peginContractPrograms, err := m.getPeginContractPrograms(claimScript)
+       if err != nil {
+               return "", nil
+       }
+       scriptHash := crypto.Sha256(peginContractPrograms)
+
+       address, err := common.NewPeginAddressWitnessScriptHash(scriptHash, &consensus.ActiveNetParams)
        if err != nil {
                return "", nil
        }
@@ -823,3 +886,120 @@ func (m *Manager) GetPeginControlPrograms(claimScript []byte) (string, []byte) {
 
        return address.EncodeAddress(), program
 }
+
+func (m *Manager) getPeginContractPrograms(claimScript []byte) ([]byte, error) {
+
+       pubkeys := getNewXpub(consensus.ActiveNetParams.FedpegXPubs, claimScript)
+       num := len(pubkeys)
+       fmt.Println(pubkeys)
+       if num == 0 {
+               return nil, errors.New("Fedpeg's XPubs is empty")
+       }
+       params := ""
+       unlockParams := ""
+       checkParams := "["
+
+       for index := 0; index < num; index++ {
+               param := fmt.Sprintf("pubkey%d", index+1)
+               params += param
+               checkParams += param
+               if (index + 1) < num {
+                       params += ","
+                       checkParams += ","
+               }
+       }
+       params += ": PublicKey"
+       checkParams += "],["
+
+       fmt.Println(params)
+       signNum := getNumberOfSignaturesRequired(pubkeys)
+       for index := 0; index < signNum; index++ {
+               param := fmt.Sprintf("sig%d", index+1)
+               unlockParams += param
+               checkParams += param
+               if index+1 < signNum {
+                       unlockParams += ","
+                       checkParams += ","
+               }
+       }
+
+       unlockParams += ": Signature"
+       checkParams += "]"
+
+       lockWith2of3Keys := fmt.Sprintf(lockWith2of3KeysFmt, params, unlockParams, checkParams)
+       fmt.Println(lockWith2of3Keys)
+       r := strings.NewReader(lockWith2of3Keys)
+       compiled, err := compiler.Compile(r)
+       if err != nil {
+               return nil, errors.New("Compile contract failed")
+       }
+
+       contract := compiled[len(compiled)-1]
+
+       if num < len(contract.Params) {
+               return nil, errors.New("Compile contract failed")
+       }
+
+       contractArgs, err := convertArguments(contract, pubkeys)
+       if err != nil {
+               fmt.Println("Convert arguments into contract parameters error:", err)
+               return nil, errors.New("Convert arguments into contract parameters error")
+       }
+
+       instantProg, err := instantiateContract(contract, contractArgs)
+       if err != nil {
+               fmt.Println("Instantiate contract error:", err)
+               return nil, errors.New("Instantiate contract error")
+       }
+
+       return instantProg, nil
+}
+
+func getNewXpub(federationRedeemXPub []chainkd.XPub, claimScript []byte) []ed25519.PublicKey {
+
+       var pubkeys []ed25519.PublicKey
+       for _, xpub := range federationRedeemXPub {
+               // pub + scriptPubKey 生成一个随机数A
+               var tmp [32]byte
+               h := hmac.New(sha256.New, xpub[:])
+               h.Write(claimScript)
+               tweak := h.Sum(tmp[:])
+               // pub +  A 生成一个新的公钥pub_new
+               chaildXPub := xpub.Child(tweak)
+               pubkeys = append(pubkeys, chaildXPub.PublicKey())
+       }
+       return pubkeys
+}
+
+func getNumberOfSignaturesRequired(pubkeys []ed25519.PublicKey) int {
+       return len(pubkeys)/2 + 1
+}
+
+// InstantiateContract instantiate contract parameters
+func instantiateContract(contract *compiler.Contract, args []compiler.ContractArg) ([]byte, error) {
+       program, err := compiler.Instantiate(contract.Body, contract.Params, contract.Recursive, args)
+       if err != nil {
+               return nil, err
+       }
+
+       return program, nil
+}
+
+func convertArguments(contract *compiler.Contract, args []ed25519.PublicKey) ([]compiler.ContractArg, error) {
+       var contractArgs []compiler.ContractArg
+       for i, p := range contract.Params {
+               var argument compiler.ContractArg
+               switch p.Type {
+               case "PublicKey":
+                       if len(args[i]) != 64 {
+                               return nil, errors.New("mismatch length for Asset/Hash/PublicKey argument")
+                       }
+                       argument.S = (*chainjson.HexBytes)(&args[i])
+               default:
+                       return nil, errors.New("Contract parameter type error")
+               }
+               contractArgs = append(contractArgs, argument)
+       }
+
+       return contractArgs, nil
+}
index 940d6d2..bea80e6 100644 (file)
@@ -248,6 +248,7 @@ func (a *API) buildHandler() {
                m.Handle("/recovery-wallet", jsonHandler(a.recoveryFromRootXPubs))
 
                m.Handle("/get-pegin-address", jsonHandler(a.getPeginAddress))
+               m.Handle("/get-pegin-contract-address", jsonHandler(a.getAddressForPeginContract))
                m.Handle("/claim-pegin-transaction", jsonHandler(a.claimPeginTx))
                m.Handle("/create-key-pair", jsonHandler(a.createXKeys))
                m.Handle("/get-utxo-from-transaction", jsonHandler(a.getUnspentOutputs))
index 11408df..b5da963 100644 (file)
@@ -62,3 +62,29 @@ func (a *API) getPeginAddress(ctx context.Context, ins struct {
                ClaimScript:      claimScript,
        })
 }
+
+func (a *API) getAddressForPeginContract(ctx context.Context, ins struct {
+       AccountID    string `json:"account_id"`
+       AccountAlias string `json:"account_alias"`
+}) Response {
+
+       accountID := ins.AccountID
+       if ins.AccountAlias != "" {
+               account, err := a.wallet.AccountMgr.FindByAlias(ins.AccountAlias)
+               if err != nil {
+                       return NewErrorResponse(err)
+               }
+
+               accountID = account.ID
+       }
+
+       mainchainAddress, claimScript, err := a.wallet.AccountMgr.CreatePeginContractAddress(accountID, false)
+       if err != nil {
+               return NewErrorResponse(err)
+       }
+
+       return NewSuccessResponse(fundingResp{
+               MainchainAddress: mainchainAddress,
+               ClaimScript:      claimScript,
+       })
+}
index 61c51ae..c3b2052 100644 (file)
@@ -4,6 +4,7 @@ import (
        "context"
        "encoding/json"
        "errors"
+       "fmt"
        "net"
        "net/http"
        _ "net/http/pprof"
@@ -205,27 +206,30 @@ func initActiveNetParams(config *cfg.Config) {
        if !exist {
                cmn.Exit(cmn.Fmt("chain_id[%v] don't exist", config.ChainID))
        }
-       var federationRedeemXPubs []chainkd.XPub
-       if fedpegXPubs := strings.Split(config.Side.FedpegXPubs, ","); len(fedpegXPubs) > 0 {
+       if config.Side.FedpegXPubs != "" {
+               var federationRedeemXPubs []chainkd.XPub
+               fedpegXPubs := strings.Split(config.Side.FedpegXPubs, ",")
                for _, xpubStr := range fedpegXPubs {
                        var xpub chainkd.XPub
                        xpub.UnmarshalText([]byte(xpubStr))
                        federationRedeemXPubs = append(federationRedeemXPubs, xpub)
                }
+               consensus.ActiveNetParams.FedpegXPubs = federationRedeemXPubs
        }
 
-       var signBlockXPubs []chainkd.XPub
-       if xPubs := strings.Split(config.Side.SignBlockXPubs, ","); len(xPubs) > 0 {
+       if config.Side.SignBlockXPubs != "" {
+               var signBlockXPubs []chainkd.XPub
+               fmt.Println(signBlockXPubs)
+               xPubs := strings.Split(config.Side.SignBlockXPubs, ",")
                for _, xpubStr := range xPubs {
                        var xpub chainkd.XPub
                        xpub.UnmarshalText([]byte(xpubStr))
                        signBlockXPubs = append(signBlockXPubs, xpub)
                }
+               consensus.ActiveNetParams.SignBlockXPubs = signBlockXPubs
        }
 
        consensus.ActiveNetParams.Signer = config.Signer
-       consensus.ActiveNetParams.FedpegXPubs = federationRedeemXPubs
-       consensus.ActiveNetParams.SignBlockXPubs = signBlockXPubs
        consensus.ActiveNetParams.PeginMinDepth = config.Side.PeginMinDepth
        consensus.ActiveNetParams.ParentGenesisBlockHash = config.Side.ParentGenesisBlockHash
 }