gitlab.com/SiaPrime/SiaPrime@v1.4.1/types/encoding.go (about) 1 package types 2 3 import ( 4 "bytes" 5 "encoding/hex" 6 "encoding/json" 7 "fmt" 8 "io" 9 "math/big" 10 "strings" 11 "unsafe" 12 13 "gitlab.com/SiaPrime/SiaPrime/crypto" 14 "gitlab.com/SiaPrime/SiaPrime/encoding" 15 ) 16 17 // sanityCheckWriter checks that the bytes written to w exactly match the 18 // bytes in buf. 19 type sanityCheckWriter struct { 20 w io.Writer 21 buf *bytes.Buffer 22 } 23 24 func (s sanityCheckWriter) Write(p []byte) (int, error) { 25 if !bytes.Equal(p, s.buf.Next(len(p))) { 26 panic("encoding mismatch") 27 } 28 return s.w.Write(p) 29 } 30 31 // MarshalSia implements the encoding.SiaMarshaler interface. 32 func (b Block) MarshalSia(w io.Writer) error { 33 e := encoding.NewEncoder(w) 34 e.Write(b.ParentID[:]) 35 e.Write(b.Nonce[:]) 36 e.WriteUint64(uint64(b.Timestamp)) 37 e.WriteInt(len(b.MinerPayouts)) 38 for i := range b.MinerPayouts { 39 b.MinerPayouts[i].MarshalSia(e) 40 } 41 e.WriteInt(len(b.Transactions)) 42 for i := range b.Transactions { 43 if err := b.Transactions[i].MarshalSia(e); err != nil { 44 return err 45 } 46 } 47 return e.Err() 48 } 49 50 // UnmarshalSia implements the encoding.SiaUnmarshaler interface. 51 func (b *Block) UnmarshalSia(r io.Reader) error { 52 d := encoding.NewDecoder(r, int(BlockSizeLimit*3)) 53 d.ReadFull(b.ParentID[:]) 54 d.ReadFull(b.Nonce[:]) 55 b.Timestamp = Timestamp(d.NextUint64()) 56 // MinerPayouts 57 b.MinerPayouts = make([]SiacoinOutput, d.NextPrefix(unsafe.Sizeof(SiacoinOutput{}))) 58 for i := range b.MinerPayouts { 59 b.MinerPayouts[i].UnmarshalSia(d) 60 } 61 // Transactions 62 b.Transactions = make([]Transaction, d.NextPrefix(unsafe.Sizeof(Transaction{}))) 63 for i := range b.Transactions { 64 b.Transactions[i].UnmarshalSia(d) 65 } 66 return d.Err() 67 } 68 69 // MarshalJSON marshales a block id as a hex string. 70 func (bid BlockID) MarshalJSON() ([]byte, error) { 71 return json.Marshal(bid.String()) 72 } 73 74 // String prints the block id in hex. 75 func (bid BlockID) String() string { 76 return fmt.Sprintf("%x", bid[:]) 77 } 78 79 // LoadString loads a BlockID from a string 80 func (bid *BlockID) LoadString(str string) error { 81 return (*crypto.Hash)(bid).LoadString(str) 82 } 83 84 // UnmarshalJSON decodes the json hex string of the block id. 85 func (bid *BlockID) UnmarshalJSON(b []byte) error { 86 return (*crypto.Hash)(bid).UnmarshalJSON(b) 87 } 88 89 // MarshalSia implements the encoding.SiaMarshaler interface. 90 func (cf CoveredFields) MarshalSia(w io.Writer) error { 91 e := encoding.NewEncoder(w) 92 e.WriteBool(cf.WholeTransaction) 93 fields := [][]uint64{ 94 cf.SiacoinInputs, 95 cf.SiacoinOutputs, 96 cf.FileContracts, 97 cf.FileContractRevisions, 98 cf.StorageProofs, 99 cf.SiafundInputs, 100 cf.SiafundOutputs, 101 cf.MinerFees, 102 cf.ArbitraryData, 103 cf.TransactionSignatures, 104 } 105 for _, f := range fields { 106 e.WriteInt(len(f)) 107 for _, u := range f { 108 e.WriteUint64(u) 109 } 110 } 111 return e.Err() 112 } 113 114 // MarshalSiaSize returns the encoded size of cf. 115 func (cf CoveredFields) MarshalSiaSize() (size int) { 116 size++ // WholeTransaction 117 size += 8 + len(cf.SiacoinInputs)*8 118 size += 8 + len(cf.SiacoinOutputs)*8 119 size += 8 + len(cf.FileContracts)*8 120 size += 8 + len(cf.FileContractRevisions)*8 121 size += 8 + len(cf.StorageProofs)*8 122 size += 8 + len(cf.SiafundInputs)*8 123 size += 8 + len(cf.SiafundOutputs)*8 124 size += 8 + len(cf.MinerFees)*8 125 size += 8 + len(cf.ArbitraryData)*8 126 size += 8 + len(cf.TransactionSignatures)*8 127 return 128 } 129 130 // UnmarshalSia implements the encoding.SiaUnmarshaler interface. 131 func (cf *CoveredFields) UnmarshalSia(r io.Reader) error { 132 d := encoding.NewDecoder(r, encoding.DefaultAllocLimit) 133 buf := make([]byte, 1) 134 d.ReadFull(buf) 135 cf.WholeTransaction = (buf[0] == 1) 136 fields := []*[]uint64{ 137 &cf.SiacoinInputs, 138 &cf.SiacoinOutputs, 139 &cf.FileContracts, 140 &cf.FileContractRevisions, 141 &cf.StorageProofs, 142 &cf.SiafundInputs, 143 &cf.SiafundOutputs, 144 &cf.MinerFees, 145 &cf.ArbitraryData, 146 &cf.TransactionSignatures, 147 } 148 for i := range fields { 149 f := make([]uint64, d.NextPrefix(unsafe.Sizeof(uint64(0)))) 150 for i := range f { 151 f[i] = d.NextUint64() 152 } 153 *fields[i] = f 154 } 155 return d.Err() 156 } 157 158 // MarshalJSON implements the json.Marshaler interface. 159 func (c Currency) MarshalJSON() ([]byte, error) { 160 // Must enclosed the value in quotes; otherwise JS will convert it to a 161 // double and lose precision. 162 return []byte(`"` + c.String() + `"`), nil 163 } 164 165 // UnmarshalJSON implements the json.Unmarshaler interface. An error is 166 // returned if a negative number is provided. 167 func (c *Currency) UnmarshalJSON(b []byte) error { 168 // UnmarshalJSON does not expect quotes 169 b = bytes.Trim(b, `"`) 170 err := c.i.UnmarshalJSON(b) 171 if err != nil { 172 return err 173 } 174 if c.i.Sign() < 0 { 175 c.i = *big.NewInt(0) 176 return ErrNegativeCurrency 177 } 178 return nil 179 } 180 181 // MarshalSia implements the encoding.SiaMarshaler interface. It writes the 182 // byte-slice representation of the Currency's internal big.Int to w. Note 183 // that as the bytes of the big.Int correspond to the absolute value of the 184 // integer, there is no way to marshal a negative Currency. 185 func (c Currency) MarshalSia(w io.Writer) error { 186 // from math/big/arith.go 187 const ( 188 _m = ^big.Word(0) 189 _logS = _m>>8&1 + _m>>16&1 + _m>>32&1 190 _S = 1 << _logS // number of bytes per big.Word 191 ) 192 193 // get raw bits and seek to first zero byte 194 bits := c.i.Bits() 195 var i int 196 for i = len(bits)*_S - 1; i >= 0; i-- { 197 if bits[i/_S]>>(uint(i%_S)*8) != 0 { 198 break 199 } 200 } 201 202 // write length prefix 203 e := encoding.NewEncoder(w) 204 e.WriteInt(i + 1) 205 206 // write bytes 207 for ; i >= 0; i-- { 208 e.WriteByte(byte(bits[i/_S] >> (uint(i%_S) * 8))) 209 } 210 return e.Err() 211 } 212 213 // MarshalSiaSize returns the encoded size of c. 214 func (c Currency) MarshalSiaSize() int { 215 // from math/big/arith.go 216 const ( 217 _m = ^big.Word(0) 218 _logS = _m>>8&1 + _m>>16&1 + _m>>32&1 219 _S = 1 << _logS // number of bytes per big.Word 220 ) 221 222 // start with the number of Words * number of bytes per Word, then 223 // subtract trailing bytes that are 0 224 bits := c.i.Bits() 225 size := len(bits) * _S 226 zeros: 227 for i := len(bits) - 1; i >= 0; i-- { 228 for j := _S - 1; j >= 0; j-- { 229 if (bits[i] >> uintptr(j*8)) != 0 { 230 break zeros 231 } 232 size-- 233 } 234 } 235 return 8 + size // account for length prefix 236 } 237 238 // UnmarshalSia implements the encoding.SiaUnmarshaler interface. 239 func (c *Currency) UnmarshalSia(r io.Reader) error { 240 d := encoding.NewDecoder(r, encoding.DefaultAllocLimit) 241 var dec Currency 242 dec.i.SetBytes(d.ReadPrefixedBytes()) 243 *c = dec 244 return d.Err() 245 } 246 247 // HumanString prints the Currency using human readable units. The unit used 248 // will be the largest unit that results in a value greater than 1. The value is 249 // rounded to 4 significant digits. 250 func (c Currency) HumanString() string { 251 pico := SiacoinPrecision.Div64(1e12) 252 if c.Cmp(pico) < 0 { 253 return c.String() + " H" 254 } 255 256 // iterate until we find a unit greater than c 257 mag := pico 258 unit := "" 259 for _, unit = range []string{"pS", "nS", "uS", "mS", "SC", "KS", "MS", "GS", "TS"} { 260 if c.Cmp(mag.Mul64(1e3)) < 0 { 261 break 262 } else if unit != "TS" { 263 // don't want to perform this multiply on the last iter; that 264 // would give us 1.235 TS instead of 1235 TS 265 mag = mag.Mul64(1e3) 266 } 267 } 268 269 num := new(big.Rat).SetInt(c.Big()) 270 denom := new(big.Rat).SetInt(mag.Big()) 271 res, _ := new(big.Rat).Mul(num, denom.Inv(denom)).Float64() 272 273 return fmt.Sprintf("%.4g %s", res, unit) 274 } 275 276 // String implements the fmt.Stringer interface. 277 func (c Currency) String() string { 278 return c.i.String() 279 } 280 281 // Scan implements the fmt.Scanner interface, allowing Currency values to be 282 // scanned from text. 283 func (c *Currency) Scan(s fmt.ScanState, ch rune) error { 284 var dec Currency 285 err := dec.i.Scan(s, ch) 286 if err != nil { 287 return err 288 } 289 if dec.i.Sign() < 0 { 290 return ErrNegativeCurrency 291 } 292 *c = dec 293 return nil 294 } 295 296 // MarshalSia implements the encoding.SiaMarshaler interface. 297 func (fc FileContract) MarshalSia(w io.Writer) error { 298 e := encoding.NewEncoder(w) 299 e.WriteUint64(fc.FileSize) 300 e.Write(fc.FileMerkleRoot[:]) 301 e.WriteUint64(uint64(fc.WindowStart)) 302 e.WriteUint64(uint64(fc.WindowEnd)) 303 fc.Payout.MarshalSia(e) 304 e.WriteInt(len(fc.ValidProofOutputs)) 305 for _, sco := range fc.ValidProofOutputs { 306 sco.MarshalSia(e) 307 } 308 e.WriteInt(len(fc.MissedProofOutputs)) 309 for _, sco := range fc.MissedProofOutputs { 310 sco.MarshalSia(e) 311 } 312 e.Write(fc.UnlockHash[:]) 313 e.WriteUint64(fc.RevisionNumber) 314 return e.Err() 315 } 316 317 // MarshalSiaSize returns the encoded size of fc. 318 func (fc FileContract) MarshalSiaSize() (size int) { 319 size += 8 // FileSize 320 size += len(fc.FileMerkleRoot) 321 size += 8 + 8 // WindowStart + WindowEnd 322 size += fc.Payout.MarshalSiaSize() 323 size += 8 324 for _, sco := range fc.ValidProofOutputs { 325 size += sco.Value.MarshalSiaSize() 326 size += len(sco.UnlockHash) 327 } 328 size += 8 329 for _, sco := range fc.MissedProofOutputs { 330 size += sco.Value.MarshalSiaSize() 331 size += len(sco.UnlockHash) 332 } 333 size += len(fc.UnlockHash) 334 size += 8 // RevisionNumber 335 return 336 } 337 338 // UnmarshalSia implements the encoding.SiaUnmarshaler interface. 339 func (fc *FileContract) UnmarshalSia(r io.Reader) error { 340 d := encoding.NewDecoder(r, encoding.DefaultAllocLimit) 341 fc.FileSize = d.NextUint64() 342 d.ReadFull(fc.FileMerkleRoot[:]) 343 fc.WindowStart = BlockHeight(d.NextUint64()) 344 fc.WindowEnd = BlockHeight(d.NextUint64()) 345 fc.Payout.UnmarshalSia(d) 346 fc.ValidProofOutputs = make([]SiacoinOutput, d.NextPrefix(unsafe.Sizeof(SiacoinOutput{}))) 347 for i := range fc.ValidProofOutputs { 348 fc.ValidProofOutputs[i].UnmarshalSia(d) 349 } 350 fc.MissedProofOutputs = make([]SiacoinOutput, d.NextPrefix(unsafe.Sizeof(SiacoinOutput{}))) 351 for i := range fc.MissedProofOutputs { 352 fc.MissedProofOutputs[i].UnmarshalSia(d) 353 } 354 d.ReadFull(fc.UnlockHash[:]) 355 fc.RevisionNumber = d.NextUint64() 356 return d.Err() 357 } 358 359 // MarshalSia implements the encoding.SiaMarshaler interface. 360 func (fcr FileContractRevision) MarshalSia(w io.Writer) error { 361 e := encoding.NewEncoder(w) 362 e.Write(fcr.ParentID[:]) 363 fcr.UnlockConditions.MarshalSia(e) 364 e.WriteUint64(fcr.NewRevisionNumber) 365 e.WriteUint64(fcr.NewFileSize) 366 e.Write(fcr.NewFileMerkleRoot[:]) 367 e.WriteUint64(uint64(fcr.NewWindowStart)) 368 e.WriteUint64(uint64(fcr.NewWindowEnd)) 369 e.WriteInt(len(fcr.NewValidProofOutputs)) 370 for _, sco := range fcr.NewValidProofOutputs { 371 sco.MarshalSia(e) 372 } 373 e.WriteInt(len(fcr.NewMissedProofOutputs)) 374 for _, sco := range fcr.NewMissedProofOutputs { 375 sco.MarshalSia(e) 376 } 377 e.Write(fcr.NewUnlockHash[:]) 378 return e.Err() 379 } 380 381 // MarshalSiaSize returns the encoded size of fcr. 382 func (fcr FileContractRevision) MarshalSiaSize() (size int) { 383 size += len(fcr.ParentID) 384 size += fcr.UnlockConditions.MarshalSiaSize() 385 size += 8 // NewRevisionNumber 386 size += 8 // NewFileSize 387 size += len(fcr.NewFileMerkleRoot) 388 size += 8 + 8 // NewWindowStart + NewWindowEnd 389 size += 8 390 for _, sco := range fcr.NewValidProofOutputs { 391 size += sco.Value.MarshalSiaSize() 392 size += len(sco.UnlockHash) 393 } 394 size += 8 395 for _, sco := range fcr.NewMissedProofOutputs { 396 size += sco.Value.MarshalSiaSize() 397 size += len(sco.UnlockHash) 398 } 399 size += len(fcr.NewUnlockHash) 400 return 401 } 402 403 // UnmarshalSia implements the encoding.SiaUnmarshaler interface. 404 func (fcr *FileContractRevision) UnmarshalSia(r io.Reader) error { 405 d := encoding.NewDecoder(r, encoding.DefaultAllocLimit) 406 d.ReadFull(fcr.ParentID[:]) 407 fcr.UnlockConditions.UnmarshalSia(d) 408 fcr.NewRevisionNumber = d.NextUint64() 409 fcr.NewFileSize = d.NextUint64() 410 d.ReadFull(fcr.NewFileMerkleRoot[:]) 411 fcr.NewWindowStart = BlockHeight(d.NextUint64()) 412 fcr.NewWindowEnd = BlockHeight(d.NextUint64()) 413 fcr.NewValidProofOutputs = make([]SiacoinOutput, d.NextPrefix(unsafe.Sizeof(SiacoinOutput{}))) 414 for i := range fcr.NewValidProofOutputs { 415 fcr.NewValidProofOutputs[i].UnmarshalSia(d) 416 } 417 fcr.NewMissedProofOutputs = make([]SiacoinOutput, d.NextPrefix(unsafe.Sizeof(SiacoinOutput{}))) 418 for i := range fcr.NewMissedProofOutputs { 419 fcr.NewMissedProofOutputs[i].UnmarshalSia(d) 420 } 421 d.ReadFull(fcr.NewUnlockHash[:]) 422 return d.Err() 423 } 424 425 // LoadString loads a FileContractID from a string 426 func (fcid *FileContractID) LoadString(str string) error { 427 return (*crypto.Hash)(fcid).LoadString(str) 428 } 429 430 // MarshalJSON marshals an id as a hex string. 431 func (fcid FileContractID) MarshalJSON() ([]byte, error) { 432 return json.Marshal(fcid.String()) 433 } 434 435 // String prints the id in hex. 436 func (fcid FileContractID) String() string { 437 return fmt.Sprintf("%x", fcid[:]) 438 } 439 440 // UnmarshalJSON decodes the json hex string of the id. 441 func (fcid *FileContractID) UnmarshalJSON(b []byte) error { 442 return (*crypto.Hash)(fcid).UnmarshalJSON(b) 443 } 444 445 // MarshalJSON marshals an id as a hex string. 446 func (oid OutputID) MarshalJSON() ([]byte, error) { 447 return json.Marshal(oid.String()) 448 } 449 450 // String prints the id in hex. 451 func (oid OutputID) String() string { 452 return fmt.Sprintf("%x", oid[:]) 453 } 454 455 // UnmarshalJSON decodes the json hex string of the id. 456 func (oid *OutputID) UnmarshalJSON(b []byte) error { 457 return (*crypto.Hash)(oid).UnmarshalJSON(b) 458 } 459 460 // MarshalSia implements the encoding.SiaMarshaler interface. 461 func (sci SiacoinInput) MarshalSia(w io.Writer) error { 462 e := encoding.NewEncoder(w) 463 e.Write(sci.ParentID[:]) 464 sci.UnlockConditions.MarshalSia(e) 465 return e.Err() 466 } 467 468 // UnmarshalSia implements the encoding.SiaUnmarshaler interface. 469 func (sci *SiacoinInput) UnmarshalSia(r io.Reader) error { 470 d := encoding.NewDecoder(r, encoding.DefaultAllocLimit) 471 d.ReadFull(sci.ParentID[:]) 472 sci.UnlockConditions.UnmarshalSia(d) 473 return d.Err() 474 } 475 476 // MarshalSia implements the encoding.SiaMarshaler interface. 477 func (sco SiacoinOutput) MarshalSia(w io.Writer) error { 478 e := encoding.NewEncoder(w) 479 sco.Value.MarshalSia(e) 480 e.Write(sco.UnlockHash[:]) 481 return e.Err() 482 } 483 484 // UnmarshalSia implements the encoding.SiaUnmarshaler interface. 485 func (sco *SiacoinOutput) UnmarshalSia(r io.Reader) error { 486 d := encoding.NewDecoder(r, encoding.DefaultAllocLimit) 487 sco.Value.UnmarshalSia(d) 488 d.ReadFull(sco.UnlockHash[:]) 489 return d.Err() 490 } 491 492 // MarshalJSON marshals an id as a hex string. 493 func (scoid SiacoinOutputID) MarshalJSON() ([]byte, error) { 494 return json.Marshal(scoid.String()) 495 } 496 497 // String prints the id in hex. 498 func (scoid SiacoinOutputID) String() string { 499 return fmt.Sprintf("%x", scoid[:]) 500 } 501 502 // UnmarshalJSON decodes the json hex string of the id. 503 func (scoid *SiacoinOutputID) UnmarshalJSON(b []byte) error { 504 return (*crypto.Hash)(scoid).UnmarshalJSON(b) 505 } 506 507 // MarshalSia implements the encoding.SiaMarshaler interface. 508 func (sfi SiafundInput) MarshalSia(w io.Writer) error { 509 e := encoding.NewEncoder(w) 510 e.Write(sfi.ParentID[:]) 511 sfi.UnlockConditions.MarshalSia(e) 512 e.Write(sfi.ClaimUnlockHash[:]) 513 return e.Err() 514 } 515 516 // UnmarshalSia implements the encoding.SiaUnmarshaler interface. 517 func (sfi *SiafundInput) UnmarshalSia(r io.Reader) error { 518 d := encoding.NewDecoder(r, encoding.DefaultAllocLimit) 519 d.ReadFull(sfi.ParentID[:]) 520 sfi.UnlockConditions.UnmarshalSia(d) 521 d.ReadFull(sfi.ClaimUnlockHash[:]) 522 return d.Err() 523 } 524 525 // MarshalSia implements the encoding.SiaMarshaler interface. 526 func (sfo SiafundOutput) MarshalSia(w io.Writer) error { 527 e := encoding.NewEncoder(w) 528 sfo.Value.MarshalSia(e) 529 e.Write(sfo.UnlockHash[:]) 530 sfo.ClaimStart.MarshalSia(e) 531 return e.Err() 532 } 533 534 // UnmarshalSia implements the encoding.SiaUnmarshaler interface. 535 func (sfo *SiafundOutput) UnmarshalSia(r io.Reader) error { 536 d := encoding.NewDecoder(r, encoding.DefaultAllocLimit) 537 sfo.Value.UnmarshalSia(d) 538 d.ReadFull(sfo.UnlockHash[:]) 539 sfo.ClaimStart.UnmarshalSia(d) 540 return d.Err() 541 } 542 543 // MarshalJSON marshals an id as a hex string. 544 func (sfoid SiafundOutputID) MarshalJSON() ([]byte, error) { 545 return json.Marshal(sfoid.String()) 546 } 547 548 // String prints the id in hex. 549 func (sfoid SiafundOutputID) String() string { 550 return fmt.Sprintf("%x", sfoid[:]) 551 } 552 553 // UnmarshalJSON decodes the json hex string of the id. 554 func (sfoid *SiafundOutputID) UnmarshalJSON(b []byte) error { 555 return (*crypto.Hash)(sfoid).UnmarshalJSON(b) 556 } 557 558 // MarshalSia implements the encoding.SiaMarshaler interface. 559 func (spk SiaPublicKey) MarshalSia(w io.Writer) error { 560 e := encoding.NewEncoder(w) 561 e.Write(spk.Algorithm[:]) 562 e.WritePrefixedBytes(spk.Key) 563 return e.Err() 564 } 565 566 // UnmarshalSia implements the encoding.SiaUnmarshaler interface. 567 func (spk *SiaPublicKey) UnmarshalSia(r io.Reader) error { 568 d := encoding.NewDecoder(r, encoding.DefaultAllocLimit) 569 d.ReadFull(spk.Algorithm[:]) 570 spk.Key = d.ReadPrefixedBytes() 571 return d.Err() 572 } 573 574 // LoadString is the inverse of SiaPublicKey.String(). 575 func (spk *SiaPublicKey) LoadString(s string) { 576 parts := strings.Split(s, ":") 577 if len(parts) != 2 { 578 return 579 } 580 var err error 581 spk.Key, err = hex.DecodeString(parts[1]) 582 if err != nil { 583 spk.Key = nil 584 return 585 } 586 copy(spk.Algorithm[:], []byte(parts[0])) 587 } 588 589 // String defines how to print a SiaPublicKey - hex is used to keep things 590 // compact during logging. The key type prefix and lack of a checksum help to 591 // separate it from a sia address. 592 func (spk SiaPublicKey) String() string { 593 if spk.Algorithm == SignatureEd25519 { 594 buf := make([]byte, 72) 595 copy(buf[:8], "ed25519:") 596 hex.Encode(buf[8:], spk.Key) 597 return string(buf) 598 } 599 return spk.Algorithm.String() + ":" + hex.EncodeToString(spk.Key) 600 } 601 602 // UnmarshalJSON unmarshals a SiaPublicKey as JSON. 603 func (spk *SiaPublicKey) UnmarshalJSON(b []byte) error { 604 spk.LoadString(string(bytes.Trim(b, `"`))) 605 if spk.Key == nil { 606 // fallback to old (base64) encoding 607 var oldSPK struct { 608 Algorithm Specifier 609 Key []byte 610 } 611 if err := json.Unmarshal(b, &oldSPK); err != nil { 612 return err 613 } 614 spk.Algorithm, spk.Key = oldSPK.Algorithm, oldSPK.Key 615 } 616 return nil 617 } 618 619 // MarshalJSON marshals a specifier as a string. 620 func (s Specifier) MarshalJSON() ([]byte, error) { 621 return json.Marshal(s.String()) 622 } 623 624 // String returns the specifier as a string, trimming any trailing zeros. 625 func (s Specifier) String() string { 626 return string(bytes.TrimRight(s[:], string(0))) 627 } 628 629 // UnmarshalJSON decodes the json string of the specifier. 630 func (s *Specifier) UnmarshalJSON(b []byte) error { 631 var str string 632 if err := json.Unmarshal(b, &str); err != nil { 633 return err 634 } 635 copy(s[:], str) 636 return nil 637 } 638 639 // MarshalSia implements the encoding.SiaMarshaler interface. 640 func (sp *StorageProof) MarshalSia(w io.Writer) error { 641 e := encoding.NewEncoder(w) 642 e.Write(sp.ParentID[:]) 643 e.Write(sp.Segment[:]) 644 e.WriteInt(len(sp.HashSet)) 645 for i := range sp.HashSet { 646 e.Write(sp.HashSet[i][:]) 647 } 648 return e.Err() 649 } 650 651 // UnmarshalSia implements the encoding.SiaUnmarshaler interface. 652 func (sp *StorageProof) UnmarshalSia(r io.Reader) error { 653 d := encoding.NewDecoder(r, encoding.DefaultAllocLimit) 654 d.ReadFull(sp.ParentID[:]) 655 d.ReadFull(sp.Segment[:]) 656 sp.HashSet = make([]crypto.Hash, d.NextPrefix(unsafe.Sizeof(crypto.Hash{}))) 657 for i := range sp.HashSet { 658 d.ReadFull(sp.HashSet[i][:]) 659 } 660 return d.Err() 661 } 662 663 // MarshalSia implements the encoding.SiaMarshaler interface. 664 func (t Transaction) MarshalSia(w io.Writer) error { 665 e := encoding.NewEncoder(w) 666 t.MarshalSiaNoSignatures(e) 667 e.WriteInt(len((t.TransactionSignatures))) 668 for i := range t.TransactionSignatures { 669 t.TransactionSignatures[i].MarshalSia(e) 670 } 671 return e.Err() 672 } 673 674 // MarshalSiaNoSignatures is a helper function for calculating certain hashes 675 // that do not include the transaction's signatures. 676 func (t Transaction) MarshalSiaNoSignatures(w io.Writer) { 677 e := encoding.NewEncoder(w) 678 e.WriteInt(len((t.SiacoinInputs))) 679 for i := range t.SiacoinInputs { 680 t.SiacoinInputs[i].MarshalSia(e) 681 } 682 e.WriteInt(len((t.SiacoinOutputs))) 683 for i := range t.SiacoinOutputs { 684 t.SiacoinOutputs[i].MarshalSia(e) 685 } 686 e.WriteInt(len((t.FileContracts))) 687 for i := range t.FileContracts { 688 t.FileContracts[i].MarshalSia(e) 689 } 690 e.WriteInt(len((t.FileContractRevisions))) 691 for i := range t.FileContractRevisions { 692 t.FileContractRevisions[i].MarshalSia(e) 693 } 694 e.WriteInt(len((t.StorageProofs))) 695 for i := range t.StorageProofs { 696 t.StorageProofs[i].MarshalSia(e) 697 } 698 e.WriteInt(len((t.SiafundInputs))) 699 for i := range t.SiafundInputs { 700 t.SiafundInputs[i].MarshalSia(e) 701 } 702 e.WriteInt(len((t.SiafundOutputs))) 703 for i := range t.SiafundOutputs { 704 t.SiafundOutputs[i].MarshalSia(e) 705 } 706 e.WriteInt(len((t.MinerFees))) 707 for i := range t.MinerFees { 708 t.MinerFees[i].MarshalSia(e) 709 } 710 e.WriteInt(len((t.ArbitraryData))) 711 for i := range t.ArbitraryData { 712 e.WritePrefixedBytes(t.ArbitraryData[i]) 713 } 714 } 715 716 // MarshalSiaSize returns the encoded size of t. 717 func (t Transaction) MarshalSiaSize() (size int) { 718 size += 8 719 for _, sci := range t.SiacoinInputs { 720 size += len(sci.ParentID) 721 size += sci.UnlockConditions.MarshalSiaSize() 722 } 723 size += 8 724 for _, sco := range t.SiacoinOutputs { 725 size += sco.Value.MarshalSiaSize() 726 size += len(sco.UnlockHash) 727 } 728 size += 8 729 for i := range t.FileContracts { 730 size += t.FileContracts[i].MarshalSiaSize() 731 } 732 size += 8 733 for i := range t.FileContractRevisions { 734 size += t.FileContractRevisions[i].MarshalSiaSize() 735 } 736 size += 8 737 for _, sp := range t.StorageProofs { 738 size += len(sp.ParentID) 739 size += len(sp.Segment) 740 size += 8 + len(sp.HashSet)*crypto.HashSize 741 } 742 size += 8 743 for _, sfi := range t.SiafundInputs { 744 size += len(sfi.ParentID) 745 size += len(sfi.ClaimUnlockHash) 746 size += sfi.UnlockConditions.MarshalSiaSize() 747 } 748 size += 8 749 for _, sfo := range t.SiafundOutputs { 750 size += sfo.Value.MarshalSiaSize() 751 size += len(sfo.UnlockHash) 752 size += sfo.ClaimStart.MarshalSiaSize() 753 } 754 size += 8 755 for i := range t.MinerFees { 756 size += t.MinerFees[i].MarshalSiaSize() 757 } 758 size += 8 759 for i := range t.ArbitraryData { 760 size += 8 + len(t.ArbitraryData[i]) 761 } 762 size += 8 763 for _, ts := range t.TransactionSignatures { 764 size += len(ts.ParentID) 765 size += 8 // ts.PublicKeyIndex 766 size += 8 // ts.Timelock 767 size += ts.CoveredFields.MarshalSiaSize() 768 size += 8 + len(ts.Signature) 769 } 770 return 771 } 772 773 // UnmarshalSia implements the encoding.SiaUnmarshaler interface. 774 func (t *Transaction) UnmarshalSia(r io.Reader) error { 775 d := encoding.NewDecoder(r, encoding.DefaultAllocLimit) 776 t.SiacoinInputs = make([]SiacoinInput, d.NextPrefix(unsafe.Sizeof(SiacoinInput{}))) 777 for i := range t.SiacoinInputs { 778 t.SiacoinInputs[i].UnmarshalSia(d) 779 } 780 t.SiacoinOutputs = make([]SiacoinOutput, d.NextPrefix(unsafe.Sizeof(SiacoinOutput{}))) 781 for i := range t.SiacoinOutputs { 782 t.SiacoinOutputs[i].UnmarshalSia(d) 783 } 784 t.FileContracts = make([]FileContract, d.NextPrefix(unsafe.Sizeof(FileContract{}))) 785 for i := range t.FileContracts { 786 t.FileContracts[i].UnmarshalSia(d) 787 } 788 t.FileContractRevisions = make([]FileContractRevision, d.NextPrefix(unsafe.Sizeof(FileContractRevision{}))) 789 for i := range t.FileContractRevisions { 790 t.FileContractRevisions[i].UnmarshalSia(d) 791 } 792 t.StorageProofs = make([]StorageProof, d.NextPrefix(unsafe.Sizeof(StorageProof{}))) 793 for i := range t.StorageProofs { 794 t.StorageProofs[i].UnmarshalSia(d) 795 } 796 t.SiafundInputs = make([]SiafundInput, d.NextPrefix(unsafe.Sizeof(SiafundInput{}))) 797 for i := range t.SiafundInputs { 798 t.SiafundInputs[i].UnmarshalSia(d) 799 } 800 t.SiafundOutputs = make([]SiafundOutput, d.NextPrefix(unsafe.Sizeof(SiafundOutput{}))) 801 for i := range t.SiafundOutputs { 802 t.SiafundOutputs[i].UnmarshalSia(d) 803 } 804 t.MinerFees = make([]Currency, d.NextPrefix(unsafe.Sizeof(Currency{}))) 805 for i := range t.MinerFees { 806 t.MinerFees[i].UnmarshalSia(d) 807 } 808 t.ArbitraryData = make([][]byte, d.NextPrefix(unsafe.Sizeof([]byte{}))) 809 for i := range t.ArbitraryData { 810 t.ArbitraryData[i] = d.ReadPrefixedBytes() 811 } 812 t.TransactionSignatures = make([]TransactionSignature, d.NextPrefix(unsafe.Sizeof(TransactionSignature{}))) 813 for i := range t.TransactionSignatures { 814 t.TransactionSignatures[i].UnmarshalSia(d) 815 } 816 return d.Err() 817 } 818 819 // MarshalJSON marshals an id as a hex string. 820 func (tid TransactionID) MarshalJSON() ([]byte, error) { 821 return json.Marshal(tid.String()) 822 } 823 824 // String prints the id in hex. 825 func (tid TransactionID) String() string { 826 return fmt.Sprintf("%x", tid[:]) 827 } 828 829 // UnmarshalJSON decodes the json hex string of the id. 830 func (tid *TransactionID) UnmarshalJSON(b []byte) error { 831 return (*crypto.Hash)(tid).UnmarshalJSON(b) 832 } 833 834 // MarshalSia implements the encoding.SiaMarshaler interface. 835 func (ts TransactionSignature) MarshalSia(w io.Writer) error { 836 e := encoding.NewEncoder(w) 837 e.Write(ts.ParentID[:]) 838 e.WriteUint64(ts.PublicKeyIndex) 839 e.WriteUint64(uint64(ts.Timelock)) 840 ts.CoveredFields.MarshalSia(e) 841 e.WritePrefixedBytes(ts.Signature) 842 return e.Err() 843 } 844 845 // UnmarshalSia implements the encoding.SiaUnmarshaler interface. 846 func (ts *TransactionSignature) UnmarshalSia(r io.Reader) error { 847 d := encoding.NewDecoder(r, encoding.DefaultAllocLimit) 848 d.ReadFull(ts.ParentID[:]) 849 ts.PublicKeyIndex = d.NextUint64() 850 ts.Timelock = BlockHeight(d.NextUint64()) 851 ts.CoveredFields.UnmarshalSia(d) 852 ts.Signature = d.ReadPrefixedBytes() 853 return d.Err() 854 } 855 856 // MarshalSia implements the encoding.SiaMarshaler interface. 857 func (uc UnlockConditions) MarshalSia(w io.Writer) error { 858 e := encoding.NewEncoder(w) 859 e.WriteUint64(uint64(uc.Timelock)) 860 e.WriteInt(len(uc.PublicKeys)) 861 for _, spk := range uc.PublicKeys { 862 spk.MarshalSia(e) 863 } 864 e.WriteUint64(uc.SignaturesRequired) 865 return e.Err() 866 } 867 868 // MarshalSiaSize returns the encoded size of uc. 869 func (uc UnlockConditions) MarshalSiaSize() (size int) { 870 size += 8 // Timelock 871 size += 8 // length prefix for PublicKeys 872 for _, spk := range uc.PublicKeys { 873 size += len(spk.Algorithm) 874 size += 8 + len(spk.Key) 875 } 876 size += 8 // SignaturesRequired 877 return 878 } 879 880 // UnmarshalSia implements the encoding.SiaUnmarshaler interface. 881 func (uc *UnlockConditions) UnmarshalSia(r io.Reader) error { 882 d := encoding.NewDecoder(r, encoding.DefaultAllocLimit) 883 uc.Timelock = BlockHeight(d.NextUint64()) 884 uc.PublicKeys = make([]SiaPublicKey, d.NextPrefix(unsafe.Sizeof(SiaPublicKey{}))) 885 for i := range uc.PublicKeys { 886 uc.PublicKeys[i].UnmarshalSia(d) 887 } 888 uc.SignaturesRequired = d.NextUint64() 889 return d.Err() 890 } 891 892 // MarshalJSON is implemented on the unlock hash to always produce a hex string 893 // upon marshalling. 894 func (uh UnlockHash) MarshalJSON() ([]byte, error) { 895 return json.Marshal(uh.String()) 896 } 897 898 // UnmarshalJSON is implemented on the unlock hash to recover an unlock hash 899 // that has been encoded to a hex string. 900 func (uh *UnlockHash) UnmarshalJSON(b []byte) error { 901 // Check the length of b. 902 if len(b) != crypto.HashSize*2+UnlockHashChecksumSize*2+2 && len(b) != crypto.HashSize*2+2 { 903 return ErrUnlockHashWrongLen 904 } 905 return uh.LoadString(string(b[1 : len(b)-1])) 906 } 907 908 // String returns the hex representation of the unlock hash as a string - this 909 // includes a checksum. 910 func (uh UnlockHash) String() string { 911 uhChecksum := crypto.HashObject(uh) 912 return fmt.Sprintf("%x%x", uh[:], uhChecksum[:UnlockHashChecksumSize]) 913 } 914 915 // LoadString loads a hex representation (including checksum) of an unlock hash 916 // into an unlock hash object. An error is returned if the string is invalid or 917 // fails the checksum. 918 func (uh *UnlockHash) LoadString(strUH string) error { 919 // Check the length of strUH. 920 if len(strUH) != crypto.HashSize*2+UnlockHashChecksumSize*2 { 921 return ErrUnlockHashWrongLen 922 } 923 924 // Decode the unlock hash. 925 var byteUnlockHash []byte 926 var checksum []byte 927 _, err := fmt.Sscanf(strUH[:crypto.HashSize*2], "%x", &byteUnlockHash) 928 if err != nil { 929 return err 930 } 931 932 // Decode and verify the checksum. 933 _, err = fmt.Sscanf(strUH[crypto.HashSize*2:], "%x", &checksum) 934 if err != nil { 935 return err 936 } 937 expectedChecksum := crypto.HashBytes(byteUnlockHash) 938 if !bytes.Equal(expectedChecksum[:UnlockHashChecksumSize], checksum) { 939 return ErrInvalidUnlockHashChecksum 940 } 941 942 copy(uh[:], byteUnlockHash[:]) 943 return nil 944 } 945 946 // Scan implements the fmt.Scanner interface, allowing UnlockHash values to be 947 // scanned from text. 948 func (uh *UnlockHash) Scan(s fmt.ScanState, ch rune) error { 949 s.SkipSpace() 950 tok, err := s.Token(false, nil) 951 if err != nil { 952 return err 953 } 954 return uh.LoadString(string(tok)) 955 } 956 957 // MustParseAddress parses an address string to an UnlockHash, panicking 958 // if parsing fails. 959 // 960 // MustParseAddress should never be called on untrusted input; it is 961 // provided only for convenience when working with address strings that are 962 // known to be valid, such as the addresses in GenesisSiafundAllocation. To 963 // parse untrusted address strings, use the LoadString method of UnlockHash. 964 func MustParseAddress(addrStr string) (addr UnlockHash) { 965 if err := addr.LoadString(addrStr); err != nil { 966 panic(err) 967 } 968 return 969 }