github.com/igggame/nebulas-go@v2.1.0+incompatible/core/access.go (about) 1 // Copyright (C) 2018 go-nebulas authors 2 // 3 // This file is part of the go-nebulas library. 4 // 5 // the go-nebulas library is free software: you can redistribute it and/or modify 6 // it under the terms of the GNU General Public License as published by 7 // the Free Software Foundation, either version 3 of the License, or 8 // (at your option) any later version. 9 // 10 // the go-nebulas library is distributed in the hope that it will be useful, 11 // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 // GNU General Public License for more details. 14 // 15 // You should have received a copy of the GNU General Public License 16 // along with the go-nebulas library. If not, see <http://www.gnu.org/licenses/>. 17 // 18 19 package core 20 21 import ( 22 "encoding/json" 23 "errors" 24 "fmt" 25 "io/ioutil" 26 "path/filepath" 27 "regexp" 28 "strings" 29 30 "github.com/gogo/protobuf/proto" 31 "github.com/nebulasio/go-nebulas/core/pb" 32 ) 33 34 const ( 35 NRC20FuncTransfer = "transfer" 36 NRC20FuncTransferFrom = "transferFrom" 37 NRC20FuncApprove = "approve" 38 ) 39 40 type Access struct { 41 access *corepb.Access 42 } 43 44 // NewAccess returns the Access 45 func NewAccess(path string) (*Access, error) { 46 if path != "" { 47 path, err := filepath.Abs(path) 48 if err != nil { 49 return nil, err 50 } 51 bytes, err := ioutil.ReadFile(path) 52 if err != nil { 53 return nil, err 54 } 55 content := string(bytes) 56 57 access := new(corepb.Access) 58 if err = proto.UnmarshalText(content, access); err != nil { 59 return nil, err 60 } 61 return &Access{access: access}, nil 62 } 63 return &Access{}, nil 64 } 65 66 // CheckTransaction Check that the transaction meets the conditions 67 func (a *Access) CheckTransaction(tx *Transaction) error { 68 if a.access == nil { 69 // no access config need to check 70 return nil 71 } 72 if a.access.Blacklist != nil { 73 for _, addr := range a.access.Blacklist.From { 74 if addr == tx.from.String() { 75 return ErrRestrictedFromAddress 76 } 77 } 78 for _, addr := range a.access.Blacklist.To { 79 if addr == tx.to.String() { 80 return ErrRestrictedToAddress 81 } 82 } 83 84 if tx.Type() == TxPayloadDeployType || tx.Type() == TxPayloadCallType { 85 for _, contract := range a.access.Blacklist.Contracts { 86 match := false 87 if contract.Address != "" { 88 match = contract.Address == tx.to.String() 89 } 90 if tx.Type() == TxPayloadCallType && len(contract.Functions) > 0 { 91 payload, err := tx.LoadPayload() 92 callPayload := payload.(*CallPayload) 93 if err != nil { 94 return err 95 } 96 funcMatch := false 97 for _, function := range contract.Functions { 98 if function == callPayload.Function { 99 funcMatch = true 100 break 101 } 102 } 103 match = match && funcMatch 104 } 105 if match { 106 return ErrUnsupportedFunction 107 } 108 if tx.Type() == TxPayloadDeployType && len(contract.Keywords) > 0 { 109 data := strings.ToLower(string(tx.Data())) 110 for _, keyword := range contract.Keywords { 111 keyword = strings.ToLower(keyword) 112 if strings.Contains(data, keyword) { 113 unsupportedKeywordError := fmt.Sprintf("transaction data has unsupported keyword(keyword: %s)", keyword) 114 return errors.New(unsupportedKeywordError) 115 } 116 } 117 } 118 } 119 } 120 } 121 122 if a.access.Nrc20List != nil { 123 // check nrc20 security 124 if err := a.nrc20SecurityCheck(tx); err != nil { 125 return err 126 } 127 } 128 return nil 129 } 130 131 // nrc20SecurityCheck check nrc20 contract params security 132 func (a *Access) nrc20SecurityCheck(tx *Transaction) error { 133 if tx.Type() == TxPayloadCallType && len(a.access.Nrc20List.Contracts) > 0 { 134 for _, contract := range a.access.Nrc20List.Contracts { 135 // check nrc20 security 136 if tx.To().String() == contract { 137 payload, err := tx.LoadPayload() 138 if err != nil { 139 return err 140 } 141 call := payload.(*CallPayload) 142 valueIndex := 0 143 switch call.Function { 144 case NRC20FuncTransfer: 145 valueIndex = 1 146 case NRC20FuncTransferFrom: 147 valueIndex = 2 148 case NRC20FuncApprove: 149 valueIndex = 2 150 default: 151 valueIndex = -1 152 } 153 if valueIndex > 0 { 154 var argsObj []string 155 if err := json.Unmarshal([]byte(call.Args), &argsObj); err != nil { 156 return ErrNrc20ArgsCheckFailed 157 } 158 addr := argsObj[0] 159 if _, err := AddressParse(addr); err != nil { 160 return ErrNrc20AddressCheckFailed 161 } 162 value := argsObj[valueIndex] 163 if matched, err := regexp.MatchString("^[0-9]+$", value); matched == false || err != nil { 164 return ErrNrc20ValueCheckFailed 165 } 166 } 167 } 168 } 169 } 170 return nil 171 }