Skip to content

Commit

Permalink
Merge pull request #58 from ipfs/migrate-block-format
Browse files Browse the repository at this point in the history
Migrate `go-block-format`
  • Loading branch information
Jorropo authored Jan 26, 2023
2 parents 7a8eed3 + 64e1c1b commit 38b7ae8
Show file tree
Hide file tree
Showing 4 changed files with 182 additions and 2 deletions.
82 changes: 82 additions & 0 deletions blocks/blocks.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
// Package blocks contains the lowest level of IPLD data structures.
// A block is raw data accompanied by a CID. The CID contains the multihash
// corresponding to the block.
package blocks

import (
"errors"
"fmt"

cid "github.com/ipfs/go-cid"
u "github.com/ipfs/go-ipfs-util"
mh "github.com/multiformats/go-multihash"
)

// ErrWrongHash is returned when the Cid of a block is not the expected
// according to the contents. It is currently used only when debugging.
var ErrWrongHash = errors.New("data did not match given hash")

// Block provides abstraction for blocks implementations.
type Block interface {
RawData() []byte
Cid() cid.Cid
String() string
Loggable() map[string]interface{}
}

// A BasicBlock is a singular block of data in ipfs. It implements the Block
// interface.
type BasicBlock struct {
cid cid.Cid
data []byte
}

// NewBlock creates a Block object from opaque data. It will hash the data.
func NewBlock(data []byte) *BasicBlock {
// TODO: fix assumptions
return &BasicBlock{data: data, cid: cid.NewCidV0(u.Hash(data))}
}

// NewBlockWithCid creates a new block when the hash of the data
// is already known, this is used to save time in situations where
// we are able to be confident that the data is correct.
func NewBlockWithCid(data []byte, c cid.Cid) (*BasicBlock, error) {
if u.Debug {
chkc, err := c.Prefix().Sum(data)
if err != nil {
return nil, err
}

if !chkc.Equals(c) {
return nil, ErrWrongHash
}
}
return &BasicBlock{data: data, cid: c}, nil
}

// Multihash returns the hash contained in the block CID.
func (b *BasicBlock) Multihash() mh.Multihash {
return b.cid.Hash()
}

// RawData returns the block raw contents as a byte slice.
func (b *BasicBlock) RawData() []byte {
return b.data
}

// Cid returns the content identifier of the block.
func (b *BasicBlock) Cid() cid.Cid {
return b.cid
}

// String provides a human-readable representation of the block CID.
func (b *BasicBlock) String() string {
return fmt.Sprintf("[Block %s]", b.Cid())
}

// Loggable returns a go-log loggable item.
func (b *BasicBlock) Loggable() map[string]interface{} {
return map[string]interface{}{
"block": b.Cid().String(),
}
}
98 changes: 98 additions & 0 deletions blocks/blocks_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
package blocks

import (
"bytes"
"testing"

cid "github.com/ipfs/go-cid"
u "github.com/ipfs/go-ipfs-util"
mh "github.com/multiformats/go-multihash"
)

func TestBlocksBasic(t *testing.T) {

// Test empty data
empty := []byte{}
NewBlock(empty)

// Test nil case
NewBlock(nil)

// Test some data
NewBlock([]byte("Hello world!"))
}

func TestData(t *testing.T) {
data := []byte("some data")
block := NewBlock(data)

if !bytes.Equal(block.RawData(), data) {
t.Error("data is wrong")
}
}

func TestHash(t *testing.T) {
data := []byte("some other data")
block := NewBlock(data)

hash, err := mh.Sum(data, mh.SHA2_256, -1)
if err != nil {
t.Fatal(err)
}

if !bytes.Equal(block.Multihash(), hash) {
t.Error("wrong multihash")
}
}

func TestCid(t *testing.T) {
data := []byte("yet another data")
block := NewBlock(data)
c := block.Cid()

if !bytes.Equal(block.Multihash(), c.Hash()) {
t.Error("key contains wrong data")
}
}

func TestManualHash(t *testing.T) {
oldDebugState := u.Debug
defer (func() {
u.Debug = oldDebugState
})()

data := []byte("I can't figure out more names .. data")
hash, err := mh.Sum(data, mh.SHA2_256, -1)
if err != nil {
t.Fatal(err)
}

c := cid.NewCidV0(hash)

u.Debug = false
block, err := NewBlockWithCid(data, c)
if err != nil {
t.Fatal(err)
}

if !bytes.Equal(block.Multihash(), hash) {
t.Error("wrong multihash")
}

data[5] = byte((uint32(data[5]) + 5) % 256) // Transfrom hash to be different
block, err = NewBlockWithCid(data, c)
if err != nil {
t.Fatal(err)
}

if !bytes.Equal(block.Multihash(), hash) {
t.Error("wrong multihash")
}

u.Debug = true

_, err = NewBlockWithCid(data, c)
if err != ErrWrongHash {
t.Fatal(err)
}
}
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ require (
github.com/crackcomm/go-gitignore v0.0.0-20170627025303-887ab5e44cc3
github.com/gorilla/mux v1.8.0
github.com/ipfs/go-cid v0.3.2
github.com/ipfs/go-ipfs-util v0.0.2
github.com/ipfs/go-ipns v0.3.0
github.com/ipfs/go-log/v2 v2.5.1
github.com/libp2p/go-libp2p v0.23.4
Expand All @@ -24,7 +25,6 @@ require (
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.1.0 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/ipfs/go-ipfs-util v0.0.2 // indirect
github.com/ipld/go-ipld-prime v0.9.0 // indirect
github.com/klauspost/cpuid/v2 v2.1.1 // indirect
github.com/libp2p/go-buffer-pool v0.1.0 // indirect
Expand Down
2 changes: 1 addition & 1 deletion version.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
{
"version": "v0.2.0"
"version": "v0.3.0"
}

0 comments on commit 38b7ae8

Please sign in to comment.