github.com/fozzysec/SiaPrime@v0.0.0-20190612043147-66c8e8d11fe3/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 "SiaPrime/build" 15 "SiaPrime/crypto" 16 "SiaPrime/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 // LoadString loads a FileContractID from a string 638 func (fcid *FileContractID) LoadString(str string) error { 639 return (*crypto.Hash)(fcid).LoadString(str) 640 } 641 642 // MarshalJSON marshals an id as a hex string. 643 func (fcid FileContractID) MarshalJSON() ([]byte, error) { 644 return json.Marshal(fcid.String()) 645 } 646 647 // String prints the id in hex. 648 func (fcid FileContractID) String() string { 649 return fmt.Sprintf("%x", fcid[:]) 650 } 651 652 // UnmarshalJSON decodes the json hex string of the id. 653 func (fcid *FileContractID) UnmarshalJSON(b []byte) error { 654 return (*crypto.Hash)(fcid).UnmarshalJSON(b) 655 } 656 657 // MarshalJSON marshals an id as a hex string. 658 func (oid OutputID) MarshalJSON() ([]byte, error) { 659 return json.Marshal(oid.String()) 660 } 661 662 // String prints the id in hex. 663 func (oid OutputID) String() string { 664 return fmt.Sprintf("%x", oid[:]) 665 } 666 667 // UnmarshalJSON decodes the json hex string of the id. 668 func (oid *OutputID) UnmarshalJSON(b []byte) error { 669 return (*crypto.Hash)(oid).UnmarshalJSON(b) 670 } 671 672 // MarshalSia implements the encoding.SiaMarshaler interface. 673 func (sci SiacoinInput) MarshalSia(w io.Writer) error { 674 e := encoder(w) 675 e.Write(sci.ParentID[:]) 676 sci.UnlockConditions.MarshalSia(e) 677 return e.Err() 678 } 679 680 // UnmarshalSia implements the encoding.SiaUnmarshaler interface. 681 func (sci *SiacoinInput) UnmarshalSia(r io.Reader) error { 682 d := decoder(r) 683 d.ReadFull(sci.ParentID[:]) 684 sci.UnlockConditions.UnmarshalSia(d) 685 return d.Err() 686 } 687 688 // MarshalSia implements the encoding.SiaMarshaler interface. 689 func (sco SiacoinOutput) MarshalSia(w io.Writer) error { 690 e := encoder(w) 691 sco.Value.MarshalSia(e) 692 e.Write(sco.UnlockHash[:]) 693 return e.Err() 694 } 695 696 // UnmarshalSia implements the encoding.SiaUnmarshaler interface. 697 func (sco *SiacoinOutput) UnmarshalSia(r io.Reader) error { 698 d := decoder(r) 699 sco.Value.UnmarshalSia(d) 700 d.ReadFull(sco.UnlockHash[:]) 701 return d.Err() 702 } 703 704 // MarshalJSON marshals an id as a hex string. 705 func (scoid SiacoinOutputID) MarshalJSON() ([]byte, error) { 706 return json.Marshal(scoid.String()) 707 } 708 709 // String prints the id in hex. 710 func (scoid SiacoinOutputID) String() string { 711 return fmt.Sprintf("%x", scoid[:]) 712 } 713 714 // UnmarshalJSON decodes the json hex string of the id. 715 func (scoid *SiacoinOutputID) UnmarshalJSON(b []byte) error { 716 return (*crypto.Hash)(scoid).UnmarshalJSON(b) 717 } 718 719 // MarshalSia implements the encoding.SiaMarshaler interface. 720 func (sfi SiafundInput) MarshalSia(w io.Writer) error { 721 e := encoder(w) 722 e.Write(sfi.ParentID[:]) 723 sfi.UnlockConditions.MarshalSia(e) 724 e.Write(sfi.ClaimUnlockHash[:]) 725 return e.Err() 726 } 727 728 // UnmarshalSia implements the encoding.SiaUnmarshaler interface. 729 func (sfi *SiafundInput) UnmarshalSia(r io.Reader) error { 730 d := decoder(r) 731 d.ReadFull(sfi.ParentID[:]) 732 sfi.UnlockConditions.UnmarshalSia(d) 733 d.ReadFull(sfi.ClaimUnlockHash[:]) 734 return d.Err() 735 } 736 737 // MarshalSia implements the encoding.SiaMarshaler interface. 738 func (sfo SiafundOutput) MarshalSia(w io.Writer) error { 739 e := encoder(w) 740 sfo.Value.MarshalSia(e) 741 e.Write(sfo.UnlockHash[:]) 742 sfo.ClaimStart.MarshalSia(e) 743 return e.Err() 744 } 745 746 // UnmarshalSia implements the encoding.SiaUnmarshaler interface. 747 func (sfo *SiafundOutput) UnmarshalSia(r io.Reader) error { 748 d := decoder(r) 749 sfo.Value.UnmarshalSia(d) 750 d.ReadFull(sfo.UnlockHash[:]) 751 sfo.ClaimStart.UnmarshalSia(d) 752 return d.Err() 753 } 754 755 // MarshalJSON marshals an id as a hex string. 756 func (sfoid SiafundOutputID) MarshalJSON() ([]byte, error) { 757 return json.Marshal(sfoid.String()) 758 } 759 760 // String prints the id in hex. 761 func (sfoid SiafundOutputID) String() string { 762 return fmt.Sprintf("%x", sfoid[:]) 763 } 764 765 // UnmarshalJSON decodes the json hex string of the id. 766 func (sfoid *SiafundOutputID) UnmarshalJSON(b []byte) error { 767 return (*crypto.Hash)(sfoid).UnmarshalJSON(b) 768 } 769 770 // MarshalSia implements the encoding.SiaMarshaler interface. 771 func (spk SiaPublicKey) MarshalSia(w io.Writer) error { 772 e := encoder(w) 773 e.Write(spk.Algorithm[:]) 774 e.WritePrefix(spk.Key) 775 return e.Err() 776 } 777 778 // UnmarshalSia implements the encoding.SiaUnmarshaler interface. 779 func (spk *SiaPublicKey) UnmarshalSia(r io.Reader) error { 780 d := decoder(r) 781 d.ReadFull(spk.Algorithm[:]) 782 spk.Key = d.ReadPrefix() 783 return d.Err() 784 } 785 786 // LoadString is the inverse of SiaPublicKey.String(). 787 func (spk *SiaPublicKey) LoadString(s string) { 788 parts := strings.Split(s, ":") 789 if len(parts) != 2 { 790 return 791 } 792 var err error 793 spk.Key, err = hex.DecodeString(parts[1]) 794 if err != nil { 795 spk.Key = nil 796 return 797 } 798 copy(spk.Algorithm[:], []byte(parts[0])) 799 } 800 801 // String defines how to print a SiaPublicKey - hex is used to keep things 802 // compact during logging. The key type prefix and lack of a checksum help to 803 // separate it from a sia address. 804 func (spk *SiaPublicKey) String() string { 805 return spk.Algorithm.String() + ":" + fmt.Sprintf("%x", spk.Key) 806 } 807 808 // UnmarshalJSON unmarshals a SiaPublicKey as JSON. 809 func (spk *SiaPublicKey) UnmarshalJSON(b []byte) error { 810 spk.LoadString(string(bytes.Trim(b, `"`))) 811 if spk.Key == nil { 812 // fallback to old (base64) encoding 813 var oldSPK struct { 814 Algorithm Specifier 815 Key []byte 816 } 817 if err := json.Unmarshal(b, &oldSPK); err != nil { 818 return err 819 } 820 spk.Algorithm, spk.Key = oldSPK.Algorithm, oldSPK.Key 821 } 822 return nil 823 } 824 825 // MarshalJSON marshals a specifier as a string. 826 func (s Specifier) MarshalJSON() ([]byte, error) { 827 return json.Marshal(s.String()) 828 } 829 830 // String returns the specifier as a string, trimming any trailing zeros. 831 func (s Specifier) String() string { 832 var i int 833 for i = range s { 834 if s[i] == 0 { 835 break 836 } 837 } 838 return string(s[:i]) 839 } 840 841 // UnmarshalJSON decodes the json string of the specifier. 842 func (s *Specifier) UnmarshalJSON(b []byte) error { 843 var str string 844 if err := json.Unmarshal(b, &str); err != nil { 845 return err 846 } 847 copy(s[:], str) 848 return nil 849 } 850 851 // MarshalSia implements the encoding.SiaMarshaler interface. 852 func (sp *StorageProof) MarshalSia(w io.Writer) error { 853 e := encoder(w) 854 e.Write(sp.ParentID[:]) 855 e.Write(sp.Segment[:]) 856 e.WriteInt(len(sp.HashSet)) 857 for i := range sp.HashSet { 858 e.Write(sp.HashSet[i][:]) 859 } 860 return e.Err() 861 } 862 863 // UnmarshalSia implements the encoding.SiaUnmarshaler interface. 864 func (sp *StorageProof) UnmarshalSia(r io.Reader) error { 865 d := decoder(r) 866 d.ReadFull(sp.ParentID[:]) 867 d.ReadFull(sp.Segment[:]) 868 sp.HashSet = make([]crypto.Hash, d.NextPrefix(unsafe.Sizeof(crypto.Hash{}))) 869 for i := range sp.HashSet { 870 d.ReadFull(sp.HashSet[i][:]) 871 } 872 return d.Err() 873 } 874 875 // MarshalSia implements the encoding.SiaMarshaler interface. 876 func (t Transaction) MarshalSia(w io.Writer) error { 877 if build.DEBUG { 878 // Sanity check: compare against the old encoding 879 buf := new(bytes.Buffer) 880 encoding.NewEncoder(buf).EncodeAll( 881 t.SiacoinInputs, 882 t.SiacoinOutputs, 883 t.FileContracts, 884 t.FileContractRevisions, 885 t.StorageProofs, 886 t.SiafundInputs, 887 t.SiafundOutputs, 888 t.MinerFees, 889 t.ArbitraryData, 890 t.TransactionSignatures, 891 ) 892 w = sanityCheckWriter{w, buf} 893 } 894 895 e := encoder(w) 896 t.MarshalSiaNoSignatures(e) 897 e.WriteInt(len((t.TransactionSignatures))) 898 for i := range t.TransactionSignatures { 899 t.TransactionSignatures[i].MarshalSia(e) 900 } 901 return e.Err() 902 } 903 904 // MarshalSiaNoSignatures is a helper function for calculating certain hashes 905 // that do not include the transaction's signatures. 906 func (t Transaction) MarshalSiaNoSignatures(w io.Writer) { 907 e := encoder(w) 908 e.WriteInt(len((t.SiacoinInputs))) 909 for i := range t.SiacoinInputs { 910 t.SiacoinInputs[i].MarshalSia(e) 911 } 912 e.WriteInt(len((t.SiacoinOutputs))) 913 for i := range t.SiacoinOutputs { 914 t.SiacoinOutputs[i].MarshalSia(e) 915 } 916 e.WriteInt(len((t.FileContracts))) 917 for i := range t.FileContracts { 918 t.FileContracts[i].MarshalSia(e) 919 } 920 e.WriteInt(len((t.FileContractRevisions))) 921 for i := range t.FileContractRevisions { 922 t.FileContractRevisions[i].MarshalSia(e) 923 } 924 e.WriteInt(len((t.StorageProofs))) 925 for i := range t.StorageProofs { 926 t.StorageProofs[i].MarshalSia(e) 927 } 928 e.WriteInt(len((t.SiafundInputs))) 929 for i := range t.SiafundInputs { 930 t.SiafundInputs[i].MarshalSia(e) 931 } 932 e.WriteInt(len((t.SiafundOutputs))) 933 for i := range t.SiafundOutputs { 934 t.SiafundOutputs[i].MarshalSia(e) 935 } 936 e.WriteInt(len((t.MinerFees))) 937 for i := range t.MinerFees { 938 t.MinerFees[i].MarshalSia(e) 939 } 940 e.WriteInt(len((t.ArbitraryData))) 941 for i := range t.ArbitraryData { 942 e.WritePrefix(t.ArbitraryData[i]) 943 } 944 } 945 946 // MarshalSiaSize returns the encoded size of t. 947 func (t Transaction) MarshalSiaSize() (size int) { 948 size += 8 949 for _, sci := range t.SiacoinInputs { 950 size += len(sci.ParentID) 951 size += sci.UnlockConditions.MarshalSiaSize() 952 } 953 size += 8 954 for _, sco := range t.SiacoinOutputs { 955 size += sco.Value.MarshalSiaSize() 956 size += len(sco.UnlockHash) 957 } 958 size += 8 959 for i := range t.FileContracts { 960 size += t.FileContracts[i].MarshalSiaSize() 961 } 962 size += 8 963 for i := range t.FileContractRevisions { 964 size += t.FileContractRevisions[i].MarshalSiaSize() 965 } 966 size += 8 967 for _, sp := range t.StorageProofs { 968 size += len(sp.ParentID) 969 size += len(sp.Segment) 970 size += 8 + len(sp.HashSet)*crypto.HashSize 971 } 972 size += 8 973 for _, sfi := range t.SiafundInputs { 974 size += len(sfi.ParentID) 975 size += len(sfi.ClaimUnlockHash) 976 size += sfi.UnlockConditions.MarshalSiaSize() 977 } 978 size += 8 979 for _, sfo := range t.SiafundOutputs { 980 size += sfo.Value.MarshalSiaSize() 981 size += len(sfo.UnlockHash) 982 size += sfo.ClaimStart.MarshalSiaSize() 983 } 984 size += 8 985 for i := range t.MinerFees { 986 size += t.MinerFees[i].MarshalSiaSize() 987 } 988 size += 8 989 for i := range t.ArbitraryData { 990 size += 8 + len(t.ArbitraryData[i]) 991 } 992 size += 8 993 for _, ts := range t.TransactionSignatures { 994 size += len(ts.ParentID) 995 size += 8 // ts.PublicKeyIndex 996 size += 8 // ts.Timelock 997 size += ts.CoveredFields.MarshalSiaSize() 998 size += 8 + len(ts.Signature) 999 } 1000 1001 // Sanity check against the slower method. 1002 if build.DEBUG { 1003 expectedSize := len(encoding.Marshal(t)) 1004 if expectedSize != size { 1005 panic("Transaction size different from expected size.") 1006 } 1007 } 1008 return 1009 } 1010 1011 // UnmarshalSia implements the encoding.SiaUnmarshaler interface. 1012 func (t *Transaction) UnmarshalSia(r io.Reader) error { 1013 d := decoder(r) 1014 t.SiacoinInputs = make([]SiacoinInput, d.NextPrefix(unsafe.Sizeof(SiacoinInput{}))) 1015 for i := range t.SiacoinInputs { 1016 t.SiacoinInputs[i].UnmarshalSia(d) 1017 } 1018 t.SiacoinOutputs = make([]SiacoinOutput, d.NextPrefix(unsafe.Sizeof(SiacoinOutput{}))) 1019 for i := range t.SiacoinOutputs { 1020 t.SiacoinOutputs[i].UnmarshalSia(d) 1021 } 1022 t.FileContracts = make([]FileContract, d.NextPrefix(unsafe.Sizeof(FileContract{}))) 1023 for i := range t.FileContracts { 1024 t.FileContracts[i].UnmarshalSia(d) 1025 } 1026 t.FileContractRevisions = make([]FileContractRevision, d.NextPrefix(unsafe.Sizeof(FileContractRevision{}))) 1027 for i := range t.FileContractRevisions { 1028 t.FileContractRevisions[i].UnmarshalSia(d) 1029 } 1030 t.StorageProofs = make([]StorageProof, d.NextPrefix(unsafe.Sizeof(StorageProof{}))) 1031 for i := range t.StorageProofs { 1032 t.StorageProofs[i].UnmarshalSia(d) 1033 } 1034 t.SiafundInputs = make([]SiafundInput, d.NextPrefix(unsafe.Sizeof(SiafundInput{}))) 1035 for i := range t.SiafundInputs { 1036 t.SiafundInputs[i].UnmarshalSia(d) 1037 } 1038 t.SiafundOutputs = make([]SiafundOutput, d.NextPrefix(unsafe.Sizeof(SiafundOutput{}))) 1039 for i := range t.SiafundOutputs { 1040 t.SiafundOutputs[i].UnmarshalSia(d) 1041 } 1042 t.MinerFees = make([]Currency, d.NextPrefix(unsafe.Sizeof(Currency{}))) 1043 for i := range t.MinerFees { 1044 t.MinerFees[i].UnmarshalSia(d) 1045 } 1046 t.ArbitraryData = make([][]byte, d.NextPrefix(unsafe.Sizeof([]byte{}))) 1047 for i := range t.ArbitraryData { 1048 t.ArbitraryData[i] = d.ReadPrefix() 1049 } 1050 t.TransactionSignatures = make([]TransactionSignature, d.NextPrefix(unsafe.Sizeof(TransactionSignature{}))) 1051 for i := range t.TransactionSignatures { 1052 t.TransactionSignatures[i].UnmarshalSia(d) 1053 } 1054 return d.Err() 1055 } 1056 1057 // MarshalJSON marshals an id as a hex string. 1058 func (tid TransactionID) MarshalJSON() ([]byte, error) { 1059 return json.Marshal(tid.String()) 1060 } 1061 1062 // String prints the id in hex. 1063 func (tid TransactionID) String() string { 1064 return fmt.Sprintf("%x", tid[:]) 1065 } 1066 1067 // UnmarshalJSON decodes the json hex string of the id. 1068 func (tid *TransactionID) UnmarshalJSON(b []byte) error { 1069 return (*crypto.Hash)(tid).UnmarshalJSON(b) 1070 } 1071 1072 // MarshalSia implements the encoding.SiaMarshaler interface. 1073 func (ts TransactionSignature) MarshalSia(w io.Writer) error { 1074 e := encoder(w) 1075 e.Write(ts.ParentID[:]) 1076 e.WriteUint64(ts.PublicKeyIndex) 1077 e.WriteUint64(uint64(ts.Timelock)) 1078 ts.CoveredFields.MarshalSia(e) 1079 e.WritePrefix(ts.Signature) 1080 return e.Err() 1081 } 1082 1083 // UnmarshalSia implements the encoding.SiaUnmarshaler interface. 1084 func (ts *TransactionSignature) UnmarshalSia(r io.Reader) error { 1085 d := decoder(r) 1086 d.ReadFull(ts.ParentID[:]) 1087 ts.PublicKeyIndex = d.NextUint64() 1088 ts.Timelock = BlockHeight(d.NextUint64()) 1089 ts.CoveredFields.UnmarshalSia(d) 1090 ts.Signature = d.ReadPrefix() 1091 return d.Err() 1092 } 1093 1094 // MarshalSia implements the encoding.SiaMarshaler interface. 1095 func (uc UnlockConditions) MarshalSia(w io.Writer) error { 1096 e := encoder(w) 1097 e.WriteUint64(uint64(uc.Timelock)) 1098 e.WriteInt(len(uc.PublicKeys)) 1099 for _, spk := range uc.PublicKeys { 1100 spk.MarshalSia(e) 1101 } 1102 e.WriteUint64(uc.SignaturesRequired) 1103 return e.Err() 1104 } 1105 1106 // MarshalSiaSize returns the encoded size of uc. 1107 func (uc UnlockConditions) MarshalSiaSize() (size int) { 1108 size += 8 // Timelock 1109 size += 8 // length prefix for PublicKeys 1110 for _, spk := range uc.PublicKeys { 1111 size += len(spk.Algorithm) 1112 size += 8 + len(spk.Key) 1113 } 1114 size += 8 // SignaturesRequired 1115 return 1116 } 1117 1118 // UnmarshalSia implements the encoding.SiaUnmarshaler interface. 1119 func (uc *UnlockConditions) UnmarshalSia(r io.Reader) error { 1120 d := decoder(r) 1121 uc.Timelock = BlockHeight(d.NextUint64()) 1122 uc.PublicKeys = make([]SiaPublicKey, d.NextPrefix(unsafe.Sizeof(SiaPublicKey{}))) 1123 for i := range uc.PublicKeys { 1124 uc.PublicKeys[i].UnmarshalSia(d) 1125 } 1126 uc.SignaturesRequired = d.NextUint64() 1127 return d.Err() 1128 } 1129 1130 // MarshalJSON is implemented on the unlock hash to always produce a hex string 1131 // upon marshalling. 1132 func (uh UnlockHash) MarshalJSON() ([]byte, error) { 1133 return json.Marshal(uh.String()) 1134 } 1135 1136 // UnmarshalJSON is implemented on the unlock hash to recover an unlock hash 1137 // that has been encoded to a hex string. 1138 func (uh *UnlockHash) UnmarshalJSON(b []byte) error { 1139 // Check the length of b. 1140 if len(b) != crypto.HashSize*2+UnlockHashChecksumSize*2+2 && len(b) != crypto.HashSize*2+2 { 1141 return ErrUnlockHashWrongLen 1142 } 1143 return uh.LoadString(string(b[1 : len(b)-1])) 1144 } 1145 1146 // String returns the hex representation of the unlock hash as a string - this 1147 // includes a checksum. 1148 func (uh UnlockHash) String() string { 1149 uhChecksum := crypto.HashObject(uh) 1150 return fmt.Sprintf("%x%x", uh[:], uhChecksum[:UnlockHashChecksumSize]) 1151 } 1152 1153 // LoadString loads a hex representation (including checksum) of an unlock hash 1154 // into an unlock hash object. An error is returned if the string is invalid or 1155 // fails the checksum. 1156 func (uh *UnlockHash) LoadString(strUH string) error { 1157 // Check the length of strUH. 1158 if len(strUH) != crypto.HashSize*2+UnlockHashChecksumSize*2 { 1159 return ErrUnlockHashWrongLen 1160 } 1161 1162 // Decode the unlock hash. 1163 var byteUnlockHash []byte 1164 var checksum []byte 1165 _, err := fmt.Sscanf(strUH[:crypto.HashSize*2], "%x", &byteUnlockHash) 1166 if err != nil { 1167 return err 1168 } 1169 1170 // Decode and verify the checksum. 1171 _, err = fmt.Sscanf(strUH[crypto.HashSize*2:], "%x", &checksum) 1172 if err != nil { 1173 return err 1174 } 1175 expectedChecksum := crypto.HashBytes(byteUnlockHash) 1176 if !bytes.Equal(expectedChecksum[:UnlockHashChecksumSize], checksum) { 1177 return ErrInvalidUnlockHashChecksum 1178 } 1179 1180 copy(uh[:], byteUnlockHash[:]) 1181 return nil 1182 } 1183 1184 // Scan implements the fmt.Scanner interface, allowing UnlockHash values to be 1185 // scanned from text. 1186 func (uh *UnlockHash) Scan(s fmt.ScanState, ch rune) error { 1187 s.SkipSpace() 1188 tok, err := s.Token(false, nil) 1189 if err != nil { 1190 return err 1191 } 1192 return uh.LoadString(string(tok)) 1193 }