github.com/InjectiveLabs/sdk-go@v1.53.0/chain/ocr/types/types.go (about) 1 package types 2 3 import ( 4 "strings" 5 6 "cosmossdk.io/errors" 7 sdk "github.com/cosmos/cosmos-sdk/types" 8 sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" 9 "github.com/cosmos/gogoproto/proto" 10 "golang.org/x/crypto/sha3" 11 ) 12 13 const FeedIDMaxLength = 20 14 15 var digestPrefixCosmos = []byte("\x00\x02") 16 var digestSeparator = []byte("\x00\x00") 17 18 func (cfg *ContractConfig) Digest(chainID, feedID string) []byte { 19 data, err := proto.Marshal(cfg) 20 if err != nil { 21 panic("unmarshable") 22 } 23 24 w := sha3.NewLegacyKeccak256() 25 if _, err := w.Write(data); err != nil { 26 panic(err) 27 } 28 if _, err := w.Write(digestSeparator); err != nil { 29 panic(err) 30 } 31 if _, err := w.Write([]byte(chainID)); err != nil { 32 panic(err) 33 } 34 if _, err := w.Write(digestSeparator); err != nil { 35 panic(err) 36 } 37 if _, err := w.Write([]byte(feedID)); err != nil { 38 panic(err) 39 } 40 41 configDigest := w.Sum(nil) 42 configDigest[0] = digestPrefixCosmos[0] 43 configDigest[1] = digestPrefixCosmos[1] 44 45 return configDigest 46 } 47 48 func (cfg *FeedConfig) ValidTransmitters() map[string]struct{} { 49 transmitters := make(map[string]struct{}) 50 for _, transmitter := range cfg.Transmitters { 51 transmitters[transmitter] = struct{}{} 52 } 53 return transmitters 54 } 55 56 func (cfg *FeedConfig) TransmitterFromSigner() map[string]sdk.AccAddress { 57 transmitterFromSigner := make(map[string]sdk.AccAddress) 58 for idx, signer := range cfg.Signers { 59 addr, _ := sdk.AccAddressFromBech32(cfg.Transmitters[idx]) 60 transmitterFromSigner[signer] = addr 61 } 62 return transmitterFromSigner 63 } 64 65 func (cfg *FeedConfig) ValidateBasic() error { 66 if err := checkConfigValid( 67 len(cfg.Signers), 68 len(cfg.Transmitters), 69 int(cfg.F), 70 ); err != nil { 71 return err 72 } 73 74 if cfg.ModuleParams == nil { 75 return errors.Wrap(ErrIncorrectConfig, "onchain config is not specified") 76 } 77 78 // TODO: determine whether this is a sensible enough limitation 79 if cfg.ModuleParams.FeedId == "" || len(cfg.ModuleParams.FeedId) > FeedIDMaxLength { 80 return errors.Wrap(ErrIncorrectConfig, "feed_id is missing or incorrect length") 81 } 82 83 if strings.TrimSpace(cfg.ModuleParams.FeedId) != cfg.ModuleParams.FeedId { 84 return errors.Wrap(ErrIncorrectConfig, "feed_id cannot have leading or trailing space characters") 85 } 86 87 if cfg.ModuleParams.FeedAdmin != "" { 88 if _, err := sdk.AccAddressFromBech32(cfg.ModuleParams.FeedAdmin); err != nil { 89 return err 90 } 91 } 92 93 if cfg.ModuleParams.BillingAdmin != "" { 94 if _, err := sdk.AccAddressFromBech32(cfg.ModuleParams.BillingAdmin); err != nil { 95 return err 96 } 97 } 98 99 if cfg.ModuleParams.MinAnswer.IsNil() || cfg.ModuleParams.MaxAnswer.IsNil() { 100 return errors.Wrap(ErrIncorrectConfig, "MinAnswer and MaxAnswer cannot be nil") 101 } 102 103 if cfg.ModuleParams.LinkPerTransmission.IsNil() || !cfg.ModuleParams.LinkPerTransmission.IsPositive() { 104 return errors.Wrap(ErrIncorrectConfig, "LinkPerTransmission must be positive") 105 } 106 107 if cfg.ModuleParams.LinkPerObservation.IsNil() || !cfg.ModuleParams.LinkPerObservation.IsPositive() { 108 return errors.Wrap(ErrIncorrectConfig, "LinkPerObservation must be positive") 109 } 110 111 seenTransmitters := make(map[string]struct{}, len(cfg.Transmitters)) 112 for _, transmitter := range cfg.Transmitters { 113 addr, err := sdk.AccAddressFromBech32(transmitter) 114 if err != nil { 115 return err 116 } 117 118 if _, ok := seenTransmitters[addr.String()]; ok { 119 return ErrRepeatedAddress 120 } else { 121 seenTransmitters[addr.String()] = struct{}{} 122 } 123 } 124 125 seenSigners := make(map[string]struct{}, len(cfg.Signers)) 126 for _, signer := range cfg.Signers { 127 addr, err := sdk.AccAddressFromBech32(signer) 128 if err != nil { 129 return err 130 } 131 132 if _, ok := seenSigners[addr.String()]; ok { 133 return ErrRepeatedAddress 134 } else { 135 seenSigners[addr.String()] = struct{}{} 136 } 137 } 138 139 if cfg.ModuleParams.LinkDenom == "" { 140 return sdkerrors.ErrInvalidCoins 141 } 142 143 return nil 144 } 145 146 func checkConfigValid( 147 numSigners, numTransmitters, f int, 148 ) error { 149 if numSigners > MaxNumOracles { 150 return ErrTooManySigners 151 } 152 153 if f <= 0 { 154 return errors.Wrap(ErrIncorrectConfig, "f must be positive") 155 } 156 157 if numSigners != numTransmitters { 158 return errors.Wrap(ErrIncorrectConfig, "oracle addresses out of registration") 159 } 160 161 if numSigners <= 3*f { 162 return errors.Wrapf(ErrIncorrectConfig, "faulty-oracle f too high: %d", f) 163 } 164 165 return nil 166 } 167 168 func ReportFromBytes(buf []byte) (*ReportToSign, error) { 169 var r ReportToSign 170 if err := proto.Unmarshal(buf, &r); err != nil { 171 err = errors.Wrap(err, "failed to proto-decode ReportToSign from bytes") 172 return nil, err 173 } 174 175 return &r, nil 176 } 177 178 func (r *ReportToSign) Bytes() []byte { 179 data, err := proto.Marshal(r) 180 if err != nil { 181 panic("unmarshable") 182 } 183 184 return data 185 } 186 187 func (r *ReportToSign) Digest() []byte { 188 w := sha3.NewLegacyKeccak256() 189 w.Write(r.Bytes()) 190 return w.Sum(nil) 191 } 192 193 type Reward struct { 194 Addr sdk.AccAddress 195 Amount sdk.Coin 196 }