Commit a9a7ab52 authored by 董子豪's avatar 董子豪

test

parent 7f9981bb
version: 2.1
orbs:
go: gotest/tools@0.0.9
codecov: codecov/codecov@1.0.2
executors:
golang:
docker:
- image: circleci/golang:1.13
resource_class: small
commands:
install-deps:
steps:
- go/install-ssh
- go/install: {package: git}
prepare:
parameters:
linux:
default: true
description: is a linux build environment?
type: boolean
steps:
- checkout
- when:
condition: << parameters.linux >>
steps:
- run: sudo apt-get update
build-all:
jobs:
mod-tidy-check:
executor: golang
steps:
- install-deps
- prepare
- go/mod-download
- go/mod-tidy-check
build-all:
executor: golang
steps:
- install-deps
- prepare
- go/mod-download
- run:
command: make build
- store_artifacts:
path: go-state-types
- store_artifacts:
path: go-state-types
check-gen:
executor: golang
steps:
- install-deps
- prepare
- go/mod-download
- run:
name: "Install goimports"
command: |
cd / && go get golang.org/x/tools/cmd/goimports
- run:
name: "Ensure we don't need to run 'make gen'"
command: |
make gen && git diff --exit-code
test-all:
executor: golang
steps:
- install-deps
- prepare
- go/mod-download
- run:
command: |
make test-coverage
mkdir -p /tmp/artifacts
mv coverage.out /tmp/artifacts/coverage.out
- codecov/upload:
file: /tmp/artifacts/coverage.out
- store_artifacts:
path: go-state-types
lint: &lint
description: |
Run golangci-lint.
parameters:
executor:
type: executor
default: golang
golangci-lint-version:
type: string
default: 1.23.1
concurrency:
type: string
default: '2'
description: |
Concurrency used to run linters. Defaults to 2 because NumCPU is not
aware of container CPU limits.
args:
type: string
default: ''
description: |
Arguments to pass to golangci-lint
executor: << parameters.executor >>
steps:
- install-deps
- prepare
- run:
command: make build
- go/install-golangci-lint:
gobin: $HOME/.local/bin
version: << parameters.golangci-lint-version >>
- run:
name: Lint
command: |
$HOME/.local/bin/golangci-lint run -v --skip-dirs-use-default=false\
--concurrency << parameters.concurrency >> << parameters.args >>
lint-all:
<<: *lint
workflows:
version: 2.1
ci:
jobs:
- lint-all
- mod-tidy-check
- build-all
- test-all
- check-gen
Copyright 2020. Protocol Labs, Inc.
This library is dual-licensed under Apache 2.0 and MIT terms.
Copyright 2020. Protocol Labs, Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Copyright 2020. Protocol Labs, Inc.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
GO_BIN ?= go
GOLINT ?= golangci-lint
all: build lint test tidy
.PHONY: all
build:
$(GO_BIN) build ./...
.PHONY: build
test:
$(GO_BIN) test ./...
.PHONY: test
test-coverage:
$(GO_BIN) test -coverprofile=coverage.out ./...
.PHONY: test-coverage
tidy:
$(GO_BIN) mod tidy
.PHONY: tidy
gen:
$(GO_BIN) run ./gen/gen.go
.PHONY: gen
lint:
$(GOLINT) run ./...
.PHONY: lint
# Filecoin state types
[![CircleCI](https://circleci.com/gh/filecoin-project/go-state-types.svg?style=svg)](https://circleci.com/gh/filecoin-project/go-state-types)
[![codecov](https://codecov.io/gh/filecoin-project/go-state-types/branch/master/graph/badge.svg)](https://codecov.io/gh/filecoin-project/go-state-types)
This repository contains primitive and low level types used in the Filecoin blockchain state representation.
These are primarily intended for use by [Actors](https://github.com/filecoin-project/specs-actors) and other
modules that read chain state directly.
## Versioning
Blockchain state versioning does not naturally align with common semantic versioning conventions.
Any change in behaviour, including repairing any error that may have affected blockchain evaluation,
must be released in a major version change. We intend that to be a rare event for the contents of
this repository.
## License
This repository is dual-licensed under Apache 2.0 and MIT terms.
Copyright 2020. Protocol Labs, Inc.
package abi
import "strconv"
// A sequential number assigned to an actor when created by the InitActor.
// This ID is embedded in ID-type addresses.
type ActorID uint64
func (e ActorID) String() string {
return strconv.FormatInt(int64(e), 10)
}
// MethodNum is an integer that represents a particular method
// in an actor's function table. These numbers are used to compress
// invocation of actor code, and to decouple human language concerns
// about method names from the ability to uniquely refer to a particular
// method.
//
// Consider MethodNum numbers to be similar in concerns as for
// offsets in function tables (in programming languages), and for
// tags in ProtocolBuffer fields. Tags in ProtocolBuffers recommend
// assigning a unique tag to a field and never reusing that tag.
// If a field is no longer used, the field name may change but should
// still remain defined in the code to ensure the tag number is not
// reused accidentally. The same should apply to the MethodNum
// associated with methods in Filecoin VM Actors.
type MethodNum uint64
func (e MethodNum) String() string {
return strconv.FormatInt(int64(e), 10)
}
// Multiaddrs is a byte array representing a Libp2p MultiAddress
type Multiaddrs = []byte
// PeerID is a byte array representing a Libp2p PeerID
type PeerID = []byte
// Code generated by github.com/whyrusleeping/cbor-gen. DO NOT EDIT.
package abi
import (
"fmt"
"io"
cbg "github.com/whyrusleeping/cbor-gen"
xerrors "golang.org/x/xerrors"
)
var _ = xerrors.Errorf
var lengthBufPieceInfo = []byte{130}
func (t *PieceInfo) MarshalCBOR(w io.Writer) error {
if t == nil {
_, err := w.Write(cbg.CborNull)
return err
}
if _, err := w.Write(lengthBufPieceInfo); err != nil {
return err
}
scratch := make([]byte, 9)
// t.Size (abi.PaddedPieceSize) (uint64)
if err := cbg.WriteMajorTypeHeaderBuf(scratch, w, cbg.MajUnsignedInt, uint64(t.Size)); err != nil {
return err
}
// t.PieceCID (cid.Cid) (struct)
if err := cbg.WriteCidBuf(scratch, w, t.PieceCID); err != nil {
return xerrors.Errorf("failed to write cid field t.PieceCID: %w", err)
}
return nil
}
func (t *PieceInfo) UnmarshalCBOR(r io.Reader) error {
*t = PieceInfo{}
br := cbg.GetPeeker(r)
scratch := make([]byte, 8)
maj, extra, err := cbg.CborReadHeaderBuf(br, scratch)
if err != nil {
return err
}
if maj != cbg.MajArray {
return fmt.Errorf("cbor input should be of type array")
}
if extra != 2 {
return fmt.Errorf("cbor input had wrong number of fields")
}
// t.Size (abi.PaddedPieceSize) (uint64)
{
maj, extra, err = cbg.CborReadHeaderBuf(br, scratch)
if err != nil {
return err
}
if maj != cbg.MajUnsignedInt {
return fmt.Errorf("wrong type for uint64 field")
}
t.Size = PaddedPieceSize(extra)
}
// t.PieceCID (cid.Cid) (struct)
{
c, err := cbg.ReadCid(br)
if err != nil {
return xerrors.Errorf("failed to read cid field t.PieceCID: %w", err)
}
t.PieceCID = c
}
return nil
}
var lengthBufSectorID = []byte{130}
func (t *SectorID) MarshalCBOR(w io.Writer) error {
if t == nil {
_, err := w.Write(cbg.CborNull)
return err
}
if _, err := w.Write(lengthBufSectorID); err != nil {
return err
}
scratch := make([]byte, 9)
// t.Miner (abi.ActorID) (uint64)
if err := cbg.WriteMajorTypeHeaderBuf(scratch, w, cbg.MajUnsignedInt, uint64(t.Miner)); err != nil {
return err
}
// t.Number (abi.SectorNumber) (uint64)
if err := cbg.WriteMajorTypeHeaderBuf(scratch, w, cbg.MajUnsignedInt, uint64(t.Number)); err != nil {
return err
}
return nil
}
func (t *SectorID) UnmarshalCBOR(r io.Reader) error {
*t = SectorID{}
br := cbg.GetPeeker(r)
scratch := make([]byte, 8)
maj, extra, err := cbg.CborReadHeaderBuf(br, scratch)
if err != nil {
return err
}
if maj != cbg.MajArray {
return fmt.Errorf("cbor input should be of type array")
}
if extra != 2 {
return fmt.Errorf("cbor input had wrong number of fields")
}
// t.Miner (abi.ActorID) (uint64)
{
maj, extra, err = cbg.CborReadHeaderBuf(br, scratch)
if err != nil {
return err
}
if maj != cbg.MajUnsignedInt {
return fmt.Errorf("wrong type for uint64 field")
}
t.Miner = ActorID(extra)
}
// t.Number (abi.SectorNumber) (uint64)
{
maj, extra, err = cbg.CborReadHeaderBuf(br, scratch)
if err != nil {
return err
}
if maj != cbg.MajUnsignedInt {
return fmt.Errorf("wrong type for uint64 field")
}
t.Number = SectorNumber(extra)
}
return nil
}
package abi
import (
"strconv"
"github.com/filecoin-project/go-state-types/big"
)
// Epoch number of the chain state, which acts as a proxy for time within the VM.
type ChainEpoch int64
func (e ChainEpoch) String() string {
return strconv.FormatInt(int64(e), 10)
}
// TokenAmount is an amount of Filecoin tokens. This type is used within
// the VM in message execution, to account movement of tokens, payment
// of VM gas, and more.
//
// BigInt types are aliases rather than new types because the latter introduce incredible amounts of noise converting to
// and from types in order to manipulate values. We give up some type safety for ergonomics.
type TokenAmount = big.Int
func NewTokenAmount(t int64) TokenAmount {
return big.NewInt(t)
}
// Randomness is a string of random bytes
type Randomness []byte
// RandomnessLength is the length of the randomness slice.
const RandomnessLength = 32
package abi
import (
cid "github.com/ipfs/go-cid"
mh "github.com/multiformats/go-multihash"
)
var (
// HashFunction is the default hash function for computing CIDs.
//
// This is currently Blake2b-256.
HashFunction = uint64(mh.BLAKE2B_MIN + 31)
// When producing a CID for an IPLD block less than or equal to CIDInlineLimit
// bytes in length, the identity hash function will be used instead of
// HashFunction. This will effectively "inline" the block into the CID, allowing
// it to be extracted directly from the CID with no disk/network operations.
//
// This is currently -1 for "disabled".
//
// This is exposed for testing. Do not modify unless you know what you're doing.
CIDInlineLimit = -1
)
type cidBuilder struct {
codec uint64
}
func (cidBuilder) WithCodec(c uint64) cid.Builder {
return cidBuilder{codec: c}
}
func (b cidBuilder) GetCodec() uint64 {
return b.codec
}
func (b cidBuilder) Sum(data []byte) (cid.Cid, error) {
hf := HashFunction
if len(data) <= CIDInlineLimit {
hf = mh.IDENTITY
}
return cid.V1Builder{Codec: b.codec, MhType: hf}.Sum(data)
}
// CidBuilder is the default CID builder for Filecoin.
//
// - The default codec is CBOR. This can be changed with CidBuilder.WithCodec.
// - The default hash function is 256bit blake2b.
var CidBuilder cid.Builder = cidBuilder{codec: cid.DagCBOR}
package abi
import "github.com/filecoin-project/go-state-types/big"
type DealID uint64
// BigInt types are aliases rather than new types because the latter introduce incredible amounts of noise
// converting to and from types in order to manipulate values.
// We give up some type safety for ergonomics.
type DealWeight = big.Int // units: byte-epochs
package abi
import (
"fmt"
"io"
cbg "github.com/whyrusleeping/cbor-gen"
)
// The empty value represents absence of a value. It is used for parameter and return types for actor methods
// that don't take/return any data. This saves a byte in serialization of messages and receipts: the serialized
// form is an empty byte slice, rather than a byte slice containing a single byte CBOR encoding of nil/empty/etc.
//
// The only expected use of this is as the type of a nil reference. Don't instantiate this type.
//
// This is primarily necessary due to Go's lack of a void type and our interface-based serialization scheme.
type EmptyValue struct{}
// A typed nil pointer to EmptyValue.
var Empty *EmptyValue = nil
var _ cbg.CBORMarshaler = (*EmptyValue)(nil)
var _ cbg.CBORUnmarshaler = (*EmptyValue)(nil)
func (v *EmptyValue) MarshalCBOR(_ io.Writer) error {
// An attempt to serialize a non-nil value indicates a caller mis-using this type.
if v != nil {
return fmt.Errorf("cannot marshal empty value, try nil instead")
}
// Allow nil to write zero bytes as a convenience so callers don't need to nil-check all values before
// attempting serialization.
return nil
}
func (v *EmptyValue) UnmarshalCBOR(_ io.Reader) error {
// Read zero bytes.
return nil
}
package abi
import (
"encoding/binary"
"errors"
"github.com/filecoin-project/go-address"
"github.com/ipfs/go-cid"
)
// Keyer defines an interface required to put values in mapping.
type Keyer interface {
Key() string
}
// Adapts an address as a mapping key.
type AddrKey address.Address
func (k AddrKey) Key() string {
return string(address.Address(k).Bytes())
}
type CidKey cid.Cid
func (k CidKey) Key() string {
return cid.Cid(k).KeyString()
}
// Adapts an int64 as a mapping key.
type intKey struct {
int64
}
//noinspection GoExportedFuncWithUnexportedType
func IntKey(k int64) intKey {
return intKey{k}
}
func (k intKey) Key() string {
buf := make([]byte, 10)
n := binary.PutVarint(buf, k.int64)
return string(buf[:n])
}
//noinspection GoUnusedExportedFunction
func ParseIntKey(k string) (int64, error) {
i, n := binary.Varint([]byte(k))
if n != len(k) {
return 0, errors.New("failed to decode varint key")
}
return i, nil
}
// Adapts a uint64 as a mapping key.
type uintKey struct {
uint64
}
//noinspection GoExportedFuncWithUnexportedType
func UIntKey(k uint64) uintKey {
return uintKey{k}
}
func (k uintKey) Key() string {
buf := make([]byte, 10)
n := binary.PutUvarint(buf, k.uint64)
return string(buf[:n])
}
func ParseUIntKey(k string) (uint64, error) {
i, n := binary.Uvarint([]byte(k))
if n != len(k) {
return 0, errors.New("failed to decode varint key")
}
return i, nil
}
package abi_test
import (
"testing"
"github.com/stretchr/testify/assert"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-state-types/abi"
)
func newIDAddr(t testing.TB, id uint64) address.Address {
address, err := address.NewIDAddress(id)
if err != nil {
t.Fatal(err)
}
return address
}
func newActorAddr(t testing.TB, data string) address.Address {
address, err := address.NewActorAddress([]byte(data))
if err != nil {
t.Fatal(err)
}
return address
}
func TestAddrKey(t *testing.T) {
id_address_1 := newIDAddr(t, 101)
id_address_2 := newIDAddr(t, 102)
actor_address_1 := newActorAddr(t, "actor1")
actor_address_2 := newActorAddr(t, "222")
t.Run("address to key string conversion", func(t *testing.T) {
assert.Equal(t, "\x00\x65", abi.AddrKey(id_address_1).Key())
assert.Equal(t, "\x00\x66", abi.AddrKey(id_address_2).Key())
assert.Equal(t, "\x02\x58\xbe\x4f\xd7\x75\xa0\xc8\xcd\x9a\xed\x86\x4e\x73\xab\xb1\x86\x46\x5f\xef\xe1", abi.AddrKey(actor_address_1).Key())
assert.Equal(t, "\x02\xaa\xd0\xb2\x98\xa9\xde\xab\xbb\xb6\u007f\x80\x5f\x66\xaa\x68\x8c\xdd\x89\xad\xf5", abi.AddrKey(actor_address_2).Key())
})
}
package abi
import (
"math/bits"
cid "github.com/ipfs/go-cid"
"golang.org/x/xerrors"
)
// UnpaddedPieceSize is the size of a piece, in bytes
type UnpaddedPieceSize uint64
type PaddedPieceSize uint64
func (s UnpaddedPieceSize) Padded() PaddedPieceSize {
return PaddedPieceSize(s + (s / 127))
}
func (s UnpaddedPieceSize) Validate() error {
if s < 127 {
return xerrors.New("minimum piece size is 127 bytes")
}
// is 127 * 2^n
if uint64(s)>>bits.TrailingZeros64(uint64(s)) != 127 {
return xerrors.New("unpadded piece size must be a power of 2 multiple of 127")
}
return nil
}
func (s PaddedPieceSize) Unpadded() UnpaddedPieceSize {
return UnpaddedPieceSize(s - (s / 128))
}
func (s PaddedPieceSize) Validate() error {
if s < 128 {
return xerrors.New("minimum padded piece size is 128 bytes")
}
if bits.OnesCount64(uint64(s)) != 1 {
return xerrors.New("padded piece size must be a power of 2")
}
return nil
}
type PieceInfo struct {
Size PaddedPieceSize // Size in nodes. For BLS12-381 (capacity 254 bits), must be >= 16. (16 * 8 = 128)
PieceCID cid.Cid
}
package abi
import (
"testing"
"github.com/stretchr/testify/require"
)
func TestPieceSize(t *testing.T) {
// happy
require.NoError(t, UnpaddedPieceSize(127).Validate())
require.NoError(t, UnpaddedPieceSize(1016).Validate())
require.NoError(t, UnpaddedPieceSize(34091302912).Validate())
require.NoError(t, PaddedPieceSize(128).Validate())
require.NoError(t, PaddedPieceSize(1024).Validate())
require.NoError(t, PaddedPieceSize(34359738368).Validate())
// convert
require.Equal(t, PaddedPieceSize(128), UnpaddedPieceSize(127).Padded())
require.Equal(t, PaddedPieceSize(1024), UnpaddedPieceSize(1016).Padded())
require.Equal(t, PaddedPieceSize(34359738368), UnpaddedPieceSize(34091302912).Padded())
require.Equal(t, UnpaddedPieceSize(127), PaddedPieceSize(128).Unpadded())
require.Equal(t, UnpaddedPieceSize(1016), PaddedPieceSize(1024).Unpadded())
require.Equal(t, UnpaddedPieceSize(34091302912), PaddedPieceSize(34359738368).Unpadded())
// swap
require.NoError(t, UnpaddedPieceSize(127).Padded().Validate())
require.NoError(t, UnpaddedPieceSize(1016).Padded().Validate())
require.NoError(t, UnpaddedPieceSize(34091302912).Padded().Validate())
require.NoError(t, PaddedPieceSize(128).Unpadded().Validate())
require.NoError(t, PaddedPieceSize(1024).Unpadded().Validate())
require.NoError(t, PaddedPieceSize(34359738368).Unpadded().Validate())
// roundtrip
require.NoError(t, UnpaddedPieceSize(127).Padded().Unpadded().Validate())
require.NoError(t, UnpaddedPieceSize(1016).Padded().Unpadded().Validate())
require.NoError(t, UnpaddedPieceSize(34091302912).Padded().Unpadded().Validate())
require.NoError(t, PaddedPieceSize(128).Unpadded().Padded().Validate())
require.NoError(t, PaddedPieceSize(1024).Unpadded().Padded().Validate())
require.NoError(t, PaddedPieceSize(34359738368).Unpadded().Padded().Validate())
// unhappy
require.Error(t, UnpaddedPieceSize(9).Validate())
require.Error(t, UnpaddedPieceSize(128).Validate())
require.Error(t, UnpaddedPieceSize(99453687).Validate())
require.Error(t, UnpaddedPieceSize(1016+0x1000000).Validate())
require.Error(t, PaddedPieceSize(8).Validate())
require.Error(t, PaddedPieceSize(127).Validate())
require.Error(t, PaddedPieceSize(99453687).Validate())
require.Error(t, PaddedPieceSize(0xc00).Validate())
require.Error(t, PaddedPieceSize(1025).Validate())
}
This diff is collapsed.
package abi_test
import (
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/filecoin-project/go-state-types/abi"
)
func TestSectorSizeString(t *testing.T) {
assert.Equal(t, "0", abi.SectorSize(0).String())
assert.Equal(t, "1", abi.SectorSize(1).String())
assert.Equal(t, "1024", abi.SectorSize(1024).String())
assert.Equal(t, "1234", abi.SectorSize(1234).String())
assert.Equal(t, "1125899906842624", abi.SectorSize(1125899906842624).String())
}
func TestSectorSizeShortString(t *testing.T) {
kib := uint64(1024)
pib := uint64(1125899906842624)
assert.Equal(t, "0B", abi.SectorSize(0).ShortString())
assert.Equal(t, "1B", abi.SectorSize(1).ShortString())
assert.Equal(t, "1023B", abi.SectorSize(1023).ShortString())
assert.Equal(t, "1KiB", abi.SectorSize(kib).ShortString())
assert.Equal(t, "1KiB", abi.SectorSize(kib+1).ShortString()) // truncated
assert.Equal(t, "1KiB", abi.SectorSize(kib*2-1).ShortString()) // truncated
assert.Equal(t, "2KiB", abi.SectorSize(kib*2).ShortString())
assert.Equal(t, "2KiB", abi.SectorSize(kib*2+1).ShortString()) // truncated
assert.Equal(t, "1023KiB", abi.SectorSize(kib*1023).ShortString())
assert.Equal(t, "1MiB", abi.SectorSize(1048576).ShortString())
assert.Equal(t, "1GiB", abi.SectorSize(1073741824).ShortString())
assert.Equal(t, "1TiB", abi.SectorSize(1099511627776).ShortString())
assert.Equal(t, "1PiB", abi.SectorSize(pib).ShortString())
assert.Equal(t, "1EiB", abi.SectorSize(pib*kib).ShortString())
assert.Equal(t, "10EiB", abi.SectorSize(pib*kib*10).ShortString())
}
func TestV1_1SealProofEquivalence(t *testing.T) {
for v1 := abi.RegisteredSealProof_StackedDrg2KiBV1; v1 < abi.RegisteredSealProof_StackedDrg2KiBV1_1; v1++ {
v1Size, err := v1.SectorSize()
require.NoError(t, err)
v1Wpost, err := v1.RegisteredWindowPoStProof()
require.NoError(t, err)
v1Gpost, err := v1.RegisteredWinningPoStProof()
require.NoError(t, err)
v1_1 := v1 + 5 // RegisteredSealProof_StackedDrgXxxV1_1
v11Size, err := v1_1.SectorSize()
require.NoError(t, err)
v11Wpost, err := v1_1.RegisteredWindowPoStProof()
require.NoError(t, err)
v11Gpost, err := v1_1.RegisteredWinningPoStProof()
require.NoError(t, err)
assert.Equal(t, v1Size, v11Size)
assert.Equal(t, v1Wpost, v11Wpost)
assert.Equal(t, v1Gpost, v11Gpost)
gpost := abi.RegisteredPoStProof(v1) // RegisteredPoStProof_StackedDrgWinningXxxV1
gpostSize, err := gpost.SectorSize()
require.NoError(t, err)
assert.Equal(t, v1Size, gpostSize)
wpost := gpost + 5 // RegisteredPoStProof_StackedDrgWindowXxxV1
wpostSize, err := wpost.SectorSize()
require.NoError(t, err)
assert.Equal(t, v1Size, wpostSize)
}
}
package big
import (
"encoding/json"
"fmt"
"io"
"math/big"
cbg "github.com/whyrusleeping/cbor-gen"
)
// BigIntMaxSerializedLen is the max length of a byte slice representing a CBOR serialized big.
const BigIntMaxSerializedLen = 128
type Int struct {
*big.Int
}
func NewInt(i int64) Int {
return Int{big.NewInt(0).SetInt64(i)}
}
func NewIntUnsigned(i uint64) Int {
return Int{big.NewInt(0).SetUint64(i)}
}
func NewFromGo(i *big.Int) Int {
return Int{big.NewInt(0).Set(i)}
}
func Zero() Int {
return NewInt(0)
}
// PositiveFromUnsignedBytes interprets b as the bytes of a big-endian unsigned
// integer and returns a positive Int with this absolute value.
func PositiveFromUnsignedBytes(b []byte) Int {
i := big.NewInt(0).SetBytes(b)
return Int{i}
}
// MustFromString convers dec string into big integer and panics if conversion
// is not sucessful.
func MustFromString(s string) Int {
v, err := FromString(s)
if err != nil {
panic(err)
}
return v
}
func FromString(s string) (Int, error) {
v, ok := big.NewInt(0).SetString(s, 10)
if !ok {
return Int{}, fmt.Errorf("failed to parse string as a big int")
}
return Int{v}, nil
}
func (bi Int) Copy() Int {
return Int{Int: new(big.Int).Set(bi.Int)}
}
func Product(ints ...Int) Int {
p := NewInt(1)
for _, i := range ints {
p = Mul(p, i)
}
return p
}
func Mul(a, b Int) Int {
return Int{big.NewInt(0).Mul(a.Int, b.Int)}
}
func Div(a, b Int) Int {
return Int{big.NewInt(0).Div(a.Int, b.Int)}
}
func Mod(a, b Int) Int {
return Int{big.NewInt(0).Mod(a.Int, b.Int)}
}
func Add(a, b Int) Int {
return Int{big.NewInt(0).Add(a.Int, b.Int)}
}
func Sum(ints ...Int) Int {
sum := Zero()
for _, i := range ints {
sum = Add(sum, i)
}
return sum
}
func Subtract(num1 Int, ints ...Int) Int {
sub := num1
for _, i := range ints {
sub = Sub(sub, i)
}
return sub
}
func Sub(a, b Int) Int {
return Int{big.NewInt(0).Sub(a.Int, b.Int)}
}
// Returns a**e unless e <= 0 (in which case returns 1).
func Exp(a Int, e Int) Int {
return Int{big.NewInt(0).Exp(a.Int, e.Int, nil)}
}
// Returns x << n
func Lsh(a Int, n uint) Int {
return Int{big.NewInt(0).Lsh(a.Int, n)}
}
// Returns x >> n
func Rsh(a Int, n uint) Int {
return Int{big.NewInt(0).Rsh(a.Int, n)}
}
func BitLen(a Int) uint {
return uint(a.Int.BitLen())
}
func Max(x, y Int) Int {
// taken from max.Max()
if x.Equals(Zero()) && x.Equals(y) {
if x.Sign() != 0 {
return y
}
return x
}
if x.GreaterThan(y) {
return x
}
return y
}
func Min(x, y Int) Int {
// taken from max.Min()
if x.Equals(Zero()) && x.Equals(y) {
if x.Sign() != 0 {
return x
}
return y
}
if x.LessThan(y) {
return x
}
return y
}
func Cmp(a, b Int) int {
return a.Int.Cmp(b.Int)
}
// LessThan returns true if bi < o
func (bi Int) LessThan(o Int) bool {
return Cmp(bi, o) < 0
}
// LessThanEqual returns true if bi <= o
func (bi Int) LessThanEqual(o Int) bool {
return bi.LessThan(o) || bi.Equals(o)
}
// GreaterThan returns true if bi > o
func (bi Int) GreaterThan(o Int) bool {
return Cmp(bi, o) > 0
}
// GreaterThanEqual returns true if bi >= o
func (bi Int) GreaterThanEqual(o Int) bool {
return bi.GreaterThan(o) || bi.Equals(o)
}
// Neg returns the negative of bi.
func (bi Int) Neg() Int {
return Int{big.NewInt(0).Neg(bi.Int)}
}
// Abs returns the absolute value of bi.
func (bi Int) Abs() Int {
if bi.GreaterThanEqual(Zero()) {
return bi.Copy()
}
return bi.Neg()
}
// Equals returns true if bi == o
func (bi Int) Equals(o Int) bool {
return Cmp(bi, o) == 0
}
func (bi *Int) MarshalJSON() ([]byte, error) {
if bi.Int == nil {
zero := Zero()
return json.Marshal(zero)
}
return json.Marshal(bi.String())
}
func (bi *Int) UnmarshalJSON(b []byte) error {
var s string
if err := json.Unmarshal(b, &s); err != nil {
return err
}
i, ok := big.NewInt(0).SetString(s, 10)
if !ok {
return fmt.Errorf("failed to parse big string: '%s'", string(b))
}
bi.Int = i
return nil
}
func (bi *Int) Bytes() ([]byte, error) {
if bi.Int == nil {
return []byte{}, fmt.Errorf("failed to convert to bytes, big is nil")
}
switch {
case bi.Sign() > 0:
return append([]byte{0}, bi.Int.Bytes()...), nil
case bi.Sign() < 0:
return append([]byte{1}, bi.Int.Bytes()...), nil
default: // bi.Sign() == 0:
return []byte{}, nil
}
}
func FromBytes(buf []byte) (Int, error) {
if len(buf) == 0 {
return NewInt(0), nil
}
var negative bool
switch buf[0] {
case 0:
negative = false
case 1:
negative = true
default:
return Zero(), fmt.Errorf("big int prefix should be either 0 or 1, got %d", buf[0])
}
i := big.NewInt(0).SetBytes(buf[1:])
if negative {
i.Neg(i)
}
return Int{i}, nil
}
func (bi *Int) MarshalBinary() ([]byte, error) {
if bi.Int == nil {
zero := Zero()
return zero.Bytes()
}
return bi.Bytes()
}
func (bi *Int) UnmarshalBinary(buf []byte) error {
i, err := FromBytes(buf)
if err != nil {
return err
}
*bi = i
return nil
}
func (bi *Int) MarshalCBOR(w io.Writer) error {
if bi.Int == nil {
zero := Zero()
return zero.MarshalCBOR(w)
}
enc, err := bi.Bytes()
if err != nil {
return err
}
encLen := len(enc)
if encLen > BigIntMaxSerializedLen {
return fmt.Errorf("big integer byte array too long (%d bytes)", encLen)
}
header := cbg.CborEncodeMajorType(cbg.MajByteString, uint64(encLen))
if _, err := w.Write(header); err != nil {
return err
}
if _, err := w.Write(enc); err != nil {
return err
}
return nil
}
func (bi *Int) UnmarshalCBOR(br io.Reader) error {
maj, extra, err := cbg.CborReadHeader(br)
if err != nil {
return err
}
if maj != cbg.MajByteString {
return fmt.Errorf("cbor input for fil big int was not a byte string (%x)", maj)
}
if extra == 0 {
bi.Int = big.NewInt(0)
return nil
}
if extra > BigIntMaxSerializedLen {
return fmt.Errorf("big integer byte array too long (%d bytes)", extra)
}
buf := make([]byte, extra)
if _, err := io.ReadFull(br, buf); err != nil {
return err
}
i, err := FromBytes(buf)
if err != nil {
return err
}
*bi = i
return nil
}
func (bi *Int) IsZero() bool {
return bi.Int.Sign() == 0
}
func (bi *Int) Nil() bool {
return bi.Int == nil
}
func (bi *Int) NilOrZero() bool {
return bi.Int == nil || bi.Int.Sign() == 0
}
package big
import (
"bytes"
"fmt"
"math/big"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
cbg "github.com/whyrusleeping/cbor-gen"
)
func TestBigIntSerializationRoundTrip(t *testing.T) {
testValues := []string{
"0", "1", "10", "-10", "9999", "12345678901234567891234567890123456789012345678901234567890",
}
for _, v := range testValues {
bi, err := FromString(v)
if err != nil {
t.Fatal(err)
}
buf := new(bytes.Buffer)
if err := bi.MarshalCBOR(buf); err != nil {
t.Fatal(err)
}
var out Int
if err := out.UnmarshalCBOR(buf); err != nil {
t.Fatal(err)
}
if Cmp(out, bi) != 0 {
t.Fatal("failed to round trip Int through cbor")
}
}
// nil check
bi := Int{}
var buf bytes.Buffer
err := bi.MarshalCBOR(&buf)
require.NoError(t, err)
assert.Equal(t, "@", buf.String())
}
func TestNewInt(t *testing.T) {
a := int64(999)
ta := NewInt(a)
b := big.NewInt(999)
tb := Int{Int: b}
tc := NewIntUnsigned(999)
assert.True(t, ta.Equals(tb))
assert.True(t, ta.Equals(tc))
assert.Equal(t, "999", ta.String())
td := NewFromGo(b)
assert.True(t, td.Equals(tb))
assert.Equal(t, td.Int, b)
}
func TestInt_MarshalUnmarshalJSON(t *testing.T) {
ta := NewInt(54321)
tb := NewInt(0)
res, err := ta.MarshalJSON()
require.NoError(t, err)
assert.Equal(t, "\"54321\"", string(res[:]))
require.NoError(t, tb.UnmarshalJSON(res))
assert.Equal(t, ta, tb)
assert.EqualError(t, tb.UnmarshalJSON([]byte("123garbage"[:])), "invalid character 'g' after top-level value")
tnil := Int{}
s, err := tnil.MarshalJSON()
require.NoError(t, err)
assert.Equal(t, "\"0\"", string(s))
}
func TestOperations(t *testing.T) {
testCases := []struct {
name string
f func(Int, Int) Int
expected Int
}{
{name: "Sum", f: Add, expected: NewInt(7000)},
{name: "Sub", f: Sub, expected: NewInt(3000)},
{name: "Mul", f: Mul, expected: NewInt(10000000)},
{name: "Div", f: Div, expected: NewInt(2)},
{name: "Mod", f: Mod, expected: NewInt(1000)},
}
for _, testCase := range testCases {
t.Run(testCase.name, func(t *testing.T) {
ta := Int{Int: big.NewInt(5000)}
tb := Int{Int: big.NewInt(2000)}
assert.Equal(t, testCase.expected, testCase.f(ta, tb))
})
}
ta := NewInt(5000)
tb := NewInt(2000)
tc := NewInt(2000)
assert.Equal(t, Cmp(ta, tb), 1)
assert.Equal(t, Cmp(tb, ta), -1)
assert.Equal(t, Cmp(tb, tc), 0)
assert.True(t, ta.GreaterThan(tb))
assert.False(t, ta.LessThan(tb))
assert.True(t, tb.Equals(tc))
ta = Int{}
assert.True(t, ta.Nil())
}
func TestCopy(t *testing.T) {
b1 := NewInt(1)
b2 := b1.Copy()
require.EqualValues(t, b1, b2)
require.EqualValues(t, Zero(), Zero().Copy())
}
func TestSum(t *testing.T) {
b1 := NewInt(1)
b2 := NewInt(2)
b3 := NewInt(3)
b4 := NewInt(4)
require.EqualValues(t, NewInt(10), Sum(b1, b2, b3, b4))
require.EqualValues(t, NewInt(20), Sum(NewInt(20)))
}
func TestProduct(t *testing.T) {
b1 := NewInt(1)
b2 := NewInt(2)
b3 := NewInt(3)
b4 := NewInt(4)
require.EqualValues(t, NewInt(24), Product(b1, b2, b3, b4))
require.EqualValues(t, NewInt(20), Product(NewInt(20)))
}
func TestSubtract(t *testing.T) {
b1 := NewInt(100)
b2 := NewInt(20)
b3 := NewInt(10)
b4 := NewInt(5)
require.EqualValues(t, NewInt(65), Subtract(b1, b2, b3, b4))
require.EqualValues(t, NewInt(20), Subtract(NewInt(20)))
}
func TestInt_Format(t *testing.T) {
ta := NewInt(33333000000)
s := fmt.Sprintf("%s", ta) // nolint: gosimple
assert.Equal(t, "33333000000", s)
s1 := fmt.Sprintf("%v", ta) // nolint: gosimple
assert.Equal(t, "33333000000", s1)
s2 := fmt.Sprintf("%-15d", ta) // nolint: gosimple
assert.Equal(t, "33333000000 ", s2)
}
func TestPositveFromUnsignedBytes(t *testing.T) {
res := PositiveFromUnsignedBytes([]byte("garbage"[:]))
// garbage in, garbage out
expected := Int{Int: big.NewInt(29099066505914213)}
assert.Equal(t, expected, res)
expected2 := Int{Int: big.NewInt(12345)}
expectedRes := expected2.Int.Bytes()
res = PositiveFromUnsignedBytes(expectedRes)
assert.Equal(t, expected2, res)
assert.Equal(t, 1, res.Sign()) // positive
}
func TestFromString(t *testing.T) {
_, err := FromString("garbage")
assert.EqualError(t, err, "failed to parse string as a big int")
res, err := FromString("12345")
require.NoError(t, err)
expected := Int{Int: big.NewInt(12345)}
assert.Equal(t, expected, res)
}
func TestCBOR(t *testing.T) {
t.Run("happy", func(t *testing.T) {
ints := []Int{
NewInt(0),
NewInt(-1),
NewInt(1),
NewInt(1e18),
Lsh(NewInt(1), 80),
}
for _, n := range ints {
var b bytes.Buffer
assert.NoError(t, n.MarshalCBOR(&b))
var out Int
assert.NoError(t, out.UnmarshalCBOR(&b))
assert.Equal(t, n, out)
}
})
t.Run("fails to marshal too large", func(t *testing.T) {
giant := Lsh(NewInt(1), 8*(BigIntMaxSerializedLen-1))
var b bytes.Buffer
assert.Error(t, giant.MarshalCBOR(&b))
})
t.Run("fails to unmarshal too large", func(t *testing.T) {
// Construct CBOR for a too-large byte array
var b bytes.Buffer
header := cbg.CborEncodeMajorType(cbg.MajByteString, uint64(BigIntMaxSerializedLen+1))
_, err := b.Write(header)
require.NoError(t, err)
_, err = b.Write(make([]byte, BigIntMaxSerializedLen+1))
require.NoError(t, err)
var out Int
assert.Error(t, out.UnmarshalCBOR(&b))
})
}
package cbor
import "io"
// These interfaces are intended to match those from whyrusleeping/cbor-gen, such that code generated from that
// system is automatically usable here (but not mandatory).
type Marshaler interface {
MarshalCBOR(w io.Writer) error
}
type Unmarshaler interface {
UnmarshalCBOR(r io.Reader) error
}
type Er interface {
Marshaler
Unmarshaler
}
package crypto
// Specifies a domain for randomness generation.
type DomainSeparationTag int64
const (
DomainSeparationTag_TicketProduction DomainSeparationTag = 1 + iota
DomainSeparationTag_ElectionProofProduction
DomainSeparationTag_WinningPoStChallengeSeed
DomainSeparationTag_WindowedPoStChallengeSeed
DomainSeparationTag_SealRandomness
DomainSeparationTag_InteractiveSealChallengeSeed
DomainSeparationTag_WindowedPoStDeadlineAssignment
DomainSeparationTag_MarketDealCronSeed
DomainSeparationTag_PoStChainCommit
)
package crypto
import (
"bytes"
"fmt"
"io"
"math"
cbg "github.com/whyrusleeping/cbor-gen"
)
type SigType byte
const (
SigTypeUnknown = SigType(math.MaxUint8)
SigTypeSecp256k1 = SigType(iota)
SigTypeBLS
)
func (t SigType) Name() (string, error) {
switch t {
case SigTypeUnknown:
return "unknown", nil
case SigTypeSecp256k1:
return "secp256k1", nil
case SigTypeBLS:
return "bls", nil
default:
return "", fmt.Errorf("invalid signature type: %d", t)
}
}
const SignatureMaxLength = 200
type Signature struct {
Type SigType
Data []byte
}
func (s *Signature) Equals(o *Signature) bool {
if s == nil || o == nil {
return s == o
}
return s.Type == o.Type && bytes.Equal(s.Data, o.Data)
}
func (s *Signature) MarshalCBOR(w io.Writer) error {
if s == nil {
_, err := w.Write(cbg.CborNull)
return err
}
header := cbg.CborEncodeMajorType(cbg.MajByteString, uint64(len(s.Data)+1))
if _, err := w.Write(header); err != nil {
return err
}
if _, err := w.Write([]byte{byte(s.Type)}); err != nil {
return err
}
if _, err := w.Write(s.Data); err != nil {
return err
}
return nil
}
func (s *Signature) UnmarshalCBOR(br io.Reader) error {
maj, l, err := cbg.CborReadHeader(br)
if err != nil {
return err
}
if maj != cbg.MajByteString {
return fmt.Errorf("not a byte string")
}
if l > SignatureMaxLength {
return fmt.Errorf("string too long")
}
if l == 0 {
return fmt.Errorf("string empty")
}
buf := make([]byte, l)
if _, err = io.ReadFull(br, buf); err != nil {
return err
}
switch SigType(buf[0]) {
default:
return fmt.Errorf("invalid signature type in cbor input: %d", buf[0])
case SigTypeSecp256k1:
s.Type = SigTypeSecp256k1
case SigTypeBLS:
s.Type = SigTypeBLS
}
s.Data = buf[1:]
return nil
}
func (s *Signature) MarshalBinary() ([]byte, error) {
bs := make([]byte, len(s.Data)+1)
bs[0] = byte(s.Type)
copy(bs[1:], s.Data)
return bs, nil
}
func (s *Signature) UnmarshalBinary(bs []byte) error {
if len(bs) > SignatureMaxLength {
return fmt.Errorf("invalid signature bytes, too long (%d)", len(bs))
}
if len(bs) == 0 {
return fmt.Errorf("invalid signature bytes of length 0")
}
switch SigType(bs[0]) {
default:
// Do not error during unmarshal but leave a standard value.
// unmarshal(marshal(zero valued sig)) is valuable for test
// and type needs to be checked by caller anyway.
s.Type = SigTypeUnknown
case SigTypeSecp256k1:
s.Type = SigTypeSecp256k1
case SigTypeBLS:
s.Type = SigTypeBLS
}
s.Data = bs[1:]
return nil
}
package crypto_test
import (
"bytes"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
cbg "github.com/whyrusleeping/cbor-gen"
"github.com/filecoin-project/go-state-types/crypto"
)
func TestEquality(t *testing.T) {
a := crypto.Signature{
Type: crypto.SigTypeSecp256k1,
Data: []byte{1, 2, 3, 4},
}
assert.True(t, a.Equals(&a))
assert.False(t, a.Equals(&crypto.Signature{
Type: crypto.SigTypeBLS,
Data: a.Data,
}))
assert.False(t, a.Equals(&crypto.Signature{
Type: a.Type,
Data: []byte{1, 1, 1, 1},
}))
}
func TestCBOR(t *testing.T) {
a := crypto.Signature{
Type: crypto.SigTypeSecp256k1,
Data: []byte{1, 2, 3, 4},
}
b := crypto.Signature{
Type: crypto.SigTypeBLS,
Data: []byte{5, 6, 7, 8},
}
t.Run("round trip secp", func(t *testing.T) {
var buf bytes.Buffer
var out crypto.Signature
require.NoError(t, a.MarshalCBOR(&buf))
require.NoError(t, out.UnmarshalCBOR(&buf))
require.True(t, out.Equals(&a))
})
t.Run("round trip bls", func(t *testing.T) {
var buf bytes.Buffer
var out crypto.Signature
require.NoError(t, b.MarshalCBOR(&buf))
require.NoError(t, out.UnmarshalCBOR(&buf))
require.True(t, out.Equals(&b))
})
t.Run("require byte string", func(t *testing.T) {
var buf bytes.Buffer
var out crypto.Signature
require.NoError(t, cbg.CborWriteHeader(&buf, cbg.MajArray, 10))
assert.EqualError(t, out.UnmarshalCBOR(&buf), "not a byte string")
})
t.Run("require max length", func(t *testing.T) {
var buf bytes.Buffer
var out crypto.Signature
require.NoError(t, cbg.CborWriteHeader(&buf, cbg.MajByteString, crypto.SignatureMaxLength+1))
assert.EqualError(t, out.UnmarshalCBOR(&buf), "string too long")
})
t.Run("require non-empty", func(t *testing.T) {
var buf bytes.Buffer
var out crypto.Signature
require.NoError(t, cbg.CborWriteHeader(&buf, cbg.MajByteString, 0))
assert.EqualError(t, out.UnmarshalCBOR(&buf), "string empty")
})
t.Run("require correct length", func(t *testing.T) {
var buf bytes.Buffer
var out crypto.Signature
require.NoError(t, cbg.CborWriteHeader(&buf, cbg.MajByteString, 10))
buf.WriteString("7 bytes")
assert.EqualError(t, out.UnmarshalCBOR(&buf), "unexpected EOF")
})
t.Run("require valid type", func(t *testing.T) {
var buf bytes.Buffer
var out crypto.Signature
require.NoError(t, cbg.CborWriteHeader(&buf, cbg.MajByteString, 4))
buf.Write([]byte{byte(crypto.SigTypeUnknown)})
buf.WriteString("sig")
assert.EqualError(t, out.UnmarshalCBOR(&buf), "invalid signature type in cbor input: 255")
})
t.Run("happy decode", func(t *testing.T) {
var buf bytes.Buffer
var out crypto.Signature
require.NoError(t, cbg.CborWriteHeader(&buf, cbg.MajByteString, 4))
buf.Write([]byte{byte(crypto.SigTypeSecp256k1)})
buf.WriteString("sig")
assert.NoError(t, out.UnmarshalCBOR(&buf))
})
}
package dline
import "github.com/filecoin-project/go-state-types/abi"
// Deadline calculations with respect to a current epoch.
// "Deadline" refers to the window during which proofs may be submitted.
// Windows are non-overlapping ranges [Open, Close), but the challenge epoch for a window occurs before
// the window opens.
// The current epoch may not necessarily lie within the deadline or proving period represented here.
type Info struct {
// Deadline parameters
CurrentEpoch abi.ChainEpoch // Epoch at which this info was calculated.
PeriodStart abi.ChainEpoch // First epoch of the proving period (<= CurrentEpoch).
Index uint64 // A deadline index, in [0..d.WPoStProvingPeriodDeadlines) unless period elapsed.
Open abi.ChainEpoch // First epoch from which a proof may be submitted (>= CurrentEpoch).
Close abi.ChainEpoch // First epoch from which a proof may no longer be submitted (>= Open).
Challenge abi.ChainEpoch // Epoch at which to sample the chain for challenge (< Open).
FaultCutoff abi.ChainEpoch // First epoch at which a fault declaration is rejected (< Open).
// Protocol parameters
WPoStPeriodDeadlines uint64
WPoStProvingPeriod abi.ChainEpoch // the number of epochs in a window post proving period
WPoStChallengeWindow abi.ChainEpoch
WPoStChallengeLookback abi.ChainEpoch
FaultDeclarationCutoff abi.ChainEpoch
}
// Whether the proving period has begun.
func (d *Info) PeriodStarted() bool {
return d.CurrentEpoch >= d.PeriodStart
}
// Whether the proving period has elapsed.
func (d *Info) PeriodElapsed() bool {
return d.CurrentEpoch >= d.NextPeriodStart()
}
// The last epoch in the proving period.
func (d *Info) PeriodEnd() abi.ChainEpoch {
return d.PeriodStart + d.WPoStProvingPeriod - 1
}
// The first epoch in the next proving period.
func (d *Info) NextPeriodStart() abi.ChainEpoch {
return d.PeriodStart + d.WPoStProvingPeriod
}
// Whether the current deadline is currently open.
func (d *Info) IsOpen() bool {
return d.CurrentEpoch >= d.Open && d.CurrentEpoch < d.Close
}
// Whether the current deadline has already closed.
func (d *Info) HasElapsed() bool {
return d.CurrentEpoch >= d.Close
}
// The last epoch during which a proof may be submitted.
func (d *Info) Last() abi.ChainEpoch {
return d.Close - 1
}
// Epoch at which the subsequent deadline opens.
func (d *Info) NextOpen() abi.ChainEpoch {
return d.Close
}
// Whether the deadline's fault cutoff has passed.
func (d *Info) FaultCutoffPassed() bool {
return d.CurrentEpoch >= d.FaultCutoff
}
// Returns the next instance of this deadline that has not yet elapsed.
func (d *Info) NextNotElapsed() *Info {
// If the deadline hasn't elapsed, do nothing.
if !d.HasElapsed() {
return d
}
// find a nearby period start
// 1. first, find our period's offset from the "global" period
offset := d.PeriodStart % d.WPoStProvingPeriod
// handle negative period starts just in case.
if offset < 0 {
offset += d.WPoStProvingPeriod
}
// 2. determine the global period index.
globalPeriod := (d.CurrentEpoch / d.WPoStProvingPeriod)
// 3. Determine our next period start.
periodStart := globalPeriod*d.WPoStProvingPeriod + offset
// Backtrack so the period starts before the current epoch. This should usually run 0 or 1 times.
for periodStart > d.CurrentEpoch {
periodStart -= d.WPoStProvingPeriod
}
// If the next deadline opens at or after the current epoch, move to the next pp.
if d.CurrentEpoch >= periodStart+abi.ChainEpoch(d.Index+1)*d.WPoStChallengeWindow {
periodStart += d.WPoStProvingPeriod
}
return NewInfo(periodStart, d.Index, d.CurrentEpoch, d.WPoStPeriodDeadlines, d.WPoStProvingPeriod, d.WPoStChallengeWindow, d.WPoStChallengeLookback, d.FaultDeclarationCutoff)
}
// Returns deadline-related calculations for a deadline in some proving period and the current epoch.
func NewInfo(periodStart abi.ChainEpoch, deadlineIdx uint64, currEpoch abi.ChainEpoch, wPoStPeriodDeadlines uint64, wPoStProvingPeriod, wPoStChallengeWindow, wPoStChallengeLookback, faultDeclarationCutoff abi.ChainEpoch) *Info {
if deadlineIdx < wPoStPeriodDeadlines {
deadlineOpen := periodStart + (abi.ChainEpoch(deadlineIdx) * wPoStChallengeWindow)
return &Info{
CurrentEpoch: currEpoch,
PeriodStart: periodStart,
Index: deadlineIdx,
Open: deadlineOpen,
Close: deadlineOpen + wPoStChallengeWindow,
Challenge: deadlineOpen - wPoStChallengeLookback,
FaultCutoff: deadlineOpen - faultDeclarationCutoff,
// parameters
WPoStPeriodDeadlines: wPoStPeriodDeadlines,
WPoStProvingPeriod: wPoStProvingPeriod,
WPoStChallengeWindow: wPoStChallengeWindow,
WPoStChallengeLookback: wPoStChallengeLookback,
FaultDeclarationCutoff: faultDeclarationCutoff,
}
} else {
// Return deadline info for a no-duration deadline immediately after the last real one.
afterLastDeadline := periodStart + wPoStProvingPeriod
return &Info{
CurrentEpoch: currEpoch,
PeriodStart: periodStart,
Index: deadlineIdx,
Open: afterLastDeadline,
Close: afterLastDeadline,
Challenge: afterLastDeadline,
FaultCutoff: 0,
// parameters
WPoStPeriodDeadlines: wPoStPeriodDeadlines,
WPoStProvingPeriod: wPoStProvingPeriod,
WPoStChallengeWindow: wPoStChallengeWindow,
WPoStChallengeLookback: wPoStChallengeLookback,
FaultDeclarationCutoff: faultDeclarationCutoff,
}
}
}
package dline_test
import (
"testing"
"github.com/stretchr/testify/assert"
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/go-state-types/dline"
)
func TestProvingPeriodDeadlines(t *testing.T) {
DLs := uint64(48) // miner.WPoStPeriodDeadlines
PP := abi.ChainEpoch(2880) // miner.WPoStProvingPeriod
CW := abi.ChainEpoch(60) // miner.WPoStChallengeWindow
CL := abi.ChainEpoch(20) // miner.WPoStChallengeLookback
FDC := abi.ChainEpoch(70) // miner.FaultDeclarationCutoff
t.Run("pre-open", func(t *testing.T) {
curr := abi.ChainEpoch(0) // Current is before the period opens.
{
periodStart := FDC + 1
di := dline.NewInfo(periodStart, 0, curr, DLs, PP, CW, CL, FDC)
assert.Equal(t, curr, di.CurrentEpoch)
assert.Equal(t, periodStart, di.PeriodStart)
assert.Equal(t, uint64(0), di.Index)
assert.Equal(t, periodStart, di.Open)
assert.Equal(t, periodStart+CW, di.Close)
assert.Equal(t, periodStart-CL, di.Challenge)
assert.Equal(t, periodStart-FDC, di.FaultCutoff)
assert.False(t, di.PeriodStarted())
assert.False(t, di.PeriodElapsed())
assert.False(t, di.IsOpen())
assert.False(t, di.HasElapsed())
assert.Equal(t, periodStart+CW-1, di.Last())
assert.Equal(t, periodStart+CW, di.NextOpen())
assert.False(t, di.FaultCutoffPassed())
assert.Equal(t, periodStart+PP-1, di.PeriodEnd())
assert.Equal(t, periodStart+PP, di.NextPeriodStart())
}
{
periodStart := FDC - 1
di := dline.NewInfo(periodStart, 0, curr, DLs, PP, CW, CL, FDC)
assert.True(t, di.FaultCutoffPassed())
}
})
t.Run("proving period boundary", func(t *testing.T) {
periodStart := abi.ChainEpoch(50000)
{
// Period not yet started
curr := periodStart - 1
di := dline.NewInfo(periodStart, 0, curr, DLs, PP, CW, CL, FDC)
assert.False(t, di.PeriodStarted()) // Not yet started
assert.False(t, di.PeriodElapsed())
assert.Equal(t, periodStart+PP-1, di.PeriodEnd())
assert.Equal(t, periodStart+PP, di.NextPeriodStart())
}
{
// Period started
curr := periodStart
di := dline.NewInfo(periodStart, 0, curr, DLs, PP, CW, CL, FDC)
assert.True(t, di.PeriodStarted())
assert.False(t, di.PeriodElapsed())
assert.Equal(t, periodStart+PP-1, di.PeriodEnd())
assert.Equal(t, periodStart+PP, di.NextPeriodStart())
}
{
// Period elapsed
curr := periodStart + PP
di := dline.NewInfo(periodStart, DLs-1, curr, DLs, PP, CW, CL, FDC)
assert.True(t, di.PeriodStarted())
assert.True(t, di.PeriodElapsed())
assert.Equal(t, periodStart+PP-1, di.PeriodEnd())
assert.Equal(t, periodStart+PP, di.NextPeriodStart())
assert.False(t, di.IsOpen())
assert.True(t, di.HasElapsed())
}
})
t.Run("deadline boundaries", func(t *testing.T) {
periodStart := abi.ChainEpoch(50000)
{
// First epoch of deadline zero
curr := periodStart
di := dline.NewInfo(periodStart, 0, curr, DLs, PP, CW, CL, FDC)
assert.Equal(t, periodStart, di.Open)
assert.Equal(t, periodStart+CW, di.Close)
assert.Equal(t, periodStart-CL, di.Challenge)
assert.Equal(t, periodStart-FDC, di.FaultCutoff)
assert.True(t, di.IsOpen())
assert.False(t, di.HasElapsed())
assert.Equal(t, periodStart+CW-1, di.Last())
assert.Equal(t, periodStart+CW, di.NextOpen())
assert.True(t, di.FaultCutoffPassed())
// The last invalid epoch of a deadline is the first valid epoch for the next.
assert.Equal(t, di.Last()+1, di.NextOpen())
assert.Equal(t, di.Close, di.NextOpen())
}
{
// Before deadline zero opens
curr := periodStart - 1
di := dline.NewInfo(periodStart, 0, curr, DLs, PP, CW, CL, FDC)
assert.False(t, di.IsOpen()) // Not yet open
assert.False(t, di.HasElapsed())
assert.True(t, di.FaultCutoffPassed())
// The next not-elapsed is this one, because it hasn't even started yet.
nxt := di.NextNotElapsed()
assert.Equal(t, periodStart, nxt.PeriodStart)
assert.Equal(t, uint64(0), nxt.Index)
}
{
// During deadline zero, deadline one isn't open
curr := periodStart
di0 := dline.NewInfo(periodStart, 0, curr, DLs, PP, CW, CL, FDC)
assert.True(t, di0.IsOpen()) // Now open
assert.False(t, di0.HasElapsed())
assert.True(t, di0.FaultCutoffPassed())
// The next not-elapsed is this one, which is not yet
// open, but not elapsed either.
nxt0 := di0.NextNotElapsed()
assert.Equal(t, periodStart, nxt0.PeriodStart)
assert.Equal(t, uint64(0), nxt0.Index)
di1 := dline.NewInfo(periodStart, 1, curr, DLs, PP, CW, CL, FDC)
assert.False(t, di1.IsOpen())
assert.False(t, di1.HasElapsed())
// The fault cutoff is more than one deadline into the future.
assert.True(t, di1.FaultCutoffPassed())
// The next not-elapsed is the upcoming one
nxt1 := di1.NextNotElapsed()
assert.Equal(t, periodStart, nxt1.PeriodStart)
assert.Equal(t, uint64(1), nxt1.Index)
}
{
// Last epoch of deadline zero
curr := periodStart + CW - 1
di := dline.NewInfo(periodStart, 0, curr, DLs, PP, CW, CL, FDC)
assert.True(t, di.IsOpen())
assert.False(t, di.HasElapsed())
assert.True(t, di.FaultCutoffPassed())
// The next not-elapsed is this one still
nxt := di.NextNotElapsed()
assert.Equal(t, periodStart, nxt.PeriodStart)
assert.Equal(t, uint64(0), nxt.Index)
}
{
// Deadline zero expired
curr := periodStart + CW
di := dline.NewInfo(periodStart, 0, curr, DLs, PP, CW, CL, FDC)
assert.False(t, di.IsOpen())
assert.True(t, di.HasElapsed())
assert.True(t, di.FaultCutoffPassed())
// The next not-elapsed is the subsequent proving period
nxt := di.NextNotElapsed()
assert.Equal(t, periodStart+PP, nxt.PeriodStart)
assert.Equal(t, uint64(0), nxt.Index)
}
})
t.Run("period expired", func(t *testing.T) {
periodStart := abi.ChainEpoch(0)
curr := periodStart + PP
d := dline.NewInfo(periodStart, DLs, curr, DLs, PP, CW, CL, FDC)
assert.True(t, d.PeriodStarted())
assert.True(t, d.PeriodElapsed())
assert.Equal(t, DLs, d.Index)
assert.False(t, d.IsOpen())
assert.True(t, d.HasElapsed())
assert.True(t, d.FaultCutoffPassed())
assert.Equal(t, PP-1, d.PeriodEnd())
assert.Equal(t, PP, d.NextPeriodStart())
})
t.Run("period start", func(t *testing.T) {
periodStart := abi.ChainEpoch(0)
f := func(t *testing.T) {
for curr := -99999; curr < 99999; curr++ {
d := dline.NewInfo(periodStart, DLs, abi.ChainEpoch(curr), DLs, PP, CW, CL, FDC)
actual := d.NextNotElapsed()
expected := d
for expected.HasElapsed() {
expected = dline.NewInfo(expected.PeriodStart+PP, DLs, abi.ChainEpoch(curr), DLs, PP, CW, CL, FDC)
}
assert.Equal(t, *expected, *actual)
}
}
periodStart = 60
t.Run("small", f)
periodStart = PP + 60
t.Run("next", f)
periodStart = 5*PP + 60
t.Run("later", f)
periodStart = 60 - PP
t.Run("negative", f)
})
}
package exitcode
// Common error codes that may be shared by different actors.
// Actors may also define their own codes, including redefining these values.
const (
// Indicates a method parameter is invalid.
ErrIllegalArgument = FirstActorErrorCode + iota
// Indicates a requested resource does not exist.
ErrNotFound
// Indicates an action is disallowed.
ErrForbidden
// Indicates a balance of funds is insufficient.
ErrInsufficientFunds
// Indicates an actor's internal state is invalid.
ErrIllegalState
// Indicates de/serialization failure within actor code.
ErrSerialization
// Common error codes stop here. If you define a common error code above
// this value it will have conflicting interpretations
FirstActorSpecificExitCode = ExitCode(32)
)
package exitcode
import (
"errors"
"fmt"
"strconv"
"golang.org/x/xerrors"
)
type ExitCode int64
func (x ExitCode) IsSuccess() bool {
return x == Ok
}
func (x ExitCode) IsError() bool {
return !x.IsSuccess()
}
// Whether an exit code indicates a message send failure.
// A send failure means that the caller's CallSeqNum is not incremented and the caller has not paid
// gas fees for the message (because the caller doesn't exist or can't afford it).
// A receipt with send failure does not indicate that the message (or another one carrying the same CallSeqNum)
// could not apply in the future, against a different state.
func (x ExitCode) IsSendFailure() bool {
return x == SysErrSenderInvalid || x == SysErrSenderStateInvalid
}
// A non-canonical string representation for human inspection.
func (x ExitCode) String() string {
name, ok := names[x]
if ok {
return fmt.Sprintf("%s(%d)", name, x)
}
return strconv.FormatInt(int64(x), 10)
}
// Implement error to trigger Go compiler checking of exit code return values.
func (x ExitCode) Error() string {
return x.String()
}
// Wrapf attaches an error message, and possibly an error, to the exit
// code.
//
// err := ErrIllegalArgument.Wrapf("my description: %w", err)
// exitcode.Unwrap(exitcode.ErrIllegalState, err) == exitcode.ErrIllegalArgument
func (x ExitCode) Wrapf(msg string, args ...interface{}) error {
return &wrapped{
exitCode: x,
cause: xerrors.Errorf(msg, args...),
}
}
type wrapped struct {
exitCode ExitCode
cause error
}
func (w *wrapped) String() string {
return w.Error()
}
func (w *wrapped) Error() string {
// Don't include the exit code. That will be handled by the runtime and
// this error has likely been wrapped multiple times.
return w.cause.Error()
}
// implements the interface required by errors.As
func (w *wrapped) As(target interface{}) bool {
return errors.As(w.exitCode, target) || errors.As(w.cause, target)
}
// implements the interface required by errors.Is
func (w *wrapped) Is(target error) bool {
if _, ok := target.(ExitCode); ok {
// If the target is an exit code, make sure we shadow lower exit
// codes.
return w.exitCode == target
}
return errors.Is(w.cause, target)
}
// Unwrap extracts an exit code from an error, defaulting to the passed default
// exit code.
//
// err := ErrIllegalState.WithContext("my description: %w", err)
// exitcode.Unwrap(exitcode.ErrIllegalState, err) == exitcode.ErrIllegalArgument
func Unwrap(err error, defaultExitCode ExitCode) (code ExitCode) {
if errors.As(err, &code) {
return code
}
return defaultExitCode
}
package exitcode_test
import (
"errors"
"testing"
"github.com/stretchr/testify/assert"
"golang.org/x/xerrors"
"github.com/filecoin-project/go-state-types/exitcode"
)
func TestWithContext(t *testing.T) {
baseErr := errors.New("base error")
codedErr := exitcode.ErrForbidden.Wrapf("coded: %w", baseErr)
wrappedErr := xerrors.Errorf("wrapper: %w", codedErr)
shadowedErr := exitcode.ErrIllegalState.Wrapf("shadow: %w", codedErr)
// Test default.
assert.Equal(t, exitcode.Ok, exitcode.Unwrap(baseErr, exitcode.Ok))
assert.Equal(t, exitcode.ErrIllegalState, exitcode.Unwrap(baseErr, exitcode.ErrIllegalState))
assert.True(t, errors.Is(baseErr, baseErr))
// Test coded.
assert.Equal(t, exitcode.ErrForbidden, exitcode.Unwrap(codedErr, exitcode.Ok))
assert.True(t, errors.Is(wrappedErr, codedErr))
assert.False(t, errors.Is(codedErr, wrappedErr))
assert.False(t, errors.Is(wrappedErr, exitcode.Ok))
// Test wrapped
assert.Equal(t, exitcode.ErrForbidden, exitcode.Unwrap(wrappedErr, exitcode.Ok))
assert.True(t, errors.Is(wrappedErr, codedErr))
assert.True(t, errors.Is(wrappedErr, wrappedErr))
assert.False(t, errors.Is(wrappedErr, exitcode.Ok))
// Test shadowed
assert.Equal(t, exitcode.ErrIllegalState, exitcode.Unwrap(shadowedErr, exitcode.Ok))
assert.True(t, errors.Is(shadowedErr, exitcode.ErrIllegalState))
assert.False(t, errors.Is(shadowedErr, exitcode.ErrForbidden))
}
package exitcode
// The system error codes are reserved for use by the runtime.
// No actor may use one explicitly. Correspondingly, no runtime invocation should abort with an exit
// code outside this list.
// We could move these definitions out of this package and into the runtime spec.
const (
Ok = ExitCode(0)
// Indicates that the actor identified as the sender of a message is not valid as a message sender:
// - not present in the state tree
// - not an account actor (for top-level messages)
// - code CID is not found or invalid
// (not found in the state tree, not an account, has no code).
SysErrSenderInvalid = ExitCode(1)
// Indicates that the sender of a message is not in a state to send the message:
// - invocation out of sequence (mismatched CallSeqNum)
// - insufficient funds to cover execution
SysErrSenderStateInvalid = ExitCode(2)
// Indicates failure to find a method in an actor.
SysErrInvalidMethod = ExitCode(3)
// Unused.
SysErrReserved1 = ExitCode(4)
// Indicates that the receiver of a message is not valid (and cannot be implicitly created).
SysErrInvalidReceiver = ExitCode(5)
// Indicates that a message sender has insufficient balance for the value being sent.
// Note that this is distinct from SysErrSenderStateInvalid when a top-level sender can't cover
// value transfer + gas. This code is only expected to come from inter-actor sends.
SysErrInsufficientFunds = ExitCode(6)
// Indicates message execution (including subcalls) used more gas than the specified limit.
SysErrOutOfGas = ExitCode(7)
// Indicates message execution is forbidden for the caller by runtime caller validation.
SysErrForbidden = ExitCode(8)
// Indicates actor code performed a disallowed operation. Disallowed operations include:
// - mutating state outside of a state acquisition block
// - failing to invoke caller validation
// - aborting with a reserved exit code (including success or a system error).
SysErrorIllegalActor = ExitCode(9)
// Indicates an invalid argument passed to a runtime method.
SysErrorIllegalArgument = ExitCode(10)
// Unused
SysErrReserved2 = ExitCode(11)
SysErrReserved3 = ExitCode(12)
SysErrReserved4 = ExitCode(13)
SysErrReserved5 = ExitCode(14)
SysErrReserved6 = ExitCode(15)
)
// The initial range of exit codes is reserved for system errors.
// Actors may define codes starting with this one.
const FirstActorErrorCode = ExitCode(16)
var names = map[ExitCode]string{
Ok: "Ok",
SysErrSenderInvalid: "SysErrSenderInvalid",
SysErrSenderStateInvalid: "SysErrSenderStateInvalid",
SysErrInvalidMethod: "SysErrInvalidMethod",
SysErrReserved1: "SysErrReserved1",
SysErrInvalidReceiver: "SysErrInvalidReceiver",
SysErrInsufficientFunds: "SysErrInsufficientFunds",
SysErrOutOfGas: "SysErrOutOfGas",
SysErrForbidden: "SysErrForbidden",
SysErrorIllegalActor: "SysErrorIllegalActor",
SysErrorIllegalArgument: "SysErrorIllegalArgument",
SysErrReserved2: "SysErrReserved2",
SysErrReserved3: "SysErrReserved3",
SysErrReserved4: "SysErrReserved4",
SysErrReserved5: "SysErrReserved5",
SysErrReserved6: "SysErrReserved6",
}
package main
import (
gen "github.com/whyrusleeping/cbor-gen"
"github.com/filecoin-project/go-state-types/abi"
)
func main() {
// Common types
if err := gen.WriteTupleEncodersToFile("./abi/cbor_gen.go", "abi",
abi.PieceInfo{},
abi.SectorID{},
); err != nil {
panic(err)
}
}
module github.com/filecoin-project/go-state-types
go 1.13
require (
github.com/filecoin-project/go-address v0.0.3
github.com/ipfs/go-cid v0.0.7
github.com/multiformats/go-multihash v0.0.14
github.com/stretchr/testify v1.6.1
github.com/whyrusleeping/cbor-gen v0.0.0-20200812213548-958ddffe352c
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1
)
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/filecoin-project/go-address v0.0.3 h1:eVfbdjEbpbzIrbiSa+PiGUY+oDK9HnUn+M1R/ggoHf8=
github.com/filecoin-project/go-address v0.0.3/go.mod h1:jr8JxKsYx+lQlQZmF5i2U0Z+cGQ59wMIps/8YW/lDj8=
github.com/filecoin-project/go-crypto v0.0.0-20191218222705-effae4ea9f03 h1:2pMXdBnCiXjfCYx/hLqFxccPoqsSveQFxVLvNxy9bus=
github.com/filecoin-project/go-crypto v0.0.0-20191218222705-effae4ea9f03/go.mod h1:+viYnvGtUTgJRdy6oaeF4MTFKAfatX071MPDPBL11EQ=
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8=
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
github.com/gxed/hashland/keccakpg v0.0.1/go.mod h1:kRzw3HkwxFU1mpmPP8v1WyQzwdGfmKFJ6tItnhQ67kU=
github.com/gxed/hashland/murmur3 v0.0.1/go.mod h1:KjXop02n4/ckmZSnY2+HKcLud/tcmvhST0bie/0lS48=
github.com/ipfs/go-block-format v0.0.2 h1:qPDvcP19izTjU8rgo6p7gTXZlkMkF5bz5G3fqIsSCPE=
github.com/ipfs/go-block-format v0.0.2/go.mod h1:AWR46JfpcObNfg3ok2JHDUfdiHRgWhJgCQF+KIgOPJY=
github.com/ipfs/go-cid v0.0.1/go.mod h1:GHWU/WuQdMPmIosc4Yn1bcCT7dSeX4lBafM7iqUPQvM=
github.com/ipfs/go-cid v0.0.3/go.mod h1:GHWU/WuQdMPmIosc4Yn1bcCT7dSeX4lBafM7iqUPQvM=
github.com/ipfs/go-cid v0.0.6/go.mod h1:6Ux9z5e+HpkQdckYoX1PG/6xqKspzlEIR5SDmgqgC/I=
github.com/ipfs/go-cid v0.0.7 h1:ysQJVJA3fNDF1qigJbsSQOdjhVLsOEoPdh0+R97k3jY=
github.com/ipfs/go-cid v0.0.7/go.mod h1:6Ux9z5e+HpkQdckYoX1PG/6xqKspzlEIR5SDmgqgC/I=
github.com/ipfs/go-ipfs-util v0.0.1 h1:Wz9bL2wB2YBJqggkA4dD7oSmqB4cAnpNbGrlHJulv50=
github.com/ipfs/go-ipfs-util v0.0.1/go.mod h1:spsl5z8KUnrve+73pOhSVZND1SIxPW5RyBCNzQxlJBc=
github.com/ipfs/go-ipld-cbor v0.0.4 h1:Aw3KPOKXjvrm6VjwJvFf1F1ekR/BH3jdof3Bk7OTiSA=
github.com/ipfs/go-ipld-cbor v0.0.4/go.mod h1:BkCduEx3XBCO6t2Sfo5BaHzuok7hbhdMm9Oh8B2Ftq4=
github.com/ipfs/go-ipld-format v0.0.1 h1:HCu4eB/Gh+KD/Q0M8u888RFkorTWNIL3da4oc5dwc80=
github.com/ipfs/go-ipld-format v0.0.1/go.mod h1:kyJtbkDALmFHv3QR6et67i35QzO3S0dCDnkOJhcZkms=
github.com/ipsn/go-secp256k1 v0.0.0-20180726113642-9d62b9f0bc52 h1:QG4CGBqCeuBo6aZlGAamSkxWdgWfZGeE49eUOWJPA4c=
github.com/ipsn/go-secp256k1 v0.0.0-20180726113642-9d62b9f0bc52/go.mod h1:fdg+/X9Gg4AsAIzWpEHwnqd+QY3b7lajxyjE1m4hkq4=
github.com/jtolds/gls v4.2.1+incompatible h1:fSuqC+Gmlu6l/ZYAoZzx2pyucC8Xza35fpRVWLVmUEE=
github.com/jtolds/gls v4.2.1+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1 h1:lYpkrQH5ajf0OXOcUbGjvZxxijuBwbbmlSxLiuofa+g=
github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1/go.mod h1:pD8RvIylQ358TN4wwqatJ8rNavkEINozVn9DtGI3dfQ=
github.com/minio/sha256-simd v0.0.0-20190131020904-2d45a736cd16/go.mod h1:2FMWW+8GMoPweT6+pI63m9YE3Lmw4J71hV56Chs1E/U=
github.com/minio/sha256-simd v0.1.1-0.20190913151208-6de447530771 h1:MHkK1uRtFbVqvAgvWxafZe54+5uBxLluGylDiKgdhwo=
github.com/minio/sha256-simd v0.1.1-0.20190913151208-6de447530771/go.mod h1:B5e1o+1/KgNmWrSQK08Y6Z1Vb5pwIktudl0J58iy0KM=
github.com/mr-tron/base58 v1.1.0/go.mod h1:xcD2VGqlgYjBdcBLw+TuYLr8afG+Hj8g2eTVqeSzSU8=
github.com/mr-tron/base58 v1.1.2/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc=
github.com/mr-tron/base58 v1.1.3 h1:v+sk57XuaCKGXpWtVBX8YJzO7hMGx4Aajh4TQbdEFdc=
github.com/mr-tron/base58 v1.1.3/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc=
github.com/multiformats/go-base32 v0.0.3 h1:tw5+NhuwaOjJCC5Pp82QuXbrmLzWg7uxlMFp8Nq/kkI=
github.com/multiformats/go-base32 v0.0.3/go.mod h1:pLiuGC8y0QR3Ue4Zug5UzK9LjgbkL8NSQj0zQ5Nz/AA=
github.com/multiformats/go-base36 v0.1.0 h1:JR6TyF7JjGd3m6FbLU2cOxhC0Li8z8dLNGQ89tUg4F4=
github.com/multiformats/go-base36 v0.1.0/go.mod h1:kFGE83c6s80PklsHO9sRn2NCoffoRdUUOENyW/Vv6sM=
github.com/multiformats/go-multibase v0.0.1/go.mod h1:bja2MqRZ3ggyXtZSEDKpl0uO/gviWFaSteVbWT51qgs=
github.com/multiformats/go-multibase v0.0.3 h1:l/B6bJDQjvQ5G52jw4QGSYeOTZoAwIO77RblWplfIqk=
github.com/multiformats/go-multibase v0.0.3/go.mod h1:5+1R4eQrT3PkYZ24C3W2Ue2tPwIdYQD509ZjSb5y9Oc=
github.com/multiformats/go-multihash v0.0.1/go.mod h1:w/5tugSrLEbWqlcgJabL3oHFKTwfvkofsjW2Qa1ct4U=
github.com/multiformats/go-multihash v0.0.10/go.mod h1:YSLudS+Pi8NHE7o6tb3D8vrpKa63epEDmG8nTduyAew=
github.com/multiformats/go-multihash v0.0.13/go.mod h1:VdAWLKTwram9oKAatUcLxBNUjdtcVwxObEQBtRfuyjc=
github.com/multiformats/go-multihash v0.0.14 h1:QoBceQYQQtNUuf6s7wHxnE2c8bhbMqhfGzNI032se/I=
github.com/multiformats/go-multihash v0.0.14/go.mod h1:VdAWLKTwram9oKAatUcLxBNUjdtcVwxObEQBtRfuyjc=
github.com/multiformats/go-varint v0.0.5 h1:XVZwSo04Cs3j/jS0uAEPpT3JY6DzMcVLLoWOSnCxOjg=
github.com/multiformats/go-varint v0.0.5/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXSrVKRY101jdMZYE=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/polydawn/refmt v0.0.0-20190221155625-df39d6c2d992/go.mod h1:uIp+gprXxxrWSjjklXD+mN4wed/tMfjMMmN/9+JsA9o=
github.com/polydawn/refmt v0.0.0-20190807091052-3d65705ee9f1 h1:CskT+S6Ay54OwxBGB0R3Rsx4Muto6UnEYTyKJbyRIAI=
github.com/polydawn/refmt v0.0.0-20190807091052-3d65705ee9f1/go.mod h1:uIp+gprXxxrWSjjklXD+mN4wed/tMfjMMmN/9+JsA9o=
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM=
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
github.com/smartystreets/goconvey v0.0.0-20190222223459-a17d461953aa h1:E+gaaifzi2xF65PbDmuKI3PhLWY6G5opMLniFq8vmXA=
github.com/smartystreets/goconvey v0.0.0-20190222223459-a17d461953aa/go.mod h1:2RVY1rIf+2J2o/IM9+vPq9RzmHDSseB7FoXiSNIUsoU=
github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI=
github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/warpfork/go-wish v0.0.0-20180510122957-5ad1f5abf436 h1:qOpVTI+BrstcjTZLm2Yz/3sOnqkzj3FQoh0g+E5s3Gc=
github.com/warpfork/go-wish v0.0.0-20180510122957-5ad1f5abf436/go.mod h1:x6AKhvSSexNrVSrViXSHUEbICjmGXhtgABaHIySUSGw=
github.com/whyrusleeping/cbor-gen v0.0.0-20200123233031-1cdf64d27158/go.mod h1:Xj/M2wWU+QdTdRbu/L/1dIZY8/Wb2K9pAhtroQuxJJI=
github.com/whyrusleeping/cbor-gen v0.0.0-20200810223238-211df3b9e24c/go.mod h1:fgkXqYy7bV2cFeIEOkVTZS/WjXARfBqSH6Q2qHL33hQ=
github.com/whyrusleeping/cbor-gen v0.0.0-20200812213548-958ddffe352c h1:otRnI08JoahNBxUFqX3372Ab9GnTj8L5J9iP5ImyxGU=
github.com/whyrusleeping/cbor-gen v0.0.0-20200812213548-958ddffe352c/go.mod h1:fgkXqYy7bV2cFeIEOkVTZS/WjXARfBqSH6Q2qHL33hQ=
golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8 h1:1wopBVtVdWnn03fZelqdXTqk7U7zPQCb+T4rbU9ZEoU=
golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190219092855-153ac476189d/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d h1:+R4KGOnez64A81RvjARKc4UT5/tI9ujCIVX+P5KiHuI=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
package network
import "math"
// Enumeration of network upgrades where actor behaviour can change (without necessarily
// vendoring and versioning the whole actor codebase).
type Version uint
const (
Version0 = Version(iota) // genesis (specs-actors v0.9.3)
Version1 // breeze (specs-actors v0.9.7)
Version2 // smoke (specs-actors v0.9.8)
Version3 // ignition (specs-actors v0.9.11)
Version4 // actors v2 (specs-actors v2.0.3)
Version5 // tape (specs-actors v2.1.0)
Version6 // kumquat (specs-actors v2.2.0)
Version7 // calico (specs-actors v2.3.2)
Version8 // persian (post-2.3.2 behaviour transition)
Version9 // orange (post-2.3.2 behaviour transition)
Version10 // actors v3 (specs-actors v3.0.3)
Version11 // norwegian (specs-actors v3.1.0)
Version12 // actors v4 (specs-actors v4.0.0)
Version13 // reserved (specs-actors v5.x)
// VersionMax is the maximum version number
VersionMax = Version(math.MaxUint32)
)
package rt
import (
"github.com/filecoin-project/go-state-types/cbor"
"github.com/ipfs/go-cid"
)
// VMActor is a concrete implementation of an actor, to be used by a Filecoin
// VM.
type VMActor interface {
// Exports returns a slice of methods exported by this actor, indexed by
// method number. Skipped/deprecated method numbers will be nil.
Exports() []interface{}
// Code returns the code ID for this actor.
Code() cid.Cid
// State returns a new State object for this actor. This can be used to
// decode the actor's state.
State() cbor.Er
// NOTE: methods like "IsSingleton" are intentionally excluded from this
// interface. That way, we can add additional attributes actors in newer
// specs-actors versions, without having to update previous specs-actors
// versions.
}
// IsSingletonActor returns true if the actor is a singleton actor (i.e., cannot
// be constructed).
func IsSingletonActor(a VMActor) bool {
s, ok := a.(interface{ IsSingleton() bool })
return ok && s.IsSingleton()
}
package rt
// Specifies importance of message, LogLevel numbering is consistent with the uber-go/zap package.
type LogLevel int
const (
// DebugLevel logs are typically voluminous, and are usually disabled in
// production.
DEBUG LogLevel = iota - 1
// InfoLevel is the default logging priority.
INFO
// WarnLevel logs are more important than Info, but don't need individual
// human review.
WARN
// ErrorLevel logs are high-priority. If an application is running smoothly,
// it shouldn't generate any error-level logs.
ERROR
)
## Contributing
Please [read the spec process](https://filecoin-project.github.io/specs/#intro__process). Please file PRs on github with fixes.
Copyright 2020. Protocol Labs, Inc.
This library is dual-licensed under Apache 2.0 and MIT terms.
Copyright 2020. Protocol Labs, Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Copyright 2020. Protocol Labs, Inc.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
GO_BIN ?= go
GOLINT ?= golangci-lint
all: build lint test tidy
.PHONY: all
build:
$(GO_BIN) build ./...
.PHONY: build
test:
$(GO_BIN) test ./...
.PHONY: test
test-coverage:
$(GO_BIN) test -coverprofile=coverage.out ./...
.PHONY: test-coverage
tidy:
$(GO_BIN) mod tidy
.PHONY: tidy
lint:
$(GOLINT) run ./...
.PHONY: lint
# specs-storage
Specification of the sector storage interface
## Disclaimer
Please report your issues with regards to storage-fsm at the [lotus issue tracker](https://github.com/filecoin-project/lotus/issues)
module github.com/filecoin-project/specs-storage
go 1.13
require (
github.com/filecoin-project/go-state-types v0.0.0-20200904021452-1883f36ca2f4
github.com/filecoin-project/specs-actors v0.9.4
github.com/ipfs/go-cid v0.0.7
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550 // indirect
golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456 // indirect
)
This diff is collapsed.
package storage
import (
"context"
"io"
"github.com/filecoin-project/go-state-types/abi"
"github.com/ipfs/go-cid"
proof "github.com/filecoin-project/specs-actors/actors/runtime/proof"
)
type Data = io.Reader
type SectorRef struct {
ID abi.SectorID
ProofType abi.RegisteredSealProof
}
type Storage interface {
// Creates a new empty sector (only allocate on disk. Layers above
// storage are responsible for assigning sector IDs)
NewSector(ctx context.Context, sector SectorRef) error
// Add a piece to an existing *unsealed* sector
AddPiece(ctx context.Context, sector SectorRef, pieceSizes []abi.UnpaddedPieceSize, newPieceSize abi.UnpaddedPieceSize, pieceData Data) (abi.PieceInfo, error)
}
type Prover interface {
GenerateWinningPoSt(ctx context.Context, minerID abi.ActorID, sectorInfo []proof.SectorInfo, randomness abi.PoStRandomness) ([]proof.PoStProof, error)
GenerateWindowPoSt(ctx context.Context, minerID abi.ActorID, sectorInfo []proof.SectorInfo, randomness abi.PoStRandomness) (proof []proof.PoStProof, skipped []abi.SectorID, err error)
}
type PreCommit1Out []byte
type Commit1Out []byte
type Proof []byte
type SectorCids struct {
Unsealed cid.Cid
Sealed cid.Cid
}
type Range struct {
Offset abi.UnpaddedPieceSize
Size abi.UnpaddedPieceSize
}
type Sealer interface {
SealPreCommit1(ctx context.Context, sector SectorRef, ticket abi.SealRandomness, pieces []abi.PieceInfo) (PreCommit1Out, error)
SealPreCommit2(ctx context.Context, sector SectorRef, pc1o PreCommit1Out) (SectorCids, error)
SealCommit1(ctx context.Context, sector SectorRef, ticket abi.SealRandomness, seed abi.InteractiveSealRandomness, pieces []abi.PieceInfo, cids SectorCids) (Commit1Out, error)
SealCommit2(ctx context.Context, sector SectorRef, c1o Commit1Out) (Proof, error)
FinalizeSector(ctx context.Context, sector SectorRef, keepUnsealed []Range) error
// ReleaseUnsealed marks parts of the unsealed sector file as safe to drop
// (called by the fsm on restart, allows storage to keep no persistent
// state about unsealed fast-retrieval copies)
ReleaseUnsealed(ctx context.Context, sector SectorRef, safeToFree []Range) error
// Removes all data associated with the specified sector
Remove(ctx context.Context, sector SectorRef) error
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment