github.com/iotexproject/iotex-core@v1.14.1-rc1/ioctl/cmd/ins/insregister.go (about) 1 package ins 2 3 import ( 4 "encoding/hex" 5 "fmt" 6 "math/big" 7 "strings" 8 "time" 9 10 "github.com/ethereum/go-ethereum/accounts/abi" 11 "github.com/ethereum/go-ethereum/common" 12 "github.com/iotexproject/iotex-address/address" 13 "github.com/spf13/cobra" 14 "golang.org/x/crypto/sha3" 15 16 "github.com/iotexproject/iotex-core/ioctl/cmd/action" 17 "github.com/iotexproject/iotex-core/ioctl/config" 18 "github.com/iotexproject/iotex-core/ioctl/output" 19 ) 20 21 // Multi-language support 22 var ( 23 _registerUsages = map[config.Language]string{ 24 config.English: "register NAME", 25 config.Chinese: "register 名称", 26 } 27 _registerShorts = map[config.Language]string{ 28 config.English: "Register INS name", 29 config.Chinese: "注册 INS 域名", 30 } 31 _registerControllerUsages = map[config.Language]string{ 32 config.English: "controller contract address", 33 config.Chinese: "控制器合约地址", 34 } 35 _registerResolverUsages = map[config.Language]string{ 36 config.English: "resolver contract address", 37 config.Chinese: "解析器合约地址", 38 } 39 _registerOwnerUsages = map[config.Language]string{ 40 config.English: "name owner address", 41 config.Chinese: "域名 Owner 地址", 42 } 43 ) 44 45 var ( 46 duration = big.NewInt(365 * 24 * 60 * 60) 47 secret = [32]byte{} 48 controller string 49 resolver string 50 owner string 51 52 setAddrABI = `[ 53 { 54 "inputs": [ 55 { 56 "internalType": "bytes32", 57 "name": "node", 58 "type": "bytes32" 59 }, 60 { 61 "internalType": "address", 62 "name": "a", 63 "type": "address" 64 } 65 ], 66 "name": "setAddr", 67 "outputs": [], 68 "stateMutability": "nonpayable", 69 "type": "function" 70 } 71 ]` 72 controllerABI = `[ 73 { 74 "inputs": [ 75 { 76 "internalType": "bytes32", 77 "name": "commitment", 78 "type": "bytes32" 79 } 80 ], 81 "name": "commit", 82 "outputs": [], 83 "stateMutability": "nonpayable", 84 "type": "function" 85 }, 86 { 87 "inputs": [ 88 { 89 "internalType": "string", 90 "name": "name", 91 "type": "string" 92 }, 93 { 94 "internalType": "uint256", 95 "name": "duration", 96 "type": "uint256" 97 } 98 ], 99 "name": "rentPrice", 100 "outputs": [ 101 { 102 "components": [ 103 { 104 "internalType": "uint256", 105 "name": "base", 106 "type": "uint256" 107 }, 108 { 109 "internalType": "uint256", 110 "name": "premium", 111 "type": "uint256" 112 } 113 ], 114 "internalType": "struct IPriceOracle.Price", 115 "name": "price", 116 "type": "tuple" 117 } 118 ], 119 "stateMutability": "view", 120 "type": "function" 121 }, 122 { 123 "inputs": [ 124 { 125 "internalType": "string", 126 "name": "name", 127 "type": "string" 128 }, 129 { 130 "internalType": "address", 131 "name": "owner", 132 "type": "address" 133 }, 134 { 135 "internalType": "uint256", 136 "name": "duration", 137 "type": "uint256" 138 }, 139 { 140 "internalType": "bytes32", 141 "name": "secret", 142 "type": "bytes32" 143 }, 144 { 145 "internalType": "address", 146 "name": "resolver", 147 "type": "address" 148 }, 149 { 150 "internalType": "bytes[]", 151 "name": "data", 152 "type": "bytes[]" 153 }, 154 { 155 "internalType": "bool", 156 "name": "reverseRecord", 157 "type": "bool" 158 }, 159 { 160 "internalType": "uint16", 161 "name": "ownerControlledFuses", 162 "type": "uint16" 163 } 164 ], 165 "name": "register", 166 "outputs": [], 167 "stateMutability": "payable", 168 "type": "function" 169 } 170 ]` 171 ) 172 173 // _insRegisterCmd represents the action hash command 174 var _insRegisterCmd = &cobra.Command{ 175 Use: config.TranslateInLang(_registerUsages, config.UILanguage), 176 Short: config.TranslateInLang(_registerShorts, config.UILanguage), 177 Args: cobra.MinimumNArgs(1), 178 RunE: func(cmd *cobra.Command, args []string) error { 179 err := register(args) 180 return output.PrintError(err) 181 }, 182 } 183 184 func init() { 185 _insRegisterCmd.Flags().StringVarP( 186 &controller, "controller", "c", 187 "0x8aA6acF9BFeEE0243578305706766065180E68d4", 188 config.TranslateInLang(_registerControllerUsages, config.UILanguage), 189 ) 190 _insRegisterCmd.Flags().StringVarP( 191 &resolver, "resolver", "r", 192 "0x41B9132D4661E016A09a61B314a1DFc0038CE3e8", 193 config.TranslateInLang(_registerResolverUsages, config.UILanguage), 194 ) 195 _insRegisterCmd.Flags().StringVarP( 196 &owner, "owner", "w", 197 "", 198 config.TranslateInLang(_registerOwnerUsages, config.UILanguage), 199 ) 200 201 // init secret 202 sha := sha3.NewLegacyKeccak256() 203 sha.Write([]byte("secret")) 204 hash := sha.Sum(nil) 205 copy(secret[:], hash) 206 } 207 208 func makeCommitment( 209 name string, 210 owner common.Address, 211 duration *big.Int, 212 secret [32]byte, 213 data [][]byte, 214 reverseRecord bool, 215 ownerControlledFuses uint16, 216 ) ([32]byte, error) { 217 resolver := common.HexToAddress(resolver) 218 sha := sha3.NewLegacyKeccak256() 219 sha.Write([]byte(name)) 220 lable := [32]byte{} 221 copy(lable[:], sha.Sum(nil)) 222 223 Bytes32, _ := abi.NewType("bytes32", "", nil) 224 Address, _ := abi.NewType("address", "", nil) 225 Uint256, _ := abi.NewType("uint256", "", nil) 226 BytesArray, _ := abi.NewType("bytes[]", "", nil) 227 Bool, _ := abi.NewType("bool", "", nil) 228 Uint16, _ := abi.NewType("uint16", "", nil) 229 args := abi.Arguments{ 230 {Type: Bytes32, Name: "name"}, 231 {Type: Address, Name: "owner"}, 232 {Type: Uint256, Name: "duration"}, 233 {Type: Bytes32, Name: "secret"}, 234 {Type: Address, Name: "resolver"}, 235 {Type: BytesArray, Name: "data"}, 236 {Type: Bool, Name: "reverseRecord"}, 237 {Type: Uint16, Name: "ownerControlledFuses"}, 238 } 239 240 packed, err := args.Pack(lable, owner, duration, secret, resolver, data, reverseRecord, ownerControlledFuses) 241 if err != nil { 242 return [32]byte{}, err 243 } 244 245 hash := sha3.NewLegacyKeccak256() 246 hash.Write(packed) 247 result := [32]byte{} 248 copy(result[:], hash.Sum(nil)) 249 250 return result, nil 251 } 252 253 func commit(name string, data []byte, ioController address.Address, controllerAbi abi.ABI) error { 254 commitment, err := makeCommitment( 255 name, 256 common.HexToAddress(owner), 257 duration, 258 secret, 259 [][]byte{data}, 260 true, 261 0, 262 ) 263 if err != nil { 264 return err 265 } 266 fmt.Printf("commit commitment for %s: %s ...\n", name, hex.EncodeToString(commitment[:])) 267 268 commitData, err := controllerAbi.Pack("commit", commitment) 269 if err != nil { 270 return output.NewError(output.ConvertError, "failed to pack commit arguments", err) 271 } 272 err = action.Execute(ioController.String(), big.NewInt(0), commitData) 273 if err != nil { 274 return output.NewError(output.UpdateError, "failed to commit commitment", err) 275 } 276 return nil 277 } 278 279 func register(args []string) error { 280 name := args[0] 281 282 if owner == "" { 283 signer, err := action.Signer() 284 if err != nil { 285 return output.NewError(output.AddressError, "failed to get signer address", err) 286 } 287 signerAddr, err := address.FromString(signer) 288 if err != nil { 289 return output.NewError(output.AddressError, "failed to convert signer address", err) 290 } 291 owner = signerAddr.Hex() 292 } 293 294 hash, err := nameHash(name) 295 if err != nil { 296 return output.NewError(output.SerializationError, "failed to compute namehash", err) 297 } 298 299 setAddrAbi, err := abi.JSON(strings.NewReader(setAddrABI)) 300 if err != nil { 301 return output.NewError(output.SerializationError, "failed to unmarshal abi", err) 302 } 303 setAddrData, err := setAddrAbi.Pack("setAddr", hash, common.HexToAddress(owner)) 304 if err != nil { 305 return output.NewError(output.ConvertError, "failed to pack setAddr arguments", err) 306 } 307 308 ioController, err := address.FromHex(controller) 309 if err != nil { 310 return output.NewError(output.AddressError, "failed to convert controller address", err) 311 } 312 controllerAbi, err := abi.JSON(strings.NewReader(controllerABI)) 313 if err != nil { 314 return output.NewError(output.SerializationError, "failed to unmarshal abi", err) 315 } 316 317 if err = commit(name, setAddrData, ioController, controllerAbi); err != nil { 318 return err 319 } 320 321 fmt.Printf("sleep for activation commitment ...\n") 322 time.Sleep(60 * time.Second) 323 324 priceData, err := controllerAbi.Pack("rentPrice", name, duration) 325 if err != nil { 326 return output.NewError(output.ConvertError, "failed to pack price arguments", err) 327 } 328 priceHex, err := action.Read(ioController, "0", priceData) 329 if err != nil { 330 return output.NewError(output.APIError, "failed to read contract", err) 331 } 332 basePrice, _ := hex.DecodeString(priceHex[:64]) 333 premiumPrice, _ := hex.DecodeString(priceHex[64:]) 334 price := new(big.Int).Add(new(big.Int).SetBytes(basePrice), new(big.Int).SetBytes(premiumPrice)) 335 336 registerData, err := controllerAbi.Pack( 337 "register", 338 name, 339 common.HexToAddress(owner), 340 duration, 341 secret, 342 common.HexToAddress(resolver), 343 [][]byte{setAddrData}, 344 true, 345 uint16(0), 346 ) 347 if err != nil { 348 return output.NewError(output.ConvertError, "failed to pack register arguments", err) 349 } 350 351 return action.Execute(ioController.String(), price, registerData) 352 }