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