Exemplo n.º 1
0
// UnmarshalBinary assumes that the Binary is all good.  We do error
// out if there isn't enough data, or the transaction is too large.
func (b *FBlock) UnmarshalBinaryData(data []byte) (newdata []byte, err error) {

	// To catch memory errors, I capture the panic and turn it into
	// a reported error.
	defer func() {
		if r := recover(); r != nil {
			err = fmt.Errorf("Error unmarshalling transaction: %v", r)
		}
	}()

	// To capture the panic, my code needs to be in a function.  So I'm
	// creating one here, and call it at the end of this function.
	if bytes.Compare(data[:fct.ADDRESS_LENGTH], fct.FACTOID_CHAINID[:]) != 0 {
		return nil, fmt.Errorf("Block does not begin with the Factoid ChainID")
	}
	data = data[32:]

	b.BodyMR = new(fct.Hash)
	data, err = b.BodyMR.UnmarshalBinaryData(data)
	if err != nil {
		return nil, err
	}

	b.PrevKeyMR = new(fct.Hash)
	data, err = b.PrevKeyMR.UnmarshalBinaryData(data)
	if err != nil {
		return nil, err
	}

	b.PrevLedgerKeyMR = new(fct.Hash)
	data, err = b.PrevLedgerKeyMR.UnmarshalBinaryData(data)
	if err != nil {
		return nil, err
	}

	b.ExchRate, data = binary.BigEndian.Uint64(data[0:8]), data[8:]
	b.DBHeight, data = binary.BigEndian.Uint32(data[0:4]), data[4:]

	skip, data := fct.DecodeVarInt(data) // Skip the Expansion Header, if any, since
	data = data[skip:]                   // we don't know what to do with it.

	cnt, data := binary.BigEndian.Uint32(data[0:4]), data[4:]

	data = data[4:] // Just skip the size... We don't really need it.

	b.Transactions = make([]fct.ITransaction, cnt, cnt)
	for i, _ := range b.endOfPeriod {
		b.endOfPeriod[i] = 0
	}
	var periodMark = 0
	for i := uint32(0); i < cnt; i++ {

		for data[0] == fct.MARKER {
			b.endOfPeriod[periodMark] = int(i)
			data = data[1:]
			periodMark++
		}

		trans := new(fct.Transaction)
		data, err = trans.UnmarshalBinaryData(data)
		if err != nil {
			return nil, fmt.Errorf("Failed to unmarshal a transaction in block.\n" + err.Error())
		}
		b.Transactions[i] = trans
	}

	return data, nil

}