package account
import (
+ "crypto/hmac"
+ "crypto/sha256"
"encoding/json"
+ "fmt"
"reflect"
"sort"
"strings"
"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"
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
}
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
+}
"context"
"encoding/json"
"errors"
+ "fmt"
"net"
"net/http"
_ "net/http/pprof"
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
}