OSDN Git Service

0221bef2e12c4a97eba749a3deb7c3db6cf3494e
[bytom/vapor.git] / consensus / federation / federation.go
1 package federation
2
3 import (
4         "encoding/json"
5         "errors"
6
7         log "github.com/sirupsen/logrus"
8
9         "github.com/vapor/blockchain/signers"
10         "github.com/vapor/crypto/ed25519"
11         "github.com/vapor/crypto/ed25519/chainkd"
12         "github.com/vapor/protocol/vm/vmutil"
13 )
14
15 const fedCfgJson = `
16 {
17     "xpubs" : [
18         "7f23aae65ee4307c38d342699e328f21834488e18191ebd66823d220b5a58303496c9d09731784372bade78d5e9a4a6249b2cfe2e3a85464e5a4017aa5611e47",
19         "585e20143db413e45fbc82f03cb61f177e9916ef1df0012daa8cbf6dbb1025ce8f98e51ae319327b63505b64fdbbf6d36ef916d79e6dd67d51b0bfe76fe544c5",
20         "b58170b51ca61604028ba1cb412377dfc2bc6567c0afc84c83aae1c0c297d0227ccf568561df70851f4144bbf069b525129f2434133c145e35949375b22a6c9d",
21         "983705ae71949c1a5d0fcf953658dd9ecc549f02c63e197b4d087ae31148097ece816bbc60d9012c316139fc550fa0f4b00beb0887f6b152f7a69bc8f392b9fa",
22         "d72fb92fa13bf3e0deb39de3a47c8d6eef5584719f7877c82a4c009f78fddf924d9706d48f15b2c782ec80b6bdd621a1f7ba2a0044b0e6f92245de9436885cb9",
23         "6798460919e8dc7095ee8b9f9d65033ef3da8c2334813149da5a1e52e9c6da07ba7d0e7379baaa0c8bdcb21890a54e6b7290bee077c645ee4b74b0c1ae9da59a"
24     ],
25     "quorum" : 4
26 }
27 `
28
29 type federation struct {
30         XPubs          []chainkd.XPub `json:"xpubs"`
31         Quorum         int            `json:"quorum"`
32         Path           [][]byte
33         ControlProgram []byte
34 }
35
36 func parseFedConfig() *federation {
37         fed := &federation{}
38         if err := json.Unmarshal([]byte(fedCfgJson), fed); err != nil {
39                 log.Fatalln("invalid federation config json")
40         }
41
42         return fed
43 }
44
45 // CheckFedConfig checks the high-level rule for federation config, whereas
46 // signers.Create checks the low-level rule
47 func CheckFedConfig() error {
48         fed := parseFedConfig()
49         if len(fed.XPubs) <= 1 {
50                 return errors.New("federation should have more than 1 member")
51         }
52         if fed.Quorum < 1 {
53                 return errors.New("federation quorum should be >= 1")
54         }
55
56         return nil
57 }
58
59 func GetFederation() *federation {
60         fed := parseFedConfig()
61         // use 1 for AssetKeyIndex
62         assetSigner, err := signers.Create("asset", fed.XPubs, fed.Quorum, 1, signers.BIP0032)
63         if err != nil {
64                 log.Fatalf("fail to create federation assetSigner: %v", err)
65         }
66
67         fed.Path = signers.GetBip0032Path(assetSigner, signers.AssetKeySpace)
68         derivedXPubs := chainkd.DeriveXPubs(assetSigner.XPubs, fed.Path)
69         derivedPKs := chainkd.XPubKeys(derivedXPubs)
70         if controlProgram, err := buildPegInControlProgram(derivedPKs, assetSigner.Quorum); err == nil {
71                 fed.ControlProgram = controlProgram
72         } else {
73                 log.Fatalf("fail to build peg-in script: %v", err)
74         }
75
76         return fed
77 }
78
79 func buildPegInControlProgram(pubkeys []ed25519.PublicKey, nrequired int) (program []byte, err error) {
80         controlProg, err := vmutil.P2SPMultiSigProgram(pubkeys, nrequired)
81         if err != nil {
82                 return nil, err
83         }
84         builder := vmutil.NewBuilder()
85         builder.AddRawBytes(controlProg)
86         prog, err := builder.Build()
87         return prog, err
88 }