10 log "github.com/sirupsen/logrus"
11 "github.com/vapor/consensus"
12 "github.com/vapor/crypto/ed25519"
13 "github.com/vapor/crypto/ed25519/chainkd"
14 chainjson "github.com/vapor/encoding/json"
15 "github.com/vapor/equity/compiler"
18 const module = "pegin_contract"
20 var lockWith2of3KeysFmt = `
21 contract LockWith2of3Keys(%s) locks amount of asset {
22 clause unlockWith2Sigs(%s) {
23 verify checkTxMultiSig(%s)
24 unlock amount of asset
29 func GetPeginContractPrograms(claimScript []byte) ([]byte, error) {
31 pubkeys := getNewXpub(consensus.ActiveNetParams.FedpegXPubs, claimScript)
34 return nil, errors.New("Fedpeg's XPubs is empty")
40 for index := 0; index < num; index++ {
41 param := fmt.Sprintf("pubkey%d", index+1)
44 if (index + 1) < num {
49 params += ": PublicKey"
52 signNum := getNumberOfSignaturesRequired(pubkeys)
53 for index := 0; index < signNum; index++ {
54 param := fmt.Sprintf("sig%d", index+1)
57 if index+1 < signNum {
63 unlockParams += ": Signature"
66 lockWith2of3Keys := fmt.Sprintf(lockWith2of3KeysFmt, params, unlockParams, checkParams)
67 r := strings.NewReader(lockWith2of3Keys)
68 compiled, err := compiler.Compile(r)
70 return nil, errors.New("Compile contract failed")
73 contract := compiled[len(compiled)-1]
75 if num < len(contract.Params) {
76 return nil, errors.New("Compile contract failed")
79 contractArgs, err := convertArguments(contract, pubkeys)
81 log.WithFields(log.Fields{"module": module, "error": err}).Error("Convert arguments into contract parameters error")
82 return nil, errors.New("Convert arguments into contract parameters error")
85 instantProg, err := instantiateContract(contract, contractArgs)
87 log.WithFields(log.Fields{"module": module, "error": err}).Error("Instantiate contract error")
88 return nil, errors.New("Instantiate contract error")
91 return instantProg, nil
94 func getNewXpub(federationRedeemXPub []chainkd.XPub, claimScript []byte) []ed25519.PublicKey {
96 var pubkeys []ed25519.PublicKey
97 for _, xpub := range federationRedeemXPub {
98 // pub + scriptPubKey 生成一个随机数A
100 h := hmac.New(sha256.New, xpub[:])
102 tweak := h.Sum(tmp[:])
103 // pub + A 生成一个新的公钥pub_new
104 chaildXPub := xpub.Child(tweak)
105 pubkeys = append(pubkeys, chaildXPub.PublicKey())
110 func getNumberOfSignaturesRequired(pubkeys []ed25519.PublicKey) int {
111 return len(pubkeys)/2 + 1
114 // InstantiateContract instantiate contract parameters
115 func instantiateContract(contract *compiler.Contract, args []compiler.ContractArg) ([]byte, error) {
116 program, err := compiler.Instantiate(contract.Body, contract.Params, contract.Recursive, args)
124 func convertArguments(contract *compiler.Contract, args []ed25519.PublicKey) ([]compiler.ContractArg, error) {
125 var contractArgs []compiler.ContractArg
126 for i, p := range contract.Params {
127 var argument compiler.ContractArg
130 argument.S = (*chainjson.HexBytes)(&args[i])
132 return nil, errors.New("Contract parameter type error")
134 contractArgs = append(contractArgs, argument)
137 return contractArgs, nil