github.com/FusionFoundation/efsn/v4@v4.2.0/common/fsnparams.go (about) 1 package common 2 3 import ( 4 "fmt" 5 "math/big" 6 7 "github.com/FusionFoundation/efsn/v4/rlp" 8 ) 9 10 /////////////////// param type /////////////////////// 11 // FSNCallParam wacom 12 type FSNCallParam struct { 13 Func FSNCallFunc 14 Data []byte 15 } 16 17 // GenAssetParam wacom 18 type GenAssetParam struct { 19 Name string 20 Symbol string 21 Decimals uint8 22 Total *big.Int `json:",string"` 23 CanChange bool 24 Description string 25 } 26 27 // BuyTicketParam wacom 28 type BuyTicketParam struct { 29 Start uint64 30 End uint64 31 } 32 33 // SendAssetParam wacom 34 type SendAssetParam struct { 35 AssetID Hash 36 To Address 37 Value *big.Int `json:",string"` 38 } 39 40 // AssetValueChangeExParam wacom 41 type AssetValueChangeExParam struct { 42 AssetID Hash 43 To Address 44 Value *big.Int `json:",string"` 45 IsInc bool 46 TransacData string 47 } 48 49 // TimeLockParam wacom 50 type TimeLockParam struct { 51 Type TimeLockType 52 AssetID Hash 53 To Address 54 StartTime uint64 55 EndTime uint64 56 Value *big.Int `json:",string"` 57 } 58 59 // MakeSwapParam wacom 60 type MakeSwapParam struct { 61 FromAssetID Hash 62 FromStartTime uint64 63 FromEndTime uint64 64 MinFromAmount *big.Int `json:",string"` 65 ToAssetID Hash 66 ToStartTime uint64 67 ToEndTime uint64 68 MinToAmount *big.Int `json:",string"` 69 SwapSize *big.Int `json:",string"` 70 Targes []Address 71 Time *big.Int 72 Description string 73 } 74 75 // MakeMultiSwapParam wacom 76 type MakeMultiSwapParam struct { 77 FromAssetID []Hash 78 FromStartTime []uint64 79 FromEndTime []uint64 80 MinFromAmount []*big.Int `json:",string"` 81 ToAssetID []Hash 82 ToStartTime []uint64 83 ToEndTime []uint64 84 MinToAmount []*big.Int `json:",string"` 85 SwapSize *big.Int `json:",string"` 86 Targes []Address 87 Time *big.Int 88 Description string 89 } 90 91 // RecallSwapParam wacom 92 type RecallSwapParam struct { 93 SwapID Hash 94 } 95 96 // RecallMultiSwapParam wacom 97 type RecallMultiSwapParam struct { 98 SwapID Hash 99 } 100 101 // TakeSwapParam wacom 102 type TakeSwapParam struct { 103 SwapID Hash 104 Size *big.Int `json:",string"` 105 } 106 107 // TakeMultiSwapParam wacom 108 type TakeMultiSwapParam struct { 109 SwapID Hash 110 Size *big.Int `json:",string"` 111 } 112 113 /////////////////// param ToBytes /////////////////////// 114 // ToBytes wacom 115 func (p *FSNCallParam) ToBytes() ([]byte, error) { 116 return rlp.EncodeToBytes(p) 117 } 118 119 // ToBytes wacom 120 func (p *GenAssetParam) ToBytes() ([]byte, error) { 121 return rlp.EncodeToBytes(p) 122 } 123 124 // ToBytes wacom 125 func (p *SendAssetParam) ToBytes() ([]byte, error) { 126 return rlp.EncodeToBytes(p) 127 } 128 129 // ToBytes wacom 130 func (p *TimeLockParam) ToBytes() ([]byte, error) { 131 return rlp.EncodeToBytes(p) 132 } 133 134 // ToBytes wacom 135 func (p *BuyTicketParam) ToBytes() ([]byte, error) { 136 return rlp.EncodeToBytes(p) 137 } 138 139 // ToBytes wacom 140 func (p *AssetValueChangeExParam) ToBytes() ([]byte, error) { 141 return rlp.EncodeToBytes(p) 142 } 143 144 // ToBytes wacom 145 func (p *MakeSwapParam) ToBytes() ([]byte, error) { 146 return rlp.EncodeToBytes(p) 147 } 148 149 // ToBytes wacom 150 func (p *RecallSwapParam) ToBytes() ([]byte, error) { 151 return rlp.EncodeToBytes(p) 152 } 153 154 // ToBytes wacom 155 func (p *TakeSwapParam) ToBytes() ([]byte, error) { 156 return rlp.EncodeToBytes(p) 157 } 158 159 // ToBytes wacom 160 func (p *MakeMultiSwapParam) ToBytes() ([]byte, error) { 161 return rlp.EncodeToBytes(p) 162 } 163 164 // ToBytes wacom 165 func (p *RecallMultiSwapParam) ToBytes() ([]byte, error) { 166 return rlp.EncodeToBytes(p) 167 } 168 169 // ToBytes wacom 170 func (p *TakeMultiSwapParam) ToBytes() ([]byte, error) { 171 return rlp.EncodeToBytes(p) 172 } 173 174 type EmptyParam struct{} 175 176 func (p *EmptyParam) ToBytes() ([]byte, error) { 177 return nil, nil 178 } 179 180 func DecodeFsnCallParam(fsnCall *FSNCallParam, funcParam interface{}) (interface{}, error) { 181 if len(fsnCall.Data) != 0 { 182 err := rlp.DecodeBytes(fsnCall.Data, funcParam) 183 if err != nil { 184 return nil, fmt.Errorf("decode FSNCallParam err %v", err) 185 } 186 } 187 decodedParam := &struct { 188 FuncType string 189 FuncParam interface{} 190 }{ 191 FuncType: fsnCall.Func.Name(), 192 FuncParam: funcParam, 193 } 194 return decodedParam, nil 195 } 196 197 func DecodeTxInput(input []byte) (interface{}, error) { 198 var fsnCall FSNCallParam 199 err := rlp.DecodeBytes(input, &fsnCall) 200 if err != nil { 201 return nil, fmt.Errorf("decode to FSNCallParam err %v", err) 202 } 203 204 switch fsnCall.Func { 205 case GenNotationFunc: 206 return DecodeFsnCallParam(&fsnCall, &EmptyParam{}) 207 case GenAssetFunc: 208 return DecodeFsnCallParam(&fsnCall, &GenAssetParam{}) 209 case SendAssetFunc: 210 return DecodeFsnCallParam(&fsnCall, &SendAssetParam{}) 211 case TimeLockFunc: 212 return DecodeFsnCallParam(&fsnCall, &TimeLockParam{}) 213 case BuyTicketFunc: 214 return DecodeFsnCallParam(&fsnCall, &BuyTicketParam{}) 215 case AssetValueChangeFunc: 216 return DecodeFsnCallParam(&fsnCall, &AssetValueChangeExParam{}) 217 case EmptyFunc: 218 case MakeSwapFunc, MakeSwapFuncExt: 219 return DecodeFsnCallParam(&fsnCall, &MakeSwapParam{}) 220 case RecallSwapFunc: 221 return DecodeFsnCallParam(&fsnCall, &RecallSwapParam{}) 222 case TakeSwapFunc, TakeSwapFuncExt: 223 return DecodeFsnCallParam(&fsnCall, &TakeSwapParam{}) 224 case RecallMultiSwapFunc: 225 return DecodeFsnCallParam(&fsnCall, &RecallMultiSwapParam{}) 226 case MakeMultiSwapFunc: 227 return DecodeFsnCallParam(&fsnCall, &MakeMultiSwapParam{}) 228 case TakeMultiSwapFunc: 229 return DecodeFsnCallParam(&fsnCall, &TakeMultiSwapParam{}) 230 case ReportIllegalFunc: 231 return fsnCall, fmt.Errorf("ReportIllegal should processed by datong.DecodeTxInput") 232 } 233 return nil, fmt.Errorf("Unknown FuncType %v", fsnCall.Func) 234 } 235 236 /////////////////// param checking /////////////////////// 237 // Check wacom 238 func (p *FSNCallParam) Check(blockNumber *big.Int) error { 239 return nil 240 } 241 242 // Check wacom 243 func (p *GenAssetParam) Check(blockNumber *big.Int) error { 244 if len(p.Name) == 0 || len(p.Symbol) == 0 || p.Total == nil || p.Total.Cmp(Big0) < 0 { 245 return fmt.Errorf("GenAssetFunc name, symbol and total must be set") 246 } 247 if p.Decimals > 18 { 248 return fmt.Errorf("GenAssetFunc decimals must be between 0 and 18") 249 } 250 if len(p.Description) > 1024 { 251 return fmt.Errorf("GenAsset description length is greater than 1024 chars") 252 } 253 if len(p.Name) > 128 { 254 return fmt.Errorf("GenAsset name length is greater than 128 chars") 255 } 256 if len(p.Symbol) > 64 { 257 return fmt.Errorf("GenAsset symbol length is greater than 64 chars") 258 259 } 260 return nil 261 } 262 263 // Check wacom 264 func (p *SendAssetParam) Check(blockNumber *big.Int) error { 265 if p.Value == nil || p.Value.Cmp(Big0) <= 0 { 266 return fmt.Errorf("Value must be set and greater than 0") 267 } 268 if p.To == (Address{}) { 269 return fmt.Errorf("receiver address must be set and not zero address") 270 } 271 if p.AssetID == (Hash{}) { 272 return fmt.Errorf("empty asset ID, 'asset' must be specified instead of AssetID.") 273 } 274 return nil 275 } 276 277 // Check wacom 278 func (p *TimeLockParam) Check(blockNumber *big.Int, timestamp uint64) error { 279 280 if p.Value == nil || p.Value.Cmp(Big0) <= 0 { 281 return fmt.Errorf("Value must be set and greater than 0") 282 } 283 if p.StartTime > p.EndTime { 284 return fmt.Errorf("StartTime must be less than or equal to EndTime") 285 } 286 if p.EndTime < timestamp { 287 return fmt.Errorf("EndTime must be greater than latest block time") 288 } 289 290 return nil 291 } 292 293 // Check wacom 294 func (p *BuyTicketParam) Check(blockNumber *big.Int, timestamp uint64) error { 295 start, end := p.Start, p.End 296 // check lifetime too short ticket 297 if end <= start || end < start+30*24*3600 { 298 return fmt.Errorf("BuyTicket end must be greater than start + 1 month") 299 } 300 if timestamp != 0 { 301 // check future ticket 302 if start > timestamp+3*3600 { 303 return fmt.Errorf("BuyTicket start must be lower than latest block time + 3 hour") 304 } 305 // check ticket lifetime 306 if IsHardFork(2, blockNumber) { 307 // use 29 days here to check lifetime, to relax auto buy ticket tx checking in txpool 308 if end < timestamp+29*24*3600 { 309 return fmt.Errorf("BuyTicket end must be greater than latest block time + 1 month") 310 } 311 } else { 312 if end < timestamp+7*24*3600 { 313 return fmt.Errorf("BuyTicket end must be greater than latest block time + 1 week") 314 } 315 } 316 } 317 return nil 318 } 319 320 // Check wacom 321 func (p *AssetValueChangeExParam) Check(blockNumber *big.Int) error { 322 if p.Value == nil || p.Value.Cmp(Big0) <= 0 { 323 return fmt.Errorf("Value must be set and greater than 0") 324 } 325 if len(p.TransacData) > 256 { 326 return fmt.Errorf("TransacData must not be greater than 256") 327 } 328 return nil 329 } 330 331 // Check wacom 332 func (p *MakeSwapParam) Check(blockNumber *big.Int, timestamp uint64) error { 333 if p.MinFromAmount == nil || p.MinFromAmount.Cmp(Big0) <= 0 || 334 p.MinToAmount == nil || p.MinToAmount.Cmp(Big0) <= 0 || 335 p.SwapSize == nil || p.SwapSize.Cmp(Big0) <= 0 { 336 return fmt.Errorf("MinFromAmount,MinToAmount and SwapSize must be ge 1") 337 } 338 if len(p.Description) > 1024 { 339 return fmt.Errorf("MakeSwap description length is greater than 1024 chars") 340 } 341 total := new(big.Int).Mul(p.MinFromAmount, p.SwapSize) 342 if total.Cmp(Big0) <= 0 { 343 return fmt.Errorf("size * MinFromAmount too large") 344 } 345 346 toTotal := new(big.Int).Mul(p.MinToAmount, p.SwapSize) 347 if toTotal.Cmp(Big0) <= 0 { 348 return fmt.Errorf("size * MinToAmount too large") 349 } 350 351 if p.FromStartTime > p.FromEndTime { 352 return fmt.Errorf("MakeSwap FromStartTime > FromEndTime") 353 } 354 if p.ToStartTime > p.ToEndTime { 355 return fmt.Errorf("MakeSwap ToStartTime > ToEndTime") 356 } 357 358 if p.FromEndTime <= timestamp { 359 return fmt.Errorf("MakeSwap FromEndTime <= latest blockTime") 360 } 361 if p.ToEndTime <= timestamp { 362 return fmt.Errorf("MakeSwap ToEndTime <= latest blockTime") 363 } 364 365 if p.ToAssetID == OwnerUSANAssetID { 366 return fmt.Errorf("USAN's cannot be swapped") 367 } 368 369 return nil 370 } 371 372 // Check wacom 373 func (p *RecallSwapParam) Check(blockNumber *big.Int, swap *Swap) error { 374 return nil 375 } 376 377 // Check wacom 378 func (p *TakeSwapParam) Check(blockNumber *big.Int, swap *Swap, timestamp uint64) error { 379 if p.Size == nil || p.Size.Cmp(Big0) <= 0 || 380 swap.SwapSize == nil || p.Size.Cmp(swap.SwapSize) > 0 { 381 382 return fmt.Errorf("Size must be ge 1 and le Swapsize") 383 } 384 385 if swap.FromEndTime <= timestamp { 386 return fmt.Errorf("swap expired: FromEndTime <= latest blockTime") 387 } 388 if swap.ToEndTime <= timestamp { 389 return fmt.Errorf("swap expired: ToEndTime <= latest blockTime") 390 } 391 392 return nil 393 } 394 395 // Check wacom 396 func (p *MakeMultiSwapParam) Check(blockNumber *big.Int, timestamp uint64) error { 397 if p.MinFromAmount == nil || len(p.MinFromAmount) == 0 { 398 return fmt.Errorf("MinFromAmount must be specified") 399 } 400 if p.MinToAmount == nil || len(p.MinToAmount) == 0 { 401 return fmt.Errorf("MinToAmount must be specified") 402 } 403 if p.SwapSize == nil || p.SwapSize.Cmp(Big0) <= 0 { 404 return fmt.Errorf("SwapSize must be ge 1") 405 } 406 407 if len(p.MinFromAmount) != len(p.FromEndTime) || 408 len(p.MinFromAmount) != len(p.FromAssetID) || 409 len(p.MinFromAmount) != len(p.FromStartTime) { 410 return fmt.Errorf("MinFromAmount FromEndTime and FromStartTime array length must be same size") 411 } 412 if len(p.MinToAmount) != len(p.ToEndTime) || 413 len(p.MinToAmount) != len(p.ToAssetID) || 414 len(p.MinToAmount) != len(p.ToStartTime) { 415 return fmt.Errorf("MinToAmount ToEndTime and ToStartTime array length must be same size") 416 } 417 418 ln := len(p.MinFromAmount) 419 for i := 0; i < ln; i++ { 420 if p.MinFromAmount[i] == nil || p.MinFromAmount[i].Cmp(Big0) <= 0 { 421 return fmt.Errorf("MinFromAmounts must be ge 1") 422 } 423 total := new(big.Int).Mul(p.MinFromAmount[i], p.SwapSize) 424 if total.Cmp(Big0) <= 0 { 425 return fmt.Errorf("size * MinFromAmount too large") 426 } 427 if p.FromStartTime[i] > p.FromEndTime[i] { 428 return fmt.Errorf("MakeMultiSwap FromStartTime > FromEndTime") 429 } 430 if p.FromEndTime[i] <= timestamp { 431 return fmt.Errorf("MakeMultiSwap FromEndTime <= latest blockTime") 432 } 433 } 434 435 ln = len(p.MinToAmount) 436 for i := 0; i < ln; i++ { 437 if p.MinToAmount[i] == nil || p.MinToAmount[i].Cmp(Big0) <= 0 { 438 return fmt.Errorf("MinToAmounts must be ge 1") 439 } 440 toTotal := new(big.Int).Mul(p.MinToAmount[i], p.SwapSize) 441 if toTotal.Cmp(Big0) <= 0 { 442 return fmt.Errorf("size * MinToAmount too large") 443 } 444 if p.ToStartTime[i] > p.ToEndTime[i] { 445 return fmt.Errorf("MakeMultiSwap ToStartTime > ToEndTime") 446 } 447 if p.ToEndTime[i] <= timestamp { 448 return fmt.Errorf("MakeMultiSwap ToEndTime <= latest blockTime") 449 } 450 } 451 452 if len(p.Description) > 1024 { 453 return fmt.Errorf("MakeSwap description length is greater than 1024 chars") 454 } 455 456 for _, toAssetID := range p.ToAssetID { 457 if toAssetID == OwnerUSANAssetID { 458 return fmt.Errorf("USAN's cannot be multi swapped") 459 } 460 } 461 for _, fromAssetID := range p.FromAssetID { 462 if fromAssetID == OwnerUSANAssetID { 463 return fmt.Errorf("USAN's cannot be multi swapped") 464 } 465 } 466 return nil 467 } 468 469 // Check wacom 470 func (p *RecallMultiSwapParam) Check(blockNumber *big.Int, swap *MultiSwap) error { 471 return nil 472 } 473 474 // Check wacom 475 func (p *TakeMultiSwapParam) Check(blockNumber *big.Int, swap *MultiSwap, timestamp uint64) error { 476 if p.Size == nil || p.Size.Cmp(Big0) <= 0 || 477 swap.SwapSize == nil || p.Size.Cmp(swap.SwapSize) > 0 { 478 479 return fmt.Errorf("Size must be ge 1 and le Swapsize") 480 } 481 482 ln := len(swap.FromEndTime) 483 for i := 0; i < ln; i++ { 484 if swap.FromEndTime[i] <= timestamp { 485 return fmt.Errorf("swap expired: FromEndTime <= latest blockTime") 486 } 487 } 488 489 ln = len(swap.ToEndTime) 490 for i := 0; i < ln; i++ { 491 if swap.ToEndTime[i] <= timestamp { 492 return fmt.Errorf("swap expired: ToEndTime <= latest blockTime") 493 } 494 } 495 return nil 496 }