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