// 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 }