-
Notifications
You must be signed in to change notification settings - Fork 136
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
FVM integration #217
FVM integration #217
Changes from 64 commits
f48a5c8
665619b
0a0463c
7e6e4c8
497da29
67ce452
768ed2a
97279f3
cb7bc67
061b759
dd1f6e2
6ab5769
db01ec7
27ff0fa
f42386e
6bae4f3
deb3597
7b89e76
65f2e4e
e6730c4
81bf427
a5ead0e
b6cfd8e
f4fb585
dc4040f
86f38e0
8807f57
a729528
88fd1a1
951c965
5ccdbe4
b71619c
1898f2f
8229d7c
1e18dc4
c689267
73f84f3
f029f27
0ddea12
021290c
a220a54
d65d377
f87048c
7dc35f8
2c66830
c588fb9
9ff2301
23ba048
1db75b0
3cd2aea
98e5f6b
a671fb8
d3c8c6d
3369d4b
ce15391
7bf4d92
048c3b6
843cd56
ae1a4a5
084ee86
6865a5e
c2668aa
4b620e6
decb2a0
12b6b1e
e81d302
d7affa9
bd31298
27aa405
20b1cd2
046b147
5df6856
7b28c52
f69feda
7f93fe5
5ec79e9
dd1c85a
5bb0764
9522c86
d418486
bf1b7b1
4b939fe
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,130 @@ | ||
package cgo | ||
|
||
import ( | ||
"unsafe" | ||
|
||
blocks "github.com/ipfs/go-block-format" | ||
"github.com/ipfs/go-cid" | ||
blockstore "github.com/ipfs/go-ipfs-blockstore" | ||
) | ||
|
||
/* | ||
#include <stdint.h> | ||
typedef const uint8_t* buf_t; | ||
dignifiedquire marked this conversation as resolved.
Show resolved
Hide resolved
|
||
*/ | ||
import "C" | ||
|
||
func toCid(k C.buf_t, kLen C.int32_t) cid.Cid { | ||
type cidRepr struct { | ||
str string | ||
} | ||
return *(*cid.Cid)(unsafe.Pointer(&cidRepr{ | ||
str: C.GoStringN((*C.char)(unsafe.Pointer(k)), kLen), | ||
})) | ||
} | ||
|
||
//export cgo_blockstore_get | ||
func cgo_blockstore_get(handle C.uint64_t, k C.buf_t, kLen C.int32_t, block **C.uint8_t, size *C.int32_t) C.int32_t { | ||
c := toCid(k, kLen) | ||
externs, ctx := Lookup(uint64(handle)) | ||
if externs == nil { | ||
return ErrInvalidHandle | ||
} | ||
|
||
err := externs.View(ctx, c, func(data []byte) error { | ||
*block = (C.buf_t)(C.CBytes(data)) | ||
*size = C.int32_t(len(data)) | ||
return nil | ||
}) | ||
|
||
switch err { | ||
case nil: | ||
return 0 | ||
case blockstore.ErrNotFound: | ||
return ErrNotFound | ||
default: | ||
return ErrIO | ||
} | ||
} | ||
|
||
//export cgo_blockstore_put | ||
func cgo_blockstore_put(handle C.uint64_t, k C.buf_t, kLen C.int32_t, block C.buf_t, blockLen C.int32_t) C.int32_t { | ||
c := toCid(k, kLen) | ||
externs, ctx := Lookup(uint64(handle)) | ||
if externs == nil { | ||
return ErrInvalidHandle | ||
} | ||
b, _ := blocks.NewBlockWithCid(C.GoBytes(unsafe.Pointer(block), blockLen), c) | ||
if externs.Put(ctx, b) != nil { | ||
return ErrIO | ||
} | ||
return 0 | ||
} | ||
|
||
//export cgo_blockstore_put_many | ||
func cgo_blockstore_put_many(handle C.uint64_t, lengths *C.int32_t, lengthsLen C.int32_t, blockBuf C.buf_t) C.int32_t { | ||
externs, ctx := Lookup(uint64(handle)) | ||
if externs == nil { | ||
return ErrInvalidHandle | ||
} | ||
// Get a reference to the lengths vector without copying. | ||
const MAX_LEN = 1 << 30 | ||
if lengthsLen > MAX_LEN { | ||
return ErrInvalidArgument | ||
} | ||
|
||
lengthsGo := (*[MAX_LEN]C.int32_t)(unsafe.Pointer(lengths))[:lengthsLen:lengthsLen] | ||
blocksGo := make([]blocks.Block, 0, lengthsLen) | ||
for _, length := range lengthsGo { | ||
if length > MAX_LEN { | ||
return ErrInvalidArgument | ||
} | ||
// get the next buffer. We could use C.GoBytes, but that copies. | ||
buf := (*[MAX_LEN]byte)(unsafe.Pointer(blockBuf))[:length:length] | ||
|
||
// read the CID. This function will copy the CID internally. | ||
cidLen, k, err := cid.CidFromBytes(buf) | ||
if err != nil { | ||
return ErrInvalidArgument | ||
} | ||
buf = buf[cidLen:] | ||
|
||
// Read the block and copy it. Unfortunately, our blockstore makes no guarantees | ||
// about not holding onto blocks. | ||
block := make([]byte, len(buf)) | ||
copy(block, buf) | ||
b, _ := blocks.NewBlockWithCid(block, k) | ||
|
||
// Add it to the batch. | ||
blocksGo = append(blocksGo, b) | ||
|
||
// Advance the block buffer. | ||
blockBuf = (C.buf_t)(unsafe.Pointer(uintptr(unsafe.Pointer(blockBuf)) + uintptr(length))) | ||
} | ||
if externs.PutMany(ctx, blocksGo) != nil { | ||
return ErrIO | ||
} | ||
return 0 | ||
} | ||
|
||
//export cgo_blockstore_has | ||
func cgo_blockstore_has(handle C.uint64_t, k C.buf_t, kLen C.int32_t) C.int32_t { | ||
c := toCid(k, kLen) | ||
externs, ctx := Lookup(uint64(handle)) | ||
if externs == nil { | ||
return ErrInvalidHandle | ||
} | ||
has, err := externs.Has(ctx, c) | ||
switch err { | ||
case nil: | ||
case blockstore.ErrNotFound: | ||
// Some old blockstores still return this. | ||
return 0 | ||
default: | ||
return ErrIO | ||
} | ||
if has { | ||
return 1 | ||
} | ||
return 0 | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
package cgo | ||
|
||
const ( | ||
ErrInvalidHandle = -1 - iota | ||
Stebalien marked this conversation as resolved.
Show resolved
Hide resolved
|
||
ErrNotFound | ||
ErrIO | ||
ErrInvalidArgument | ||
) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,97 @@ | ||
package cgo | ||
|
||
/* | ||
#include <stdint.h> | ||
typedef const uint8_t* buf_t; | ||
*/ | ||
import "C" | ||
import ( | ||
"unsafe" | ||
|
||
"github.com/filecoin-project/go-address" | ||
|
||
"github.com/filecoin-project/go-state-types/abi" | ||
"github.com/filecoin-project/go-state-types/crypto" | ||
) | ||
|
||
//export cgo_extern_get_chain_randomness | ||
func cgo_extern_get_chain_randomness( | ||
handle C.uint64_t, pers C.int64_t, round C.int64_t, | ||
entropy C.buf_t, entropyLen C.int32_t, | ||
output C.buf_t, | ||
) C.int32_t { | ||
out := (*[32]byte)(unsafe.Pointer(output)) | ||
externs, ctx := Lookup(uint64(handle)) | ||
if externs == nil { | ||
return ErrInvalidHandle | ||
} | ||
|
||
rand, err := externs.GetChainRandomness(ctx, crypto.DomainSeparationTag(pers), abi.ChainEpoch(round), C.GoBytes(unsafe.Pointer(entropy), entropyLen)) | ||
|
||
switch err { | ||
case nil: | ||
copy(out[:], rand) | ||
return 0 | ||
default: | ||
return ErrIO | ||
} | ||
} | ||
|
||
//export cgo_extern_get_beacon_randomness | ||
func cgo_extern_get_beacon_randomness( | ||
handle C.uint64_t, pers C.int64_t, round C.int64_t, | ||
entropy C.buf_t, entropyLen C.int32_t, | ||
output C.buf_t, | ||
) C.int32_t { | ||
out := (*[32]byte)(unsafe.Pointer(output)) | ||
externs, ctx := Lookup(uint64(handle)) | ||
if externs == nil { | ||
return ErrInvalidHandle | ||
} | ||
|
||
rand, err := externs.GetBeaconRandomness(ctx, crypto.DomainSeparationTag(pers), abi.ChainEpoch(round), C.GoBytes(unsafe.Pointer(entropy), entropyLen)) | ||
|
||
switch err { | ||
case nil: | ||
copy(out[:], rand) | ||
return 0 | ||
default: | ||
return ErrIO | ||
} | ||
} | ||
|
||
//export cgo_extern_verify_consensus_fault | ||
func cgo_extern_verify_consensus_fault( | ||
handle C.uint64_t, | ||
h1 C.buf_t, h1Len C.int32_t, | ||
h2 C.buf_t, h2Len C.int32_t, | ||
extra C.buf_t, extraLen C.int32_t, | ||
minerId *C.uint64_t, | ||
Stebalien marked this conversation as resolved.
Show resolved
Hide resolved
|
||
epoch *C.int64_t, | ||
fault *C.int64_t, | ||
gasUsed *C.int64_t, | ||
) C.int32_t { | ||
externs, ctx := Lookup(uint64(handle)) | ||
if externs == nil { | ||
return ErrInvalidHandle | ||
} | ||
|
||
h1Go := C.GoBytes(unsafe.Pointer(h1), h1Len) | ||
h2Go := C.GoBytes(unsafe.Pointer(h2), h2Len) | ||
extraGo := C.GoBytes(unsafe.Pointer(extra), extraLen) | ||
|
||
res, gas := externs.VerifyConsensusFault(ctx, h1Go, h2Go, extraGo) | ||
*gasUsed = C.int64_t(gas) | ||
*fault = C.int64_t(res.Type) | ||
|
||
if res.Type != ConsensusFaultNone { | ||
id, err := address.IDFromAddress(res.Target) | ||
if err != nil { | ||
return ErrIO | ||
} | ||
*epoch = C.int64_t(res.Epoch) | ||
*minerId = C.uint64_t(id) | ||
} | ||
|
||
return 0 | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
package cgo | ||
|
||
import ( | ||
"context" | ||
|
||
"github.com/filecoin-project/go-address" | ||
"github.com/filecoin-project/go-state-types/abi" | ||
"github.com/filecoin-project/go-state-types/crypto" | ||
blockstore "github.com/ipfs/go-ipfs-blockstore" | ||
) | ||
|
||
type ConsensusFault struct { | ||
// Address of the miner at fault (always an ID address). | ||
Target address.Address | ||
// Epoch of the fault, which is the higher epoch of the two blocks causing it. | ||
Epoch abi.ChainEpoch | ||
// Type of fault. | ||
Type ConsensusFaultType | ||
} | ||
|
||
type ConsensusFaultType int64 | ||
|
||
const ( | ||
ConsensusFaultNone ConsensusFaultType = 0 | ||
ConsensusFaultDoubleForkMining ConsensusFaultType = 1 | ||
ConsensusFaultParentGrinding ConsensusFaultType = 2 | ||
ConsensusFaultTimeOffsetMining ConsensusFaultType = 3 | ||
) | ||
|
||
type Externs interface { | ||
GetChainRandomness(ctx context.Context, personalization crypto.DomainSeparationTag, epoch abi.ChainEpoch, entropy []byte) ([]byte, error) | ||
GetBeaconRandomness(ctx context.Context, personalization crypto.DomainSeparationTag, epoch abi.ChainEpoch, entropy []byte) ([]byte, error) | ||
VerifyConsensusFault(ctx context.Context, h1, h2, extra []byte) (*ConsensusFault, int64) | ||
|
||
blockstore.Blockstore | ||
blockstore.Viewer | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
package cgo | ||
|
||
import ( | ||
"context" | ||
"sync" | ||
) | ||
|
||
var ( | ||
mu sync.RWMutex | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @Stebalien are you planning on pulling the atomic version into this? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Does it work? IIRC, it was slower, right? But anyways, I'd kind of like to merge this version first, if possible. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I meant this one that you wrote: https://github.com/filecoin-project/cgo-blockstore/blob/master/blockstore.go#L17 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Oh, hell no. Not unless this turns out to be the bottleneck. |
||
registry map[uint64]registeredExterns | ||
nextId uint64 | ||
) | ||
|
||
type registeredExterns struct { | ||
context.Context | ||
Externs | ||
} | ||
|
||
// Register a new item and get a handle. | ||
func Register(ctx context.Context, externs Externs) uint64 { | ||
mu.Lock() | ||
defer mu.Unlock() | ||
if registry == nil { | ||
registry = make(map[uint64]registeredExterns) | ||
} | ||
id := nextId | ||
nextId++ | ||
registry[id] = registeredExterns{ctx, externs} | ||
return id | ||
} | ||
|
||
// Unregister a blockstore. | ||
// | ||
// WARNING: This method must be called at most _once_ with a handle previously returned by Register. | ||
func Unregister(handle uint64) { | ||
mu.Lock() | ||
defer mu.Unlock() | ||
|
||
delete(registry, handle) | ||
} | ||
|
||
// Lookup a blockstore by handle. | ||
func Lookup(handle uint64) (Externs, context.Context) { | ||
mu.RLock() | ||
externs := registry[handle] | ||
mu.RUnlock() | ||
|
||
return externs.Externs, externs.Context | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
FYI this version is significantly out of date in terms of bugfix releases, the latest is 1.16.15. 1.16.x is also unsupported now that 1.18 is out, but I imagine you're already aware of that.