From eb0c993d24867089a7cd6a682afb5f38f9e96d16 Mon Sep 17 00:00:00 2001 From: Silas Davis <silas@monax.io> Date: Sun, 22 Jul 2018 14:18:54 +0100 Subject: [PATCH] GovTx based validator set changes implemented and tested Signed-off-by: Silas Davis <silas@monax.io> --- Gopkg.lock | 3 +- acm/balance/balance.go | 118 ++++ acm/balance/balance.pb.go | 337 ++++++++++ acm/balance/balance_test.go | 22 + acm/balance/type.go | 51 ++ acm/validator.go | 92 --- acm/validator/ring.go | 265 ++++++++ .../validator/ring_test.go | 26 +- .../validators.go => acm/validator/set.go | 126 ++-- .../validator/set_test.go | 8 +- acm/validator/validator.go | 27 + acm/validator/validator.pb.go | 405 ++++++++++++ acm/validator/validators.go | 111 ++++ acm/validator_test.go | 1 - {blockchain => bcm}/blockchain.go | 195 +++--- {blockchain => bcm}/blockchain_test.go | 23 +- blockchain/validators_ring.go | 198 ------ cmd/burrow/commands/configure.go | 4 +- cmd/burrow/commands/helpers.go | 2 +- cmd/burrow/commands/tx.go | 1 + config/config.go | 12 +- consensus/tendermint/abci/app.go | 90 +-- consensus/tendermint/config.go | 7 +- consensus/tendermint/{query => }/node_view.go | 12 +- .../{validator => }/priv_validator_memory.go | 2 +- .../tendermint/{validator => }/sign_info.go | 2 +- consensus/tendermint/tendermint.go | 8 +- consensus/tendermint/{validator => }/wire.go | 2 +- core/kernel.go | 98 +-- crypto/public_key.go | 12 + execution/contexts/call_context.go | 6 +- execution/contexts/governance_context.go | 36 +- execution/contexts/name_context.go | 4 +- execution/contexts/permissions_context.go | 16 +- execution/contexts/send_context.go | 9 +- execution/contexts/shared.go | 63 +- execution/errors/errors.go | 11 +- execution/errors/errors_test.go | 2 - execution/errors/vm.go | 5 +- execution/evm/vm.go | 20 +- execution/exec/exec.pb.go | 128 ++-- execution/execution.go | 55 +- execution/execution_test.go | 28 +- execution/simulated_call.go | 8 +- execution/transactor.go | 13 +- execution/transactor_test.go | 7 +- genesis/deterministic_genesis.go | 8 +- genesis/genesis.go | 30 +- genesis/genesis_test.go | 8 +- genesis/spec/genesis_spec.go | 8 +- genesis/spec/genesis_spec_test.go | 5 +- genesis/spec/presets.go | 20 +- genesis/spec/presets_test.go | 11 +- genesis/spec/spec.pb.go | 166 +++-- genesis/spec/template_account.go | 17 +- governance/governance.go | 38 ++ governance/governance_test.go | 23 + integration/core/kernel_test.go | 65 +- integration/governance/governance_test.go | 172 +++++ integration/governance/main_test.go | 55 +- integration/governance/validators_test.go | 7 - integration/integration.go | 71 +-- integration/integration_test.go | 28 + integration/rpcevents/main_test.go | 4 +- integration/rpcquery/main_test.go | 4 +- integration/rpctransact/main_test.go | 4 +- .../rpctransact/transact_server_test.go | 2 +- integration/tm/main_test.go | 4 +- logging/config/presets/instructions_test.go | 51 -- logging/config/sort.go | 1 - logging/lifecycle/lifecycle.go | 8 +- logging/{config => logconfig}/config.go | 16 +- logging/{config => logconfig}/config_test.go | 2 +- logging/{config => logconfig}/filter.go | 2 +- logging/{config => logconfig}/filter_test.go | 2 +- .../presets/instructions.go | 64 +- .../logconfig/presets/instructions_test.go | 51 ++ logging/{config => logconfig}/sinks.go | 13 +- logging/{config => logconfig}/sinks_test.go | 2 +- logging/logconfig/sort.go | 1 + logging/loggers/burrow_format_logger.go | 3 +- permission/account_permissions.go | 13 + permission/util.go | 23 +- permission/util_test.go | 10 +- protobuf/acm.proto | 7 +- protobuf/balance.proto | 20 + protobuf/exec.proto | 2 +- protobuf/payload.proto | 12 +- protobuf/rpcquery.proto | 15 + protobuf/rpctransact.proto | 10 +- protobuf/spec.proto | 25 +- protobuf/validator.proto | 22 + rpc/result.go | 8 +- rpc/rpcevents/execution_events_server.go | 6 +- rpc/rpcquery/query_server.go | 39 +- rpc/rpcquery/rpcquery.pb.go | 603 +++++++++++++++++- rpc/rpctransact/rpctransact.pb.go | 355 ++--------- rpc/rpctransact/transact_server.go | 60 +- rpc/service.go | 39 +- txs/amino_codec.go | 4 +- txs/payload/bond_tx.go | 6 + txs/payload/call_tx.go | 6 + txs/payload/gov_tx.go | 23 + txs/payload/governance_tx.go | 17 - txs/payload/name_tx.go | 6 + txs/payload/payload.go | 50 +- txs/payload/payload.pb.go | 391 ++++++++---- txs/payload/{permission_tx.go => perms_tx.go} | 22 +- txs/payload/send_tx.go | 6 + txs/payload/unbond_tx.go | 6 + txs/tx.go | 2 +- txs/tx_test.go | 4 +- util/logging/cmd/main.go | 2 +- 113 files changed, 3711 insertions(+), 1740 deletions(-) create mode 100644 acm/balance/balance.go create mode 100644 acm/balance/balance.pb.go create mode 100644 acm/balance/balance_test.go create mode 100644 acm/balance/type.go delete mode 100644 acm/validator.go create mode 100644 acm/validator/ring.go rename blockchain/validators_ring_test.go => acm/validator/ring_test.go (86%) rename blockchain/validators.go => acm/validator/set.go (51%) rename blockchain/validators_test.go => acm/validator/set_test.go (81%) create mode 100644 acm/validator/validator.go create mode 100644 acm/validator/validator.pb.go create mode 100644 acm/validator/validators.go delete mode 100644 acm/validator_test.go rename {blockchain => bcm}/blockchain.go (53%) rename {blockchain => bcm}/blockchain_test.go (60%) delete mode 100644 blockchain/validators_ring.go create mode 100644 cmd/burrow/commands/tx.go rename consensus/tendermint/{query => }/node_view.go (86%) rename consensus/tendermint/{validator => }/priv_validator_memory.go (98%) rename consensus/tendermint/{validator => }/sign_info.go (99%) rename consensus/tendermint/{validator => }/wire.go (89%) create mode 100644 governance/governance_test.go create mode 100644 integration/governance/governance_test.go delete mode 100644 integration/governance/validators_test.go create mode 100644 integration/integration_test.go delete mode 100644 logging/config/presets/instructions_test.go delete mode 100644 logging/config/sort.go rename logging/{config => logconfig}/config.go (84%) rename logging/{config => logconfig}/config_test.go (97%) rename logging/{config => logconfig}/filter.go (99%) rename logging/{config => logconfig}/filter_test.go (99%) rename logging/{config => logconfig}/presets/instructions.go (66%) create mode 100644 logging/logconfig/presets/instructions_test.go rename logging/{config => logconfig}/sinks.go (97%) rename logging/{config => logconfig}/sinks_test.go (99%) create mode 100644 logging/logconfig/sort.go create mode 100644 protobuf/balance.proto create mode 100644 protobuf/validator.proto create mode 100644 txs/payload/gov_tx.go delete mode 100644 txs/payload/governance_tx.go rename txs/payload/{permission_tx.go => perms_tx.go} (53%) diff --git a/Gopkg.lock b/Gopkg.lock index 6eb70eac..ac4f2f28 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -572,14 +572,15 @@ "github.com/tendermint/tendermint/consensus", "github.com/tendermint/tendermint/consensus/types", "github.com/tendermint/tendermint/crypto", + "github.com/tendermint/tendermint/crypto/tmhash", "github.com/tendermint/tendermint/libs/common", "github.com/tendermint/tendermint/libs/db", "github.com/tendermint/tendermint/libs/log", "github.com/tendermint/tendermint/libs/pubsub", - "github.com/tendermint/tendermint/mempool", "github.com/tendermint/tendermint/node", "github.com/tendermint/tendermint/p2p", "github.com/tendermint/tendermint/proxy", + "github.com/tendermint/tendermint/rpc/core", "github.com/tendermint/tendermint/rpc/core/types", "github.com/tendermint/tendermint/state", "github.com/tendermint/tendermint/types", diff --git a/acm/balance/balance.go b/acm/balance/balance.go new file mode 100644 index 00000000..20b5cc85 --- /dev/null +++ b/acm/balance/balance.go @@ -0,0 +1,118 @@ +package balance + +import "fmt" + +type Balances []Balance + +func (b Balance) String() string { + return fmt.Sprintf("{%v: %d}", b.Type, b.Amount) +} + +func New() Balances { + return []Balance{} +} + +func (bs Balances) Len() int { + return len(bs) +} + +func (bs Balances) Less(i, j int) bool { + if bs[i].Type < bs[j].Type { + return true + } + return bs[i].Type == bs[j].Type && bs[i].Amount < bs[j].Amount +} + +func (bs Balances) Swap(i, j int) { + bs[i], bs[j] = bs[j], bs[i] +} + +func (bs Balances) Add(ty Type, amount uint64) Balances { + return append(bs, Balance{ + Type: ty, + Amount: amount, + }) +} + +func (bs Balances) Native(amount uint64) Balances { + return bs.Add(TypeNative, amount) +} + +func (bs Balances) Power(amount uint64) Balances { + return bs.Add(TypePower, amount) +} + +func (bs Balances) Sum(bss ...Balances) Balances { + return Sum(append(bss, bs)...) +} + +func Sum(bss ...Balances) Balances { + sum := New() + sumMap := make(map[Type]uint64) + for _, bs := range bss { + for _, b := range bs { + sumMap[b.Type] += b.Amount + } + } + for k, v := range sumMap { + sum = sum.Add(k, v) + } + return sum +} + +func Native(native uint64) Balance { + return Balance{ + Type: TypeNative, + Amount: native, + } +} + +func Power(power uint64) Balance { + return Balance{ + Type: TypePower, + Amount: power, + } +} + +func (bs Balances) Has(ty Type) bool { + for _, b := range bs { + if b.Type == ty { + return true + } + } + return false +} + +func (bs Balances) Get(ty Type) *uint64 { + for _, b := range bs { + if b.Type == ty { + return &b.Amount + } + } + return nil +} + +func (bs Balances) GetFallback(ty Type, fallback uint64) uint64 { + for _, b := range bs { + if b.Type == ty { + return b.Amount + } + } + return fallback +} + +func (bs Balances) GetNative(fallback uint64) uint64 { + return bs.GetFallback(TypeNative, fallback) +} + +func (bs Balances) GetPower(fallback uint64) uint64 { + return bs.GetFallback(TypePower, fallback) +} + +func (bs Balances) HasNative() bool { + return bs.Has(TypeNative) +} + +func (bs Balances) HasPower() bool { + return bs.Has(TypePower) +} diff --git a/acm/balance/balance.pb.go b/acm/balance/balance.pb.go new file mode 100644 index 00000000..c1e0bdbd --- /dev/null +++ b/acm/balance/balance.pb.go @@ -0,0 +1,337 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: balance.proto + +/* + Package balance is a generated protocol buffer package. + + It is generated from these files: + balance.proto + + It has these top-level messages: + Balance +*/ +package balance + +import proto "github.com/gogo/protobuf/proto" +import golang_proto "github.com/golang/protobuf/proto" +import fmt "fmt" +import math "math" +import _ "github.com/gogo/protobuf/gogoproto" + +import io "io" + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = golang_proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.GoGoProtoPackageIsVersion2 // please upgrade the proto package + +type Balance struct { + Type Type `protobuf:"varint,1,opt,name=Type,proto3,casttype=Type" json:"Type,omitempty"` + Amount uint64 `protobuf:"varint,2,opt,name=Amount,proto3" json:"Amount,omitempty"` +} + +func (m *Balance) Reset() { *m = Balance{} } +func (*Balance) ProtoMessage() {} +func (*Balance) Descriptor() ([]byte, []int) { return fileDescriptorBalance, []int{0} } + +func (m *Balance) GetType() Type { + if m != nil { + return m.Type + } + return 0 +} + +func (m *Balance) GetAmount() uint64 { + if m != nil { + return m.Amount + } + return 0 +} + +func (*Balance) XXX_MessageName() string { + return "balance.Balance" +} +func init() { + proto.RegisterType((*Balance)(nil), "balance.Balance") + golang_proto.RegisterType((*Balance)(nil), "balance.Balance") +} +func (m *Balance) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalTo(dAtA) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *Balance) MarshalTo(dAtA []byte) (int, error) { + var i int + _ = i + var l int + _ = l + if m.Type != 0 { + dAtA[i] = 0x8 + i++ + i = encodeVarintBalance(dAtA, i, uint64(m.Type)) + } + if m.Amount != 0 { + dAtA[i] = 0x10 + i++ + i = encodeVarintBalance(dAtA, i, uint64(m.Amount)) + } + return i, nil +} + +func encodeVarintBalance(dAtA []byte, offset int, v uint64) int { + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return offset + 1 +} +func (m *Balance) Size() (n int) { + var l int + _ = l + if m.Type != 0 { + n += 1 + sovBalance(uint64(m.Type)) + } + if m.Amount != 0 { + n += 1 + sovBalance(uint64(m.Amount)) + } + return n +} + +func sovBalance(x uint64) (n int) { + for { + n++ + x >>= 7 + if x == 0 { + break + } + } + return n +} +func sozBalance(x uint64) (n int) { + return sovBalance(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *Balance) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowBalance + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: Balance: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: Balance: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Type", wireType) + } + m.Type = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowBalance + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Type |= (Type(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Amount", wireType) + } + m.Amount = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowBalance + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Amount |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipBalance(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthBalance + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipBalance(dAtA []byte) (n int, err error) { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowBalance + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + wireType := int(wire & 0x7) + switch wireType { + case 0: + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowBalance + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + iNdEx++ + if dAtA[iNdEx-1] < 0x80 { + break + } + } + return iNdEx, nil + case 1: + iNdEx += 8 + return iNdEx, nil + case 2: + var length int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowBalance + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + length |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + iNdEx += length + if length < 0 { + return 0, ErrInvalidLengthBalance + } + return iNdEx, nil + case 3: + for { + var innerWire uint64 + var start int = iNdEx + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowBalance + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + innerWire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + innerWireType := int(innerWire & 0x7) + if innerWireType == 4 { + break + } + next, err := skipBalance(dAtA[start:]) + if err != nil { + return 0, err + } + iNdEx = start + next + } + return iNdEx, nil + case 4: + return iNdEx, nil + case 5: + iNdEx += 4 + return iNdEx, nil + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + } + panic("unreachable") +} + +var ( + ErrInvalidLengthBalance = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowBalance = fmt.Errorf("proto: integer overflow") +) + +func init() { proto.RegisterFile("balance.proto", fileDescriptorBalance) } +func init() { golang_proto.RegisterFile("balance.proto", fileDescriptorBalance) } + +var fileDescriptorBalance = []byte{ + // 187 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xe2, 0x4d, 0x4a, 0xcc, 0x49, + 0xcc, 0x4b, 0x4e, 0xd5, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x62, 0x87, 0x72, 0xa5, 0x74, 0xd3, + 0x33, 0x4b, 0x32, 0x4a, 0x93, 0xf4, 0x92, 0xf3, 0x73, 0xf5, 0xd3, 0xf3, 0xd3, 0xf3, 0xf5, 0xc1, + 0xf2, 0x49, 0xa5, 0x69, 0x60, 0x1e, 0x98, 0x03, 0x66, 0x41, 0xf4, 0x29, 0xb9, 0x72, 0xb1, 0x3b, + 0x41, 0x74, 0x0a, 0xc9, 0x70, 0xb1, 0x84, 0x54, 0x16, 0xa4, 0x4a, 0x30, 0x2a, 0x30, 0x6a, 0xf0, + 0x3a, 0x71, 0xfc, 0xba, 0x27, 0x0f, 0xe6, 0x07, 0x81, 0x49, 0x21, 0x31, 0x2e, 0x36, 0xc7, 0xdc, + 0xfc, 0xd2, 0xbc, 0x12, 0x09, 0x26, 0x05, 0x46, 0x0d, 0x96, 0x20, 0x28, 0xcf, 0x8a, 0x65, 0xc6, + 0x02, 0x79, 0x06, 0x27, 0xfb, 0x13, 0x8f, 0xe4, 0x18, 0x2f, 0x3c, 0x92, 0x63, 0x7c, 0xf0, 0x48, + 0x8e, 0xf1, 0xc0, 0x63, 0x39, 0xc6, 0x13, 0x8f, 0xe5, 0x18, 0xa3, 0x34, 0x91, 0xdc, 0x92, 0x51, + 0x59, 0x90, 0x5a, 0x94, 0x93, 0x9a, 0x92, 0x9e, 0x5a, 0xa4, 0x9f, 0x54, 0x5a, 0x54, 0x94, 0x5f, + 0xae, 0x9f, 0x98, 0x9c, 0xab, 0x0f, 0x75, 0x76, 0x12, 0x1b, 0xd8, 0x39, 0xc6, 0x80, 0x00, 0x00, + 0x00, 0xff, 0xff, 0x1d, 0x22, 0xfc, 0x8b, 0xd7, 0x00, 0x00, 0x00, +} diff --git a/acm/balance/balance_test.go b/acm/balance/balance_test.go new file mode 100644 index 00000000..d6710e09 --- /dev/null +++ b/acm/balance/balance_test.go @@ -0,0 +1,22 @@ +package balance + +import ( + "sort" + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestSum(t *testing.T) { + one := New().Power(23223).Native(34).Native(1111) + two := New().Power(3).Native(22) + sum := one.Sum(two) + assert.Equal(t, New().Power(23226).Native(1167), sum) +} + +func TestSort(t *testing.T) { + balances := New().Power(232).Native(2523543).Native(232).Power(2).Power(4).Native(1) + sortedBalances := New().Native(1).Native(232).Native(2523543).Power(2).Power(4).Power(232) + sort.Sort(balances) + assert.Equal(t, sortedBalances, balances) +} diff --git a/acm/balance/type.go b/acm/balance/type.go new file mode 100644 index 00000000..8b8ece9a --- /dev/null +++ b/acm/balance/type.go @@ -0,0 +1,51 @@ +package balance + +type Type uint32 + +const ( + TypeNative Type = 1 + TypePower Type = 2 +) + +var nameFromType = map[Type]string{ + TypeNative: "Native", + TypePower: "Power", +} + +var typeFromName = make(map[string]Type) + +func init() { + for t, n := range nameFromType { + typeFromName[n] = t + } +} + +func TypeFromString(name string) Type { + return typeFromName[name] +} + +func (typ Type) String() string { + name, ok := nameFromType[typ] + if ok { + return name + } + return "UnknownBalanceType" +} + +func (typ Type) MarshalText() ([]byte, error) { + return []byte(typ.String()), nil +} + +func (typ *Type) UnmarshalText(data []byte) error { + *typ = TypeFromString(string(data)) + return nil +} + +// Protobuf support +func (typ Type) Marshal() ([]byte, error) { + return typ.MarshalText() +} + +func (typ *Type) Unmarshal(data []byte) error { + return typ.UnmarshalText(data) +} diff --git a/acm/validator.go b/acm/validator.go deleted file mode 100644 index ddf471ec..00000000 --- a/acm/validator.go +++ /dev/null @@ -1,92 +0,0 @@ -package acm - -import ( - "encoding/json" - - "github.com/hyperledger/burrow/crypto" -) - -type Validator interface { - crypto.Addressable - // The validator's voting power - Power() uint64 -} - -// Neither abci_types or tm_types has quite the representation we want -type ConcreteValidator struct { - Address crypto.Address - PublicKey crypto.PublicKey - Power uint64 -} - -type concreteValidatorWrapper struct { - *ConcreteValidator `json:"unwrap"` -} - -var _ Validator = concreteValidatorWrapper{} - -func AsValidator(account Account) Validator { - return ConcreteValidator{ - Address: account.Address(), - PublicKey: account.PublicKey(), - Power: account.Balance(), - }.Validator() -} - -func AsConcreteValidator(validator Validator) *ConcreteValidator { - if validator == nil { - return nil - } - if ca, ok := validator.(concreteValidatorWrapper); ok { - return ca.ConcreteValidator - } - return &ConcreteValidator{ - Address: validator.Address(), - PublicKey: validator.PublicKey(), - Power: validator.Power(), - } -} - -func (cvw concreteValidatorWrapper) Address() crypto.Address { - return cvw.ConcreteValidator.Address -} - -func (cvw concreteValidatorWrapper) PublicKey() crypto.PublicKey { - return cvw.ConcreteValidator.PublicKey -} - -func (cvw concreteValidatorWrapper) Power() uint64 { - return cvw.ConcreteValidator.Power -} - -func (cvw concreteValidatorWrapper) WithNewPower(power uint64) Validator { - cv := cvw.Copy() - cv.Power = power - return concreteValidatorWrapper{ - ConcreteValidator: cv, - } -} - -func (cv ConcreteValidator) Validator() Validator { - return concreteValidatorWrapper{ - ConcreteValidator: &cv, - } -} - -func (cv *ConcreteValidator) Copy() *ConcreteValidator { - cvCopy := *cv - return &cvCopy -} - -func (cv *ConcreteValidator) String() string { - if cv == nil { - return "Nil Validator" - } - - bs, err := json.Marshal(cv) - if err != nil { - return "error serialising Validator" - } - - return string(bs) -} diff --git a/acm/validator/ring.go b/acm/validator/ring.go new file mode 100644 index 00000000..bbc6fa56 --- /dev/null +++ b/acm/validator/ring.go @@ -0,0 +1,265 @@ +package validator + +import ( + "fmt" + "math/big" + + "github.com/hyperledger/burrow/crypto" +) + +type Ring struct { + // The validator power history stored in buckets as a ring buffer + // The changes committed at rotation i + delta []*Set + // The cumulative changes at rotation i - 1 + cum []*Set + // Totals for each validator across all buckets + power *Set + // Current flow totals for each validator in the Head bucket + flow *Set + // Index of current head bucket + head int64 + // Number of buckets + size int64 +} + +var big1 = big.NewInt(1) +var big3 = big.NewInt(3) + +// Provides a sliding window over the last size buckets of validator power changes +func NewRing(initialSet Iterable, windowSize int) *Ring { + if windowSize < 1 { + windowSize = 1 + } + vw := &Ring{ + delta: make([]*Set, windowSize), + cum: make([]*Set, windowSize), + power: NewSet(), + flow: NewSet(), + size: int64(windowSize), + } + for i := 0; i < windowSize; i++ { + vw.delta[i] = NewSet() + // Important that this is trim set for accurate count + vw.cum[i] = NewTrimSet() + } + vw.cum[0] = Copy(initialSet) + + return vw +} + +// Implement Reader +// Get power at index from the delta bucket then falling through to the cumulative +func (vc *Ring) PowerAt(index int64, id crypto.Addressable) *big.Int { + power := vc.Head().MaybePower(id) + if power != nil { + return power + } + return vc.Cum().Power(id) +} + +func (vc *Ring) Power(id crypto.Addressable) *big.Int { + return vc.PowerAt(vc.head, id) +} + +// Return the resultant set at index of current cum plus delta +func (vc *Ring) Resultant(index int64) *Set { + i := vc.index(index) + cum := CopyTrim(vc.cum[i]) + vc.delta[i].Iterate(func(id crypto.Addressable, power *big.Int) (stop bool) { + cum.AlterPower(id, power) + return + }) + return cum +} + +func (vc *Ring) TotalPower() *big.Int { + return vc.Resultant(vc.head).totalPower +} + +// Updates the current head bucket (accumulator) with some safety checks +func (vc *Ring) AlterPower(id crypto.Addressable, power *big.Int) (*big.Int, error) { + if power.Sign() == -1 { + return nil, fmt.Errorf("cannot set negative validator power: %v", power) + } + if !power.IsInt64() { + return nil, fmt.Errorf("for tendermint compatibility validator power must fit within an Int64 bur %v "+ + "does not", power) + } + // if flow > maxflow then we cannot alter the power + flow := vc.Flow(id, power) + maxFlow := vc.MaxFlow() + // Set flow for this id to update flow.totalPower (total flow) for comparison below, keep track of flow for each id + // so that we only count flow once for each id + vc.flow.ChangePower(id, flow) + // The totalPower of the Flow Set is the absolute value of all power changes made so far + if vc.flow.totalPower.Cmp(maxFlow) == 1 { + // Reset flow to previous value to undo update above + prevFlow := vc.Flow(id, vc.Head().Power(id)) + vc.flow.ChangePower(id, prevFlow) + allowable := new(big.Int).Sub(maxFlow, vc.flow.totalPower) + return nil, fmt.Errorf("cannot change validator power of %v from %v to %v because that would result in a flow "+ + "greater than or equal to 1/3 of total power for the next commit: flow induced by change: %v, "+ + "current total flow: %v/%v (cumulative/max), remaining allowable flow: %v", + id.Address(), vc.Cum().Power(id), power, flow, vc.flow.totalPower, maxFlow, allowable) + } + // Add to total power + vc.Head().ChangePower(id, power) + return flow, nil +} + +// Returns the flow that would be induced by a validator change by comparing the head accumulater with the current set +func (vc *Ring) Flow(id crypto.Addressable, power *big.Int) *big.Int { + flow := new(big.Int) + return flow.Abs(flow.Sub(power, vc.Cum().Power(id))) +} + +// To ensure that in the maximum valildator shift at least one unit +// of validator power in the intersection of last block validators and this block validators must have at least one +// non-byzantine validator who can tell you if you've been lied to about the validator set +// So need at most ceiling((Total Power)/3) - 1, in integer division we have ceiling(X*p/q) = (p(X+1)-1)/q +// For p = 1 just X/q +// So we want (Total Power)/3 - 1 +func (vc *Ring) MaxFlow() *big.Int { + max := vc.Cum().TotalPower() + return max.Sub(max.Div(max, big3), big1) +} + +// Advance the current head bucket to the next bucket and returns the change in total power between the previous bucket +// and the current head, and the total flow which is the sum of absolute values of all changes each validator's power +// after rotation the next head is a copy of the current head +func (vc *Ring) Rotate() (totalPowerChange *big.Int, totalFlow *big.Int, err error) { + // Subtract the tail bucket (if any) from the total + err = Subtract(vc.power, vc.Next()) + if err != nil { + return + } + // Add head delta to total power + err = Add(vc.power, vc.Head()) + if err != nil { + return + } + // Copy current cumulative bucket + cum := CopyTrim(vc.Cum()) + // Copy delta into what will be the next cumulative bucket + err = Alter(cum, vc.Head()) + if err != nil { + return + } + // Advance the ring buffer + vc.head = vc.index(1) + // Overwrite new head bucket (previous tail) with a fresh delta accumulator + vc.delta[vc.head] = NewSet() + // Set the next cum + vc.cum[vc.head] = cum + // Capture flow before we wipe it + totalFlow = vc.flow.totalPower + // New flow accumulator + vc.flow = NewSet() + // Subtract the previous bucket total power so we can add on the current buckets power after this + totalPowerChange = new(big.Int).Sub(vc.Cum().TotalPower(), vc.cum[vc.index(-1)].TotalPower()) + return +} + +func (vc *Ring) CurrentSet() *Set { + return vc.cum[vc.head] +} + +func (vc *Ring) PreviousSet() *Set { + return vc.cum[vc.index(-1)] +} + +func (vc *Ring) Cum() *Set { + return vc.cum[vc.head] +} + +// Get the current accumulator bucket +func (vc *Ring) Head() *Set { + return vc.delta[vc.head] +} + +func (vc *Ring) Next() *Set { + return vc.delta[vc.index(1)] +} + +func (vc *Ring) index(i int64) int64 { + idx := (vc.size + vc.head + i) % vc.size + return idx +} + +// Get the number of buckets in the ring (use Current().Count() to get the current number of validators) +func (vc *Ring) Size() int64 { + return vc.size +} + +// Returns buckets in order head, previous, ... +func (vc *Ring) OrderedBuckets() (delta, cum []*Set) { + delta = make([]*Set, len(vc.delta)) + cum = make([]*Set, len(vc.cum)) + for i := int64(0); i < vc.size; i++ { + index := vc.index(-i) + delta[i] = vc.delta[index] + cum[i] = vc.cum[index] + } + return +} + +func (vc *Ring) String() string { + delta, _ := vc.OrderedBuckets() + return fmt.Sprintf("ValidatorsWindow{Total: %v; Delta: Head->%v<-Tail}", vc.power, delta) +} + +func (vc *Ring) Equal(vwOther *Ring) bool { + if vc.size != vwOther.size || vc.head != vwOther.head || len(vc.delta) != len(vwOther.delta) || + !vc.flow.Equal(vwOther.flow) || !vc.power.Equal(vwOther.power) { + return false + } + for i := 0; i < len(vc.delta); i++ { + if !vc.delta[i].Equal(vwOther.delta[i]) || !vc.cum[i].Equal(vwOther.cum[i]) { + return false + } + } + return true +} + +type PersistedRing struct { + Delta [][]*Validator + Cum [][]*Validator + Power []*Validator + Flow []*Validator + Head int64 +} + +func (vc *Ring) Persistable() PersistedRing { + delta := make([][]*Validator, len(vc.delta)) + cum := make([][]*Validator, len(vc.cum)) + for i := 0; i < len(delta); i++ { + delta[i] = vc.delta[i].Validators() + cum[i] = vc.cum[i].Validators() + + } + return PersistedRing{ + Delta: delta, + Cum: cum, + Power: vc.power.Validators(), + Flow: vc.flow.Validators(), + Head: vc.head, + } +} + +func UnpersistRing(pc PersistedRing) *Ring { + delta := make([]*Set, len(pc.Delta)) + cum := make([]*Set, len(pc.Cum)) + for i := 0; i < len(delta); i++ { + delta[i] = UnpersistSet(pc.Delta[i]) + cum[i] = UnpersistSet(pc.Cum[i]) + } + return &Ring{ + delta: delta, + cum: cum, + head: pc.Head, + power: UnpersistSet(pc.Power), + flow: UnpersistSet(pc.Flow), + size: int64(len(delta)), + } +} diff --git a/blockchain/validators_ring_test.go b/acm/validator/ring_test.go similarity index 86% rename from blockchain/validators_ring_test.go rename to acm/validator/ring_test.go index d0c81628..66d00db9 100644 --- a/blockchain/validators_ring_test.go +++ b/acm/validator/ring_test.go @@ -1,4 +1,4 @@ -package blockchain +package validator import ( "fmt" @@ -14,10 +14,12 @@ var pubB = pubKey(2) var pubC = pubKey(3) func TestValidatorsWindow_AlterPower(t *testing.T) { - vs := NewValidators() + vsBase := NewSet() powAInitial := int64(10000) - vs.AlterPower(pubA, big.NewInt(powAInitial)) - vw := NewValidatorsRing(vs, 3) + vsBase.ChangePower(pubA, big.NewInt(powAInitial)) + + vs := Copy(vsBase) + vw := NewRing(vs, 3) // Just allowable validator tide var powA, powB, powC int64 = 7000, 23, 309 @@ -27,7 +29,8 @@ func TestValidatorsWindow_AlterPower(t *testing.T) { assert.Equal(t, big.NewInt(powAInitial/3-1), totalFlow) // This one is not - vw = NewValidatorsRing(vs, 5) + vs = Copy(vsBase) + vw = NewRing(vs, 5) powA, powB, powC = 7000, 23, 310 powerChange, totalFlow, err = alterPowers(t, vw, powA, powB, powC) require.Error(t, err) @@ -77,21 +80,21 @@ func TestValidatorsWindow_AlterPower(t *testing.T) { func TestValidatorsRing_Persistable(t *testing.T) { - vs := NewValidators() + vs := NewSet() powAInitial := int64(10000) - vs.AlterPower(pubA, big.NewInt(powAInitial)) - vw := NewValidatorsRing(vs, 30) + vs.ChangePower(pubA, big.NewInt(powAInitial)) + vw := NewRing(vs, 30) for i := int64(0); i < 61; i++ { _, _, err := alterPowers(t, vw, 10000, 200*i, 200*((i+1)%4)) require.NoError(t, err) } - vwOut := UnpersistValidatorsRing(vw.Persistable()) + vwOut := UnpersistRing(vw.Persistable()) assert.True(t, vw.Equal(vwOut), "should re equal across persistence") } -func alterPowers(t testing.TB, vw *ValidatorsRing, powA, powB, powC int64) (powerChange, totalFlow *big.Int, err error) { +func alterPowers(t testing.TB, vw *Ring, powA, powB, powC int64) (powerChange, totalFlow *big.Int, err error) { fmt.Println(vw) _, err = vw.AlterPower(pubA, big.NewInt(powA)) if err != nil { @@ -106,7 +109,8 @@ func alterPowers(t testing.TB, vw *ValidatorsRing, powA, powB, powC int64) (powe return nil, nil, err } maxFlow := vw.MaxFlow() - powerChange, totalFlow = vw.Rotate() + powerChange, totalFlow, err = vw.Rotate() + require.NoError(t, err) // totalFlow > maxFlow if totalFlow.Cmp(maxFlow) == 1 { return powerChange, totalFlow, fmt.Errorf("totalFlow (%v) exceeds maxFlow (%v)", totalFlow, maxFlow) diff --git a/blockchain/validators.go b/acm/validator/set.go similarity index 51% rename from blockchain/validators.go rename to acm/validator/set.go index ea2ddfd4..1ce7d010 100644 --- a/blockchain/validators.go +++ b/acm/validator/set.go @@ -1,4 +1,4 @@ -package blockchain +package validator import ( "fmt" @@ -12,80 +12,76 @@ import ( var big0 = big.NewInt(0) // A Validator multiset - can be used to capture the global state of validators or as an accumulator each block -type Validators struct { +type Set struct { powers map[crypto.Address]*big.Int publicKeys map[crypto.Address]crypto.Addressable totalPower *big.Int + trim bool } -type ValidatorSet interface { - AlterPower(id crypto.Addressable, power *big.Int) (flow *big.Int, err error) -} - -// Create a new Validators which can act as an accumulator for validator power changes -func NewValidators() *Validators { - return &Validators{ +func newSet() *Set { + return &Set{ totalPower: new(big.Int), powers: make(map[crypto.Address]*big.Int), publicKeys: make(map[crypto.Address]crypto.Addressable), } } +// Create a new Validators which can act as an accumulator for validator power changes +func NewSet() *Set { + return newSet() +} + +// Like Set but removes entries when power is set to 0 this make Count() == CountNonZero() and prevents a set from leaking +// but does mean that a zero will not be iterated over when performing an update which is necessary in Ring +func NewTrimSet() *Set { + s := newSet() + s.trim = true + return s +} + +// Implements Writer, but will never error +func (vs *Set) AlterPower(id crypto.Addressable, power *big.Int) (flow *big.Int, err error) { + return vs.ChangePower(id, power), nil +} + // Add the power of a validator and returns the flow into that validator -func (vs *Validators) AlterPower(id crypto.Addressable, power *big.Int) *big.Int { - if power.Sign() == -1 { - panic("ASRRRH") - } +func (vs *Set) ChangePower(id crypto.Addressable, power *big.Int) *big.Int { address := id.Address() // Calculcate flow into this validator (postive means in, negative means out) flow := new(big.Int).Sub(power, vs.Power(id)) vs.totalPower.Add(vs.totalPower, flow) - if power.Cmp(big0) == 0 { - // Remove from set so that we return an accurate length + + if vs.trim && power.Sign() == 0 { delete(vs.publicKeys, address) delete(vs.powers, address) - return flow + } else { + vs.publicKeys[address] = crypto.MemoizeAddressable(id) + vs.powers[address] = new(big.Int).Set(power) } - vs.publicKeys[address] = crypto.MemoizeAddressable(id) - vs.powers[address] = new(big.Int).Set(power) return flow } -// Adds vsOther to vs -func (vs *Validators) Add(vsOther *Validators) { - vsOther.Iterate(func(id crypto.Addressable, power *big.Int) (stop bool) { - vs.AddPower(id, power) - return - }) -} - -func (vs *Validators) AddPower(id crypto.Addressable, power *big.Int) { - // Current power + power - vs.AlterPower(id, new(big.Int).Add(vs.Power(id), power)) -} - -// Subtracts vsOther from vs -func (vs *Validators) Subtract(vsOther *Validators) { - vsOther.Iterate(func(id crypto.Addressable, power *big.Int) (stop bool) { - vs.SubtractPower(id, power) - return - }) +func (vs *Set) TotalPower() *big.Int { + return new(big.Int).Set(vs.totalPower) } -func (vs *Validators) SubtractPower(id crypto.Addressable, power *big.Int) { - // Current power - power - thisPower := vs.Power(id) - vs.AlterPower(id, new(big.Int).Sub(thisPower, power)) +// Returns the power of id but only if it is set +func (vs *Set) MaybePower(id crypto.Addressable) *big.Int { + if vs.powers[id.Address()] == nil { + return nil + } + return new(big.Int).Set(vs.powers[id.Address()]) } -func (vs *Validators) Power(id crypto.Addressable) *big.Int { +func (vs *Set) Power(id crypto.Addressable) *big.Int { if vs.powers[id.Address()] == nil { return new(big.Int) } return new(big.Int).Set(vs.powers[id.Address()]) } -func (vs *Validators) Equal(vsOther *Validators) bool { +func (vs *Set) Equal(vsOther *Set) bool { if vs.Count() != vsOther.Count() { return false } @@ -100,7 +96,7 @@ func (vs *Validators) Equal(vsOther *Validators) bool { } // Iterates over validators sorted by address -func (vs *Validators) Iterate(iter func(id crypto.Addressable, power *big.Int) (stop bool)) (stopped bool) { +func (vs *Set) Iterate(iter func(id crypto.Addressable, power *big.Int) (stop bool)) (stopped bool) { if vs == nil { return } @@ -117,55 +113,47 @@ func (vs *Validators) Iterate(iter func(id crypto.Addressable, power *big.Int) ( return } -func (vs *Validators) Count() int { - return len(vs.publicKeys) -} - -func (vs *Validators) TotalPower() *big.Int { - return new(big.Int).Set(vs.totalPower) -} - -func (vs *Validators) Copy() *Validators { - vsCopy := NewValidators() +func (vs *Set) CountNonZero() int { + var count int vs.Iterate(func(id crypto.Addressable, power *big.Int) (stop bool) { - vsCopy.AlterPower(id, power) + if power.Sign() != 0 { + count++ + } return }) - return vsCopy + return count } -type PersistedValidator struct { - PublicKey crypto.PublicKey - PowerBytes []byte +func (vs *Set) Count() int { + return len(vs.publicKeys) } -func (vs *Validators) Persistable() []PersistedValidator { +func (vs *Set) Validators() []*Validator { if vs == nil { return nil } - pvs := make([]PersistedValidator, 0, vs.Count()) + pvs := make([]*Validator, 0, vs.Count()) vs.Iterate(func(id crypto.Addressable, power *big.Int) (stop bool) { - pvs = append(pvs, PersistedValidator{PublicKey: id.PublicKey(), PowerBytes: power.Bytes()}) + pvs = append(pvs, &Validator{PublicKey: id.PublicKey(), Power: power.Uint64()}) return }) return pvs } -func UnpersistValidators(pvs []PersistedValidator) *Validators { - vs := NewValidators() +func UnpersistSet(pvs []*Validator) *Set { + vs := NewSet() for _, pv := range pvs { - power := new(big.Int).SetBytes(pv.PowerBytes) - vs.AlterPower(pv.PublicKey, power) + vs.ChangePower(pv.PublicKey, new(big.Int).SetUint64(pv.Power)) } return vs } -func (vs *Validators) String() string { +func (vs *Set) String() string { return fmt.Sprintf("Validators{TotalPower: %v; Count: %v; %v}", vs.TotalPower(), vs.Count(), - vs.ValidatorStrings()) + vs.Strings()) } -func (vs *Validators) ValidatorStrings() string { +func (vs *Set) Strings() string { strs := make([]string, 0, vs.Count()) vs.Iterate(func(id crypto.Addressable, power *big.Int) (stop bool) { strs = append(strs, fmt.Sprintf("%v->%v", id.Address(), power)) diff --git a/blockchain/validators_test.go b/acm/validator/set_test.go similarity index 81% rename from blockchain/validators_test.go rename to acm/validator/set_test.go index 1bc7970e..ea0eeb63 100644 --- a/blockchain/validators_test.go +++ b/acm/validator/set_test.go @@ -1,4 +1,4 @@ -package blockchain +package validator import ( "fmt" @@ -11,12 +11,12 @@ import ( ) func TestValidators_AlterPower(t *testing.T) { - vs := NewValidators() + vs := NewSet() pow1 := big.NewInt(2312312321) pubA := pubKey(1) - vs.AlterPower(pubA, pow1) + vs.ChangePower(pubA, pow1) assert.Equal(t, pow1, vs.TotalPower()) - vs.AlterPower(pubA, big.NewInt(0)) + vs.ChangePower(pubA, big.NewInt(0)) assertZero(t, vs.TotalPower()) } diff --git a/acm/validator/validator.go b/acm/validator/validator.go new file mode 100644 index 00000000..d2bdc174 --- /dev/null +++ b/acm/validator/validator.go @@ -0,0 +1,27 @@ +package validator + +import ( + "fmt" + + "github.com/hyperledger/burrow/acm" +) + +func (v Validator) String() string { + return fmt.Sprintf("Validator{Address: %v, PublicKey: %v, Power: %v}", v.Address, v.PublicKey, v.Power) +} + +func (v Validator) FillAddress() { + if v.Address == nil { + address := v.PublicKey.Address() + v.Address = &address + } +} + +func FromAccount(acc acm.Account, power uint64) Validator { + address := acc.Address() + return Validator{ + Address: &address, + PublicKey: acc.PublicKey(), + Power: power, + } +} diff --git a/acm/validator/validator.pb.go b/acm/validator/validator.pb.go new file mode 100644 index 00000000..93c8b77d --- /dev/null +++ b/acm/validator/validator.pb.go @@ -0,0 +1,405 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: validator.proto + +/* + Package validator is a generated protocol buffer package. + + It is generated from these files: + validator.proto + + It has these top-level messages: + Validator +*/ +package validator + +import proto "github.com/gogo/protobuf/proto" +import golang_proto "github.com/golang/protobuf/proto" +import fmt "fmt" +import math "math" +import _ "github.com/gogo/protobuf/gogoproto" +import _ "github.com/hyperledger/burrow/permission" +import crypto "github.com/hyperledger/burrow/crypto" + +import github_com_hyperledger_burrow_crypto "github.com/hyperledger/burrow/crypto" + +import io "io" + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = golang_proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.GoGoProtoPackageIsVersion2 // please upgrade the proto package + +type Validator struct { + Address *github_com_hyperledger_burrow_crypto.Address `protobuf:"bytes,1,opt,name=Address,proto3,customtype=github.com/hyperledger/burrow/crypto.Address" json:"Address,omitempty"` + PublicKey crypto.PublicKey `protobuf:"bytes,2,opt,name=PublicKey" json:"PublicKey"` + Power uint64 `protobuf:"varint,3,opt,name=Power,proto3" json:"Power,omitempty"` +} + +func (m *Validator) Reset() { *m = Validator{} } +func (*Validator) ProtoMessage() {} +func (*Validator) Descriptor() ([]byte, []int) { return fileDescriptorValidator, []int{0} } + +func (m *Validator) GetPublicKey() crypto.PublicKey { + if m != nil { + return m.PublicKey + } + return crypto.PublicKey{} +} + +func (m *Validator) GetPower() uint64 { + if m != nil { + return m.Power + } + return 0 +} + +func (*Validator) XXX_MessageName() string { + return "validator.Validator" +} +func init() { + proto.RegisterType((*Validator)(nil), "validator.Validator") + golang_proto.RegisterType((*Validator)(nil), "validator.Validator") +} +func (m *Validator) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalTo(dAtA) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *Validator) MarshalTo(dAtA []byte) (int, error) { + var i int + _ = i + var l int + _ = l + if m.Address != nil { + dAtA[i] = 0xa + i++ + i = encodeVarintValidator(dAtA, i, uint64(m.Address.Size())) + n1, err := m.Address.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n1 + } + dAtA[i] = 0x12 + i++ + i = encodeVarintValidator(dAtA, i, uint64(m.PublicKey.Size())) + n2, err := m.PublicKey.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n2 + if m.Power != 0 { + dAtA[i] = 0x18 + i++ + i = encodeVarintValidator(dAtA, i, uint64(m.Power)) + } + return i, nil +} + +func encodeVarintValidator(dAtA []byte, offset int, v uint64) int { + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return offset + 1 +} +func (m *Validator) Size() (n int) { + var l int + _ = l + if m.Address != nil { + l = m.Address.Size() + n += 1 + l + sovValidator(uint64(l)) + } + l = m.PublicKey.Size() + n += 1 + l + sovValidator(uint64(l)) + if m.Power != 0 { + n += 1 + sovValidator(uint64(m.Power)) + } + return n +} + +func sovValidator(x uint64) (n int) { + for { + n++ + x >>= 7 + if x == 0 { + break + } + } + return n +} +func sozValidator(x uint64) (n int) { + return sovValidator(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *Validator) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowValidator + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: Validator: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: Validator: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Address", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowValidator + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthValidator + } + postIndex := iNdEx + byteLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + var v github_com_hyperledger_burrow_crypto.Address + m.Address = &v + if err := m.Address.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field PublicKey", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowValidator + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthValidator + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.PublicKey.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 3: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Power", wireType) + } + m.Power = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowValidator + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Power |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipValidator(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthValidator + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipValidator(dAtA []byte) (n int, err error) { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowValidator + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + wireType := int(wire & 0x7) + switch wireType { + case 0: + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowValidator + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + iNdEx++ + if dAtA[iNdEx-1] < 0x80 { + break + } + } + return iNdEx, nil + case 1: + iNdEx += 8 + return iNdEx, nil + case 2: + var length int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowValidator + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + length |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + iNdEx += length + if length < 0 { + return 0, ErrInvalidLengthValidator + } + return iNdEx, nil + case 3: + for { + var innerWire uint64 + var start int = iNdEx + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowValidator + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + innerWire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + innerWireType := int(innerWire & 0x7) + if innerWireType == 4 { + break + } + next, err := skipValidator(dAtA[start:]) + if err != nil { + return 0, err + } + iNdEx = start + next + } + return iNdEx, nil + case 4: + return iNdEx, nil + case 5: + iNdEx += 4 + return iNdEx, nil + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + } + panic("unreachable") +} + +var ( + ErrInvalidLengthValidator = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowValidator = fmt.Errorf("proto: integer overflow") +) + +func init() { proto.RegisterFile("validator.proto", fileDescriptorValidator) } +func init() { golang_proto.RegisterFile("validator.proto", fileDescriptorValidator) } + +var fileDescriptorValidator = []byte{ + // 255 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xe2, 0x2f, 0x4b, 0xcc, 0xc9, + 0x4c, 0x49, 0x2c, 0xc9, 0x2f, 0xd2, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0xe2, 0x84, 0x0b, 0x48, + 0xe9, 0xa6, 0x67, 0x96, 0x64, 0x94, 0x26, 0xe9, 0x25, 0xe7, 0xe7, 0xea, 0xa7, 0xe7, 0xa7, 0xe7, + 0xeb, 0x83, 0x55, 0x24, 0x95, 0xa6, 0x81, 0x79, 0x60, 0x0e, 0x98, 0x05, 0xd1, 0x29, 0x25, 0x50, + 0x90, 0x5a, 0x94, 0x9b, 0x59, 0x5c, 0x9c, 0x99, 0x9f, 0x07, 0x15, 0xe1, 0x49, 0x2e, 0xaa, 0x2c, + 0x28, 0x81, 0xca, 0x2b, 0xad, 0x62, 0xe4, 0xe2, 0x0c, 0x83, 0x19, 0x2e, 0xe4, 0xc5, 0xc5, 0xee, + 0x98, 0x92, 0x52, 0x94, 0x5a, 0x5c, 0x2c, 0xc1, 0xa8, 0xc0, 0xa8, 0xc1, 0xe3, 0x64, 0x70, 0xeb, + 0x9e, 0xbc, 0x0e, 0x92, 0x8d, 0x19, 0x95, 0x05, 0xa9, 0x45, 0x39, 0xa9, 0x29, 0xe9, 0xa9, 0x45, + 0xfa, 0x49, 0xa5, 0x45, 0x45, 0xf9, 0xe5, 0xfa, 0x50, 0xe3, 0xa0, 0xfa, 0x82, 0x60, 0x06, 0x08, + 0x99, 0x72, 0x71, 0x06, 0x94, 0x26, 0xe5, 0x64, 0x26, 0x7b, 0xa7, 0x56, 0x4a, 0x30, 0x29, 0x30, + 0x6a, 0x70, 0x1b, 0x09, 0xea, 0x41, 0x15, 0xc3, 0x25, 0x9c, 0x58, 0x4e, 0xdc, 0x93, 0x67, 0x08, + 0x42, 0xa8, 0x14, 0x12, 0xe1, 0x62, 0x0d, 0xc8, 0x2f, 0x4f, 0x2d, 0x92, 0x60, 0x56, 0x60, 0xd4, + 0x60, 0x09, 0x82, 0x70, 0xac, 0x58, 0x66, 0x2c, 0x90, 0x67, 0x70, 0x72, 0x3c, 0xf1, 0x48, 0x8e, + 0xf1, 0xc2, 0x23, 0x39, 0xc6, 0x07, 0x8f, 0xe4, 0x18, 0x0f, 0x3c, 0x96, 0x63, 0x3c, 0xf1, 0x58, + 0x8e, 0x31, 0x4a, 0x1b, 0xbf, 0xfb, 0x12, 0x93, 0x73, 0xf5, 0xe1, 0xc1, 0x97, 0xc4, 0x06, 0xf6, + 0xb6, 0x31, 0x20, 0x00, 0x00, 0xff, 0xff, 0x1c, 0xca, 0xd9, 0x6f, 0x63, 0x01, 0x00, 0x00, +} diff --git a/acm/validator/validators.go b/acm/validator/validators.go new file mode 100644 index 00000000..21313b7a --- /dev/null +++ b/acm/validator/validators.go @@ -0,0 +1,111 @@ +package validator + +import ( + "math/big" + + "sync" + + "github.com/hyperledger/burrow/crypto" +) + +type Writer interface { + AlterPower(id crypto.Addressable, power *big.Int) (flow *big.Int, err error) +} + +type Reader interface { + Power(id crypto.Addressable) *big.Int +} + +type Iterable interface { + Iterate(func(id crypto.Addressable, power *big.Int) (stop bool)) (stopped bool) +} + +type IterableReader interface { + Reader + Iterable +} + +type ReaderWriter interface { + Reader + Writer +} + +type IterableReaderWriter interface { + ReaderWriter + Iterable +} + +type WriterFunc func(id crypto.Addressable, power *big.Int) (flow *big.Int, err error) + +func SyncWriter(locker sync.Locker, writerFunc WriterFunc) WriterFunc { + return WriterFunc(func(id crypto.Addressable, power *big.Int) (flow *big.Int, err error) { + locker.Lock() + defer locker.Unlock() + return writerFunc(id, power) + }) +} + +func (wf WriterFunc) AlterPower(id crypto.Addressable, power *big.Int) (flow *big.Int, err error) { + return wf(id, power) +} + +func AddPower(vs ReaderWriter, id crypto.Addressable, power *big.Int) error { + // Current power + power + _, err := vs.AlterPower(id, new(big.Int).Add(vs.Power(id), power)) + return err +} + +func SubtractPower(vs ReaderWriter, id crypto.Addressable, power *big.Int) error { + _, err := vs.AlterPower(id, new(big.Int).Sub(vs.Power(id), power)) + return err +} + +func Alter(vs Writer, vsOther Iterable) (err error) { + vsOther.Iterate(func(id crypto.Addressable, power *big.Int) (stop bool) { + _, err = vs.AlterPower(id, power) + if err != nil { + return true + } + return + }) + return +} + +// Adds vsOther to vs +func Add(vs ReaderWriter, vsOther Iterable) (err error) { + vsOther.Iterate(func(id crypto.Addressable, power *big.Int) (stop bool) { + err = AddPower(vs, id, power) + if err != nil { + return true + } + return + }) + return +} + +// Subtracts vsOther from vs +func Subtract(vs ReaderWriter, vsOther Iterable) (err error) { + vsOther.Iterate(func(id crypto.Addressable, power *big.Int) (stop bool) { + err = SubtractPower(vs, id, power) + if err != nil { + return true + } + return + }) + return +} + +func Copy(vs Iterable) *Set { + vsCopy := NewSet() + vs.Iterate(func(id crypto.Addressable, power *big.Int) (stop bool) { + vsCopy.ChangePower(id, power) + return + }) + return vsCopy +} + +func CopyTrim(vs Iterable) *Set { + s := Copy(vs) + s.trim = true + return s +} diff --git a/acm/validator_test.go b/acm/validator_test.go deleted file mode 100644 index 51299081..00000000 --- a/acm/validator_test.go +++ /dev/null @@ -1 +0,0 @@ -package acm diff --git a/blockchain/blockchain.go b/bcm/blockchain.go similarity index 53% rename from blockchain/blockchain.go rename to bcm/blockchain.go index 43be5ca7..d12afd6f 100644 --- a/blockchain/blockchain.go +++ b/bcm/blockchain.go @@ -12,16 +12,17 @@ // See the License for the specific language governing permissions and // limitations under the License. -package blockchain +package bcm import ( "bytes" "fmt" "math/big" - "sync" "time" - "github.com/hyperledger/burrow/crypto" + "sync" + + "github.com/hyperledger/burrow/acm/validator" "github.com/hyperledger/burrow/genesis" "github.com/hyperledger/burrow/logging" "github.com/tendermint/go-amino" @@ -33,55 +34,44 @@ const DefaultValidatorsWindowSize = 10 var stateKey = []byte("BlockchainState") -type TipInfo interface { +type BlockchainInfo interface { + GenesisHash() []byte + GenesisDoc() genesis.GenesisDoc ChainID() string LastBlockHeight() uint64 LastBlockTime() time.Time LastBlockHash() []byte AppHashAfterLastBlock() []byte - IterateValidators(iter func(id crypto.Addressable, power *big.Int) (stop bool)) (stopped bool) + Validators() validator.IterableReader + ValidatorsHistory() (currentSet *validator.Set, deltas []*validator.Set, height uint64) NumValidators() int } -type BlockchainInfo interface { - TipInfo - GenesisHash() []byte - GenesisDoc() genesis.GenesisDoc -} - -type Root struct { - genesisHash []byte - genesisDoc genesis.GenesisDoc -} - -type Tip struct { +type Blockchain struct { + sync.RWMutex + db dbm.DB + genesisHash []byte + genesisDoc genesis.GenesisDoc chainID string lastBlockHeight uint64 lastBlockTime time.Time lastBlockHash []byte appHashAfterLastBlock []byte - validators *ValidatorsRing + validatorCache *validator.Ring + validatorCheckCache *validator.Ring } -type Blockchain struct { - *Root - *Tip - sync.RWMutex - db dbm.DB -} - -var _ TipInfo = &Blockchain{} +var _ BlockchainInfo = &Blockchain{} type PersistedState struct { AppHashAfterLastBlock []byte LastBlockHeight uint64 GenesisDoc genesis.GenesisDoc - Validators PersistedValidatorsRing + ValidatorSet []validator.Validator + ValidatorCache validator.PersistedRing } -func LoadOrNewBlockchain(db dbm.DB, genesisDoc *genesis.GenesisDoc, - logger *logging.Logger) (*Blockchain, error) { - +func LoadOrNewBlockchain(db dbm.DB, genesisDoc *genesis.GenesisDoc, logger *logging.Logger) (*Blockchain, error) { logger = logger.WithScope("LoadOrNewBlockchain") logger.InfoMsg("Trying to load blockchain state from database", "database_key", stateKey) @@ -94,7 +84,8 @@ func LoadOrNewBlockchain(db dbm.DB, genesisDoc *genesis.GenesisDoc, argHash := genesisDoc.Hash() if !bytes.Equal(dbHash, argHash) { return nil, fmt.Errorf("GenesisDoc passed to LoadOrNewBlockchain has hash: 0x%X, which does not "+ - "match the one found in database: 0x%X", argHash, dbHash) + "match the one found in database: 0x%X, database genesis:\n%v\npassed genesis:\n%v\n", + argHash, dbHash, bc.genesisDoc.JSONString(), genesisDoc.JSONString()) } return bc, nil } @@ -105,15 +96,19 @@ func LoadOrNewBlockchain(db dbm.DB, genesisDoc *genesis.GenesisDoc, // Pointer to blockchain state initialised from genesis func newBlockchain(db dbm.DB, genesisDoc *genesis.GenesisDoc) *Blockchain { - vs := NewValidators() + vs := validator.NewTrimSet() for _, gv := range genesisDoc.Validators { - vs.AlterPower(gv.PublicKey, new(big.Int).SetUint64(gv.Amount)) + vs.ChangePower(gv.PublicKey, new(big.Int).SetUint64(gv.Amount)) } - root := NewRoot(genesisDoc) bc := &Blockchain{ - db: db, - Root: root, - Tip: NewTip(genesisDoc.ChainID(), root.genesisDoc.GenesisTime, root.genesisHash, vs), + db: db, + genesisHash: genesisDoc.Hash(), + genesisDoc: *genesisDoc, + chainID: genesisDoc.ChainID(), + lastBlockTime: genesisDoc.GenesisTime, + appHashAfterLastBlock: genesisDoc.Hash(), + validatorCache: validator.NewRing(vs, DefaultValidatorsWindowSize), + validatorCheckCache: validator.NewRing(vs, 1), } return bc } @@ -131,50 +126,38 @@ func loadBlockchain(db dbm.DB) (*Blockchain, error) { return bc, nil } -func NewRoot(genesisDoc *genesis.GenesisDoc) *Root { - return &Root{ - genesisHash: genesisDoc.Hash(), - genesisDoc: *genesisDoc, - } +func (bc *Blockchain) ValidatorChecker() validator.Writer { + return validator.SyncWriter(bc, bc.validatorCheckCache.AlterPower) } -// Create genesis Tip -func NewTip(chainID string, genesisTime time.Time, genesisHash []byte, initialValidators *Validators) *Tip { - return &Tip{ - chainID: chainID, - lastBlockTime: genesisTime, - appHashAfterLastBlock: genesisHash, - validators: NewValidatorsRing(initialValidators, DefaultValidatorsWindowSize), - } +func (bc *Blockchain) ValidatorWriter() validator.Writer { + return validator.SyncWriter(bc, bc.validatorCache.AlterPower) } -func (bc *Blockchain) AlterPower(id crypto.Addressable, power *big.Int) (*big.Int, error) { - return bc.validators.AlterPower(id, power) -} - -func (bc *Blockchain) CommitBlock(blockTime time.Time, blockHash, appHash []byte) error { +func (bc *Blockchain) CommitBlock(blockTime time.Time, + blockHash, appHash []byte) (totalPowerChange, totalFlow *big.Int, err error) { bc.Lock() defer bc.Unlock() // Checkpoint on the _previous_ block. If we die, this is where we will resume since we know it must have been // committed since we are committing the next block. If we fall over we can resume a safe committed state and // Tendermint will catch us up - err := bc.save() + err = bc.save() + if err != nil { + return + } + totalPowerChange, totalFlow, err = bc.validatorCache.Rotate() if err != nil { - return err + return } - maxFlow := bc.validators.MaxFlow() - // Update validator set - _, totalFlow := bc.validators.Rotate() - if totalFlow.Cmp(maxFlow) == 1 { - return fmt.Errorf("total flow during block was %v exceeding the maximum allowablw flow of %v - this "+ - "should have been prevented on a per transaction basis - we cannot continue", - totalFlow, maxFlow) + _, _, err = bc.validatorCheckCache.Rotate() + if err != nil { + return } bc.lastBlockHeight += 1 bc.lastBlockTime = blockTime bc.lastBlockHash = blockHash bc.appHashAfterLastBlock = appHash - return nil + return } func (bc *Blockchain) save() error { @@ -195,7 +178,7 @@ func (bc *Blockchain) Encode() ([]byte, error) { GenesisDoc: bc.genesisDoc, AppHashAfterLastBlock: bc.appHashAfterLastBlock, LastBlockHeight: bc.lastBlockHeight, - Validators: bc.validators.Persistable(), + ValidatorCache: bc.validatorCache.Persistable(), } encodedState, err := cdc.MarshalBinary(persistedState) if err != nil { @@ -213,46 +196,84 @@ func DecodeBlockchain(encodedState []byte) (*Blockchain, error) { bc := newBlockchain(nil, &persistedState.GenesisDoc) bc.lastBlockHeight = persistedState.LastBlockHeight bc.appHashAfterLastBlock = persistedState.AppHashAfterLastBlock - bc.validators = UnpersistValidatorsRing(persistedState.Validators) + bc.validatorCache = validator.UnpersistRing(persistedState.ValidatorCache) + bc.validatorCheckCache = validator.UnpersistRing(persistedState.ValidatorCache) return bc, nil } -func (r *Root) GenesisHash() []byte { - return r.genesisHash +func (bc *Blockchain) GenesisHash() []byte { + return bc.genesisHash +} + +func (bc *Blockchain) GenesisDoc() genesis.GenesisDoc { + return bc.genesisDoc +} + +func (bc *Blockchain) ChainID() string { + return bc.chainID +} + +func (bc *Blockchain) LastBlockHeight() uint64 { + bc.RLock() + defer bc.RUnlock() + return bc.lastBlockHeight } -func (r *Root) GenesisDoc() genesis.GenesisDoc { - return r.genesisDoc +func (bc *Blockchain) LastBlockTime() time.Time { + bc.RLock() + defer bc.RUnlock() + return bc.lastBlockTime } -func (t *Tip) ChainID() string { - return t.chainID +func (bc *Blockchain) LastBlockHash() []byte { + bc.RLock() + defer bc.RUnlock() + return bc.lastBlockHash } -func (t *Tip) LastBlockHeight() uint64 { - return t.lastBlockHeight +func (bc *Blockchain) AppHashAfterLastBlock() []byte { + bc.RLock() + defer bc.RUnlock() + return bc.appHashAfterLastBlock } -func (t *Tip) LastBlockTime() time.Time { - return t.lastBlockTime +func (bc *Blockchain) PendingValidators() validator.IterableReader { + bc.RLock() + defer bc.RUnlock() + return bc.validatorCache.Head() } -func (t *Tip) LastBlockHash() []byte { - return t.lastBlockHash +func (bc *Blockchain) Validators() validator.IterableReader { + bc.RLock() + defer bc.RUnlock() + return bc.validatorCache.CurrentSet() } -func (t *Tip) AppHashAfterLastBlock() []byte { - return t.appHashAfterLastBlock +func (bc *Blockchain) ValidatorsHistory() (*validator.Set, []*validator.Set, uint64) { + bc.RLock() + defer bc.RUnlock() + delta, _ := bc.validatorCache.OrderedBuckets() + deltas := make([]*validator.Set, len(delta)) + for i, d := range delta { + deltas[i] = validator.Copy(d) + } + return validator.CopyTrim(bc.validatorCache.CurrentSet()), deltas, bc.lastBlockHeight } -func (t *Tip) Validators() *Validators { - return t.validators.Prev().Copy() +func (bc *Blockchain) CurrentValidators() *validator.Set { + bc.RLock() + defer bc.RUnlock() + return bc.validatorCache.CurrentSet() } -func (t *Tip) IterateValidators(iter func(id crypto.Addressable, power *big.Int) (stop bool)) (stopped bool) { - return t.validators.Prev().Copy().Iterate(iter) +func (bc *Blockchain) PreviousValidators() *validator.Set { + bc.RLock() + defer bc.RUnlock() + return bc.validatorCache.PreviousSet() } -func (t *Tip) NumValidators() int { - return t.validators.Prev().Count() +func (bc *Blockchain) NumValidators() int { + bc.RLock() + defer bc.RUnlock() + return bc.validatorCache.CurrentSet().Count() } diff --git a/blockchain/blockchain_test.go b/bcm/blockchain_test.go similarity index 60% rename from blockchain/blockchain_test.go rename to bcm/blockchain_test.go index aaa6f7ee..c5f5bc62 100644 --- a/blockchain/blockchain_test.go +++ b/bcm/blockchain_test.go @@ -1,4 +1,4 @@ -package blockchain +package bcm import ( "fmt" @@ -7,12 +7,14 @@ import ( "time" "github.com/hyperledger/burrow/genesis" - "github.com/hyperledger/burrow/logging/config" + "github.com/hyperledger/burrow/logging/logconfig" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "github.com/tendermint/tendermint/libs/db" ) +var big0 = big.NewInt(0) + func TestBlockchain_Encode(t *testing.T) { genesisDoc, _, validators := genesis.NewDeterministicGenesis(234). GenesisDoc(5, true, 232, 3, true, 34) @@ -20,27 +22,32 @@ func TestBlockchain_Encode(t *testing.T) { bs, err := bc.Encode() require.NoError(t, err) bcOut, err := DecodeBlockchain(bs) - require.True(t, bc.validators.Equal(bcOut.validators)) + require.True(t, bc.validatorCache.Equal(bcOut.validatorCache)) require.Equal(t, bc.genesisDoc.GenesisTime, bcOut.genesisDoc.GenesisTime) - assert.Equal(t, config.JSONString(bc.genesisDoc), config.JSONString(bcOut.genesisDoc)) + assert.Equal(t, logconfig.JSONString(bc.genesisDoc), logconfig.JSONString(bcOut.genesisDoc)) require.Equal(t, bc.genesisDoc.Hash(), bcOut.genesisDoc.Hash()) power := new(big.Int).SetUint64(genesisDoc.Validators[1].Amount) id1 := validators[1].PublicKey() var flow *big.Int for i := 0; i < 100; i++ { power := power.Div(power, big.NewInt(2)) - flow, err = bc.AlterPower(id1, power) + flow, err = bc.ValidatorWriter().AlterPower(id1, power) fmt.Println(flow) require.NoError(t, err) - err = bc.CommitBlock(time.Now(), []byte("blockhash"), []byte("apphash")) + _, _, err = bc.CommitBlock(time.Now(), []byte("blockhash"), []byte("apphash")) require.NoError(t, err) bs, err = bc.Encode() require.NoError(t, err) bcOut, err = DecodeBlockchain(bs) - require.True(t, bc.validators.Equal(bcOut.validators)) + require.True(t, bc.validatorCache.Equal(bcOut.validatorCache)) } // Should have exponentially decayed to 0 assertZero(t, flow) - assertZero(t, bc.validators.Prev().Power(id1)) + assertZero(t, bc.validatorCache.Power(id1)) +} + +// Since we have -0 and 0 with big.Int due to its representation with a neg flag +func assertZero(t testing.TB, i *big.Int) { + assert.True(t, big0.Cmp(i) == 0, "expected 0 but got %v", i) } diff --git a/blockchain/validators_ring.go b/blockchain/validators_ring.go deleted file mode 100644 index 2709b27c..00000000 --- a/blockchain/validators_ring.go +++ /dev/null @@ -1,198 +0,0 @@ -package blockchain - -import ( - "fmt" - "math/big" - - "github.com/hyperledger/burrow/crypto" -) - -type ValidatorsRing struct { - buckets []*Validators - // Totals for each validator across all buckets - power *Validators - // Current flow totals for each validator in the Head bucket - flow *Validators - // Index of current head bucekt - head int64 - size int64 -} - -var big1 = big.NewInt(1) -var big3 = big.NewInt(3) - -// Provides a sliding window over the last size buckets of validator power changes -func NewValidatorsRing(initialValidators *Validators, size int) *ValidatorsRing { - if size < 2 { - size = 2 - } - vw := &ValidatorsRing{ - buckets: make([]*Validators, size), - power: NewValidators(), - flow: NewValidators(), - size: int64(size), - } - for i := 0; i < size; i++ { - vw.buckets[i] = NewValidators() - } - - initialValidators.Iterate(func(id crypto.Addressable, power *big.Int) (stop bool) { - // Existing set - vw.buckets[vw.index(-1)].AlterPower(id, power) - // Current accumulator - vw.buckets[vw.head].AlterPower(id, power) - - vw.power.AddPower(id, power.Add(power, power)) - return - }) - - return vw -} - -// Updates the current head bucket (accumulator) with some safety checks -func (vw *ValidatorsRing) AlterPower(id crypto.Addressable, power *big.Int) (*big.Int, error) { - if power.Sign() == -1 { - return nil, fmt.Errorf("cannot set negative validator power: %v", power) - } - // if flow > maxflow then we cannot alter the power - flow := vw.Flow(id, power) - maxFlow := vw.MaxFlow() - // Set flow to update total flow - vw.flow.AlterPower(id, flow) - if vw.flow.totalPower.Cmp(maxFlow) == 1 { - // Reset flow to previous value - vw.flow.AlterPower(id, vw.Flow(id, vw.Head().Power(id))) - allowable := new(big.Int).Sub(maxFlow, vw.flow.totalPower) - return nil, fmt.Errorf("cannot change validator power of %v from %v to %v because that would result in a flow "+ - "greater than or equal to 1/3 of total power for the next commit: flow induced by change: %v, "+ - "current total flow: %v/%v (cumulative/max), remaining allowable flow: %v", - id.Address(), vw.Prev().Power(id), power, flow, vw.flow.totalPower, maxFlow, allowable) - } - // Add to total power - vw.Head().AlterPower(id, power) - return flow, nil -} - -// Returns the flow that would be induced by a validator change by comparing the current accumulator with the previous -// bucket -func (vw *ValidatorsRing) Flow(id crypto.Addressable, power *big.Int) *big.Int { - flow := new(big.Int) - prevPower := vw.Prev().Power(id) - return flow.Abs(flow.Sub(power, prevPower)) -} - -// To ensure that in the maximum valildator shift at least one unit -// of validator power in the intersection of last block validators and this block validators must have at least one -// non-byzantine validator who can tell you if you've been lied to about the validator set -// So need at most ceiling((Total Power)/3) - 1, in integer division we have ceiling(X*p/q) = (p(X+1)-1)/q -// For p = 1 just X/q -// So we want (Total Power)/3 - 1 -func (vw *ValidatorsRing) MaxFlow() *big.Int { - max := vw.Prev().TotalPower() - return max.Sub(max.Div(max, big3), big1) -} - -// Advance the current head bucket to the next bucket and returns the change in total power between the previous bucket -// and the current head, and the total flow which is the sum of absolute values of all changes each validator's power -// after rotation the next head is a copy of the current head -func (vw *ValidatorsRing) Rotate() (totalPowerChange *big.Int, totalFlow *big.Int) { - // Subtract the previous bucket total power so we can add on the current buckets power after this - totalPowerChange = new(big.Int).Sub(vw.Head().totalPower, vw.Prev().totalPower) - // Capture flow before we wipe it - totalFlow = vw.flow.totalPower - // Subtract the tail bucket (if any) from the total - vw.power.Subtract(vw.Next()) - // Copy head bucket - headCopy := vw.Head().Copy() - // add it to total - vw.power.Add(headCopy) - // move the ring buffer on - vw.head = vw.index(1) - // Overwrite new head bucket (previous tail) with previous bucket copy updated with current head - vw.buckets[vw.head] = headCopy - // New flow accumulator1 - vw.flow = NewValidators() - // Advance the ring - return totalPowerChange, totalFlow -} - -func (vw *ValidatorsRing) Prev() *Validators { - return vw.buckets[vw.index(-1)] -} - -func (vw *ValidatorsRing) Head() *Validators { - return vw.buckets[vw.head] -} - -func (vw *ValidatorsRing) Next() *Validators { - return vw.buckets[vw.index(1)] -} - -func (vw *ValidatorsRing) index(i int64) int64 { - return (vw.size + vw.head + i) % vw.size -} - -func (vw *ValidatorsRing) Size() int64 { - return vw.size -} - -// Returns buckets in order head, previous, ... -func (vw *ValidatorsRing) OrderedBuckets() []*Validators { - buckets := make([]*Validators, len(vw.buckets)) - for i := int64(0); i < vw.size; i++ { - buckets[i] = vw.buckets[vw.index(-i)] - } - return buckets -} - -func (vw *ValidatorsRing) String() string { - return fmt.Sprintf("ValidatorsWindow{Total: %v; Buckets: Head->%v<-Tail}", vw.power, vw.OrderedBuckets()) -} - -func (vw *ValidatorsRing) Equal(vwOther *ValidatorsRing) bool { - if vw.size != vwOther.size || vw.head != vwOther.head || len(vw.buckets) != len(vwOther.buckets) || - !vw.flow.Equal(vwOther.flow) || !vw.power.Equal(vwOther.power) { - return false - } - for i, b := range vw.buckets { - if !b.Equal(vwOther.buckets[i]) { - return false - } - } - return true -} - -type PersistedValidatorsRing struct { - Buckets [][]PersistedValidator - Power []PersistedValidator - Flow []PersistedValidator - Head int64 -} - -func (vw *ValidatorsRing) Persistable() PersistedValidatorsRing { - buckets := make([][]PersistedValidator, len(vw.buckets)) - for i, vs := range vw.buckets { - buckets[i] = vs.Persistable() - } - return PersistedValidatorsRing{ - Buckets: buckets, - Power: vw.power.Persistable(), - Flow: vw.flow.Persistable(), - Head: vw.head, - } -} - -func UnpersistValidatorsRing(pvr PersistedValidatorsRing) *ValidatorsRing { - buckets := make([]*Validators, len(pvr.Buckets)) - for i, pv := range pvr.Buckets { - buckets[i] = UnpersistValidators(pv) - } - - return &ValidatorsRing{ - buckets: buckets, - head: pvr.Head, - power: UnpersistValidators(pvr.Power), - flow: UnpersistValidators(pvr.Flow), - size: int64(len(buckets)), - } -} diff --git a/cmd/burrow/commands/configure.go b/cmd/burrow/commands/configure.go index 35788d6a..d0c149b2 100644 --- a/cmd/burrow/commands/configure.go +++ b/cmd/burrow/commands/configure.go @@ -15,8 +15,8 @@ import ( "github.com/hyperledger/burrow/genesis/spec" "github.com/hyperledger/burrow/keys" "github.com/hyperledger/burrow/logging" - logging_config "github.com/hyperledger/burrow/logging/config" - "github.com/hyperledger/burrow/logging/config/presets" + logging_config "github.com/hyperledger/burrow/logging/logconfig" + "github.com/hyperledger/burrow/logging/logconfig/presets" cli "github.com/jawher/mow.cli" amino "github.com/tendermint/go-amino" tm_crypto "github.com/tendermint/tendermint/crypto" diff --git a/cmd/burrow/commands/helpers.go b/cmd/burrow/commands/helpers.go index ee8807e0..2ac4c741 100644 --- a/cmd/burrow/commands/helpers.go +++ b/cmd/burrow/commands/helpers.go @@ -9,7 +9,7 @@ import ( "github.com/hyperledger/burrow/config" "github.com/hyperledger/burrow/config/source" "github.com/hyperledger/burrow/genesis" - logging_config "github.com/hyperledger/burrow/logging/config" + logging_config "github.com/hyperledger/burrow/logging/logconfig" ) type Output interface { diff --git a/cmd/burrow/commands/tx.go b/cmd/burrow/commands/tx.go new file mode 100644 index 00000000..cdff10da --- /dev/null +++ b/cmd/burrow/commands/tx.go @@ -0,0 +1 @@ +package commands diff --git a/config/config.go b/config/config.go index c22ddbb1..8e3f7b8e 100644 --- a/config/config.go +++ b/config/config.go @@ -1,20 +1,18 @@ package config import ( - "fmt" - "context" + "fmt" "github.com/hyperledger/burrow/config/source" "github.com/hyperledger/burrow/consensus/tendermint" - "github.com/hyperledger/burrow/consensus/tendermint/validator" "github.com/hyperledger/burrow/core" "github.com/hyperledger/burrow/crypto" "github.com/hyperledger/burrow/execution" "github.com/hyperledger/burrow/genesis" "github.com/hyperledger/burrow/keys" - logging_config "github.com/hyperledger/burrow/logging/config" "github.com/hyperledger/burrow/logging/lifecycle" + logging_config "github.com/hyperledger/burrow/logging/logconfig" "github.com/hyperledger/burrow/rpc" ) @@ -76,7 +74,7 @@ func (conf *BurrowConfig) Kernel(ctx context.Context) (*core.Kernel, error) { if err != nil { return nil, err } - privValidator := validator.NewPrivValidatorMemory(val, signer) + privValidator := tendermint.NewPrivValidatorMemory(val, signer) var exeOptions []execution.ExecutionOption if conf.Execution != nil { @@ -86,8 +84,8 @@ func (conf *BurrowConfig) Kernel(ctx context.Context) (*core.Kernel, error) { } } - return core.NewKernel(ctx, keyClient, privValidator, conf.GenesisDoc, conf.Tendermint.TendermintConfig(), conf.RPC, conf.Keys, - keyStore, exeOptions, logger) + return core.NewKernel(ctx, keyClient, privValidator, conf.GenesisDoc, conf.Tendermint.TendermintConfig(), conf.RPC, + conf.Keys, keyStore, exeOptions, logger) } func (conf *BurrowConfig) JSONString() string { diff --git a/consensus/tendermint/abci/app.go b/consensus/tendermint/abci/app.go index ce47eef2..cbacbc94 100644 --- a/consensus/tendermint/abci/app.go +++ b/consensus/tendermint/abci/app.go @@ -8,10 +8,12 @@ import ( "runtime/debug" - bcm "github.com/hyperledger/burrow/blockchain" + "github.com/hyperledger/burrow/acm/validator" + "github.com/hyperledger/burrow/bcm" "github.com/hyperledger/burrow/consensus/tendermint/codes" "github.com/hyperledger/burrow/crypto" "github.com/hyperledger/burrow/execution" + errors2 "github.com/hyperledger/burrow/execution/errors" "github.com/hyperledger/burrow/logging" "github.com/hyperledger/burrow/logging/structure" "github.com/hyperledger/burrow/project" @@ -20,9 +22,9 @@ import ( abciTypes "github.com/tendermint/tendermint/abci/types" ) -const responseInfoName = "Burrow" - type App struct { + // Node information to return in Info + nodeInfo string // State blockchain *bcm.Blockchain checker execution.BatchExecutor @@ -40,16 +42,18 @@ type App struct { var _ abciTypes.Application = &App{} -func NewApp(blockchain *bcm.Blockchain, checker execution.BatchExecutor, committer execution.BatchCommitter, +func NewApp(nodeInfo string, blockchain *bcm.Blockchain, checker execution.BatchExecutor, committer execution.BatchCommitter, txDecoder txs.Decoder, panicFunc func(error), logger *logging.Logger) *App { return &App{ + nodeInfo: nodeInfo, blockchain: blockchain, checker: checker, committer: committer, checkTx: txExecutor(checker, txDecoder, logger.WithScope("CheckTx")), deliverTx: txExecutor(committer, txDecoder, logger.WithScope("DeliverTx")), panicFunc: panicFunc, - logger: logger.WithScope("abci.NewApp").With(structure.ComponentKey, "ABCI_App"), + logger: logger.WithScope("abci.NewApp").With(structure.ComponentKey, "ABCI_App", + "node_info", nodeInfo), } } @@ -61,12 +65,11 @@ func (app *App) SetMempoolLocker(mempoolLocker sync.Locker) { } func (app *App) Info(info abciTypes.RequestInfo) abciTypes.ResponseInfo { - tip := app.blockchain.Tip return abciTypes.ResponseInfo{ - Data: responseInfoName, + Data: app.nodeInfo, Version: project.History.CurrentVersion().String(), - LastBlockHeight: int64(tip.LastBlockHeight()), - LastBlockAppHash: tip.AppHashAfterLastBlock(), + LastBlockHeight: int64(app.blockchain.LastBlockHeight()), + LastBlockAppHash: app.blockchain.AppHashAfterLastBlock(), } } @@ -88,10 +91,15 @@ func (app *App) InitChain(chain abciTypes.RequestInitChain) (respInitChain abciT app.panicFunc(fmt.Errorf("panic occurred in abci.App/InitChain: %v\n%s", r, debug.Stack())) } }() - err := app.checkValidatorsMatch(chain.Validators) - if err != nil { - app.logger.InfoMsg("Initial validator set mistmatch", structure.ErrorKey, err) - panic(err) + if len(chain.Validators) != app.blockchain.NumValidators() { + panic(fmt.Errorf("Tendermint passes %d validators to InitChain but Burrow's Blockchain has %d", + len(chain.Validators), app.blockchain.NumValidators())) + } + for _, v := range chain.Validators { + err := app.checkValidatorMatches(app.blockchain.Validators(), v) + if err != nil { + panic(err) + } } app.logger.InfoMsg("Initial validator set matches") return @@ -105,31 +113,33 @@ func (app *App) BeginBlock(block abciTypes.RequestBeginBlock) (respBeginBlock ab } }() if block.Header.Height > 1 { - validators := make([]abciTypes.Validator, len(block.Validators)) - for i, v := range block.Validators { - validators[i] = v.Validator - } - err := app.checkValidatorsMatch(validators) - if err != nil { + var err error + // Tendermint runs a block behind with the validators passed in here + previousValidators := app.blockchain.PreviousValidators() + if len(block.Validators) != previousValidators.Count() { + err = fmt.Errorf("Tendermint passes %d validators to BeginBlock but Burrow's Blockchain has %d", + len(block.Validators), previousValidators.Count()) panic(err) } + for _, v := range block.Validators { + err = app.checkValidatorMatches(previousValidators, v.Validator) + if err != nil { + panic(err) + } + } } return } -func (app *App) checkValidatorsMatch(validators []abciTypes.Validator) error { - tendermintValidators := bcm.NewValidators() - for _, v := range validators { - publicKey, err := crypto.PublicKeyFromABCIPubKey(v.PubKey) - if err != nil { - panic(err) - } - tendermintValidators.AlterPower(publicKey, big.NewInt(v.Power)) +func (app *App) checkValidatorMatches(ours validator.Reader, v abciTypes.Validator) error { + publicKey, err := crypto.PublicKeyFromABCIPubKey(v.PubKey) + if err != nil { + return err } - burrowValidators := app.blockchain.Validators() - if !burrowValidators.Equal(tendermintValidators) { - return fmt.Errorf("validators provided by Tendermint at InitChain do not match those held by Burrow: "+ - "Tendermint gives: %v, Burrow gives: %v", tendermintValidators, burrowValidators) + power := ours.Power(publicKey) + if power.Cmp(big.NewInt(v.Power)) != 0 { + return fmt.Errorf("validator %v has power %d from Tendermint but power %d from Burrow", + publicKey.Address(), v.Power, power) } return nil } @@ -137,6 +147,7 @@ func (app *App) checkValidatorsMatch(validators []abciTypes.Validator) error { func (app *App) CheckTx(txBytes []byte) abciTypes.ResponseCheckTx { defer func() { if r := recover(); r != nil { + fmt.Println("BeginBlock") app.panicFunc(fmt.Errorf("panic occurred in abci.App/CheckTx: %v\n%s", r, debug.Stack())) } }() @@ -177,19 +188,20 @@ func txExecutor(executor execution.BatchExecutor, txDecoder txs.Decoder, logger txe, err := executor.Execute(txEnv) if err != nil { + ex := errors2.AsException(err) logger.TraceMsg("Execution error", structure.ErrorKey, err, "tx_hash", txEnv.Tx.Hash()) return abciTypes.ResponseCheckTx{ - Code: codes.EncodingErrorCode, - Log: fmt.Sprintf("Could not execute transaction: %s, error: %v", txEnv, err), + Code: codes.TxExecutionErrorCode, + Log: fmt.Sprintf("Could not execute transaction: %s, error: %v", txEnv, ex.Exception), } } bs, err := txe.Receipt.Encode() if err != nil { return abciTypes.ResponseCheckTx{ - Code: codes.TxExecutionErrorCode, + Code: codes.EncodingErrorCode, Log: fmt.Sprintf("Could not serialise receipt: %s", err), } } @@ -207,11 +219,13 @@ func txExecutor(executor execution.BatchExecutor, txDecoder txs.Decoder, logger func (app *App) EndBlock(reqEndBlock abciTypes.RequestEndBlock) abciTypes.ResponseEndBlock { var validatorUpdates abciTypes.Validators - app.blockchain.IterateValidators(func(id crypto.Addressable, power *big.Int) (stop bool) { + app.blockchain.PendingValidators().Iterate(func(id crypto.Addressable, power *big.Int) (stop bool) { + app.logger.InfoMsg("Updating validator power", "validator_address", id.Address(), + "new_power", power) validatorUpdates = append(validatorUpdates, abciTypes.Validator{ Address: id.Address().Bytes(), PubKey: id.PublicKey().ABCIPubKey(), - // Must be ensured during execution + // Must ensure power fits in an int64 during execution Power: power.Int64(), }) return @@ -235,8 +249,8 @@ func (app *App) Commit() abciTypes.ResponseCommit { "hash", app.block.Hash, "txs", app.block.Header.NumTxs, "block_time", blockTime, - "last_block_time", app.blockchain.Tip.LastBlockTime(), - "last_block_hash", app.blockchain.Tip.LastBlockHash()) + "last_block_time", app.blockchain.LastBlockTime(), + "last_block_hash", app.blockchain.LastBlockHash()) // Lock the checker while we reset it and possibly while recheckTxs replays transactions app.checker.Lock() diff --git a/consensus/tendermint/config.go b/consensus/tendermint/config.go index 46e391d0..d736e4ba 100644 --- a/consensus/tendermint/config.go +++ b/consensus/tendermint/config.go @@ -13,14 +13,16 @@ type BurrowTendermintConfig struct { // Peers to which we automatically connect PersistentPeers string ListenAddress string + // Optional external that nodes my provide with their NodeInfo + ExternalAddress string Moniker string TendermintRoot string } func DefaultBurrowTendermintConfig() *BurrowTendermintConfig { - tmDefaultConfig := tm_config.DefaultConfig() + //tmDefaultConfig := tm_config.DefaultConfig() return &BurrowTendermintConfig{ - ListenAddress: tmDefaultConfig.P2P.ListenAddress, + ListenAddress: "tcp://127.0.0.1:26656", //stmDefaultConfig.P2P.ListenAddress, TendermintRoot: ".burrow", } } @@ -37,6 +39,7 @@ func (btc *BurrowTendermintConfig) TendermintConfig() *tm_config.Config { conf.P2P.Seeds = btc.Seeds conf.P2P.PersistentPeers = btc.PersistentPeers conf.P2P.ListenAddress = btc.ListenAddress + conf.P2P.ExternalAddress = btc.ListenAddress conf.Moniker = btc.Moniker // Unfortunately this stops metrics from being used at all conf.Instrumentation.Prometheus = false diff --git a/consensus/tendermint/query/node_view.go b/consensus/tendermint/node_view.go similarity index 86% rename from consensus/tendermint/query/node_view.go rename to consensus/tendermint/node_view.go index 4c547bc2..62a50085 100644 --- a/consensus/tendermint/query/node_view.go +++ b/consensus/tendermint/node_view.go @@ -1,26 +1,24 @@ -package query +package tendermint import ( "fmt" - "github.com/hyperledger/burrow/consensus/tendermint" "github.com/hyperledger/burrow/crypto" - tm_crypto "github.com/tendermint/tendermint/crypto" - "github.com/hyperledger/burrow/txs" "github.com/tendermint/tendermint/consensus" ctypes "github.com/tendermint/tendermint/consensus/types" + tmCrypto "github.com/tendermint/tendermint/crypto" "github.com/tendermint/tendermint/p2p" "github.com/tendermint/tendermint/state" "github.com/tendermint/tendermint/types" ) type NodeView struct { - tmNode *tendermint.Node + tmNode *Node txDecoder txs.Decoder } -func NewNodeView(tmNode *tendermint.Node, txDecoder txs.Decoder) *NodeView { +func NewNodeView(tmNode *Node, txDecoder txs.Decoder) *NodeView { return &NodeView{ tmNode: tmNode, txDecoder: txDecoder, @@ -28,7 +26,7 @@ func NewNodeView(tmNode *tendermint.Node, txDecoder txs.Decoder) *NodeView { } func (nv *NodeView) PrivValidatorPublicKey() (crypto.PublicKey, error) { - pub := nv.tmNode.PrivValidator().GetPubKey().(tm_crypto.PubKeyEd25519) + pub := nv.tmNode.PrivValidator().GetPubKey().(tmCrypto.PubKeyEd25519) return crypto.PublicKeyFromBytes(pub[:], crypto.CurveTypeEd25519) } diff --git a/consensus/tendermint/validator/priv_validator_memory.go b/consensus/tendermint/priv_validator_memory.go similarity index 98% rename from consensus/tendermint/validator/priv_validator_memory.go rename to consensus/tendermint/priv_validator_memory.go index 5159e503..fb63b76a 100644 --- a/consensus/tendermint/validator/priv_validator_memory.go +++ b/consensus/tendermint/priv_validator_memory.go @@ -1,4 +1,4 @@ -package validator +package tendermint import ( "github.com/hyperledger/burrow/crypto" diff --git a/consensus/tendermint/validator/sign_info.go b/consensus/tendermint/sign_info.go similarity index 99% rename from consensus/tendermint/validator/sign_info.go rename to consensus/tendermint/sign_info.go index 40230651..1a11cbf7 100644 --- a/consensus/tendermint/validator/sign_info.go +++ b/consensus/tendermint/sign_info.go @@ -1,4 +1,4 @@ -package validator +package tendermint import ( "bytes" diff --git a/consensus/tendermint/tendermint.go b/consensus/tendermint/tendermint.go index 31f0c8cf..0122f580 100644 --- a/consensus/tendermint/tendermint.go +++ b/consensus/tendermint/tendermint.go @@ -4,13 +4,10 @@ import ( "os" "path" - bcm "github.com/hyperledger/burrow/blockchain" "github.com/hyperledger/burrow/consensus/tendermint/abci" - "github.com/hyperledger/burrow/execution" "github.com/hyperledger/burrow/genesis" "github.com/hyperledger/burrow/logging" "github.com/hyperledger/burrow/logging/structure" - "github.com/hyperledger/burrow/txs" "github.com/tendermint/tendermint/config" tmCrypto "github.com/tendermint/tendermint/crypto" dbm "github.com/tendermint/tendermint/libs/db" @@ -45,8 +42,7 @@ func (n *Node) Close() { } func NewNode(conf *config.Config, privValidator tmTypes.PrivValidator, genesisDoc *tmTypes.GenesisDoc, - blockchain *bcm.Blockchain, checker execution.BatchExecutor, committer execution.BatchCommitter, - txDecoder txs.Decoder, metricsProvider node.MetricsProvider, panicFunc func(error), logger *logging.Logger) (*Node, error) { + app *abci.App, metricsProvider node.MetricsProvider, logger *logging.Logger) (*Node, error) { var err error // disable Tendermint's RPC @@ -58,8 +54,6 @@ func NewNode(conf *config.Config, privValidator tmTypes.PrivValidator, genesisDo } nde := &Node{} - app := abci.NewApp(blockchain, checker, committer, txDecoder, panicFunc, logger) - conf.NodeKeyFile() nde.Node, err = node.NewNode(conf, privValidator, proxy.NewLocalClientCreator(app), func() (*tmTypes.GenesisDoc, error) { diff --git a/consensus/tendermint/validator/wire.go b/consensus/tendermint/wire.go similarity index 89% rename from consensus/tendermint/validator/wire.go rename to consensus/tendermint/wire.go index 3cdd4f0d..24f0bc11 100644 --- a/consensus/tendermint/validator/wire.go +++ b/consensus/tendermint/wire.go @@ -1,4 +1,4 @@ -package validator +package tendermint import ( amino "github.com/tendermint/go-amino" diff --git a/core/kernel.go b/core/kernel.go index 72329f2d..46854844 100644 --- a/core/kernel.go +++ b/core/kernel.go @@ -27,9 +27,9 @@ import ( "time" kitlog "github.com/go-kit/kit/log" - bcm "github.com/hyperledger/burrow/blockchain" + "github.com/hyperledger/burrow/bcm" "github.com/hyperledger/burrow/consensus/tendermint" - "github.com/hyperledger/burrow/consensus/tendermint/query" + "github.com/hyperledger/burrow/consensus/tendermint/abci" "github.com/hyperledger/burrow/event" "github.com/hyperledger/burrow/execution" "github.com/hyperledger/burrow/genesis" @@ -51,10 +51,11 @@ import ( ) const ( - CooldownMilliseconds = 1000 - ServerShutdownTimeoutMilliseconds = 1000 - LoggingCallerDepth = 5 - AccountsRingMutexCount = 100 + FirstBlockTimeout = 3 * time.Second + CooldownTime = 1000 * time.Millisecond + ServerShutdownTimeout = 1000 * time.Millisecond + LoggingCallerDepth = 5 + AccountsRingMutexCount = 100 ) // Kernel is the root structure of Burrow @@ -64,8 +65,10 @@ type Kernel struct { Service *rpc.Service Launchers []process.Launcher State *execution.State - Blockchain bcm.BlockchainInfo + Blockchain *bcm.Blockchain + Node *tendermint.Node Logger *logging.Logger + nodeInfo string processes map[string]process.Process shutdownNotify chan struct{} shutdownOnce sync.Once @@ -75,57 +78,58 @@ func NewKernel(ctx context.Context, keyClient keys.KeyClient, privValidator tmTy genesisDoc *genesis.GenesisDoc, tmConf *tmConfig.Config, rpcConfig *rpc.RPCConfig, keyConfig *keys.KeysConfig, keyStore *keys.KeyStore, exeOptions []execution.ExecutionOption, logger *logging.Logger) (*Kernel, error) { + var err error kern := &Kernel{ processes: make(map[string]process.Process), shutdownNotify: make(chan struct{}), } logger = logger.WithScope("NewKernel()").With(structure.TimeKey, kitlog.DefaultTimestampUTC) tmLogger := logger.With(structure.CallerKey, kitlog.Caller(LoggingCallerDepth+1)) - logger = logger.WithInfo(structure.CallerKey, kitlog.Caller(LoggingCallerDepth)) + kern.Logger = logger.WithInfo(structure.CallerKey, kitlog.Caller(LoggingCallerDepth)) stateDB := dbm.NewDB("burrow_state", dbm.GoLevelDBBackend, tmConf.DBDir()) - blockchain, err := bcm.LoadOrNewBlockchain(stateDB, genesisDoc, logger) + kern.Blockchain, err = bcm.LoadOrNewBlockchain(stateDB, genesisDoc, kern.Logger) if err != nil { return nil, fmt.Errorf("error creating or loading blockchain state: %v", err) } - var state *execution.State // These should be in sync unless we are at the genesis block - if blockchain.LastBlockHeight() > 0 { - state, err = execution.LoadState(stateDB, blockchain.AppHashAfterLastBlock()) + if kern.Blockchain.LastBlockHeight() > 0 { + kern.State, err = execution.LoadState(stateDB, kern.Blockchain.AppHashAfterLastBlock()) if err != nil { return nil, fmt.Errorf("could not load persisted execution state at hash 0x%X: %v", - blockchain.AppHashAfterLastBlock(), err) + kern.Blockchain.AppHashAfterLastBlock(), err) } } else { - state, err = execution.MakeGenesisState(stateDB, genesisDoc) + kern.State, err = execution.MakeGenesisState(stateDB, genesisDoc) } txCodec := txs.NewAminoCodec() tmGenesisDoc := tendermint.DeriveGenesisDoc(genesisDoc) - checker := execution.NewBatchChecker(state, blockchain, logger) + checker := execution.NewBatchChecker(kern.State, kern.Blockchain, kern.Logger) - emitter := event.NewEmitter(logger) - committer := execution.NewBatchCommitter(state, blockchain, emitter, logger, exeOptions...) + kern.Emitter = event.NewEmitter(kern.Logger) + committer := execution.NewBatchCommitter(kern.State, kern.Blockchain, kern.Emitter, kern.Logger, exeOptions...) - // We could use this to provide/register our own metrics (though this will register them with us). Unforunately + kern.nodeInfo = fmt.Sprintf("Burrow_%s_%X", genesisDoc.ChainID(), privValidator.GetAddress()) + app := abci.NewApp(kern.nodeInfo, kern.Blockchain, checker, committer, txCodec, kern.Panic, logger) + // We could use this to provide/register our own metrics (though this will register them with us). Unfortunately // Tendermint currently ignores the metrics passed unless its own server is turned on. metricsProvider := node.DefaultMetricsProvider - tmNode, err := tendermint.NewNode(tmConf, privValidator, tmGenesisDoc, blockchain, checker, committer, txCodec, - metricsProvider, kern.Panic, tmLogger) + kern.Node, err = tendermint.NewNode(tmConf, privValidator, tmGenesisDoc, app, metricsProvider, tmLogger) if err != nil { return nil, err } - transactor := execution.NewTransactor(blockchain.Tip, emitter, execution.NewAccounts(checker, keyClient, AccountsRingMutexCount), - tmNode.MempoolReactor().BroadcastTx, txCodec, logger) + transactor := execution.NewTransactor(kern.Blockchain, kern.Emitter, execution.NewAccounts(checker, keyClient, AccountsRingMutexCount), + kern.Node.MempoolReactor().BroadcastTx, txCodec, kern.Logger) - nameRegState := state - accountState := state - service := rpc.NewService(accountState, nameRegState, blockchain, transactor, - query.NewNodeView(tmNode, txCodec), logger) + nameRegState := kern.State + accountState := kern.State + nodeView := tendermint.NewNodeView(kern.Node, txCodec) + kern.Service = rpc.NewService(accountState, nameRegState, kern.Blockchain, nodeView, kern.Logger) - launchers := []process.Launcher{ + kern.Launchers = []process.Launcher{ { Name: "Profiling Server", Enabled: rpcConfig.Profiler.Enabled, @@ -136,7 +140,7 @@ func NewKernel(ctx context.Context, keyClient keys.KeyClient, privValidator tmTy go func() { err := debugServer.ListenAndServe() if err != nil { - logger.InfoMsg("Error from pprof debug server", structure.ErrorKey, err) + kern.Logger.InfoMsg("Error from pprof debug server", structure.ErrorKey, err) } }() return debugServer, nil @@ -157,22 +161,22 @@ func NewKernel(ctx context.Context, keyClient keys.KeyClient, privValidator tmTy Name: "Tendermint", Enabled: true, Launch: func() (process.Process, error) { - err := tmNode.Start() + err := kern.Node.Start() if err != nil { return nil, fmt.Errorf("error starting Tendermint node: %v", err) } return process.ShutdownFunc(func(ctx context.Context) error { - err := tmNode.Stop() + err := kern.Node.Stop() // Close tendermint database connections using our wrapper - defer tmNode.Close() + defer kern.Node.Close() if err != nil { return err } select { case <-ctx.Done(): return ctx.Err() - case <-tmNode.Quit(): - logger.InfoMsg("Tendermint Node has quit, closing DB connections...") + case <-kern.Node.Quit(): + kern.Logger.InfoMsg("Tendermint Node has quit, closing DB connections...") return nil } return err @@ -183,7 +187,7 @@ func NewKernel(ctx context.Context, keyClient keys.KeyClient, privValidator tmTy Name: "RPC/tm", Enabled: rpcConfig.TM.Enabled, Launch: func() (process.Process, error) { - server, err := tm.StartServer(service, "/websocket", rpcConfig.TM.ListenAddress, logger) + server, err := tm.StartServer(kern.Service, "/websocket", rpcConfig.TM.ListenAddress, kern.Logger) if err != nil { return nil, err } @@ -194,7 +198,8 @@ func NewKernel(ctx context.Context, keyClient keys.KeyClient, privValidator tmTy Name: "RPC/metrics", Enabled: rpcConfig.Metrics.Enabled, Launch: func() (process.Process, error) { - server, err := metrics.StartServer(service, rpcConfig.Metrics.MetricsPath, rpcConfig.Metrics.ListenAddress, rpcConfig.Metrics.BlockSampleSize, logger) + server, err := metrics.StartServer(kern.Service, rpcConfig.Metrics.MetricsPath, + rpcConfig.Metrics.ListenAddress, rpcConfig.Metrics.BlockSampleSize, kern.Logger) if err != nil { return nil, err } @@ -210,7 +215,7 @@ func NewKernel(ctx context.Context, keyClient keys.KeyClient, privValidator tmTy return nil, err } - grpcServer := rpc.NewGRPCServer(logger) + grpcServer := rpc.NewGRPCServer(kern.Logger) var ks *keys.KeyStore if keyStore != nil { ks = keyStore @@ -218,17 +223,18 @@ func NewKernel(ctx context.Context, keyClient keys.KeyClient, privValidator tmTy if keyConfig.GRPCServiceEnabled { if keyStore == nil { - ks = keys.NewKeyStore(keyConfig.KeysDirectory, keyConfig.AllowBadFilePermissions, logger) + ks = keys.NewKeyStore(keyConfig.KeysDirectory, keyConfig.AllowBadFilePermissions, kern.Logger) } keys.RegisterKeysServer(grpcServer, ks) } - rpcquery.RegisterQueryServer(grpcServer, rpcquery.NewQueryServer(state, nameRegState)) + rpcquery.RegisterQueryServer(grpcServer, rpcquery.NewQueryServer(kern.State, nameRegState, + kern.Blockchain, nodeView, kern.Logger)) rpctransact.RegisterTransactServer(grpcServer, rpctransact.NewTransactServer(transactor, txCodec)) - rpcevents.RegisterExecutionEventsServer(grpcServer, rpcevents.NewExecutionEventsServer(state, emitter, - blockchain.Tip, logger)) + rpcevents.RegisterExecutionEventsServer(grpcServer, rpcevents.NewExecutionEventsServer(kern.State, + kern.Emitter, kern.Blockchain, kern.Logger)) // Provides metadata about services registered //reflection.Register(grpcServer) @@ -244,12 +250,6 @@ func NewKernel(ctx context.Context, keyClient keys.KeyClient, privValidator tmTy }, } - kern.Emitter = emitter - kern.Service = service - kern.Launchers = launchers - kern.State = state - kern.Blockchain = blockchain - kern.Logger = logger return kern, nil } @@ -270,7 +270,7 @@ func (kern *Kernel) Boot() error { } func (kern *Kernel) Panic(err error) { - fmt.Fprintf(os.Stderr, "Kernel shutting down due to panic: %v", err) + fmt.Fprintf(os.Stderr, "%s: Kernel shutting down due to panic: %v", kern.nodeInfo, err) kern.Shutdown(context.Background()) os.Exit(1) } @@ -298,7 +298,7 @@ func (kern *Kernel) Shutdown(ctx context.Context) (err error) { logger := kern.Logger.WithScope("Shutdown") logger.InfoMsg("Attempting graceful shutdown...") logger.InfoMsg("Shutting down servers") - ctx, cancel := context.WithTimeout(ctx, ServerShutdownTimeoutMilliseconds*time.Millisecond) + ctx, cancel := context.WithTimeout(ctx, ServerShutdownTimeout) defer cancel() // Shutdown servers in reverse order to boot for i := len(kern.Launchers) - 1; i >= 0; i-- { @@ -322,7 +322,7 @@ func (kern *Kernel) Shutdown(ctx context.Context) (err error) { structure.Sync(kern.Logger.Trace) // We don't want to wait for them, but yielding for a cooldown Let other goroutines flush // potentially interesting final output (e.g. log messages) - time.Sleep(time.Millisecond * CooldownMilliseconds) + time.Sleep(CooldownTime) close(kern.shutdownNotify) }) return diff --git a/crypto/public_key.go b/crypto/public_key.go index 4d5764ad..27d59202 100644 --- a/crypto/public_key.go +++ b/crypto/public_key.go @@ -7,6 +7,7 @@ import ( "github.com/btcsuite/btcd/btcec" abci "github.com/tendermint/tendermint/abci/types" + tmCrypto "github.com/tendermint/tendermint/crypto" "github.com/tendermint/tendermint/crypto/tmhash" "github.com/tmthrgd/go-hex" "golang.org/x/crypto/ed25519" @@ -136,6 +137,17 @@ func (p PublicKey) ABCIPubKey() abci.PubKey { } } +func PublicKeyFromTendermintPubKey(pubKey tmCrypto.PubKey) (PublicKey, error) { + switch pk := pubKey.(type) { + case tmCrypto.PubKeyEd25519: + return PublicKeyFromBytes(pk[:], CurveTypeEd25519) + case tmCrypto.PubKeySecp256k1: + return PublicKeyFromBytes(pk[:], CurveTypeSecp256k1) + default: + return PublicKey{}, fmt.Errorf("unrecognised tendermint public key type: %v", pk) + } + +} func PublicKeyFromABCIPubKey(pubKey abci.PubKey) (PublicKey, error) { switch pubKey.Type { case CurveTypeEd25519.ABCIType(): diff --git a/execution/contexts/call_context.go b/execution/contexts/call_context.go index 5278b21c..fcf7e146 100644 --- a/execution/contexts/call_context.go +++ b/execution/contexts/call_context.go @@ -5,8 +5,8 @@ import ( "github.com/hyperledger/burrow/acm" "github.com/hyperledger/burrow/acm/state" + "github.com/hyperledger/burrow/bcm" "github.com/hyperledger/burrow/binary" - "github.com/hyperledger/burrow/blockchain" "github.com/hyperledger/burrow/execution/errors" "github.com/hyperledger/burrow/execution/evm" "github.com/hyperledger/burrow/execution/exec" @@ -19,7 +19,7 @@ import ( const GasLimit = uint64(1000000) type CallContext struct { - Tip blockchain.TipInfo + Tip bcm.BlockchainInfo StateWriter state.ReaderWriter RunCall bool VMOptions []func(*evm.VM) @@ -101,7 +101,7 @@ func (ctx *CallContext) Precheck() (*acm.MutableAccount, acm.Account, error) { return nil, nil, fmt.Errorf("attempt to call a native contract at %s, "+ "but native contracts cannot be called using CallTx. Use a "+ "contract that calls the native contract or the appropriate tx "+ - "type (eg. PermissionsTx, NameTx)", ctx.tx.Address) + "type (eg. PermsTx, NameTx)", ctx.tx.Address) } // Output account may be nil if we are still in mempool and contract was created in same block as this tx diff --git a/execution/contexts/governance_context.go b/execution/contexts/governance_context.go index dd0a8afe..39457b82 100644 --- a/execution/contexts/governance_context.go +++ b/execution/contexts/governance_context.go @@ -6,7 +6,7 @@ import ( "github.com/hyperledger/burrow/acm" "github.com/hyperledger/burrow/acm/state" - "github.com/hyperledger/burrow/blockchain" + "github.com/hyperledger/burrow/acm/validator" "github.com/hyperledger/burrow/execution/errors" "github.com/hyperledger/burrow/execution/exec" "github.com/hyperledger/burrow/genesis/spec" @@ -17,18 +17,18 @@ import ( type GovernanceContext struct { StateWriter state.ReaderWriter - ValidatorSet blockchain.ValidatorSet + ValidatorSet validator.Writer Logger *logging.Logger - tx *payload.GovernanceTx + tx *payload.GovTx txe *exec.TxExecution } -// GovernanceTx provides a set of TemplateAccounts and GovernanceContext tries to alter the chain state to match the +// GovTx provides a set of TemplateAccounts and GovernanceContext tries to alter the chain state to match the // specification given func (ctx *GovernanceContext) Execute(txe *exec.TxExecution) error { var ok bool ctx.txe = txe - ctx.tx, ok = txe.Envelope.Tx.Payload.(*payload.GovernanceTx) + ctx.tx, ok = txe.Envelope.Tx.Payload.(*payload.GovTx) if !ok { return fmt.Errorf("payload must be NameTx, but is: %v", txe.Envelope.Tx.Payload) } @@ -38,8 +38,9 @@ func (ctx *GovernanceContext) Execute(txe *exec.TxExecution) error { } // ensure all inputs have root permissions - if !allHavePermission(ctx.StateWriter, permission.Root, accounts, ctx.Logger) { - return fmt.Errorf("at least one input lacks Root permission needed for GovernanceTx") + err = allHavePermission(ctx.StateWriter, permission.Root, accounts, ctx.Logger) + if err != nil { + return errors.Wrap(err, "at least one input lacks permission for GovTx") } for _, i := range ctx.tx.Inputs { @@ -49,28 +50,25 @@ func (ctx *GovernanceContext) Execute(txe *exec.TxExecution) error { for _, update := range ctx.tx.AccountUpdates { if update.Address == nil && update.PublicKey == nil { // We do not want to generate a key - return fmt.Errorf("could not execution GovernanceTx since account template %v contains neither "+ + return fmt.Errorf("could not execution GovTx since account template %v contains neither "+ "address or public key", update) } if update.PublicKey != nil { address := update.PublicKey.Address() if update.Address != nil && address != *update.Address { return fmt.Errorf("supplied public key %v whose address %v does not match %v provided by"+ - "GovernanceTx", update.PublicKey, address, update.Address) + "GovTx", update.PublicKey, address, update.Address) } update.Address = &address } - if update.PublicKey == nil && update.Power != nil { + if update.PublicKey == nil && update.Balances().HasPower() { // If we are updating power we will need the key - return fmt.Errorf("GovernanceTx must be provided with public key when updating validator power") + return fmt.Errorf("GovTx must be provided with public key when updating validator power") } - account, err := state.GetMutableAccount(ctx.StateWriter, *update.Address) + account, err := getOrMakeOutput(ctx.StateWriter, accounts, *update.Address, ctx.Logger) if err != nil { return err } - if account == nil { - return fmt.Errorf("account %v not found so cannot update using template %v", update.Address, update) - } governAccountEvent, err := ctx.updateAccount(account, update) if err != nil { txe.GovernAccount(governAccountEvent, errors.AsException(err)) @@ -85,8 +83,8 @@ func (ctx *GovernanceContext) updateAccount(account *acm.MutableAccount, update ev = &exec.GovernAccountEvent{ AccountUpdate: update, } - if update.Amount != nil { - err = account.SetBalance(*update.Amount) + if update.Balances().HasNative() { + err = account.SetBalance(update.Balances().GetNative(0)) if err != nil { return } @@ -95,13 +93,13 @@ func (ctx *GovernanceContext) updateAccount(account *acm.MutableAccount, update // TODO: can we do something useful if provided with a NodeAddress for an account about to become a validator // like add it to persistent peers or pre gossip so it gets inbound connections? If so under which circumstances? } - if update.Power != nil { + if update.Balances().HasPower() { if update.PublicKey == nil { err = fmt.Errorf("updateAccount should have PublicKey by this point but appears not to for "+ "template account: %v", update) return } - power := new(big.Int).SetUint64(*update.Power) + power := new(big.Int).SetUint64(update.Balances().GetPower(0)) if !power.IsInt64() { err = fmt.Errorf("power supplied in update to validator power for %v does not fit into int64 and "+ "so is not supported by Tendermint", update.Address) diff --git a/execution/contexts/name_context.go b/execution/contexts/name_context.go index b5ba18a8..10c37a15 100644 --- a/execution/contexts/name_context.go +++ b/execution/contexts/name_context.go @@ -6,7 +6,7 @@ import ( "regexp" "github.com/hyperledger/burrow/acm/state" - "github.com/hyperledger/burrow/blockchain" + "github.com/hyperledger/burrow/bcm" "github.com/hyperledger/burrow/execution/errors" "github.com/hyperledger/burrow/execution/exec" "github.com/hyperledger/burrow/execution/names" @@ -21,7 +21,7 @@ var regexpAlphaNum = regexp.MustCompile("^[a-zA-Z0-9._/-@]*$") var regexpJSON = regexp.MustCompile(`^[a-zA-Z0-9_/ \-+"':,\n\t.{}()\[\]]*$`) type NameContext struct { - Tip blockchain.TipInfo + Tip bcm.BlockchainInfo StateWriter state.ReaderWriter NameReg names.ReaderWriter Logger *logging.Logger diff --git a/execution/contexts/permissions_context.go b/execution/contexts/permissions_context.go index 4572e41c..00cbd1a5 100644 --- a/execution/contexts/permissions_context.go +++ b/execution/contexts/permissions_context.go @@ -5,7 +5,7 @@ import ( "github.com/hyperledger/burrow/acm" "github.com/hyperledger/burrow/acm/state" - "github.com/hyperledger/burrow/blockchain" + "github.com/hyperledger/burrow/bcm" "github.com/hyperledger/burrow/crypto" "github.com/hyperledger/burrow/execution/errors" "github.com/hyperledger/burrow/execution/exec" @@ -16,17 +16,17 @@ import ( ) type PermissionsContext struct { - Tip blockchain.TipInfo + Tip bcm.BlockchainInfo StateWriter state.ReaderWriter Logger *logging.Logger - tx *payload.PermissionsTx + tx *payload.PermsTx } func (ctx *PermissionsContext) Execute(txe *exec.TxExecution) error { var ok bool - ctx.tx, ok = txe.Envelope.Tx.Payload.(*payload.PermissionsTx) + ctx.tx, ok = txe.Envelope.Tx.Payload.(*payload.PermsTx) if !ok { - return fmt.Errorf("payload must be PermissionsTx, but is: %v", txe.Envelope.Tx.Payload) + return fmt.Errorf("payload must be PermsTx, but is: %v", txe.Envelope.Tx.Payload) } // Validate input inAcc, err := state.GetMutableAccount(ctx.StateWriter, ctx.tx.Input.Address) @@ -41,7 +41,7 @@ func (ctx *PermissionsContext) Execute(txe *exec.TxExecution) error { err = ctx.tx.PermArgs.EnsureValid() if err != nil { - return fmt.Errorf("PermissionsTx received containing invalid PermArgs: %v", err) + return fmt.Errorf("PermsTx received containing invalid PermArgs: %v", err) } permFlag := ctx.tx.PermArgs.PermFlag @@ -61,7 +61,7 @@ func (ctx *PermissionsContext) Execute(txe *exec.TxExecution) error { value := ctx.tx.Input.Amount - ctx.Logger.TraceMsg("New PermissionsTx", + ctx.Logger.TraceMsg("New PermsTx", "perm_args", ctx.tx.PermArgs.String()) var permAcc acm.Account @@ -114,7 +114,7 @@ func (ctx *PermissionsContext) Execute(txe *exec.TxExecution) error { } // Good! - ctx.Logger.TraceMsg("Incrementing sequence number for PermissionsTx", + ctx.Logger.TraceMsg("Incrementing sequence number for PermsTx", "tag", "sequence", "account", inAcc.Address(), "old_sequence", inAcc.Sequence(), diff --git a/execution/contexts/send_context.go b/execution/contexts/send_context.go index 592cb6c4..a50c0b88 100644 --- a/execution/contexts/send_context.go +++ b/execution/contexts/send_context.go @@ -4,7 +4,7 @@ import ( "fmt" "github.com/hyperledger/burrow/acm/state" - "github.com/hyperledger/burrow/blockchain" + "github.com/hyperledger/burrow/bcm" "github.com/hyperledger/burrow/execution/errors" "github.com/hyperledger/burrow/execution/exec" "github.com/hyperledger/burrow/logging" @@ -13,7 +13,7 @@ import ( ) type SendContext struct { - Tip blockchain.TipInfo + Tip bcm.BlockchainInfo StateWriter state.ReaderWriter Logger *logging.Logger tx *payload.SendTx @@ -31,8 +31,9 @@ func (ctx *SendContext) Execute(txe *exec.TxExecution) error { } // ensure all inputs have send permissions - if !allHavePermission(ctx.StateWriter, permission.Send, accounts, ctx.Logger) { - return fmt.Errorf("at least one input lacks permission for SendTx") + err = allHavePermission(ctx.StateWriter, permission.Send, accounts, ctx.Logger) + if err != nil { + return errors.Wrap(err, "at least one input lacks permission for SendTx") } // add outputs to accounts map diff --git a/execution/contexts/shared.go b/execution/contexts/shared.go index ed97bbd1..23f645f6 100644 --- a/execution/contexts/shared.go +++ b/execution/contexts/shared.go @@ -43,38 +43,45 @@ func getOrMakeOutputs(accountGetter state.AccountGetter, accs map[crypto.Address if accs == nil { accs = make(map[crypto.Address]*acm.MutableAccount) } - // we should err if an account is being created but the inputs don't have permission - var checkedCreatePerms bool + var err error for _, out := range outs { - // Account shouldn't be duplicated - if _, ok := accs[out.Address]; ok { - return nil, errors.ErrorCodeDuplicateAddress - } - acc, err := state.GetMutableAccount(accountGetter, out.Address) + accs[out.Address], err = getOrMakeOutput(accountGetter, accs, out.Address, logger) if err != nil { return nil, err } - // output account may be nil (new) - if acc == nil { - if !checkedCreatePerms { - if !hasCreateAccountPermission(accountGetter, accs, logger) { - return nil, fmt.Errorf("at least one input does not have permission to create accounts") - } - checkedCreatePerms = true - } - acc = acm.ConcreteAccount{ - Address: out.Address, - Sequence: 0, - Balance: 0, - Permissions: permission.ZeroAccountPermissions, - }.MutableAccount() - } - accs[out.Address] = acc } return accs, nil } +func getOrMakeOutput(accountGetter state.AccountGetter, accs map[crypto.Address]*acm.MutableAccount, + outputAddress crypto.Address, logger *logging.Logger) (*acm.MutableAccount, error) { + + // Account shouldn't be duplicated + if _, ok := accs[outputAddress]; ok { + return nil, errors.ErrorCodeDuplicateAddress + } + acc, err := state.GetMutableAccount(accountGetter, outputAddress) + if err != nil { + return nil, err + } + // output account may be nil (new) + if acc == nil { + if !hasCreateAccountPermission(accountGetter, accs, logger) { + return nil, fmt.Errorf("at least one input does not have permission to create accounts") + } + logger.InfoMsg("Account not found so attempting to create it", "address", outputAddress) + acc = acm.ConcreteAccount{ + Address: outputAddress, + Sequence: 0, + Balance: 0, + Permissions: permission.ZeroAccountPermissions, + }.MutableAccount() + } + + return acc, nil +} + func validateInputs(accs map[crypto.Address]*acm.MutableAccount, ins []*payload.TxInput) (uint64, error) { total := uint64(0) for _, in := range ins { @@ -188,15 +195,17 @@ func HasPermission(accountGetter state.AccountGetter, acc acm.Account, perm perm return v } -// TODO: for debug log the failed accounts func allHavePermission(accountGetter state.AccountGetter, perm permission.PermFlag, - accs map[crypto.Address]*acm.MutableAccount, logger *logging.Logger) bool { + accs map[crypto.Address]*acm.MutableAccount, logger *logging.Logger) error { for _, acc := range accs { if !HasPermission(accountGetter, acc, perm, logger) { - return false + return errors.PermissionDenied{ + Address: acc.Address(), + Perm: perm, + } } } - return true + return nil } func hasNamePermission(accountGetter state.AccountGetter, acc acm.Account, diff --git a/execution/errors/errors.go b/execution/errors/errors.go index b3bc5541..00e49c47 100644 --- a/execution/errors/errors.go +++ b/execution/errors/errors.go @@ -44,6 +44,10 @@ func (c Code) ErrorCode() Code { return c } +func (c Code) Uint32() uint32 { + return uint32(c) +} + func (c Code) Error() string { return fmt.Sprintf("Error %d: %s", c, c.String()) } @@ -76,6 +80,8 @@ func (c Code) String() string { return "Data stack underflow" case ErrorCodeInvalidContract: return "Invalid contract" + case ErrorCodePermissionDenied: + return "Permission denied" case ErrorCodeNativeContractCodeCopy: return "Tried to copy native contract code" case ErrorCodeExecutionAborted: @@ -134,8 +140,9 @@ func AsException(err error) *Exception { } } -func Wrap(err CodedError, message string) *Exception { - return NewCodedError(err.ErrorCode(), message+": "+err.Error()) +func Wrap(err error, message string) *Exception { + ex := AsException(err) + return NewCodedError(ex.ErrorCode(), message+": "+ex.Error()) } func Errorf(format string, a ...interface{}) *Exception { diff --git a/execution/errors/errors_test.go b/execution/errors/errors_test.go index 33d487b4..c80c0572 100644 --- a/execution/errors/errors_test.go +++ b/execution/errors/errors_test.go @@ -5,8 +5,6 @@ import ( "fmt" "testing" - "fmt" - "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) diff --git a/execution/errors/vm.go b/execution/errors/vm.go index 7e97d375..95b36cca 100644 --- a/execution/errors/vm.go +++ b/execution/errors/vm.go @@ -9,7 +9,8 @@ import ( ) type PermissionDenied struct { - Perm permission.PermFlag + Address crypto.Address + Perm permission.PermFlag } func (err PermissionDenied) ErrorCode() Code { @@ -17,7 +18,7 @@ func (err PermissionDenied) ErrorCode() Code { } func (err PermissionDenied) Error() string { - return fmt.Sprintf("Contract does not have permission to %v", err.Perm) + return fmt.Sprintf("Account/contract %v does not have permission %v", err.Address, err.Perm) } type NestedCall struct { diff --git a/execution/evm/vm.go b/execution/evm/vm.go index 53d9b1eb..0182a3f5 100644 --- a/execution/evm/vm.go +++ b/execution/evm/vm.go @@ -855,7 +855,10 @@ func (vm *VM) call(callState *state.Cache, caller acm.Account, callee *acm.Mutab vm.returnData = nil if !HasPermission(callState, callee, permission.CreateContract) { - return nil, errors.PermissionDenied{Perm: permission.CreateContract} + return nil, errors.PermissionDenied{ + Address: callee.Address(), + Perm: permission.CreateContract, + } } contractValue, popErr := stack.PopU64() if popErr != nil { @@ -902,7 +905,10 @@ func (vm *VM) call(callState *state.Cache, caller acm.Account, callee *acm.Mutab vm.returnData = nil if !HasPermission(callState, callee, permission.Call) { - return nil, errors.PermissionDenied{Perm: permission.Call} + return nil, errors.PermissionDenied{ + Address: callee.Address(), + Perm: permission.Call, + } } gasLimit, popErr := stack.PopU64() if popErr != nil { @@ -982,7 +988,10 @@ func (vm *VM) call(callState *state.Cache, caller acm.Account, callee *acm.Mutab // nil account means we're sending funds to a new account if acc == nil { if !HasPermission(callState, caller, permission.CreateAccount) { - return nil, errors.PermissionDenied{Perm: permission.CreateAccount} + return nil, errors.PermissionDenied{ + Address: callee.Address(), + Perm: permission.CreateAccount, + } } acc = acm.ConcreteAccount{Address: crypto.AddressFromWord256(addr)}.MutableAccount() } @@ -1077,7 +1086,10 @@ func (vm *VM) call(callState *state.Cache, caller acm.Account, callee *acm.Mutab return nil, firstErr(err, gasErr) } if !HasPermission(callState, callee, permission.CreateContract) { - return nil, firstErr(err, errors.PermissionDenied{Perm: permission.CreateContract}) + return nil, firstErr(err, errors.PermissionDenied{ + Address: callee.Address(), + Perm: permission.CreateContract, + }) } var createErr errors.CodedError receiver, createErr = vm.createAccount(callState, callee, logger) diff --git a/execution/exec/exec.pb.go b/execution/exec/exec.pb.go index 26108e09..df1d5e80 100644 --- a/execution/exec/exec.pb.go +++ b/execution/exec/exec.pb.go @@ -28,7 +28,6 @@ import golang_proto "github.com/golang/protobuf/proto" import fmt "fmt" import math "math" import _ "github.com/gogo/protobuf/gogoproto" -import _ "github.com/tendermint/tendermint/abci/types" import errors "github.com/hyperledger/burrow/execution/errors" import names "github.com/hyperledger/burrow/execution/names" import txs "github.com/hyperledger/burrow/txs" @@ -3351,68 +3350,67 @@ func init() { proto.RegisterFile("exec.proto", fileDescriptorExec) } func init() { golang_proto.RegisterFile("exec.proto", fileDescriptorExec) } var fileDescriptorExec = []byte{ - // 999 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x56, 0x4f, 0x6f, 0x1b, 0x45, - 0x14, 0xef, 0xda, 0xeb, 0x7f, 0xcf, 0x76, 0x09, 0xa3, 0x80, 0x56, 0x3d, 0xd8, 0xd6, 0x16, 0x55, - 0x21, 0xb4, 0x6b, 0xe4, 0x12, 0x24, 0x40, 0x42, 0x8a, 0x89, 0x95, 0xa4, 0x0a, 0x09, 0x4c, 0x5d, - 0x10, 0x08, 0x0e, 0xeb, 0xdd, 0xc1, 0x59, 0xd5, 0xde, 0x59, 0xcd, 0xce, 0x86, 0xf5, 0x87, 0xe0, - 0xc6, 0xa1, 0xdc, 0xf8, 0x28, 0x1c, 0x73, 0x83, 0x0b, 0x97, 0x1e, 0x2c, 0x94, 0x7e, 0x04, 0x38, - 0xf5, 0x84, 0xe6, 0xcf, 0xae, 0xd7, 0x02, 0x35, 0x55, 0x92, 0x8b, 0x35, 0xef, 0xbd, 0xdf, 0xfc, - 0xe6, 0xcd, 0x7b, 0xbf, 0x37, 0x5e, 0x00, 0x92, 0x12, 0xcf, 0x89, 0x18, 0xe5, 0x14, 0x99, 0x62, - 0x7d, 0xe7, 0xc1, 0x34, 0xe0, 0xa7, 0xc9, 0xc4, 0xf1, 0xe8, 0xbc, 0x3f, 0xa5, 0x53, 0xda, 0x97, - 0xc1, 0x49, 0xf2, 0x83, 0xb4, 0xa4, 0x21, 0x57, 0x6a, 0xd3, 0x9d, 0xfb, 0x05, 0x38, 0x27, 0xa1, - 0x4f, 0xd8, 0x3c, 0x08, 0x79, 0xdf, 0x9d, 0x78, 0x41, 0x9f, 0x2f, 0x22, 0x12, 0xab, 0x5f, 0x8d, - 0x6e, 0x11, 0xc6, 0x28, 0xcb, 0xac, 0x66, 0xe8, 0xce, 0xf3, 0x50, 0x83, 0xa7, 0xd9, 0x72, 0x23, - 0x12, 0x2c, 0x71, 0x1c, 0xd0, 0x50, 0x7b, 0x20, 0x8e, 0xb2, 0x34, 0xed, 0x9f, 0x0d, 0xb8, 0x3d, - 0x9c, 0x51, 0xef, 0xe9, 0x28, 0x25, 0x5e, 0xc2, 0x03, 0x1a, 0xa2, 0xb7, 0xa1, 0x7a, 0x40, 0x82, - 0xe9, 0x29, 0xb7, 0x8c, 0x9e, 0xb1, 0x65, 0x62, 0x6d, 0xa1, 0x87, 0xd0, 0x94, 0xc8, 0x03, 0xe2, - 0xfa, 0x84, 0x59, 0xa5, 0x9e, 0xb1, 0xd5, 0x1c, 0xbc, 0xe9, 0xc8, 0x3b, 0x17, 0x02, 0xb8, 0x88, - 0x42, 0x3b, 0xd0, 0x1a, 0xa7, 0x39, 0x77, 0x6c, 0x95, 0x7b, 0xe5, 0xd5, 0xae, 0x42, 0x04, 0xaf, - 0xc1, 0xec, 0x8f, 0xd6, 0xce, 0x42, 0x08, 0xcc, 0x47, 0x8f, 0x4f, 0x8e, 0x65, 0x42, 0x0d, 0x2c, - 0xd7, 0x22, 0xcd, 0xe3, 0x64, 0x3e, 0x4e, 0x63, 0x99, 0x49, 0x05, 0x6b, 0xcb, 0xfe, 0xb3, 0x0c, - 0xcd, 0x02, 0x17, 0x7a, 0x04, 0xd5, 0x71, 0x3a, 0x5e, 0x44, 0x44, 0xe2, 0xda, 0xc3, 0xc1, 0xcb, - 0x65, 0xd7, 0x29, 0xd4, 0xf9, 0x74, 0x11, 0x11, 0x36, 0x23, 0xfe, 0x94, 0xb0, 0xfe, 0x24, 0x61, - 0x8c, 0xfe, 0xd8, 0xe7, 0x69, 0xdc, 0x8f, 0xdc, 0xc5, 0x8c, 0xba, 0xbe, 0x23, 0x76, 0x62, 0xcd, - 0x80, 0x3e, 0x17, 0x5c, 0x07, 0x6e, 0x7c, 0x6a, 0x95, 0x7b, 0xc6, 0x56, 0x6b, 0xb8, 0x73, 0xbe, - 0xec, 0xde, 0x7a, 0xbe, 0xec, 0x3e, 0x78, 0x35, 0xdf, 0x24, 0x08, 0x5d, 0xb6, 0x70, 0x0e, 0x48, - 0x3a, 0x5c, 0x70, 0x12, 0x63, 0x4d, 0x52, 0xa8, 0xb4, 0xb9, 0x56, 0xe9, 0x4d, 0xa8, 0x1c, 0x86, - 0x3e, 0x49, 0xad, 0x8a, 0x74, 0x2b, 0x03, 0x7d, 0x03, 0xf5, 0x51, 0x78, 0x46, 0x66, 0x34, 0x22, - 0x56, 0x55, 0x16, 0xbf, 0xed, 0x88, 0x36, 0x67, 0xce, 0xa1, 0xf3, 0x7c, 0xd9, 0xdd, 0xbe, 0xf4, - 0x66, 0x39, 0x1e, 0xe7, 0x74, 0xe8, 0x2e, 0x54, 0x47, 0x67, 0x24, 0xe4, 0xb1, 0x55, 0x93, 0xfd, - 0x69, 0xaa, 0xfe, 0x48, 0x1f, 0xd6, 0x21, 0xf4, 0x0e, 0x54, 0x31, 0x89, 0x93, 0x19, 0xb7, 0xea, - 0xf2, 0xf4, 0x96, 0x02, 0x29, 0x1f, 0xd6, 0x31, 0x74, 0x0f, 0x6a, 0x98, 0x78, 0x24, 0x88, 0xb8, - 0xd5, 0xd0, 0x30, 0x71, 0xa8, 0xf6, 0xe1, 0x2c, 0x88, 0xfa, 0xd0, 0x18, 0xa5, 0x1e, 0x89, 0x44, - 0x8f, 0x2c, 0xc8, 0xb4, 0xa4, 0x04, 0x9d, 0x07, 0xf0, 0x0a, 0x63, 0xff, 0x5e, 0x12, 0xd5, 0x92, - 0x72, 0x58, 0xb5, 0xd4, 0xb8, 0xc1, 0x96, 0x96, 0x6e, 0xa2, 0xa5, 0xef, 0x41, 0x43, 0x96, 0x4b, - 0x66, 0x57, 0x96, 0xd9, 0xb5, 0x5f, 0x2e, 0xbb, 0x2b, 0x27, 0x5e, 0x2d, 0x91, 0x05, 0x35, 0x69, - 0x1c, 0xee, 0x49, 0x01, 0x34, 0x70, 0x66, 0x16, 0x94, 0x51, 0xf9, 0x7f, 0x65, 0x54, 0x8b, 0xca, - 0x58, 0xab, 0x65, 0xed, 0xf2, 0x5a, 0x7e, 0x6c, 0x3e, 0xfb, 0xb5, 0x7b, 0xcb, 0xfe, 0xa9, 0x04, - 0x15, 0x79, 0xa0, 0x68, 0xad, 0x9e, 0x6a, 0xa3, 0xd8, 0x5a, 0x3d, 0xd0, 0x59, 0xd9, 0xef, 0x89, - 0xc3, 0xa3, 0x84, 0xeb, 0xd1, 0xdf, 0x50, 0x20, 0xe9, 0x52, 0x4a, 0x51, 0x61, 0xf4, 0x2e, 0x54, - 0x4f, 0x12, 0x2e, 0x80, 0xe5, 0xe2, 0x1b, 0xa1, 0x7c, 0x5a, 0x53, 0xca, 0x40, 0x77, 0xc1, 0xfc, - 0xcc, 0x9d, 0xcd, 0xe4, 0xf5, 0x9b, 0x83, 0x37, 0x14, 0x50, 0x78, 0x14, 0x4c, 0x06, 0x51, 0x0f, - 0xca, 0x47, 0x74, 0x2a, 0x2b, 0xd1, 0x1c, 0xdc, 0x56, 0x98, 0x23, 0x3a, 0x55, 0x10, 0x11, 0x42, - 0x9f, 0x42, 0x7b, 0x9f, 0x9e, 0x11, 0x16, 0xee, 0x7a, 0x1e, 0x4d, 0x42, 0xae, 0xe7, 0xc3, 0x52, - 0xd8, 0xb5, 0x90, 0xda, 0xb5, 0x0e, 0xd7, 0xf5, 0x78, 0x66, 0x64, 0x0a, 0x17, 0xf5, 0xc7, 0x84, - 0x27, 0x2c, 0x94, 0x05, 0x69, 0x61, 0x6d, 0x89, 0x8e, 0xed, 0xbb, 0xf1, 0x93, 0x98, 0xf8, 0xb2, - 0x08, 0x26, 0xce, 0x4c, 0xb4, 0x0d, 0x8d, 0x63, 0x77, 0x4e, 0x46, 0x21, 0x67, 0x0b, 0x7d, 0xef, - 0x96, 0xa3, 0x9e, 0x64, 0xe9, 0xc3, 0xab, 0x30, 0x7a, 0x1f, 0xea, 0x5f, 0x10, 0x36, 0xdf, 0x65, - 0xd3, 0x58, 0xdf, 0x7c, 0xd3, 0x29, 0xbc, 0xd2, 0x59, 0x0c, 0xe7, 0x28, 0xfb, 0x6f, 0x03, 0xea, - 0xd9, 0x95, 0xd1, 0x31, 0xd4, 0x76, 0x7d, 0x9f, 0x91, 0x38, 0x56, 0xd9, 0x0d, 0x3f, 0xd0, 0x9a, - 0xbd, 0xff, 0x6a, 0xcd, 0x7a, 0x6c, 0x11, 0x71, 0xea, 0xe8, 0xbd, 0x38, 0x23, 0x41, 0x87, 0x60, - 0xee, 0xb9, 0xdc, 0xbd, 0xde, 0x00, 0x48, 0x0a, 0x74, 0x04, 0xd5, 0x31, 0x8d, 0x02, 0x4f, 0x3d, - 0xf4, 0xaf, 0x9d, 0x99, 0x26, 0xfb, 0x9a, 0x32, 0x7f, 0xb0, 0xf3, 0x21, 0xd6, 0x1c, 0xf6, 0x3f, - 0x06, 0x34, 0x72, 0x31, 0xa0, 0x6d, 0xa8, 0x0b, 0x43, 0xa6, 0x6a, 0x14, 0xb5, 0x90, 0x79, 0x71, - 0x1e, 0x17, 0x79, 0x9c, 0xb0, 0x60, 0x1a, 0x84, 0xfa, 0x52, 0x57, 0xab, 0x90, 0xe6, 0x40, 0x1d, - 0x80, 0xc7, 0xdc, 0xf5, 0x9e, 0xee, 0x91, 0x88, 0xab, 0xa7, 0xdf, 0xc4, 0x05, 0x8f, 0x78, 0x43, - 0xb4, 0x5a, 0xcc, 0x6b, 0xbd, 0x21, 0x8a, 0xc4, 0xfe, 0x12, 0xd0, 0x7f, 0x25, 0x8b, 0x3e, 0x81, - 0xb6, 0xb6, 0x9f, 0x44, 0xbe, 0xcb, 0x89, 0xae, 0xc1, 0x5b, 0x8e, 0xfc, 0x37, 0x1f, 0x93, 0x79, - 0x34, 0x73, 0x39, 0xd1, 0x10, 0xbc, 0x8e, 0xb5, 0xbf, 0x03, 0x58, 0xcd, 0xe9, 0x4d, 0x0b, 0xc8, - 0xfe, 0x1e, 0x9a, 0x85, 0xe1, 0xbe, 0x71, 0xfa, 0x5f, 0x4a, 0xb0, 0xd6, 0x59, 0xb1, 0xd6, 0x4f, - 0xd5, 0x95, 0x3b, 0xab, 0x38, 0x72, 0x36, 0x72, 0x3d, 0x9d, 0x28, 0x8e, 0x7c, 0x90, 0xca, 0xd7, - 0x1f, 0xa4, 0x4d, 0xa8, 0x7c, 0xe5, 0xce, 0x12, 0xa2, 0xbf, 0x0c, 0x94, 0x81, 0x36, 0xa0, 0xbc, - 0xef, 0xc6, 0xfa, 0x3f, 0x41, 0x2c, 0x87, 0xc3, 0xf3, 0x8b, 0x8e, 0xf1, 0xc7, 0x45, 0xc7, 0xf8, - 0xeb, 0xa2, 0x63, 0xfc, 0xf6, 0xa2, 0x63, 0x9c, 0xbf, 0xe8, 0x18, 0xdf, 0x5e, 0x92, 0x3e, 0xc9, - 0x3e, 0x8e, 0xe4, 0x6a, 0x52, 0x95, 0x9f, 0x82, 0x0f, 0xff, 0x0d, 0x00, 0x00, 0xff, 0xff, 0x47, - 0x90, 0xbb, 0xef, 0xbf, 0x0a, 0x00, 0x00, + // 979 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x56, 0x4f, 0x6f, 0xe3, 0x44, + 0x14, 0x5f, 0x37, 0xce, 0xbf, 0x97, 0x64, 0x29, 0xa3, 0x82, 0xac, 0x3d, 0x24, 0x91, 0x17, 0xad, + 0x4a, 0x61, 0x1d, 0x94, 0xa5, 0x48, 0x80, 0x84, 0xd4, 0xd0, 0xa8, 0xed, 0xaa, 0xb4, 0x30, 0x9b, + 0x05, 0x81, 0xe0, 0xe0, 0x38, 0x83, 0x6b, 0xad, 0xe3, 0xb1, 0xc6, 0xe3, 0xe2, 0x7c, 0x08, 0x6e, + 0x1c, 0x96, 0x1b, 0x1f, 0x85, 0x63, 0x6f, 0x70, 0xe1, 0xb2, 0x87, 0x08, 0x75, 0x3f, 0x02, 0x9c, + 0xf6, 0x84, 0xe6, 0x8f, 0x1d, 0x47, 0xa0, 0x2d, 0xda, 0xf6, 0x36, 0xef, 0xbd, 0xdf, 0xfc, 0xe6, + 0xcd, 0x7b, 0xbf, 0x37, 0x36, 0x00, 0xc9, 0x88, 0xe7, 0xc4, 0x8c, 0x72, 0x8a, 0x4c, 0xb1, 0xbe, + 0x73, 0xdf, 0x0f, 0xf8, 0x59, 0x3a, 0x75, 0x3c, 0x3a, 0x1f, 0xf8, 0xd4, 0xa7, 0x03, 0x19, 0x9c, + 0xa6, 0xdf, 0x4b, 0x4b, 0x1a, 0x72, 0xa5, 0x36, 0xdd, 0x69, 0x13, 0xc6, 0x28, 0x4b, 0xb4, 0xd5, + 0x8a, 0xdc, 0x39, 0xc9, 0x8d, 0x26, 0xcf, 0xf2, 0xe5, 0x66, 0x4c, 0xd8, 0x3c, 0x48, 0x92, 0x80, + 0x46, 0xda, 0x03, 0x49, 0x9c, 0x1f, 0x6c, 0xff, 0x64, 0xc0, 0xed, 0x51, 0x48, 0xbd, 0x27, 0xe3, + 0x8c, 0x78, 0x29, 0x0f, 0x68, 0x84, 0xde, 0x84, 0xda, 0x21, 0x09, 0xfc, 0x33, 0x6e, 0x19, 0x7d, + 0x63, 0xdb, 0xc4, 0xda, 0x42, 0x0f, 0xa0, 0x25, 0x91, 0x87, 0xc4, 0x9d, 0x11, 0x66, 0x6d, 0xf4, + 0x8d, 0xed, 0xd6, 0xf0, 0x75, 0x47, 0xde, 0xa2, 0x14, 0xc0, 0x65, 0x14, 0xda, 0x85, 0xf6, 0x24, + 0x2b, 0xb8, 0x13, 0xab, 0xd2, 0xaf, 0xac, 0x76, 0x95, 0x22, 0x78, 0x0d, 0x66, 0x7f, 0xb8, 0x76, + 0x16, 0x42, 0x60, 0x3e, 0x7c, 0x74, 0x7a, 0x22, 0x13, 0x6a, 0x62, 0xb9, 0x16, 0x69, 0x9e, 0xa4, + 0xf3, 0x49, 0x96, 0xc8, 0x4c, 0xaa, 0x58, 0x5b, 0xf6, 0x1f, 0x15, 0x68, 0x95, 0xb8, 0xd0, 0x43, + 0xa8, 0x4d, 0xb2, 0xc9, 0x22, 0x26, 0x12, 0xd7, 0x19, 0x0d, 0x5f, 0x2c, 0x7b, 0x4e, 0xa9, 0xd0, + 0x67, 0x8b, 0x98, 0xb0, 0x90, 0xcc, 0x7c, 0xc2, 0x06, 0xd3, 0x94, 0x31, 0xfa, 0xc3, 0x80, 0x67, + 0xc9, 0x20, 0x76, 0x17, 0x21, 0x75, 0x67, 0x8e, 0xd8, 0x89, 0x35, 0x03, 0xfa, 0x4c, 0x70, 0x1d, + 0xba, 0xc9, 0x99, 0x55, 0xe9, 0x1b, 0xdb, 0xed, 0xd1, 0xee, 0xc5, 0xb2, 0x77, 0xeb, 0xd9, 0xb2, + 0x77, 0xff, 0xe5, 0x7c, 0xd3, 0x20, 0x72, 0xd9, 0xc2, 0x39, 0x24, 0xd9, 0x68, 0xc1, 0x49, 0x82, + 0x35, 0x49, 0xa9, 0xd2, 0xe6, 0x5a, 0xa5, 0xb7, 0xa0, 0x7a, 0x14, 0xcd, 0x48, 0x66, 0x55, 0xa5, + 0x5b, 0x19, 0xe8, 0x6b, 0x68, 0x8c, 0xa3, 0x73, 0x12, 0xd2, 0x98, 0x58, 0x35, 0x59, 0xfc, 0x8e, + 0x23, 0xda, 0x9c, 0x3b, 0x47, 0xce, 0xb3, 0x65, 0x6f, 0xe7, 0xca, 0x9b, 0x15, 0x78, 0x5c, 0xd0, + 0xa1, 0xbb, 0x50, 0x1b, 0x9f, 0x93, 0x88, 0x27, 0x56, 0x5d, 0xf6, 0xa7, 0xa5, 0xfa, 0x23, 0x7d, + 0x58, 0x87, 0xd0, 0x5b, 0x50, 0xc3, 0x24, 0x49, 0x43, 0x6e, 0x35, 0xe4, 0xe9, 0x6d, 0x05, 0x52, + 0x3e, 0xac, 0x63, 0xe8, 0x1e, 0xd4, 0x31, 0xf1, 0x48, 0x10, 0x73, 0xab, 0xa9, 0x61, 0xe2, 0x50, + 0xed, 0xc3, 0x79, 0x10, 0x0d, 0xa0, 0x39, 0xce, 0x3c, 0x12, 0x8b, 0x1e, 0x59, 0x90, 0x6b, 0x49, + 0x09, 0xba, 0x08, 0xe0, 0x15, 0xc6, 0xfe, 0x6d, 0x43, 0x54, 0x4b, 0xca, 0x61, 0xd5, 0x52, 0xe3, + 0x06, 0x5b, 0xba, 0x71, 0x13, 0x2d, 0x7d, 0x07, 0x9a, 0xb2, 0x5c, 0x32, 0xbb, 0x8a, 0xcc, 0xae, + 0xf3, 0x62, 0xd9, 0x5b, 0x39, 0xf1, 0x6a, 0x89, 0x2c, 0xa8, 0x4b, 0xe3, 0x68, 0x5f, 0x0a, 0xa0, + 0x89, 0x73, 0xb3, 0xa4, 0x8c, 0xea, 0x7f, 0x2b, 0xa3, 0x56, 0x56, 0xc6, 0x5a, 0x2d, 0xeb, 0x57, + 0xd7, 0xf2, 0x23, 0xf3, 0xe9, 0x2f, 0xbd, 0x5b, 0xf6, 0x8f, 0x1b, 0x50, 0x95, 0x07, 0x8a, 0xd6, + 0xea, 0xa9, 0x36, 0xca, 0xad, 0xd5, 0x03, 0x9d, 0x97, 0xfd, 0x9e, 0x38, 0x3c, 0x4e, 0xb9, 0x1e, + 0xfd, 0x4d, 0x05, 0x92, 0x2e, 0xa5, 0x14, 0x15, 0x46, 0x6f, 0x43, 0xed, 0x34, 0xe5, 0x02, 0x58, + 0x29, 0xbf, 0x11, 0xca, 0xa7, 0x35, 0xa5, 0x0c, 0x74, 0x17, 0xcc, 0x4f, 0xdd, 0x30, 0x94, 0xd7, + 0x6f, 0x0d, 0x5f, 0x53, 0x40, 0xe1, 0x51, 0x30, 0x19, 0x44, 0x7d, 0xa8, 0x1c, 0x53, 0x5f, 0x56, + 0xa2, 0x35, 0xbc, 0xad, 0x30, 0xc7, 0xd4, 0x57, 0x10, 0x11, 0x42, 0x9f, 0x40, 0xe7, 0x80, 0x9e, + 0x13, 0x16, 0xed, 0x79, 0x1e, 0x4d, 0x23, 0xae, 0xe7, 0xc3, 0x52, 0xd8, 0xb5, 0x90, 0xda, 0xb5, + 0x0e, 0xd7, 0xf5, 0x78, 0x6a, 0xe4, 0x0a, 0x17, 0xf5, 0xc7, 0x84, 0xa7, 0x2c, 0x92, 0x05, 0x69, + 0x63, 0x6d, 0x89, 0x8e, 0x1d, 0xb8, 0xc9, 0xe3, 0x84, 0xcc, 0x64, 0x11, 0x4c, 0x9c, 0x9b, 0x68, + 0x07, 0x9a, 0x27, 0xee, 0x9c, 0x8c, 0x23, 0xce, 0x16, 0xfa, 0xde, 0x6d, 0x47, 0x3d, 0xc9, 0xd2, + 0x87, 0x57, 0x61, 0xf4, 0x1e, 0x34, 0x3e, 0x27, 0x6c, 0xbe, 0xc7, 0xfc, 0x44, 0xdf, 0x7c, 0xcb, + 0x29, 0xbd, 0xd2, 0x79, 0x0c, 0x17, 0x28, 0xfb, 0x2f, 0x03, 0x1a, 0xf9, 0x95, 0xd1, 0x09, 0xd4, + 0xf7, 0x66, 0x33, 0x46, 0x92, 0x44, 0x65, 0x37, 0x7a, 0x5f, 0x6b, 0xf6, 0xdd, 0x97, 0x6b, 0xd6, + 0x63, 0x8b, 0x98, 0x53, 0x47, 0xef, 0xc5, 0x39, 0x09, 0x3a, 0x02, 0x73, 0xdf, 0xe5, 0xee, 0xf5, + 0x06, 0x40, 0x52, 0xa0, 0x63, 0xa8, 0x4d, 0x68, 0x1c, 0x78, 0xea, 0xa1, 0xff, 0xdf, 0x99, 0x69, + 0xb2, 0xaf, 0x28, 0x9b, 0x0d, 0x77, 0x3f, 0xc0, 0x9a, 0xc3, 0xfe, 0xdb, 0x80, 0x66, 0x21, 0x06, + 0xb4, 0x03, 0x0d, 0x61, 0xc8, 0x54, 0x8d, 0xb2, 0x16, 0x72, 0x2f, 0x2e, 0xe2, 0x22, 0x8f, 0x53, + 0x16, 0xf8, 0x41, 0xa4, 0x2f, 0xf5, 0x6a, 0x15, 0xd2, 0x1c, 0xa8, 0x0b, 0xf0, 0x88, 0xbb, 0xde, + 0x93, 0x7d, 0x12, 0x73, 0xf5, 0xf4, 0x9b, 0xb8, 0xe4, 0x11, 0x6f, 0x88, 0x56, 0x8b, 0x79, 0xad, + 0x37, 0x44, 0x91, 0xd8, 0x5f, 0x00, 0xfa, 0xb7, 0x64, 0xd1, 0xc7, 0xd0, 0xd1, 0xf6, 0xe3, 0x78, + 0xe6, 0x72, 0xa2, 0x6b, 0xf0, 0x86, 0x23, 0xbf, 0xe6, 0x13, 0x32, 0x8f, 0x43, 0x97, 0x13, 0x0d, + 0xc1, 0xeb, 0x58, 0xfb, 0x5b, 0x80, 0xd5, 0x9c, 0xde, 0xb4, 0x80, 0xec, 0xef, 0xa0, 0x55, 0x1a, + 0xee, 0x1b, 0xa7, 0xff, 0x79, 0x03, 0xd6, 0x3a, 0x2b, 0xd6, 0xfa, 0xa9, 0x7a, 0xe5, 0xce, 0x2a, + 0x8e, 0x82, 0x8d, 0x5c, 0x4f, 0x27, 0x8a, 0xa3, 0x18, 0xa4, 0xca, 0xf5, 0x07, 0x69, 0x0b, 0xaa, + 0x5f, 0xba, 0x61, 0x4a, 0xf4, 0x9f, 0x81, 0x32, 0xd0, 0x26, 0x54, 0x0e, 0xdc, 0x44, 0x7f, 0x13, + 0xc4, 0x72, 0x34, 0xba, 0xb8, 0xec, 0x1a, 0xbf, 0x5f, 0x76, 0x8d, 0x3f, 0x2f, 0xbb, 0xc6, 0xaf, + 0xcf, 0xbb, 0xc6, 0xc5, 0xf3, 0xae, 0xf1, 0xcd, 0x15, 0xe9, 0x93, 0xfc, 0xe7, 0x48, 0xae, 0xa6, + 0x35, 0xf9, 0x2b, 0xf8, 0xe0, 0x9f, 0x00, 0x00, 0x00, 0xff, 0xff, 0xa8, 0xaa, 0x48, 0xa0, 0x91, + 0x0a, 0x00, 0x00, } diff --git a/execution/execution.go b/execution/execution.go index 32ee4cf8..2fe05f13 100644 --- a/execution/execution.go +++ b/execution/execution.go @@ -15,17 +15,16 @@ package execution import ( + "context" "fmt" "runtime/debug" "sync" "time" - "context" - "github.com/hyperledger/burrow/acm" "github.com/hyperledger/burrow/acm/state" + "github.com/hyperledger/burrow/bcm" "github.com/hyperledger/burrow/binary" - bcm "github.com/hyperledger/burrow/blockchain" "github.com/hyperledger/burrow/crypto" "github.com/hyperledger/burrow/event" "github.com/hyperledger/burrow/execution/contexts" @@ -36,7 +35,6 @@ import ( "github.com/hyperledger/burrow/logging/structure" "github.com/hyperledger/burrow/txs" "github.com/hyperledger/burrow/txs/payload" - "github.com/pkg/errors" abciTypes "github.com/tendermint/tendermint/abci/types" ) @@ -83,7 +81,7 @@ type executor struct { blockExecution *exec.BlockExecution logger *logging.Logger vmOptions []func(*evm.VM) - txExecutors map[payload.Type]Context + contexts map[payload.Type]Context } var _ BatchExecutor = (*executor)(nil) @@ -92,20 +90,35 @@ var _ BatchExecutor = (*executor)(nil) func NewBatchChecker(backend ExecutorState, blockchain *bcm.Blockchain, logger *logging.Logger, options ...ExecutionOption) BatchExecutor { - return newExecutor("CheckCache", false, backend, blockchain, event.NewNoOpPublisher(), + exe := newExecutor("CheckCache", false, backend, blockchain, event.NewNoOpPublisher(), logger.WithScope("NewBatchExecutor"), options...) + + return exe.AddContext(payload.TypeGovernance, + &contexts.GovernanceContext{ + ValidatorSet: exe.blockchain.ValidatorChecker(), + StateWriter: exe.stateCache, + Logger: exe.logger, + }, + ) } func NewBatchCommitter(backend ExecutorState, blockchain *bcm.Blockchain, emitter event.Publisher, logger *logging.Logger, options ...ExecutionOption) BatchCommitter { - return newExecutor("CommitCache", true, backend, blockchain, emitter, + exe := newExecutor("CommitCache", true, backend, blockchain, emitter, logger.WithScope("NewBatchCommitter"), options...) + + return exe.AddContext(payload.TypeGovernance, + &contexts.GovernanceContext{ + ValidatorSet: exe.blockchain.ValidatorWriter(), + StateWriter: exe.stateCache, + Logger: exe.logger, + }, + ) } func newExecutor(name string, runCall bool, backend ExecutorState, blockchain *bcm.Blockchain, publisher event.Publisher, logger *logging.Logger, options ...ExecutionOption) *executor { - exe := &executor{ runCall: runCall, state: backend, @@ -121,7 +134,7 @@ func newExecutor(name string, runCall bool, backend ExecutorState, blockchain *b for _, option := range options { option(exe) } - exe.txExecutors = map[payload.Type]Context{ + exe.contexts = map[payload.Type]Context{ payload.TypeSend: &contexts.SendContext{ Tip: blockchain, StateWriter: exe.stateCache, @@ -145,15 +158,15 @@ func newExecutor(name string, runCall bool, backend ExecutorState, blockchain *b StateWriter: exe.stateCache, Logger: exe.logger, }, - payload.TypeGovernance: &contexts.GovernanceContext{ - ValidatorSet: blockchain, - StateWriter: exe.stateCache, - Logger: exe.logger, - }, } return exe } +func (exe *executor) AddContext(ty payload.Type, ctx Context) *executor { + exe.contexts[ty] = ctx + return exe +} + // If the tx is invalid, an error will be returned. // Unlike ExecBlock(), state will not be altered. func (exe *executor) Execute(txEnv *txs.Envelope) (txe *exec.TxExecution, err error) { @@ -176,7 +189,7 @@ func (exe *executor) Execute(txEnv *txs.Envelope) (txe *exec.TxExecution, err er return nil, err } - if txExecutor, ok := exe.txExecutors[txEnv.Tx.Type()]; ok { + if txExecutor, ok := exe.contexts[txEnv.Tx.Type()]; ok { // Establish new TxExecution txe := exe.blockExecution.Tx(txEnv) err = txExecutor.Execute(txe) @@ -251,15 +264,17 @@ func (exe *executor) Commit(blockHash []byte, blockTime time.Time, header *abciT } publishErr := exe.publisher.Publish(context.Background(), blockExecution, blockExecution.Tagged()) exe.logger.InfoMsg("Error publishing TxExecution", - "height", blockExecution.Height, - structure.ErrorKey, publishErr) - + "height", blockExecution.Height, structure.ErrorKey, publishErr) // Commit to our blockchain state which will checkpoint the previous app hash by saving it to the database // (we know the previous app hash is safely committed because we are about to commit the next) - err = exe.blockchain.CommitBlock(blockTime, blockHash, hash) + totalPowerChange, totalFlow, err := exe.blockchain.CommitBlock(blockTime, blockHash, hash) if err != nil { - panic(errors.Wrap(err, "could not commit block to blockchain state")) + panic(fmt.Errorf("could not commit block to blockchain state: %v", err)) } + exe.logger.InfoMsg("Committed block", + "total_validator_power", exe.blockchain.CurrentValidators().TotalPower(), + "total_validator_power_change", totalPowerChange, + "total_validator_flow", totalFlow) return hash, nil } diff --git a/execution/execution_test.go b/execution/execution_test.go index bfc4d96a..58b28ab4 100644 --- a/execution/execution_test.go +++ b/execution/execution_test.go @@ -17,16 +17,15 @@ package execution import ( "bytes" "fmt" + "runtime/debug" "strconv" "testing" "time" - "runtime/debug" - "github.com/hyperledger/burrow/acm" "github.com/hyperledger/burrow/acm/state" + "github.com/hyperledger/burrow/bcm" . "github.com/hyperledger/burrow/binary" - bcm "github.com/hyperledger/burrow/blockchain" "github.com/hyperledger/burrow/crypto" "github.com/hyperledger/burrow/event" "github.com/hyperledger/burrow/execution/errors" @@ -898,10 +897,10 @@ func TestSNativeTx(t *testing.T) { } func TestTxSequence(t *testing.T) { - state, privAccounts := makeGenesisState(3, true, 1000, 1, true, 1000) - acc0 := getAccount(state, privAccounts[0].Address()) + st, privAccounts := makeGenesisState(3, true, 1000, 1, true, 1000) + acc0 := getAccount(st, privAccounts[0].Address()) acc0PubKey := privAccounts[0].PublicKey() - acc1 := getAccount(state, privAccounts[1].Address()) + acc1 := getAccount(st, privAccounts[1].Address()) // Test a variety of sequence numbers for the tx. // The tx should only pass when i == 1. @@ -912,7 +911,7 @@ func TestTxSequence(t *testing.T) { tx.AddOutput(acc1.Address(), 1) txEnv := txs.Enclose(testChainID, tx) require.NoError(t, txEnv.Sign(privAccounts[0])) - stateCopy, err := state.Copy(dbm.NewMemDB()) + stateCopy, err := st.Copy(dbm.NewMemDB()) require.NoError(t, err) err = execTxWithState(stateCopy, txEnv) if i == 1 { @@ -1033,7 +1032,7 @@ func TestNameTxs(t *testing.T) { // fail to update it as non-owner // Fast forward - for exe.blockchain.Tip.LastBlockHeight() < entry.Expires-1 { + for exe.blockchain.LastBlockHeight() < entry.Expires-1 { commitNewBlock(st, exe.blockchain) } tx, _ = payload.NewNameTx(st, testPrivAccounts[1].PublicKey(), name, data, amt, fee) @@ -1086,7 +1085,7 @@ func TestNameTxs(t *testing.T) { require.NoError(t, err) validateEntry(t, entry, name, data, testPrivAccounts[0].Address(), startingBlock+numDesiredBlocks) // Fast forward - for exe.blockchain.Tip.LastBlockHeight() < entry.Expires { + for exe.blockchain.LastBlockHeight() < entry.Expires { commitNewBlock(st, exe.blockchain) } @@ -1613,7 +1612,7 @@ func execTxWithStateNewBlock(state *State, blockchain *bcm.Blockchain, txEnv *tx } func makeGenesisState(numAccounts int, randBalance bool, minBalance uint64, numValidators int, randBonded bool, - minBonded int64) (*State, []acm.AddressableSigner) { + minBonded int64) (*State, []*acm.PrivateAccount) { testGenesisDoc, privAccounts, _ := deterministicGenesis.GenesisDoc(numAccounts, randBalance, minBalance, numValidators, randBonded, minBonded) s0, err := MakeGenesisState(dbm.NewMemDB(), testGenesisDoc) @@ -1625,7 +1624,10 @@ func makeGenesisState(numAccounts int, randBalance bool, minBalance uint64, numV } func getAccount(accountGetter state.AccountGetter, address crypto.Address) *acm.MutableAccount { - acc, _ := state.GetMutableAccount(accountGetter, address) + acc, err := state.GetMutableAccount(accountGetter, address) + if err != nil { + panic(err) + } return acc } @@ -1658,7 +1660,7 @@ func execTxWaitAccountCall(t *testing.T, exe *testExecutor, txEnv *txs.Envelope, } _, err = exe.Commit([]byte("Blocky McHash"), time.Now(), nil) require.NoError(t, err) - err = exe.blockchain.CommitBlock(time.Time{}, nil, nil) + _, _, err = exe.blockchain.CommitBlock(time.Time{}, nil, nil) require.NoError(t, err) for _, ev := range evs.TaggedEvents().Filter(qry) { @@ -1725,7 +1727,7 @@ func testSNativeTx(t *testing.T, expectPass bool, batchCommitter *testExecutor, acc.MutablePermissions().Base.Set(perm, true) batchCommitter.stateCache.UpdateAccount(acc) } - tx, _ := payload.NewPermissionsTx(batchCommitter.stateCache, users[0].PublicKey(), snativeArgs) + tx, _ := payload.NewPermsTx(batchCommitter.stateCache, users[0].PublicKey(), snativeArgs) txEnv := txs.Enclose(testChainID, tx) require.NoError(t, txEnv.Sign(users[0])) _, err := batchCommitter.Execute(txEnv) diff --git a/execution/simulated_call.go b/execution/simulated_call.go index d921b5e4..0274a739 100644 --- a/execution/simulated_call.go +++ b/execution/simulated_call.go @@ -6,8 +6,8 @@ import ( "github.com/hyperledger/burrow/acm" "github.com/hyperledger/burrow/acm/state" + "github.com/hyperledger/burrow/bcm" "github.com/hyperledger/burrow/binary" - "github.com/hyperledger/burrow/blockchain" "github.com/hyperledger/burrow/crypto" "github.com/hyperledger/burrow/execution/contexts" "github.com/hyperledger/burrow/execution/evm" @@ -17,7 +17,7 @@ import ( // Run a contract's code on an isolated and unpersisted state // Cannot be used to create new contracts -func CallSim(reader state.Reader, tip blockchain.TipInfo, fromAddress, address crypto.Address, data []byte, +func CallSim(reader state.Reader, tip bcm.BlockchainInfo, fromAddress, address crypto.Address, data []byte, logger *logging.Logger) (*exec.TxExecution, error) { if evm.IsRegisteredNativeContract(address.Word256()) { @@ -38,7 +38,7 @@ func CallSim(reader state.Reader, tip blockchain.TipInfo, fromAddress, address c // Run the given code on an isolated and unpersisted state // Cannot be used to create new contracts. -func CallCodeSim(reader state.Reader, tip blockchain.TipInfo, fromAddress, address crypto.Address, code, data []byte, +func CallCodeSim(reader state.Reader, tip bcm.BlockchainInfo, fromAddress, address crypto.Address, code, data []byte, logger *logging.Logger) (_ *exec.TxExecution, err error) { // This was being run against CheckTx cache, need to understand the reasoning caller := acm.ConcreteAccount{Address: fromAddress}.MutableAccount() @@ -65,7 +65,7 @@ func CallCodeSim(reader state.Reader, tip blockchain.TipInfo, fromAddress, addre return txe, nil } -func vmParams(tip blockchain.TipInfo) evm.Params { +func vmParams(tip bcm.BlockchainInfo) evm.Params { return evm.Params{ BlockHeight: tip.LastBlockHeight(), BlockHash: binary.LeftPadWord256(tip.LastBlockHash()), diff --git a/execution/transactor.go b/execution/transactor.go index 932e3129..c1a12edc 100644 --- a/execution/transactor.go +++ b/execution/transactor.go @@ -20,10 +20,11 @@ import ( "time" "github.com/hyperledger/burrow/acm" - "github.com/hyperledger/burrow/blockchain" + "github.com/hyperledger/burrow/bcm" "github.com/hyperledger/burrow/consensus/tendermint/codes" "github.com/hyperledger/burrow/crypto" "github.com/hyperledger/burrow/event" + "github.com/hyperledger/burrow/execution/errors" "github.com/hyperledger/burrow/execution/exec" "github.com/hyperledger/burrow/logging" "github.com/hyperledger/burrow/logging/structure" @@ -46,7 +47,7 @@ const ( // for a key it holds or is provided - it is down to the key-holder to manage the mutual information between transactions // concurrent within a new block window. type Transactor struct { - Tip blockchain.TipInfo + Tip bcm.BlockchainInfo Subscribable event.Subscribable MempoolAccounts *Accounts checkTxAsync func(tx tmTypes.Tx, cb func(*abciTypes.Response)) error @@ -54,7 +55,7 @@ type Transactor struct { logger *logging.Logger } -func NewTransactor(tip blockchain.TipInfo, subscribable event.Subscribable, mempoolAccounts *Accounts, +func NewTransactor(tip bcm.BlockchainInfo, subscribable event.Subscribable, mempoolAccounts *Accounts, checkTxAsync func(tx tmTypes.Tx, cb func(*abciTypes.Response)) error, txEncoder txs.Encoder, logger *logging.Logger) *Transactor { @@ -76,7 +77,7 @@ func (trans *Transactor) BroadcastTxSync(ctx context.Context, txEnv *txs.Envelop var unlock UnlockFunc txEnv, unlock, err = trans.SignTxMempool(txEnv) if err != nil { - return nil, fmt.Errorf("error signing trnasction: %v", err) + return nil, fmt.Errorf("error signing transaction: %v", err) } defer unlock() } @@ -215,8 +216,8 @@ func (trans *Transactor) CheckTxSyncRaw(txBytes []byte) (*txs.Receipt, error) { } return receipt, nil default: - return nil, fmt.Errorf("error returned by Tendermint in BroadcastTxSync "+ - "ABCI code: %v, ABCI log: %v", checkTxResponse.Code, checkTxResponse.Log) + return nil, errors.ErrorCodef(errors.Code(checkTxResponse.Code), + "error returned by Tendermint in BroadcastTxSync ABCI log: %v", checkTxResponse.Log) } } } diff --git a/execution/transactor_test.go b/execution/transactor_test.go index 5d19f06f..3e9f82e6 100644 --- a/execution/transactor_test.go +++ b/execution/transactor_test.go @@ -17,11 +17,10 @@ package execution import ( "context" "testing" - "time" "github.com/hyperledger/burrow/acm" "github.com/hyperledger/burrow/acm/state" - "github.com/hyperledger/burrow/blockchain" + "github.com/hyperledger/burrow/bcm" "github.com/hyperledger/burrow/consensus/tendermint/codes" "github.com/hyperledger/burrow/crypto" "github.com/hyperledger/burrow/event" @@ -38,7 +37,7 @@ import ( func TestTransactor_BroadcastTxSync(t *testing.T) { chainID := "TestChain" - tip := blockchain.NewTip(chainID, time.Time{}, []byte("genesis"), blockchain.NewValidators()) + bc := &bcm.Blockchain{} logger := logging.NewNoopLogger() evc := event.NewEmitter(logger) txCodec := txs.NewAminoCodec() @@ -53,7 +52,7 @@ func TestTransactor_BroadcastTxSync(t *testing.T) { err := txEnv.Sign(privAccount) require.NoError(t, err) height := uint64(35) - trans := NewTransactor(tip, evc, NewAccounts(state.NewMemoryState(), mock.NewKeyClient(privAccount), 100), + trans := NewTransactor(bc, evc, NewAccounts(state.NewMemoryState(), mock.NewKeyClient(privAccount), 100), func(tx tmTypes.Tx, cb func(*abciTypes.Response)) error { txe := exec.NewTxExecution(txEnv) txe.Height = height diff --git a/genesis/deterministic_genesis.go b/genesis/deterministic_genesis.go index 15708c9e..d7da9d22 100644 --- a/genesis/deterministic_genesis.go +++ b/genesis/deterministic_genesis.go @@ -22,10 +22,10 @@ func NewDeterministicGenesis(seed int64) *deterministicGenesis { } func (dg *deterministicGenesis) GenesisDoc(numAccounts int, randBalance bool, minBalance uint64, numValidators int, - randBonded bool, minBonded int64) (*GenesisDoc, []acm.AddressableSigner, []acm.AddressableSigner) { + randBonded bool, minBonded int64) (*GenesisDoc, []*acm.PrivateAccount, []*acm.PrivateAccount) { accounts := make([]Account, numAccounts) - privAccounts := make([]acm.AddressableSigner, numAccounts) + privAccounts := make([]*acm.PrivateAccount, numAccounts) defaultPerms := permission.DefaultAccountPermissions for i := 0; i < numAccounts; i++ { account, privAccount := dg.Account(randBalance, minBalance) @@ -39,7 +39,7 @@ func (dg *deterministicGenesis) GenesisDoc(numAccounts int, randBalance bool, mi privAccounts[i] = privAccount } validators := make([]Validator, numValidators) - privValidators := make([]acm.AddressableSigner, numValidators) + privValidators := make([]*acm.PrivateAccount, numValidators) for i := 0; i < numValidators; i++ { validator := acm.GeneratePrivateAccountFromSecret(fmt.Sprintf("val_%v", i)) privValidators[i] = validator @@ -66,7 +66,7 @@ func (dg *deterministicGenesis) GenesisDoc(numAccounts int, randBalance bool, mi } -func (dg *deterministicGenesis) Account(randBalance bool, minBalance uint64) (acm.Account, acm.AddressableSigner) { +func (dg *deterministicGenesis) Account(randBalance bool, minBalance uint64) (acm.Account, *acm.PrivateAccount) { privateKey, err := crypto.GeneratePrivateKey(dg.random, crypto.CurveTypeEd25519) if err != nil { panic(fmt.Errorf("could not generate private key deterministically")) diff --git a/genesis/genesis.go b/genesis/genesis.go index c98607e1..bfc30c2f 100644 --- a/genesis/genesis.go +++ b/genesis/genesis.go @@ -22,6 +22,7 @@ import ( "time" "github.com/hyperledger/burrow/acm" + "github.com/hyperledger/burrow/acm/validator" "github.com/hyperledger/burrow/crypto" "github.com/hyperledger/burrow/permission" ) @@ -66,6 +67,14 @@ type GenesisDoc struct { Validators []Validator } +func (genesisDoc *GenesisDoc) JSONString() string { + bs, err := genesisDoc.JSONBytes() + if err != nil { + return fmt.Sprintf("error marshalling GenesisDoc: %v", err) + } + return string(bs) +} + // JSONBytes returns the JSON canonical bytes for a given GenesisDoc or an error. func (genesisDoc *GenesisDoc) JSONBytes() ([]byte, error) { // Just in case @@ -133,12 +142,13 @@ func (genesisAccount *Account) Clone() Account { //------------------------------------------------------------ // Validator methods -func (gv *Validator) Validator() acm.Validator { - return acm.ConcreteValidator{ - Address: gv.PublicKey.Address(), +func (gv *Validator) Validator() validator.Validator { + address := gv.PublicKey.Address() + return validator.Validator{ + Address: &address, PublicKey: gv.PublicKey, Power: uint64(gv.Amount), - }.Validator() + } } // Clone clones the genesis validator @@ -175,7 +185,7 @@ func (basicAccount *BasicAccount) Clone() BasicAccount { // failure. In particular MakeGenesisDocFromAccount uses the local time as a // timestamp for the GenesisDoc. func MakeGenesisDocFromAccounts(chainName string, salt []byte, genesisTime time.Time, accounts map[string]acm.Account, - validators map[string]acm.Validator) *GenesisDoc { + validators map[string]validator.Validator) *GenesisDoc { // Establish deterministic order of accounts by name so we obtain identical GenesisDoc // from identical input @@ -202,15 +212,15 @@ func MakeGenesisDocFromAccounts(chainName string, salt []byte, genesisTime time. genesisValidators = append(genesisValidators, Validator{ Name: name, BasicAccount: BasicAccount{ - Address: val.Address(), - PublicKey: val.PublicKey(), - Amount: val.Power(), + Address: *val.Address, + PublicKey: val.PublicKey, + Amount: val.Power, }, // Simpler to just do this by convention UnbondTo: []BasicAccount{ { - Amount: val.Power(), - Address: val.Address(), + Amount: val.Power, + Address: *val.Address, }, }, }) diff --git a/genesis/genesis_test.go b/genesis/genesis_test.go index 640bf18d..cfeb6f41 100644 --- a/genesis/genesis_test.go +++ b/genesis/genesis_test.go @@ -6,6 +6,7 @@ import ( "time" "github.com/hyperledger/burrow/acm" + "github.com/hyperledger/burrow/acm/validator" "github.com/hyperledger/burrow/permission" "github.com/stretchr/testify/assert" ) @@ -41,10 +42,11 @@ func accountMap(names ...string) map[string]acm.Account { return accounts } -func validatorMap(names ...string) map[string]acm.Validator { - validators := make(map[string]acm.Validator, len(names)) +func validatorMap(names ...string) map[string]validator.Validator { + validators := make(map[string]validator.Validator, len(names)) for _, name := range names { - validators[name] = acm.AsValidator(accountFromName(name)) + acc := accountFromName(name) + validators[name] = validator.FromAccount(acc, acc.Balance()) } return validators } diff --git a/genesis/spec/genesis_spec.go b/genesis/spec/genesis_spec.go index de96d9a7..6990afa1 100644 --- a/genesis/spec/genesis_spec.go +++ b/genesis/spec/genesis_spec.go @@ -7,6 +7,7 @@ import ( "fmt" "time" + "github.com/hyperledger/burrow/acm/balance" "github.com/hyperledger/burrow/genesis" "github.com/hyperledger/burrow/keys" "github.com/hyperledger/burrow/permission" @@ -68,9 +69,8 @@ func (gs *GenesisSpec) GenesisDoc(keyClient keys.KeyClient, generateNodeKeys boo templateAccounts := gs.Accounts if len(gs.Accounts) == 0 { - Power := DefaultPower templateAccounts = append(templateAccounts, TemplateAccount{ - Power: &Power, + Amounts: balance.New().Power(DefaultPower), }) } @@ -80,8 +80,8 @@ func (gs *GenesisSpec) GenesisDoc(keyClient keys.KeyClient, generateNodeKeys boo return nil, fmt.Errorf("could not create Account from template: %v", err) } genesisDoc.Accounts = append(genesisDoc.Accounts, *account) - // Create a corresponding validator - if templateAccount.Power != nil { + + if templateAccount.Balances().HasPower() { // Note this does not modify the input template templateAccount.Address = &account.Address validator, err := templateAccount.Validator(keyClient, i, generateNodeKeys) diff --git a/genesis/spec/genesis_spec_test.go b/genesis/spec/genesis_spec_test.go index 98665055..1d52df39 100644 --- a/genesis/spec/genesis_spec_test.go +++ b/genesis/spec/genesis_spec_test.go @@ -3,6 +3,7 @@ package spec import ( "testing" + "github.com/hyperledger/burrow/acm/balance" "github.com/hyperledger/burrow/crypto" "github.com/hyperledger/burrow/keys/mock" "github.com/hyperledger/burrow/permission" @@ -17,7 +18,7 @@ func TestGenesisSpec_GenesisDoc(t *testing.T) { amtBonded := uint64(100) genesisSpec := GenesisSpec{ Accounts: []TemplateAccount{{ - Power: &amtBonded, + Amounts: balance.New().Power(amtBonded), }}, } @@ -46,7 +47,7 @@ func TestGenesisSpec_GenesisDoc(t *testing.T) { Address: &address, }, { - Amount: &amt, + Amounts: balance.New().Native(amt), Permissions: []string{permission.CreateAccountString, permission.CallString}, }}, } diff --git a/genesis/spec/presets.go b/genesis/spec/presets.go index 3025d98c..223ae0f4 100644 --- a/genesis/spec/presets.go +++ b/genesis/spec/presets.go @@ -3,6 +3,7 @@ package spec import ( "sort" + "github.com/hyperledger/burrow/acm/balance" "github.com/hyperledger/burrow/permission" ) @@ -16,8 +17,7 @@ func FullAccount(name string) GenesisSpec { return GenesisSpec{ Accounts: []TemplateAccount{{ Name: name, - Amount: &amount, - Power: &Power, + Amounts: balance.New().Native(amount).Power(Power), Permissions: []string{permission.AllString}, }, }, @@ -30,7 +30,7 @@ func RootAccount(name string) GenesisSpec { return GenesisSpec{ Accounts: []TemplateAccount{{ Name: name, - Amount: &amount, + Amounts: balance.New().Native(amount), Permissions: []string{permission.AllString}, }, }, @@ -42,8 +42,8 @@ func ParticipantAccount(name string) GenesisSpec { amount := uint64(9999999999) return GenesisSpec{ Accounts: []TemplateAccount{{ - Name: name, - Amount: &amount, + Name: name, + Amounts: balance.New().Native(amount), Permissions: []string{permission.SendString, permission.CallString, permission.NameString, permission.HasRoleString}, }}, @@ -55,8 +55,8 @@ func DeveloperAccount(name string) GenesisSpec { amount := uint64(9999999999) return GenesisSpec{ Accounts: []TemplateAccount{{ - Name: name, - Amount: &amount, + Name: name, + Amounts: balance.New().Native(amount), Permissions: []string{permission.SendString, permission.CallString, permission.CreateContractString, permission.CreateAccountString, permission.NameString, permission.HasRoleString, permission.RemoveRoleString}, @@ -71,8 +71,7 @@ func ValidatorAccount(name string) GenesisSpec { return GenesisSpec{ Accounts: []TemplateAccount{{ Name: name, - Amount: &amount, - Power: &Power, + Amounts: balance.New().Native(amount).Power(Power), Permissions: []string{permission.BondString}, }}, } @@ -146,8 +145,7 @@ func mergeAccount(base, override TemplateAccount) TemplateAccount { base.Name = override.Name } - base.Amount = addUint64Pointers(base.Amount, override.Amount) - base.Power = addUint64Pointers(base.Power, override.Power) + base.Amounts = base.Balances().Sum(override.Balances()) base.Permissions = mergeStrings(base.Permissions, override.Permissions) base.Roles = mergeStrings(base.Roles, override.Roles) diff --git a/genesis/spec/presets_test.go b/genesis/spec/presets_test.go index 762e397b..1c11015f 100644 --- a/genesis/spec/presets_test.go +++ b/genesis/spec/presets_test.go @@ -3,6 +3,7 @@ package spec import ( "testing" + "github.com/hyperledger/burrow/acm/balance" "github.com/hyperledger/burrow/keys/mock" "github.com/hyperledger/burrow/permission" "github.com/stretchr/testify/assert" @@ -43,7 +44,7 @@ func TestMergeGenesisSpecsRepeatedAccounts(t *testing.T) { Accounts: []TemplateAccount{ { Name: name1, - Amount: &amt1, + Amounts: balance.New().Native(amt1), Permissions: []string{permission.SendString, permission.CreateAccountString, permission.HasRoleString}, Roles: []string{"fooer"}, }, @@ -53,7 +54,7 @@ func TestMergeGenesisSpecsRepeatedAccounts(t *testing.T) { Accounts: []TemplateAccount{ { Name: name1, - Amount: &amt2, + Amounts: balance.New().Native(amt2), Permissions: []string{permission.SendString, permission.CreateAccountString}, Roles: []string{"barer"}, }, @@ -62,8 +63,8 @@ func TestMergeGenesisSpecsRepeatedAccounts(t *testing.T) { gs3 := GenesisSpec{ Accounts: []TemplateAccount{ { - Name: name3, - Amount: &amt3, + Name: name3, + Amounts: balance.New().Native(amt3), }, }, } @@ -77,7 +78,7 @@ func TestMergeGenesisSpecsRepeatedAccounts(t *testing.T) { Accounts: []TemplateAccount{ { Name: name1, - Amount: &amtExpected, + Amounts: balance.New().Native(amtExpected), Permissions: []string{permission.CreateAccountString, permission.HasRoleString, permission.SendString}, Roles: []string{"barer", "fooer"}, }, diff --git a/genesis/spec/spec.pb.go b/genesis/spec/spec.pb.go index 9d568bfd..ffaaef3a 100644 --- a/genesis/spec/spec.pb.go +++ b/genesis/spec/spec.pb.go @@ -18,6 +18,7 @@ import fmt "fmt" import math "math" import _ "github.com/gogo/protobuf/gogoproto" import crypto "github.com/hyperledger/burrow/crypto" +import balance "github.com/hyperledger/burrow/acm/balance" import github_com_hyperledger_burrow_crypto "github.com/hyperledger/burrow/crypto" @@ -36,14 +37,13 @@ var _ = math.Inf const _ = proto.GoGoProtoPackageIsVersion2 // please upgrade the proto package type TemplateAccount struct { - Name string `protobuf:"bytes,1,opt,name=Name" json:"Name"` - Address *github_com_hyperledger_burrow_crypto.Address `protobuf:"bytes,2,opt,name=Address,customtype=github.com/hyperledger/burrow/crypto.Address" json:",omitempty" toml:",omitempty"` - NodeAddress *github_com_hyperledger_burrow_crypto.Address `protobuf:"bytes,3,opt,name=NodeAddress,customtype=github.com/hyperledger/burrow/crypto.Address" json:",omitempty" toml:",omitempty"` + Name string `protobuf:"bytes,1,opt,name=Name,proto3" json:"Name,omitempty"` + Address *github_com_hyperledger_burrow_crypto.Address `protobuf:"bytes,2,opt,name=Address,proto3,customtype=github.com/hyperledger/burrow/crypto.Address" json:",omitempty" toml:",omitempty"` + NodeAddress *github_com_hyperledger_burrow_crypto.Address `protobuf:"bytes,3,opt,name=NodeAddress,proto3,customtype=github.com/hyperledger/burrow/crypto.Address" json:",omitempty" toml:",omitempty"` PublicKey *crypto.PublicKey `protobuf:"bytes,4,opt,name=PublicKey" json:",omitempty" toml:",omitempty"` - Amount *uint64 `protobuf:"varint,5,opt,name=Amount" json:",omitempty" toml:",omitempty"` - Power *uint64 `protobuf:"varint,6,opt,name=Power" json:",omitempty" toml:",omitempty"` - Permissions []string `protobuf:"bytes,7,rep,name=Permissions" json:",omitempty" toml:",omitempty"` - Roles []string `protobuf:"bytes,8,rep,name=Roles" json:",omitempty" toml:",omitempty"` + Amounts []balance.Balance `protobuf:"bytes,5,rep,name=Amounts" json:",omitempty" toml:",omitempty"` + Permissions []string `protobuf:"bytes,6,rep,name=Permissions" json:",omitempty" toml:",omitempty"` + Roles []string `protobuf:"bytes,7,rep,name=Roles" json:",omitempty" toml:",omitempty"` } func (m *TemplateAccount) Reset() { *m = TemplateAccount{} } @@ -65,18 +65,11 @@ func (m *TemplateAccount) GetPublicKey() *crypto.PublicKey { return nil } -func (m *TemplateAccount) GetAmount() uint64 { - if m != nil && m.Amount != nil { - return *m.Amount - } - return 0 -} - -func (m *TemplateAccount) GetPower() uint64 { - if m != nil && m.Power != nil { - return *m.Power +func (m *TemplateAccount) GetAmounts() []balance.Balance { + if m != nil { + return m.Amounts } - return 0 + return nil } func (m *TemplateAccount) GetPermissions() []string { @@ -115,10 +108,12 @@ func (m *TemplateAccount) MarshalTo(dAtA []byte) (int, error) { _ = i var l int _ = l - dAtA[i] = 0xa - i++ - i = encodeVarintSpec(dAtA, i, uint64(len(m.Name))) - i += copy(dAtA[i:], m.Name) + if len(m.Name) > 0 { + dAtA[i] = 0xa + i++ + i = encodeVarintSpec(dAtA, i, uint64(len(m.Name))) + i += copy(dAtA[i:], m.Name) + } if m.Address != nil { dAtA[i] = 0x12 i++ @@ -149,19 +144,21 @@ func (m *TemplateAccount) MarshalTo(dAtA []byte) (int, error) { } i += n3 } - if m.Amount != nil { - dAtA[i] = 0x28 - i++ - i = encodeVarintSpec(dAtA, i, uint64(*m.Amount)) - } - if m.Power != nil { - dAtA[i] = 0x30 - i++ - i = encodeVarintSpec(dAtA, i, uint64(*m.Power)) + if len(m.Amounts) > 0 { + for _, msg := range m.Amounts { + dAtA[i] = 0x2a + i++ + i = encodeVarintSpec(dAtA, i, uint64(msg.Size())) + n, err := msg.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n + } } if len(m.Permissions) > 0 { for _, s := range m.Permissions { - dAtA[i] = 0x3a + dAtA[i] = 0x32 i++ l = len(s) for l >= 1<<7 { @@ -176,7 +173,7 @@ func (m *TemplateAccount) MarshalTo(dAtA []byte) (int, error) { } if len(m.Roles) > 0 { for _, s := range m.Roles { - dAtA[i] = 0x42 + dAtA[i] = 0x3a i++ l = len(s) for l >= 1<<7 { @@ -205,7 +202,9 @@ func (m *TemplateAccount) Size() (n int) { var l int _ = l l = len(m.Name) - n += 1 + l + sovSpec(uint64(l)) + if l > 0 { + n += 1 + l + sovSpec(uint64(l)) + } if m.Address != nil { l = m.Address.Size() n += 1 + l + sovSpec(uint64(l)) @@ -218,11 +217,11 @@ func (m *TemplateAccount) Size() (n int) { l = m.PublicKey.Size() n += 1 + l + sovSpec(uint64(l)) } - if m.Amount != nil { - n += 1 + sovSpec(uint64(*m.Amount)) - } - if m.Power != nil { - n += 1 + sovSpec(uint64(*m.Power)) + if len(m.Amounts) > 0 { + for _, e := range m.Amounts { + l = e.Size() + n += 1 + l + sovSpec(uint64(l)) + } } if len(m.Permissions) > 0 { for _, s := range m.Permissions { @@ -408,10 +407,10 @@ func (m *TemplateAccount) Unmarshal(dAtA []byte) error { } iNdEx = postIndex case 5: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field Amount", wireType) + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Amounts", wireType) } - var v uint64 + var msglen int for shift := uint(0); ; shift += 7 { if shift >= 64 { return ErrIntOverflowSpec @@ -421,33 +420,24 @@ func (m *TemplateAccount) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - v |= (uint64(b) & 0x7F) << shift + msglen |= (int(b) & 0x7F) << shift if b < 0x80 { break } } - m.Amount = &v - case 6: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field Power", wireType) + if msglen < 0 { + return ErrInvalidLengthSpec } - var v uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowSpec - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - v |= (uint64(b) & 0x7F) << shift - if b < 0x80 { - break - } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF } - m.Power = &v - case 7: + m.Amounts = append(m.Amounts, balance.Balance{}) + if err := m.Amounts[len(m.Amounts)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 6: if wireType != 2 { return fmt.Errorf("proto: wrong wireType = %d for field Permissions", wireType) } @@ -476,7 +466,7 @@ func (m *TemplateAccount) Unmarshal(dAtA []byte) error { } m.Permissions = append(m.Permissions, string(dAtA[iNdEx:postIndex])) iNdEx = postIndex - case 8: + case 7: if wireType != 2 { return fmt.Errorf("proto: wrong wireType = %d for field Roles", wireType) } @@ -635,28 +625,28 @@ func init() { proto.RegisterFile("spec.proto", fileDescriptorSpec) } func init() { golang_proto.RegisterFile("spec.proto", fileDescriptorSpec) } var fileDescriptorSpec = []byte{ - // 359 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb4, 0x92, 0x3f, 0x6f, 0xe2, 0x30, - 0x18, 0x87, 0xf1, 0x11, 0xe0, 0x30, 0x48, 0x27, 0x3c, 0x59, 0x0c, 0x49, 0xc4, 0x2d, 0xd1, 0x89, - 0x23, 0xd2, 0x6d, 0x47, 0x97, 0x12, 0xa9, 0x53, 0x25, 0x84, 0x28, 0x53, 0x37, 0x92, 0xbc, 0x0d, - 0x91, 0x62, 0x1c, 0xd9, 0x8e, 0x50, 0x3e, 0x4e, 0xbf, 0x49, 0x47, 0x46, 0xe6, 0x0e, 0x51, 0x05, - 0x43, 0xa5, 0x8e, 0xfd, 0x04, 0x55, 0x42, 0x28, 0x4c, 0x55, 0x96, 0x6e, 0xef, 0x1f, 0x3d, 0xbf, - 0xc7, 0xb2, 0x8d, 0xb1, 0x8c, 0xc1, 0x1b, 0xc5, 0x82, 0x2b, 0x4e, 0xb4, 0xbc, 0xee, 0xff, 0x0d, - 0x42, 0xb5, 0x4a, 0xdc, 0x91, 0xc7, 0x99, 0x1d, 0xf0, 0x80, 0xdb, 0xc5, 0xd2, 0x4d, 0x1e, 0x8a, - 0xae, 0x68, 0x8a, 0xea, 0x08, 0xf5, 0xbb, 0x9e, 0x48, 0x63, 0x55, 0x76, 0x83, 0x57, 0x0d, 0xff, - 0x5a, 0x00, 0x8b, 0xa3, 0xa5, 0x82, 0x89, 0xe7, 0xf1, 0x64, 0xad, 0x08, 0xc5, 0xda, 0x74, 0xc9, - 0x80, 0x22, 0x13, 0x59, 0x6d, 0x47, 0xdb, 0x66, 0x46, 0x6d, 0x5e, 0x4c, 0x08, 0xc3, 0xad, 0x89, - 0xef, 0x0b, 0x90, 0x92, 0xfe, 0x30, 0x91, 0xd5, 0x75, 0xee, 0x9e, 0x33, 0x63, 0x78, 0xe1, 0x5f, - 0xa5, 0x31, 0x88, 0x08, 0xfc, 0x00, 0x84, 0xed, 0x26, 0x42, 0xf0, 0x8d, 0x5d, 0xea, 0x4a, 0xee, - 0x2d, 0x33, 0xf0, 0x90, 0xb3, 0x50, 0x01, 0x8b, 0x55, 0xfa, 0x9e, 0x19, 0x3d, 0xc5, 0x59, 0x34, - 0x1e, 0x9c, 0x67, 0x83, 0xf9, 0xc9, 0x41, 0x12, 0xdc, 0x99, 0x72, 0x1f, 0x4e, 0xca, 0xfa, 0xf7, - 0x29, 0x2f, 0x3d, 0x64, 0x81, 0xdb, 0xb3, 0xc4, 0x8d, 0x42, 0xef, 0x16, 0x52, 0xaa, 0x99, 0xc8, - 0xea, 0xfc, 0xeb, 0x8d, 0xca, 0xcc, 0xcf, 0x85, 0xf3, 0xbb, 0x4a, 0xee, 0x39, 0x88, 0x5c, 0xe1, - 0xe6, 0x84, 0xe5, 0xf7, 0x4b, 0x1b, 0x26, 0xb2, 0xb4, 0x6a, 0x7c, 0x89, 0x90, 0xff, 0xb8, 0x31, - 0xe3, 0x1b, 0x10, 0xb4, 0x59, 0x9d, 0x3d, 0x12, 0xe4, 0x06, 0x77, 0x66, 0x20, 0x58, 0x28, 0x65, - 0xc8, 0xd7, 0x92, 0xb6, 0xcc, 0xba, 0xd5, 0xae, 0x16, 0x70, 0xc9, 0xe5, 0x27, 0x98, 0xf3, 0x08, - 0x24, 0xfd, 0x59, 0x3d, 0xe0, 0x48, 0x8c, 0xb5, 0xdd, 0xa3, 0x51, 0x73, 0xae, 0xb7, 0x7b, 0x1d, - 0xed, 0xf6, 0x3a, 0x7a, 0xd9, 0xeb, 0xe8, 0xe9, 0xa0, 0xa3, 0xed, 0x41, 0x47, 0xf7, 0x7f, 0xbe, - 0x7e, 0xc9, 0x00, 0xd6, 0x20, 0x43, 0x69, 0xe7, 0x1f, 0xfd, 0x23, 0x00, 0x00, 0xff, 0xff, 0x4b, - 0xcc, 0xe3, 0x66, 0xfb, 0x02, 0x00, 0x00, + // 367 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb4, 0x52, 0xbf, 0x6f, 0xda, 0x40, + 0x14, 0xee, 0x15, 0x03, 0xe2, 0x4c, 0xd5, 0x72, 0x93, 0xc5, 0x60, 0x5b, 0x74, 0xa8, 0x55, 0x51, + 0x5b, 0xa2, 0x53, 0x3b, 0x15, 0x4b, 0x9d, 0x22, 0x21, 0x04, 0x4c, 0xd9, 0xfc, 0xe3, 0xc5, 0x58, + 0xf2, 0xf9, 0xac, 0xbb, 0xb3, 0x22, 0xff, 0x67, 0x19, 0x33, 0x32, 0x66, 0xce, 0x60, 0x45, 0xb0, + 0x65, 0xcc, 0x5f, 0x10, 0x61, 0xe3, 0xc0, 0x14, 0x79, 0xc9, 0x74, 0xdf, 0x77, 0x4f, 0xdf, 0xf7, + 0x3d, 0xbd, 0xf7, 0x30, 0x16, 0x19, 0x04, 0x76, 0xc6, 0x99, 0x64, 0x44, 0x39, 0xe2, 0xf1, 0xaf, + 0x28, 0x96, 0xdb, 0xdc, 0xb7, 0x03, 0x46, 0x9d, 0x88, 0x45, 0xcc, 0xa9, 0x8a, 0x7e, 0x7e, 0x53, + 0xb1, 0x8a, 0x54, 0xa8, 0x16, 0x8d, 0x87, 0x01, 0x2f, 0x32, 0xd9, 0xb0, 0x2f, 0xbe, 0x97, 0x78, + 0x69, 0x00, 0x35, 0x9d, 0xdc, 0x29, 0xf8, 0xeb, 0x06, 0x68, 0x96, 0x78, 0x12, 0xe6, 0x41, 0xc0, + 0xf2, 0x54, 0x12, 0x82, 0x95, 0x85, 0x47, 0x41, 0x43, 0x26, 0xb2, 0x06, 0xab, 0x0a, 0x13, 0x8a, + 0xfb, 0xf3, 0x30, 0xe4, 0x20, 0x84, 0xf6, 0xd9, 0x44, 0xd6, 0xd0, 0x5d, 0x3f, 0x96, 0xc6, 0xf4, + 0xa2, 0x91, 0x6d, 0x91, 0x01, 0x4f, 0x20, 0x8c, 0x80, 0x3b, 0x7e, 0xce, 0x39, 0xbb, 0x75, 0x4e, + 0xb9, 0x27, 0xdd, 0x73, 0x69, 0xe0, 0x29, 0xa3, 0xb1, 0x04, 0x9a, 0xc9, 0xe2, 0xa5, 0x34, 0x46, + 0x92, 0xd1, 0xe4, 0xef, 0xe4, 0xfc, 0x37, 0x59, 0x35, 0x19, 0x24, 0xc7, 0xea, 0x82, 0x85, 0xd0, + 0x44, 0x76, 0x3e, 0x2e, 0xf2, 0x32, 0x87, 0x6c, 0xf0, 0x60, 0x99, 0xfb, 0x49, 0x1c, 0x5c, 0x41, + 0xa1, 0x29, 0x26, 0xb2, 0xd4, 0xd9, 0xc8, 0x3e, 0x79, 0xbe, 0x15, 0xdc, 0xef, 0x6d, 0x7c, 0xcf, + 0x46, 0x64, 0x8d, 0xfb, 0x73, 0x7a, 0x9c, 0xac, 0xd0, 0xba, 0x66, 0xc7, 0x52, 0x67, 0xdf, 0xec, + 0x66, 0x09, 0x6e, 0xfd, 0xba, 0x3f, 0x76, 0xa5, 0xf1, 0xa9, 0xdd, 0x84, 0x6a, 0x27, 0xf2, 0x1f, + 0xab, 0x4b, 0xe0, 0x34, 0x16, 0x22, 0x66, 0xa9, 0xd0, 0x7a, 0x66, 0xc7, 0x1a, 0xb4, 0xeb, 0xec, + 0x52, 0x47, 0xfe, 0xe0, 0xee, 0x8a, 0x25, 0x20, 0xb4, 0x7e, 0x7b, 0x83, 0x5a, 0xe1, 0xfe, 0xdb, + 0xed, 0x75, 0xf4, 0xb0, 0xd7, 0xd1, 0xd3, 0x5e, 0x47, 0xf7, 0x07, 0x1d, 0xed, 0x0e, 0x3a, 0xba, + 0xfe, 0xf9, 0xfe, 0x82, 0x22, 0x48, 0x41, 0xc4, 0xc2, 0x39, 0x1e, 0xb2, 0xdf, 0xab, 0x6e, 0xf0, + 0xf7, 0x6b, 0x00, 0x00, 0x00, 0xff, 0xff, 0x8b, 0xc3, 0x66, 0xb6, 0xe3, 0x02, 0x00, 0x00, } diff --git a/genesis/spec/template_account.go b/genesis/spec/template_account.go index b4ce1fa4..152a8097 100644 --- a/genesis/spec/template_account.go +++ b/genesis/spec/template_account.go @@ -3,6 +3,7 @@ package spec import ( "fmt" + "github.com/hyperledger/burrow/acm/balance" "github.com/hyperledger/burrow/crypto" "github.com/hyperledger/burrow/genesis" "github.com/hyperledger/burrow/keys" @@ -24,11 +25,7 @@ func (ta TemplateAccount) Validator(keyClient keys.KeyClient, index int, generat } ta.NodeAddress = &address } - if ta.Power == nil { - gv.Amount = DefaultPower - } else { - gv.Amount = *ta.Power - } + gv.Amount = ta.Balances().GetPower(DefaultPower) if ta.Name == "" { gv.Name = accountNameFromIndex(index) } else { @@ -62,11 +59,7 @@ func (ta TemplateAccount) GenesisAccount(keyClient keys.KeyClient, index int) (* if err != nil { return nil, err } - if ta.Amount == nil { - ga.Amount = DefaultAmount - } else { - ga.Amount = *ta.Amount - } + ga.Amount = ta.Balances().GetNative(DefaultAmount) if ta.Name == "" { ga.Name = accountNameFromIndex(index) } else { @@ -111,3 +104,7 @@ func (ta TemplateAccount) RealisePubKeyAndAddress(keyClient keys.KeyClient) (pub } return } + +func (ta TemplateAccount) Balances() balance.Balances { + return ta.Amounts +} diff --git a/governance/governance.go b/governance/governance.go index b3e56f5b..5ea2e125 100644 --- a/governance/governance.go +++ b/governance/governance.go @@ -2,6 +2,14 @@ // validators, and network forks. package governance +import ( + "github.com/hyperledger/burrow/acm/balance" + "github.com/hyperledger/burrow/crypto" + "github.com/hyperledger/burrow/genesis/spec" + "github.com/hyperledger/burrow/permission" + "github.com/hyperledger/burrow/txs/payload" +) + // TODO: // - Set validator power // - Set account amount(s) @@ -15,3 +23,33 @@ package governance // - Network administered proxies (i.e. instead of keys have password authentication for identities - allow calls to originate as if from address without key?) // Subject to: // - Less than 1/3 validator power change per block + +// Creates a GovTx that alters the validator power of id to the power passed +func AlterPowerTx(inputAddress crypto.Address, id crypto.Addressable, power uint64) *payload.GovTx { + return AlterBalanceTx(inputAddress, id, balance.New().Power(power)) +} + +func AlterBalanceTx(inputAddress crypto.Address, id crypto.Addressable, bal balance.Balances) *payload.GovTx { + publicKey := id.PublicKey() + return UpdateAccountTx(inputAddress, &spec.TemplateAccount{ + PublicKey: &publicKey, + Amounts: bal, + }) +} + +func AlterPermissionsTx(inputAddress crypto.Address, id crypto.Addressable, perms permission.PermFlag) *payload.GovTx { + address := id.Address() + return UpdateAccountTx(inputAddress, &spec.TemplateAccount{ + Address: &address, + Permissions: permission.PermFlagToStringList(perms), + }) +} + +func UpdateAccountTx(inputAddress crypto.Address, updates ...*spec.TemplateAccount) *payload.GovTx { + return &payload.GovTx{ + Inputs: []*payload.TxInput{{ + Address: inputAddress, + }}, + AccountUpdates: updates, + } +} diff --git a/governance/governance_test.go b/governance/governance_test.go new file mode 100644 index 00000000..42d4d396 --- /dev/null +++ b/governance/governance_test.go @@ -0,0 +1,23 @@ +package governance + +import ( + "testing" + + "github.com/hyperledger/burrow/acm" + "github.com/hyperledger/burrow/execution/exec" + "github.com/hyperledger/burrow/txs" + "github.com/stretchr/testify/require" +) + +func TestSerialise(t *testing.T) { + priv := acm.GeneratePrivateAccountFromSecret("hhelo") + tx := AlterPowerTx(priv.Address(), priv, 3242323) + txEnv := txs.Enclose("OOh", tx) + + txe := exec.NewTxExecution(txEnv) + bs, err := txe.Marshal() + require.NoError(t, err) + txeOut := new(exec.TxExecution) + err = txeOut.Unmarshal(bs) + require.NoError(t, err) +} diff --git a/integration/core/kernel_test.go b/integration/core/kernel_test.go index 4459af6c..3850fbc9 100644 --- a/integration/core/kernel_test.go +++ b/integration/core/kernel_test.go @@ -5,75 +5,75 @@ package core import ( "context" "fmt" - "os" "testing" "time" "github.com/hyperledger/burrow/config" - "github.com/hyperledger/burrow/consensus/tendermint/validator" + "github.com/hyperledger/burrow/consensus/tendermint" "github.com/hyperledger/burrow/core" "github.com/hyperledger/burrow/event" "github.com/hyperledger/burrow/execution/exec" "github.com/hyperledger/burrow/genesis" "github.com/hyperledger/burrow/integration" + "github.com/hyperledger/burrow/integration/rpctest" "github.com/hyperledger/burrow/keys" + "github.com/hyperledger/burrow/keys/mock" "github.com/hyperledger/burrow/logging" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - tmConfig "github.com/tendermint/tendermint/config" tmTypes "github.com/tendermint/tendermint/types" ) -const testDir = "./test_scratch/kernel_test" +var genesisDoc, privateAccounts, privateValidators = genesis.NewDeterministicGenesis(123).GenesisDoc(1, true, 1000, 1, true, 1000) func TestBootThenShutdown(t *testing.T) { - os.RemoveAll(testDir) - os.MkdirAll(testDir, 0777) - os.Chdir(testDir) - defer os.RemoveAll(testDir) - tmConf := tmConfig.DefaultConfig() + cleanup := integration.EnterTestDirectory() + defer cleanup() //logger, _, _ := lifecycle.NewStdErrLogger() logger := logging.NewNoopLogger() - genesisDoc, _, privateValidators := genesis.NewDeterministicGenesis(123).GenesisDoc(1, true, 1000, 1, true, 1000) - privValidator := validator.NewPrivValidatorMemory(privateValidators[0], privateValidators[0]) - assert.NoError(t, bootWaitBlocksShutdown(privValidator, integration.NewTestConfig(genesisDoc), tmConf, logger, nil)) + privValidator := tendermint.NewPrivValidatorMemory(privateValidators[0], privateValidators[0]) + assert.NoError(t, bootWaitBlocksShutdown(t, privValidator, integration.NewTestConfig(genesisDoc), logger, nil)) } func TestBootShutdownResume(t *testing.T) { - os.RemoveAll(testDir) - os.MkdirAll(testDir, 0777) - os.Chdir(testDir) - defer os.RemoveAll(testDir) - tmConf := tmConfig.DefaultConfig() - //logger, _, _ := lifecycle.NewStdErrLogger() + cleanup := integration.EnterTestDirectory() + defer cleanup() + //logger, _ := lifecycle.NewStdErrLogger() logger := logging.NewNoopLogger() - genesisDoc, _, privateValidators := genesis.NewDeterministicGenesis(123).GenesisDoc(1, true, 1000, 1, true, 1000) - privValidator := validator.NewPrivValidatorMemory(privateValidators[0], privateValidators[0]) + privValidator := tendermint.NewPrivValidatorMemory(privateValidators[0], privateValidators[0]) + testConfig := integration.NewTestConfig(genesisDoc) i := uint64(0) // asserts we get a consecutive run of blocks blockChecker := func(block *exec.BlockExecution) bool { - assert.Equal(t, i+1, block.Height) + if i == 0 { + // We send some synchronous transactions so catch up to latest block + i = block.Height - 1 + } + require.Equal(t, i+1, block.Height) i++ // stop every third block - return i%3 != 0 + if i%3 == 0 { + i = 0 + return false + } + return true } - testConfig := integration.NewTestConfig(genesisDoc) // First run - require.NoError(t, bootWaitBlocksShutdown(privValidator, testConfig, tmConf, logger, blockChecker)) + require.NoError(t, bootWaitBlocksShutdown(t, privValidator, testConfig, logger, blockChecker)) // Resume and check we pick up where we left off - require.NoError(t, bootWaitBlocksShutdown(privValidator, testConfig, tmConf, logger, blockChecker)) + require.NoError(t, bootWaitBlocksShutdown(t, privValidator, testConfig, logger, blockChecker)) // Resuming with mismatched genesis should fail genesisDoc.Salt = []byte("foo") - assert.Error(t, bootWaitBlocksShutdown(privValidator, testConfig, tmConf, logger, blockChecker)) + assert.Error(t, bootWaitBlocksShutdown(t, privValidator, testConfig, logger, blockChecker)) } -func bootWaitBlocksShutdown(privValidator tmTypes.PrivValidator, testConfig *config.BurrowConfig, - tmConf *tmConfig.Config, logger *logging.Logger, +func bootWaitBlocksShutdown(t testing.TB, privValidator tmTypes.PrivValidator, testConfig *config.BurrowConfig, + logger *logging.Logger, blockChecker func(block *exec.BlockExecution) (cont bool)) error { keyStore := keys.NewKeyStore(keys.DefaultKeysDir, false, logger) - keyClient := keys.NewLocalKeyClient(keyStore, logging.NewNoopLogger()) + keyClient := mock.NewKeyClient(privateAccounts...) kern, err := core.NewKernel(context.Background(), keyClient, privValidator, testConfig.GenesisDoc, testConfig.Tendermint.TendermintConfig(), @@ -89,6 +89,13 @@ func bootWaitBlocksShutdown(privValidator tmTypes.PrivValidator, testConfig *con return err } + inputAddress := privateAccounts[0].Address() + tcli := rpctest.NewTransactClient(t, testConfig.RPC.GRPC.ListenAddress) + // Generate a few transactions + for i := 0; i < 3; i++ { + rpctest.CreateContract(t, tcli, inputAddress) + } + subID := event.GenSubID() ch, err := kern.Emitter.Subscribe(context.Background(), subID, exec.QueryForBlockExecution(), 10) if err != nil { diff --git a/integration/governance/governance_test.go b/integration/governance/governance_test.go new file mode 100644 index 00000000..b188331c --- /dev/null +++ b/integration/governance/governance_test.go @@ -0,0 +1,172 @@ +// +build integration + +package governance + +import ( + "context" + "fmt" + "math/big" + "testing" + + "github.com/hyperledger/burrow/acm" + "github.com/hyperledger/burrow/acm/balance" + "github.com/hyperledger/burrow/acm/validator" + "github.com/hyperledger/burrow/crypto" + "github.com/hyperledger/burrow/execution/errors" + "github.com/hyperledger/burrow/execution/exec" + "github.com/hyperledger/burrow/governance" + "github.com/hyperledger/burrow/integration/rpctest" + "github.com/hyperledger/burrow/permission" + "github.com/hyperledger/burrow/rpc/rpcevents" + "github.com/hyperledger/burrow/rpc/rpcquery" + "github.com/hyperledger/burrow/rpc/rpctransact" + "github.com/hyperledger/burrow/txs/payload" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "github.com/tendermint/tendermint/rpc/core" +) + +func TestAlterValidators(t *testing.T) { + inputAddress := privateAccounts[0].Address() + grpcAddress := testConfigs[0].RPC.GRPC.ListenAddress + tcli := rpctest.NewTransactClient(t, grpcAddress) + qcli := rpctest.NewQueryClient(t, grpcAddress) + ecli := rpctest.NewExecutionEventsClient(t, grpcAddress) + + // Build a batch of validator alterations to make + vs := validator.NewTrimSet() + alterPower(vs, 3, 2131) + alterPower(vs, 2, 4561) + alterPower(vs, 5, 7831) + alterPower(vs, 8, 9931) + + vs.Iterate(func(id crypto.Addressable, power *big.Int) (stop bool) { + _, err := govSync(t, tcli, governance.AlterPowerTx(inputAddress, id, power.Uint64())) + require.NoError(t, err) + return + }) + + vsOut := getValidatorHistory(t, qcli) + // Include the genesis validator and compare the sets + alterPower(vs, 0, genesisDoc.Validators[0].Amount) + assertValidatorsEqual(t, vs, vsOut) + + // Remove validator from chain + txe, err := govSync(t, tcli, governance.AlterPowerTx(inputAddress, account(3), 0)) + // Mirror in our check set + alterPower(vs, 3, 0) + fmt.Println(txe.Events) + vsOut = getValidatorHistory(t, qcli) + assertValidatorsEqual(t, vs, vsOut) + + waitNBlocks(t, ecli, 3) + height := int64(kernels[4].Blockchain.LastBlockHeight()) + kernels[4].Node.ConfigureRPC() + tmVals, err := core.Validators(&height) + require.NoError(t, err) + vsOut = validator.NewTrimSet() + + for _, v := range tmVals.Validators { + publicKey, err := crypto.PublicKeyFromTendermintPubKey(v.PubKey) + require.NoError(t, err) + vsOut.AlterPower(publicKey, big.NewInt(v.VotingPower)) + } + assertValidatorsEqual(t, vs, vsOut) +} + +func TestNoRootPermission(t *testing.T) { + grpcAddress := testConfigs[0].RPC.GRPC.ListenAddress + tcli := rpctest.NewTransactClient(t, grpcAddress) + // Account does not have Root permission + inputAddress := privateAccounts[4].Address() + _, err := govSync(t, tcli, governance.AlterPowerTx(inputAddress, account(5), 3433)) + require.Error(t, err) + assert.Contains(t, err.Error(), errors.ErrorCodePermissionDenied.Error()) +} + +func TestAlterAmount(t *testing.T) { + inputAddress := privateAccounts[0].Address() + grpcAddress := testConfigs[0].RPC.GRPC.ListenAddress + tcli := rpctest.NewTransactClient(t, grpcAddress) + qcli := rpctest.NewQueryClient(t, grpcAddress) + var amount uint64 = 18889 + acc := account(5) + _, err := govSync(t, tcli, governance.AlterBalanceTx(inputAddress, acc, balance.New().Native(amount))) + require.NoError(t, err) + ca, err := qcli.GetAccount(context.Background(), &rpcquery.GetAccountParam{Address: acc.Address()}) + require.NoError(t, err) + assert.Equal(t, amount, ca.Balance) +} + +func TestAlterPermissions(t *testing.T) { + inputAddress := privateAccounts[0].Address() + grpcAddress := testConfigs[0].RPC.GRPC.ListenAddress + tcli := rpctest.NewTransactClient(t, grpcAddress) + qcli := rpctest.NewQueryClient(t, grpcAddress) + acc := account(5) + _, err := govSync(t, tcli, governance.AlterPermissionsTx(inputAddress, acc, permission.Send)) + require.NoError(t, err) + ca, err := qcli.GetAccount(context.Background(), &rpcquery.GetAccountParam{Address: acc.Address()}) + require.NoError(t, err) + assert.Equal(t, permission.AccountPermissions{ + Base: permission.BasePermissions{ + Perms: permission.Send, + SetBit: permission.Send, + }, + }, ca.Permissions) +} + +func TestCreateAccount(t *testing.T) { + inputAddress := privateAccounts[0].Address() + grpcAddress := testConfigs[0].RPC.GRPC.ListenAddress + tcli := rpctest.NewTransactClient(t, grpcAddress) + qcli := rpctest.NewQueryClient(t, grpcAddress) + var amount uint64 = 18889 + acc := acm.GeneratePrivateAccountFromSecret("we almost certainly don't exist") + _, err := govSync(t, tcli, governance.AlterBalanceTx(inputAddress, acc, balance.New().Native(amount))) + require.NoError(t, err) + ca, err := qcli.GetAccount(context.Background(), &rpcquery.GetAccountParam{Address: acc.Address()}) + require.NoError(t, err) + assert.Equal(t, amount, ca.Balance) +} + +func getValidatorHistory(t testing.TB, qcli rpcquery.QueryClient) *validator.Set { + history, err := qcli.GetValidatorSet(context.Background(), &rpcquery.GetValidatorSetParam{ + IncludeHistory: true, + }) + require.NoError(t, err) + + // Include the genesis validator and compare the sets + return validator.UnpersistSet(history.Set) +} + +func account(i int) *acm.PrivateAccount { + return rpctest.PrivateAccounts[i] +} + +func govSync(t testing.TB, cli rpctransact.TransactClient, tx *payload.GovTx) (*exec.TxExecution, error) { + return cli.BroadcastTxSync(context.Background(), &rpctransact.TxEnvelopeParam{ + Payload: tx.Any(), + }) +} + +func assertValidatorsEqual(t testing.TB, expected, actual *validator.Set) { + if !assert.True(t, expected.Equal(actual), "sets should be equal") { + fmt.Printf("Expected:\n%v\nActual:\n%v\n", expected, actual) + } +} + +func alterPower(vs *validator.Set, i int, power uint64) { + vs.AlterPower(account(i), new(big.Int).SetUint64(power)) +} + +func waitNBlocks(t testing.TB, ecli rpcevents.ExecutionEventsClient, n int) { + stream, err := ecli.GetBlocks(context.Background(), &rpcevents.BlocksRequest{ + BlockRange: rpcevents.NewBlockRange(rpcevents.LatestBound(), rpcevents.StreamBound()), + }) + defer stream.CloseSend() + for i := 0; i < n; i++ { + require.NoError(t, err) + _, err = stream.Recv() + } +} diff --git a/integration/governance/main_test.go b/integration/governance/main_test.go index 21b39516..65e338e3 100644 --- a/integration/governance/main_test.go +++ b/integration/governance/main_test.go @@ -21,28 +21,59 @@ import ( "context" "os" "testing" + "time" + "github.com/hyperledger/burrow/config" "github.com/hyperledger/burrow/core" "github.com/hyperledger/burrow/integration" - "github.com/hyperledger/burrow/integration/rpctest" + "github.com/hyperledger/burrow/logging/logconfig" + "github.com/hyperledger/burrow/permission" ) +var privateAccounts = integration.MakePrivateAccounts(10) // make keys +var genesisDoc = integration.TestGenesisDoc(privateAccounts) var _ = integration.ClaimPorts() -var inputAddress = rpctest.PrivateAccounts[0].Address() -var gene -var testConfig = integration.NewTestConfig(rpctest.GenesisDoc) -var kern *core.Kernel +var testConfigs []*config.BurrowConfig +var kernels []*core.Kernel // Needs to be in a _test.go file to be picked up func TestMain(m *testing.M) { - kern = integration.TestKernel(rpctest.PrivateAccounts, testConfig) - err := kern.Boot() + cleanup := integration.EnterTestDirectory() + defer cleanup() + testConfigs = make([]*config.BurrowConfig, len(privateAccounts)) + kernels = make([]*core.Kernel, len(privateAccounts)) + genesisDoc.Accounts[4].Permissions = permission.NewAccountPermissions(permission.Send | permission.Call) + for i, acc := range privateAccounts { + testConfig := integration.NewTestConfig(genesisDoc) + testConfigs[i] = testConfig + kernels[i] = integration.TestKernel(acc, privateAccounts, testConfigs[i], + logconfig.New().Root(func(sink *logconfig.SinkConfig) *logconfig.SinkConfig { + return sink.SetTransform(logconfig.FilterTransform(logconfig.IncludeWhenAllMatch, + "total_validator")).SetOutput(logconfig.StdoutOutput()) + })) + err := kernels[i].Boot() + if err != nil { + panic(err) + } + // Sometimes better to not shutdown as logging errors on shutdown may obscure real issue + defer func() { + kernels[i].Shutdown(context.Background()) + }() + } + time.Sleep(1 * time.Second) + for i := 0; i < len(kernels); i++ { + for j := i; j < len(kernels); j++ { + if i != j { + connectKernels(kernels[i], kernels[j]) + } + } + } + os.Exit(m.Run()) +} + +func connectKernels(k1, k2 *core.Kernel) { + err := k1.Node.Switch().DialPeerWithAddress(k2.Node.NodeInfo().NetAddress(), false) if err != nil { panic(err) } - // Sometimes better to not shutdown as logging errors on shutdown may obscure real issue - defer func() { - kern.Shutdown(context.Background()) - }() - os.Exit(m.Run()) } diff --git a/integration/governance/validators_test.go b/integration/governance/validators_test.go deleted file mode 100644 index 07b8008d..00000000 --- a/integration/governance/validators_test.go +++ /dev/null @@ -1,7 +0,0 @@ -package governance - -import "testing" - -func TestName(t *testing.T) { - -} diff --git a/integration/integration.go b/integration/integration.go index 280f8320..ae3cf0ba 100644 --- a/integration/integration.go +++ b/integration/integration.go @@ -25,27 +25,25 @@ import ( "time" "github.com/hyperledger/burrow/acm" + "github.com/hyperledger/burrow/acm/validator" "github.com/hyperledger/burrow/config" - "github.com/hyperledger/burrow/consensus/tendermint/validator" + "github.com/hyperledger/burrow/consensus/tendermint" "github.com/hyperledger/burrow/core" "github.com/hyperledger/burrow/execution/evm/sha3" "github.com/hyperledger/burrow/genesis" "github.com/hyperledger/burrow/keys/mock" "github.com/hyperledger/burrow/logging" - lConfig "github.com/hyperledger/burrow/logging/config" "github.com/hyperledger/burrow/logging/lifecycle" - "github.com/hyperledger/burrow/logging/structure" + lConfig "github.com/hyperledger/burrow/logging/logconfig" "github.com/hyperledger/burrow/permission" ) const ( - chainName = "Integration_Test_Chain" + ChainName = "Integration_Test_Chain" testDir = "./test_scratch/tm_test" ) // Enable logger output during tests -//var debugLogging = true -var debugLogging = false // Starting point for assigning range of ports for tests // Start at unprivileged port (hoping for the best) @@ -58,41 +56,25 @@ const startingPortBuckets = 1000 // Mutable port to assign to next claimant var port = uint32(startingPort) -// We use this to wrap tests -func TestKernel(privateAccounts []*acm.PrivateAccount, testConfig *config.BurrowConfig) *core.Kernel { - fmt.Println("Running with integration TestWrapper (core/integration/integration.go)...") - - os.RemoveAll(testDir) - os.MkdirAll(testDir, 0777) - os.Chdir(testDir) - defer os.RemoveAll(testDir) +var node uint64 = 0 - os.MkdirAll("config", 0777) +// We use this to wrap tests +func TestKernel(validatorAccount *acm.PrivateAccount, keysAccounts []*acm.PrivateAccount, + testConfig *config.BurrowConfig, loggingConfig *lConfig.LoggingConfig) *core.Kernel { + fmt.Println("Creating integration test Kernel...") logger := logging.NewNoopLogger() - if debugLogging { + if loggingConfig != nil { var err error // Change config as needed - logger, err = lifecycle.NewLoggerFromLoggingConfig(&lConfig.LoggingConfig{ - ExcludeTrace: false, - RootSink: lConfig.Sink(). - SetTransform(lConfig.FilterTransform(lConfig.IncludeWhenAnyMatches, - structure.ComponentKey, "Tendermint", - structure.ScopeKey, "executor.Execute\\(tx txs.Tx\\)", - )). - //AddSinks(config.Sink().SetTransform(config.FilterTransform(config.ExcludeWhenAnyMatches, "run_call", "false")). - AddSinks(lConfig.Sink().SetTransform(lConfig.PruneTransform("log_channel", "trace", "scope", "returns", "run_id", "args")). - AddSinks(lConfig.Sink().SetTransform(lConfig.SortTransform("tx_hash", "time", "message", "method")). - SetOutput(lConfig.StdoutOutput()))), - }) + logger, err = lifecycle.NewLoggerFromLoggingConfig(loggingConfig) if err != nil { panic(err) } } - validatorAccount := privateAccounts[0] - privValidator := validator.NewPrivValidatorMemory(validatorAccount, validatorAccount) - keyClient := mock.NewKeyClient(privateAccounts...) + privValidator := tendermint.NewPrivValidatorMemory(validatorAccount, validatorAccount) + keyClient := mock.NewKeyClient(keysAccounts...) kernel, err := core.NewKernel(context.Background(), keyClient, privValidator, testConfig.GenesisDoc, testConfig.Tendermint.TendermintConfig(), @@ -106,6 +88,14 @@ func TestKernel(privateAccounts []*acm.PrivateAccount, testConfig *config.Burrow return kernel } +func EnterTestDirectory() (cleanup func()) { + os.RemoveAll(testDir) + os.MkdirAll(testDir, 0777) + os.Chdir(testDir) + os.MkdirAll("config", 0777) + return func() { os.RemoveAll(testDir) } +} + func TestGenesisDoc(addressables []*acm.PrivateAccount) *genesis.GenesisDoc { accounts := make(map[string]acm.Account, len(addressables)) for i, pa := range addressables { @@ -118,9 +108,9 @@ func TestGenesisDoc(addressables []*acm.PrivateAccount) *genesis.GenesisDoc { if err != nil { panic("could not parse test genesis time") } - return genesis.MakeGenesisDocFromAccounts(chainName, nil, genesisTime, accounts, - map[string]acm.Validator{ - "genesis_validator": acm.AsValidator(accounts["user_0"]), + return genesis.MakeGenesisDocFromAccounts(ChainName, nil, genesisTime, accounts, + map[string]validator.Validator{ + "genesis_validator": validator.FromAccount(accounts["user_0"], 1<<16), }) } @@ -152,17 +142,26 @@ func GetPort() uint16 { return uint16(atomic.AddUint32(&port, 1)) } +// Gets an name based on an incrementing counter for running multiple nodes +func GetName() string { + nodeNumber := atomic.AddUint64(&node, 1) + return fmt.Sprintf("node_%03d", nodeNumber) +} + func GetLocalAddress() string { - return fmt.Sprintf("localhost:%v", GetPort()) + return fmt.Sprintf("127.0.0.1:%v", GetPort()) } func GetTCPLocalAddress() string { - return fmt.Sprintf("tcp://localhost:%v", GetPort()) + return fmt.Sprintf("tcp://127.0.0.1:%v", GetPort()) } func NewTestConfig(genesisDoc *genesis.GenesisDoc) *config.BurrowConfig { + name := GetName() cnf := config.DefaultBurrowConfig() cnf.GenesisDoc = genesisDoc + cnf.Tendermint.Moniker = name + cnf.Tendermint.TendermintRoot = fmt.Sprintf(".burrow_%s", name) cnf.Tendermint.ListenAddress = GetTCPLocalAddress() cnf.RPC.GRPC.ListenAddress = GetLocalAddress() cnf.RPC.Metrics.ListenAddress = GetTCPLocalAddress() diff --git a/integration/integration_test.go b/integration/integration_test.go new file mode 100644 index 00000000..485a5bd9 --- /dev/null +++ b/integration/integration_test.go @@ -0,0 +1,28 @@ +// Copyright 2017 Monax Industries Limited +// +// 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. + +package integration + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestNamesAndPorts(t *testing.T) { + assert.Equal(t, "node_001", GetName()) + assert.Equal(t, "node_002", GetName()) + assert.Equal(t, startingPort+1, GetPort()) + assert.Equal(t, startingPort+2, GetPort()) +} diff --git a/integration/rpcevents/main_test.go b/integration/rpcevents/main_test.go index 1a842bd9..1acbd46f 100644 --- a/integration/rpcevents/main_test.go +++ b/integration/rpcevents/main_test.go @@ -34,7 +34,9 @@ var kern *core.Kernel // Needs to be in a _test.go file to be picked up func TestMain(m *testing.M) { - kern = integration.TestKernel(rpctest.PrivateAccounts, testConfig) + cleanup := integration.EnterTestDirectory() + defer cleanup() + kern = integration.TestKernel(rpctest.PrivateAccounts[0], rpctest.PrivateAccounts, testConfig, nil) err := kern.Boot() if err != nil { panic(err) diff --git a/integration/rpcquery/main_test.go b/integration/rpcquery/main_test.go index 9f13b06b..d6e9694e 100644 --- a/integration/rpcquery/main_test.go +++ b/integration/rpcquery/main_test.go @@ -33,7 +33,9 @@ var kern *core.Kernel // Needs to be in a _test.go file to be picked up func TestMain(m *testing.M) { - kern = integration.TestKernel(rpctest.PrivateAccounts, testConfig) + cleanup := integration.EnterTestDirectory() + defer cleanup() + kern = integration.TestKernel(rpctest.PrivateAccounts[0], rpctest.PrivateAccounts, testConfig, nil) err := kern.Boot() if err != nil { panic(err) diff --git a/integration/rpctransact/main_test.go b/integration/rpctransact/main_test.go index 1f773a00..5b0d3d05 100644 --- a/integration/rpctransact/main_test.go +++ b/integration/rpctransact/main_test.go @@ -33,7 +33,9 @@ var kern *core.Kernel // Needs to be in a _test.go file to be picked up func TestMain(m *testing.M) { - kern = integration.TestKernel(rpctest.PrivateAccounts, testConfig) + cleanup := integration.EnterTestDirectory() + defer cleanup() + kern = integration.TestKernel(rpctest.PrivateAccounts[0], rpctest.PrivateAccounts, testConfig, nil) err := kern.Boot() if err != nil { panic(err) diff --git a/integration/rpctransact/transact_server_test.go b/integration/rpctransact/transact_server_test.go index 096f80b2..1132faf6 100644 --- a/integration/rpctransact/transact_server_test.go +++ b/integration/rpctransact/transact_server_test.go @@ -88,7 +88,7 @@ func TestBroadcastTxLocallySigned(t *testing.T) { func TestFormulateTx(t *testing.T) { cli := rpctest.NewTransactClient(t, testConfig.RPC.GRPC.ListenAddress) - txEnv, err := cli.FormulateTx(context.Background(), &rpctransact.PayloadParam{ + txEnv, err := cli.FormulateTx(context.Background(), &payload.Any{ CallTx: &payload.CallTx{ Input: &payload.TxInput{ Address: inputAddress, diff --git a/integration/tm/main_test.go b/integration/tm/main_test.go index 627fa6d2..44e733ab 100644 --- a/integration/tm/main_test.go +++ b/integration/tm/main_test.go @@ -41,7 +41,9 @@ var clients = map[string]tmClient.RPCClient{ // Needs to be in a _test.go file to be picked up func TestMain(m *testing.M) { - kern = integration.TestKernel(rpctest.PrivateAccounts, testConfig) + cleanup := integration.EnterTestDirectory() + defer cleanup() + kern = integration.TestKernel(rpctest.PrivateAccounts[0], rpctest.PrivateAccounts, testConfig, nil) err := kern.Boot() if err != nil { panic(err) diff --git a/logging/config/presets/instructions_test.go b/logging/config/presets/instructions_test.go deleted file mode 100644 index c8398cc5..00000000 --- a/logging/config/presets/instructions_test.go +++ /dev/null @@ -1,51 +0,0 @@ -package presets - -import ( - "testing" - - "github.com/hyperledger/burrow/logging/config" - "github.com/hyperledger/burrow/logging/loggers" - "github.com/hyperledger/burrow/logging/structure" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" -) - -func TestBuildSinkConfig(t *testing.T) { - builtSink, err := BuildSinkConfig(IncludeAny, Info, Stdout, Terminal, Down, Down, Info, Stdout, Up, Info, Stderr) - require.NoError(t, err) - expectedSink := config.Sink(). - SetTransform(config.FilterTransform(config.IncludeWhenAnyMatches, - structure.ChannelKey, structure.InfoChannelName)).SetOutput(config.StdoutOutput().SetFormat(loggers.TerminalFormat)).AddSinks( - config.Sink().SetTransform(config.FilterTransform(config.NoFilterMode, - structure.ChannelKey, structure.InfoChannelName)).SetOutput(config.StderrOutput()).AddSinks( - config.Sink().SetTransform(config.FilterTransform(config.NoFilterMode, - structure.ChannelKey, structure.InfoChannelName)).SetOutput(config.StdoutOutput()))) - - //fmt.Println(config.JSONString(expectedSink), "\n", config.JSONString(builtSink)) - assert.Equal(t, config.JSONString(expectedSink), config.JSONString(builtSink)) -} - -func TestMinimalPreset(t *testing.T) { - builtSink, err := BuildSinkConfig(Minimal, Stderr) - require.NoError(t, err) - expectedSink := config.Sink(). - AddSinks(config.Sink().SetTransform(config.PruneTransform(structure.TraceKey, structure.RunId)). - AddSinks(config.Sink().SetTransform(config.FilterTransform(config.IncludeWhenAllMatch, - structure.ChannelKey, structure.InfoChannelName)). - AddSinks(config.Sink().SetTransform(config.FilterTransform(config.ExcludeWhenAnyMatches, - structure.ComponentKey, "Tendermint", - "module", "p2p", - "module", "mempool")).SetOutput(config.StderrOutput())))) - //fmt.Println(config.TOMLString(expectedSink), "\n", config.TOMLString(builtSink)) - assert.Equal(t, config.TOMLString(expectedSink), config.TOMLString(builtSink)) -} - -func TestFileOutput(t *testing.T) { - path := "foo.log" - builtSink, err := BuildSinkConfig(Down, File, path, JSON) - require.NoError(t, err) - expectedSink := config.Sink(). - AddSinks(config.Sink().SetOutput(config.FileOutput(path).SetFormat(loggers.JSONFormat))) - //fmt.Println(config.TOMLString(expectedSink), "\n", config.TOMLString(builtSink)) - assert.Equal(t, config.TOMLString(expectedSink), config.TOMLString(builtSink)) -} diff --git a/logging/config/sort.go b/logging/config/sort.go deleted file mode 100644 index d912156b..00000000 --- a/logging/config/sort.go +++ /dev/null @@ -1 +0,0 @@ -package config diff --git a/logging/lifecycle/lifecycle.go b/logging/lifecycle/lifecycle.go index f17622e6..911525bf 100644 --- a/logging/lifecycle/lifecycle.go +++ b/logging/lifecycle/lifecycle.go @@ -21,7 +21,7 @@ import ( "time" "github.com/hyperledger/burrow/logging/adapters/stdlib" - "github.com/hyperledger/burrow/logging/config" + "github.com/hyperledger/burrow/logging/logconfig" "github.com/hyperledger/burrow/logging/loggers" "github.com/hyperledger/burrow/logging/structure" @@ -37,7 +37,7 @@ import ( // to set up their root logger and capture any other logging output. // Obtain a logger from a LoggingConfig -func NewLoggerFromLoggingConfig(loggingConfig *config.LoggingConfig) (*logging.Logger, error) { +func NewLoggerFromLoggingConfig(loggingConfig *logconfig.LoggingConfig) (*logging.Logger, error) { if loggingConfig == nil { return NewStdErrLogger() } else { @@ -61,7 +61,7 @@ func NewLoggerFromLoggingConfig(loggingConfig *config.LoggingConfig) (*logging.L // Hot swap logging config by replacing output loggers of passed InfoTraceLogger // with those built from loggingConfig -func SwapOutputLoggersFromLoggingConfig(logger *logging.Logger, loggingConfig *config.LoggingConfig) (error, channels.Channel) { +func SwapOutputLoggersFromLoggingConfig(logger *logging.Logger, loggingConfig *logconfig.LoggingConfig) (error, channels.Channel) { outputLogger, errCh, err := loggerFromLoggingConfig(loggingConfig) if err != nil { return err, channels.NewDeadChannel() @@ -99,7 +99,7 @@ func CaptureStdlibLogOutput(infoTraceLogger *logging.Logger) { } // Helpers -func loggerFromLoggingConfig(loggingConfig *config.LoggingConfig) (kitlog.Logger, channels.Channel, error) { +func loggerFromLoggingConfig(loggingConfig *logconfig.LoggingConfig) (kitlog.Logger, channels.Channel, error) { outputLogger, _, err := loggingConfig.RootSink.BuildLogger() if err != nil { return nil, nil, err diff --git a/logging/config/config.go b/logging/logconfig/config.go similarity index 84% rename from logging/config/config.go rename to logging/logconfig/config.go index 8616aeb7..d5ffd0e8 100644 --- a/logging/config/config.go +++ b/logging/logconfig/config.go @@ -1,4 +1,4 @@ -package config +package logconfig import ( "bytes" @@ -39,6 +39,20 @@ func DefaultClientLoggingConfig() *LoggingConfig { } } +func New() *LoggingConfig { + return &LoggingConfig{} +} + +func (lc *LoggingConfig) NoTrace() *LoggingConfig { + lc.ExcludeTrace = true + return lc +} + +func (lc *LoggingConfig) Root(configure func(sink *SinkConfig) *SinkConfig) *LoggingConfig { + lc.RootSink = configure(Sink()) + return lc +} + // Returns the TOML for a top-level logging config wrapped with [logging] func (lc *LoggingConfig) RootTOMLString() string { return TOMLString(LoggingConfigWrapper{lc}) diff --git a/logging/config/config_test.go b/logging/logconfig/config_test.go similarity index 97% rename from logging/config/config_test.go rename to logging/logconfig/config_test.go index 089710aa..af0c3a5e 100644 --- a/logging/config/config_test.go +++ b/logging/logconfig/config_test.go @@ -1,4 +1,4 @@ -package config +package logconfig import ( "testing" diff --git a/logging/config/filter.go b/logging/logconfig/filter.go similarity index 99% rename from logging/config/filter.go rename to logging/logconfig/filter.go index d4d4aede..a048ebc8 100644 --- a/logging/config/filter.go +++ b/logging/logconfig/filter.go @@ -1,4 +1,4 @@ -package config +package logconfig import ( "fmt" diff --git a/logging/config/filter_test.go b/logging/logconfig/filter_test.go similarity index 99% rename from logging/config/filter_test.go rename to logging/logconfig/filter_test.go index 9602fa71..967d0c0d 100644 --- a/logging/config/filter_test.go +++ b/logging/logconfig/filter_test.go @@ -1,4 +1,4 @@ -package config +package logconfig import ( "testing" diff --git a/logging/config/presets/instructions.go b/logging/logconfig/presets/instructions.go similarity index 66% rename from logging/config/presets/instructions.go rename to logging/logconfig/presets/instructions.go index 91065d2f..6bc4c4f7 100644 --- a/logging/config/presets/instructions.go +++ b/logging/logconfig/presets/instructions.go @@ -3,7 +3,7 @@ package presets import ( "fmt" - "github.com/hyperledger/burrow/logging/config" + "github.com/hyperledger/burrow/logging/logconfig" "github.com/hyperledger/burrow/logging/loggers" "github.com/hyperledger/burrow/logging/structure" ) @@ -20,7 +20,7 @@ type Instruction struct { // by mutating the sink at the top of the stack and may move the cursor or by pushing child sinks // to the stack. The builder may also return a modified ops slice whereby it may insert Instruction calls // acting as a macro or consume ops as arguments. - builder func(stack []*config.SinkConfig, args []string) ([]*config.SinkConfig, error) + builder func(stack []*logconfig.SinkConfig, args []string) ([]*logconfig.SinkConfig, error) } func (i Instruction) Name() string { @@ -48,26 +48,26 @@ var instructions = []Instruction{ { name: Up, desc: "Ascend the sink tree by travelling up the stack to the previous sink recorded on the stack", - builder: func(stack []*config.SinkConfig, args []string) ([]*config.SinkConfig, error) { + builder: func(stack []*logconfig.SinkConfig, args []string) ([]*logconfig.SinkConfig, error) { return pop(stack), nil }, }, { name: Down, desc: "Descend the sink tree by inserting a sink as a child to the current sink and adding it to the stack", - builder: func(stack []*config.SinkConfig, args []string) ([]*config.SinkConfig, error) { - return push(stack, config.Sink()), nil + builder: func(stack []*logconfig.SinkConfig, args []string) ([]*logconfig.SinkConfig, error) { + return push(stack, logconfig.Sink()), nil }, }, { name: Minimal, desc: "A generally less chatty log output, follow with output options", - builder: func(stack []*config.SinkConfig, args []string) ([]*config.SinkConfig, error) { + builder: func(stack []*logconfig.SinkConfig, args []string) ([]*logconfig.SinkConfig, error) { return push(stack, - config.Sink().SetTransform(config.PruneTransform(structure.TraceKey, structure.RunId)), - config.Sink().SetTransform(config.FilterTransform(config.IncludeWhenAllMatch, + logconfig.Sink().SetTransform(logconfig.PruneTransform(structure.TraceKey, structure.RunId)), + logconfig.Sink().SetTransform(logconfig.FilterTransform(logconfig.IncludeWhenAllMatch, structure.ChannelKey, structure.InfoChannelName)), - config.Sink().SetTransform(config.FilterTransform(config.ExcludeWhenAnyMatches, + logconfig.Sink().SetTransform(logconfig.FilterTransform(logconfig.ExcludeWhenAnyMatches, structure.ComponentKey, "Tendermint", "module", "p2p", "module", "mempool"))), nil @@ -76,17 +76,17 @@ var instructions = []Instruction{ { name: IncludeAny, desc: "Establish an 'include when any predicate matches' filter transform at this this sink", - builder: func(stack []*config.SinkConfig, args []string) ([]*config.SinkConfig, error) { + builder: func(stack []*logconfig.SinkConfig, args []string) ([]*logconfig.SinkConfig, error) { sink := peek(stack) ensureFilter(sink) - sink.Transform.FilterConfig.FilterMode = config.IncludeWhenAnyMatches + sink.Transform.FilterConfig.FilterMode = logconfig.IncludeWhenAnyMatches return stack, nil }, }, { name: Info, desc: "Add a filter predicate to match the Info logging channel", - builder: func(stack []*config.SinkConfig, args []string) ([]*config.SinkConfig, error) { + builder: func(stack []*logconfig.SinkConfig, args []string) ([]*logconfig.SinkConfig, error) { sink := peek(stack) ensureFilter(sink) sink.Transform.FilterConfig.AddPredicate(structure.ChannelKey, structure.InfoChannelName) @@ -96,27 +96,27 @@ var instructions = []Instruction{ { name: Stdout, desc: "Use Stdout output for this sink", - builder: func(stack []*config.SinkConfig, args []string) ([]*config.SinkConfig, error) { + builder: func(stack []*logconfig.SinkConfig, args []string) ([]*logconfig.SinkConfig, error) { sink := peek(stack) ensureOutput(sink) - sink.Output.OutputType = config.Stdout + sink.Output.OutputType = logconfig.Stdout return stack, nil }, }, { name: Stderr, desc: "Use Stderr output for this sink", - builder: func(stack []*config.SinkConfig, args []string) ([]*config.SinkConfig, error) { + builder: func(stack []*logconfig.SinkConfig, args []string) ([]*logconfig.SinkConfig, error) { sink := peek(stack) ensureOutput(sink) - sink.Output.OutputType = config.Stderr + sink.Output.OutputType = logconfig.Stderr return stack, nil }, }, { name: Terminal, desc: "Use the the terminal output format for this sink", - builder: func(stack []*config.SinkConfig, args []string) ([]*config.SinkConfig, error) { + builder: func(stack []*logconfig.SinkConfig, args []string) ([]*logconfig.SinkConfig, error) { sink := peek(stack) ensureOutput(sink) sink.Output.Format = loggers.TerminalFormat @@ -126,7 +126,7 @@ var instructions = []Instruction{ { name: JSON, desc: "Use the the terminal output format for this sink", - builder: func(stack []*config.SinkConfig, args []string) ([]*config.SinkConfig, error) { + builder: func(stack []*logconfig.SinkConfig, args []string) ([]*logconfig.SinkConfig, error) { sink := peek(stack) ensureOutput(sink) sink.Output.Format = loggers.JSONFormat @@ -137,11 +137,11 @@ var instructions = []Instruction{ name: File, desc: "Use the the terminal output format for this sink", nargs: 1, - builder: func(stack []*config.SinkConfig, args []string) ([]*config.SinkConfig, error) { + builder: func(stack []*logconfig.SinkConfig, args []string) ([]*logconfig.SinkConfig, error) { sink := peek(stack) ensureOutput(sink) - sink.Output.OutputType = config.File - sink.Output.FileConfig = &config.FileConfig{ + sink.Output.OutputType = logconfig.File + sink.Output.FileConfig = &logconfig.FileConfig{ Path: args[0], } return stack, nil @@ -172,8 +172,8 @@ func Describe(name string) string { return preset.desc } -func BuildSinkConfig(ops ...string) (*config.SinkConfig, error) { - stack := []*config.SinkConfig{config.Sink()} +func BuildSinkConfig(ops ...string) (*logconfig.SinkConfig, error) { + stack := []*logconfig.SinkConfig{logconfig.Sink()} var err error pos := 0 for len(ops) > 0 { @@ -199,24 +199,24 @@ func BuildSinkConfig(ops ...string) (*config.SinkConfig, error) { return stack[0], nil } -func ensureFilter(sinkConfig *config.SinkConfig) { +func ensureFilter(sinkConfig *logconfig.SinkConfig) { if sinkConfig.Transform == nil { - sinkConfig.Transform = &config.TransformConfig{} + sinkConfig.Transform = &logconfig.TransformConfig{} } if sinkConfig.Transform.FilterConfig == nil { - sinkConfig.Transform.FilterConfig = &config.FilterConfig{} + sinkConfig.Transform.FilterConfig = &logconfig.FilterConfig{} } - sinkConfig.Transform.TransformType = config.Filter + sinkConfig.Transform.TransformType = logconfig.Filter } -func ensureOutput(sinkConfig *config.SinkConfig) { +func ensureOutput(sinkConfig *logconfig.SinkConfig) { if sinkConfig.Output == nil { - sinkConfig.Output = &config.OutputConfig{} + sinkConfig.Output = &logconfig.OutputConfig{} } } // Push a path sequence of sinks onto the stack -func push(stack []*config.SinkConfig, sinkConfigs ...*config.SinkConfig) []*config.SinkConfig { +func push(stack []*logconfig.SinkConfig, sinkConfigs ...*logconfig.SinkConfig) []*logconfig.SinkConfig { for _, sinkConfig := range sinkConfigs { peek(stack).AddSinks(sinkConfig) stack = append(stack, sinkConfig) @@ -224,10 +224,10 @@ func push(stack []*config.SinkConfig, sinkConfigs ...*config.SinkConfig) []*conf return stack } -func pop(stack []*config.SinkConfig) []*config.SinkConfig { +func pop(stack []*logconfig.SinkConfig) []*logconfig.SinkConfig { return stack[:len(stack)-1] } -func peek(stack []*config.SinkConfig) *config.SinkConfig { +func peek(stack []*logconfig.SinkConfig) *logconfig.SinkConfig { return stack[len(stack)-1] } diff --git a/logging/logconfig/presets/instructions_test.go b/logging/logconfig/presets/instructions_test.go new file mode 100644 index 00000000..7cd1adb1 --- /dev/null +++ b/logging/logconfig/presets/instructions_test.go @@ -0,0 +1,51 @@ +package presets + +import ( + "testing" + + "github.com/hyperledger/burrow/logging/logconfig" + "github.com/hyperledger/burrow/logging/loggers" + "github.com/hyperledger/burrow/logging/structure" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestBuildSinkConfig(t *testing.T) { + builtSink, err := BuildSinkConfig(IncludeAny, Info, Stdout, Terminal, Down, Down, Info, Stdout, Up, Info, Stderr) + require.NoError(t, err) + expectedSink := logconfig.Sink(). + SetTransform(logconfig.FilterTransform(logconfig.IncludeWhenAnyMatches, + structure.ChannelKey, structure.InfoChannelName)).SetOutput(logconfig.StdoutOutput().SetFormat(loggers.TerminalFormat)).AddSinks( + logconfig.Sink().SetTransform(logconfig.FilterTransform(logconfig.NoFilterMode, + structure.ChannelKey, structure.InfoChannelName)).SetOutput(logconfig.StderrOutput()).AddSinks( + logconfig.Sink().SetTransform(logconfig.FilterTransform(logconfig.NoFilterMode, + structure.ChannelKey, structure.InfoChannelName)).SetOutput(logconfig.StdoutOutput()))) + + //fmt.Println(config.JSONString(expectedSink), "\n", config.JSONString(builtSink)) + assert.Equal(t, logconfig.JSONString(expectedSink), logconfig.JSONString(builtSink)) +} + +func TestMinimalPreset(t *testing.T) { + builtSink, err := BuildSinkConfig(Minimal, Stderr) + require.NoError(t, err) + expectedSink := logconfig.Sink(). + AddSinks(logconfig.Sink().SetTransform(logconfig.PruneTransform(structure.TraceKey, structure.RunId)). + AddSinks(logconfig.Sink().SetTransform(logconfig.FilterTransform(logconfig.IncludeWhenAllMatch, + structure.ChannelKey, structure.InfoChannelName)). + AddSinks(logconfig.Sink().SetTransform(logconfig.FilterTransform(logconfig.ExcludeWhenAnyMatches, + structure.ComponentKey, "Tendermint", + "module", "p2p", + "module", "mempool")).SetOutput(logconfig.StderrOutput())))) + //fmt.Println(config.TOMLString(expectedSink), "\n", config.TOMLString(builtSink)) + assert.Equal(t, logconfig.TOMLString(expectedSink), logconfig.TOMLString(builtSink)) +} + +func TestFileOutput(t *testing.T) { + path := "foo.log" + builtSink, err := BuildSinkConfig(Down, File, path, JSON) + require.NoError(t, err) + expectedSink := logconfig.Sink(). + AddSinks(logconfig.Sink().SetOutput(logconfig.FileOutput(path).SetFormat(loggers.JSONFormat))) + //fmt.Println(config.TOMLString(expectedSink), "\n", config.TOMLString(builtSink)) + assert.Equal(t, logconfig.TOMLString(expectedSink), logconfig.TOMLString(builtSink)) +} diff --git a/logging/config/sinks.go b/logging/logconfig/sinks.go similarity index 97% rename from logging/config/sinks.go rename to logging/logconfig/sinks.go index aa30a69e..e323fdab 100644 --- a/logging/config/sinks.go +++ b/logging/logconfig/sinks.go @@ -1,4 +1,4 @@ -package config +package logconfig import ( "fmt" @@ -236,14 +236,17 @@ func PruneTransform(keys ...string) *TransformConfig { } } -func FilterTransform(fmode filterMode, keyvalueRegexes ...string) *TransformConfig { - length := len(keyvalueRegexes) / 2 +func FilterTransform(fmode filterMode, keyValueRegexes ...string) *TransformConfig { + if len(keyValueRegexes)%2 == 1 { + keyValueRegexes = append(keyValueRegexes, "") + } + length := len(keyValueRegexes) / 2 predicates := make([]*KeyValuePredicateConfig, length) for i := 0; i < length; i++ { kv := i * 2 predicates[i] = &KeyValuePredicateConfig{ - KeyRegex: keyvalueRegexes[kv], - ValueRegex: keyvalueRegexes[kv+1], + KeyRegex: keyValueRegexes[kv], + ValueRegex: keyValueRegexes[kv+1], } } return &TransformConfig{ diff --git a/logging/config/sinks_test.go b/logging/logconfig/sinks_test.go similarity index 99% rename from logging/config/sinks_test.go rename to logging/logconfig/sinks_test.go index ba722a9d..8eba2628 100644 --- a/logging/config/sinks_test.go +++ b/logging/logconfig/sinks_test.go @@ -1,4 +1,4 @@ -package config +package logconfig import ( "encoding/json" diff --git a/logging/logconfig/sort.go b/logging/logconfig/sort.go new file mode 100644 index 00000000..6b6aa674 --- /dev/null +++ b/logging/logconfig/sort.go @@ -0,0 +1 @@ +package logconfig diff --git a/logging/loggers/burrow_format_logger.go b/logging/loggers/burrow_format_logger.go index f32d0933..1a8070bf 100644 --- a/logging/loggers/burrow_format_logger.go +++ b/logging/loggers/burrow_format_logger.go @@ -20,6 +20,7 @@ import ( kitlog "github.com/go-kit/kit/log" "github.com/hyperledger/burrow/logging/structure" + "github.com/tmthrgd/go-hex" ) // Logger that implements some formatting conventions for burrow and burrow-client @@ -48,7 +49,7 @@ func (bfl *burrowFormatLogger) Log(keyvals ...interface{}) error { case fmt.Stringer: value = v.String() case []byte: - value = fmt.Sprintf("%X", v) + value = hex.EncodeUpperToString(v) case time.Time: value = v.Format(time.RFC3339Nano) } diff --git a/permission/account_permissions.go b/permission/account_permissions.go index 6de0a443..fdc30427 100644 --- a/permission/account_permissions.go +++ b/permission/account_permissions.go @@ -2,6 +2,19 @@ package permission import "github.com/hyperledger/burrow/binary" +func NewAccountPermissions(pss ...PermFlag) AccountPermissions { + var perms PermFlag + for _, ps := range pss { + perms |= ps + } + return AccountPermissions{ + Base: BasePermissions{ + Perms: perms, + SetBit: perms, + }, + } +} + // Returns true if the role is found func (ap AccountPermissions) HasRole(role string) bool { role = string(binary.RightPadBytes([]byte(role), 32)) diff --git a/permission/util.go b/permission/util.go index 6f4ba1eb..0436f939 100644 --- a/permission/util.go +++ b/permission/util.go @@ -15,7 +15,6 @@ package permission import ( - "fmt" "strings" ) @@ -83,40 +82,28 @@ func PermFlagFromStringList(permissions []string) (PermFlag, error) { // Builds a list of set permissions from a BasePermission by creating a list of permissions strings // from the resultant permissions of basePermissions -func BasePermissionsToStringList(basePermissions BasePermissions) ([]string, error) { +func BasePermissionsToStringList(basePermissions BasePermissions) []string { return PermFlagToStringList(basePermissions.ResultantPerms()) } // Creates a list of individual permission flag strings from a possibly composite PermFlag // by projecting out each bit and adding its permission string if it is set -func PermFlagToStringList(permFlag PermFlag) ([]string, error) { +func PermFlagToStringList(permFlag PermFlag) []string { permStrings := make([]string, 0, NumPermissions) - if permFlag > AllPermFlags { - return nil, fmt.Errorf("resultant permission 0b%b is invalid: has permission flag set above top flag 0b%b", - permFlag, TopPermFlag) - } for i := uint(0); i < NumPermissions; i++ { permFlag := permFlag & (1 << i) if permFlag > 0 { permStrings = append(permStrings, permFlag.String()) } } - return permStrings, nil + return permStrings } // Generates a human readable string from the resultant permissions of basePermission func BasePermissionsString(basePermissions BasePermissions) string { - permStrings, err := BasePermissionsToStringList(basePermissions) - if err != nil { - return UnknownString - } - return strings.Join(permStrings, " | ") + return strings.Join(BasePermissionsToStringList(basePermissions), " | ") } func String(permFlag PermFlag) string { - permStrings, err := PermFlagToStringList(permFlag) - if err != nil { - return UnknownString - } - return strings.Join(permStrings, " | ") + return strings.Join(PermFlagToStringList(permFlag), " | ") } diff --git a/permission/util_test.go b/permission/util_test.go index 10553612..86f0ed62 100644 --- a/permission/util_test.go +++ b/permission/util_test.go @@ -25,17 +25,15 @@ func TestBasePermissionsFromStringList(t *testing.T) { } func TestBasePermissionsToStringList(t *testing.T) { - permStrings, err := BasePermissionsToStringList(allSetBasePermission(Root | HasRole | SetBase | Call)) - require.NoError(t, err) + permStrings := BasePermissionsToStringList(allSetBasePermission(Root | HasRole | SetBase | Call)) assert.Equal(t, []string{"root", "call", "setBase", "hasRole"}, permStrings) - permStrings, err = BasePermissionsToStringList(allSetBasePermission(AllPermFlags)) - require.NoError(t, err) + permStrings = BasePermissionsToStringList(allSetBasePermission(AllPermFlags)) assert.Equal(t, []string{"root", "send", "call", "createContract", "createAccount", "bond", "name", "hasBase", "setBase", "unsetBase", "setGlobal", "hasRole", "addRole", "removeRole"}, permStrings) - permStrings, err = BasePermissionsToStringList(allSetBasePermission(AllPermFlags + 1)) - assert.Error(t, err) + permStrings = BasePermissionsToStringList(allSetBasePermission(AllPermFlags + 1)) + assert.Equal(t, []string{}, permStrings) } func TestBasePermissionsString(t *testing.T) { diff --git a/protobuf/acm.proto b/protobuf/acm.proto index 8a52a277..1fef3bd9 100644 --- a/protobuf/acm.proto +++ b/protobuf/acm.proto @@ -9,15 +9,10 @@ import "github.com/gogo/protobuf/gogoproto/gogo.proto"; import "permission.proto"; import "crypto.proto"; -// Enable custom Marshal method. option (gogoproto.marshaler_all) = true; -// Enable custom Unmarshal method. option (gogoproto.unmarshaler_all) = true; -// Enable custom Size method (Required by Marshal and Unmarshal). option (gogoproto.sizer_all) = true; -// Enable registration with golang/protobuf for the grpc-gateway. option (gogoproto.goproto_registration) = true; -// Enable generation of XXX_MessageName methods for grpc-go/status. option (gogoproto.messagename_all) = true; message ConcreteAccount { @@ -28,4 +23,4 @@ message ConcreteAccount { uint64 Balance = 4; bytes Code = 5 [(gogoproto.customtype) = "Bytecode", (gogoproto.nullable) = false]; permission.AccountPermissions Permissions = 6 [(gogoproto.nullable) = false]; -} \ No newline at end of file +} diff --git a/protobuf/balance.proto b/protobuf/balance.proto new file mode 100644 index 00000000..ea71f6c4 --- /dev/null +++ b/protobuf/balance.proto @@ -0,0 +1,20 @@ +// Needed to proto2 rather than proto3 to get pointer field for PermArg +syntax = 'proto3'; + +option go_package = "github.com/hyperledger/burrow/acm/balance"; + +import "github.com/gogo/protobuf/gogoproto/gogo.proto"; + +package balance; + +option (gogoproto.marshaler_all) = true; +option (gogoproto.unmarshaler_all) = true; +option (gogoproto.sizer_all) = true; +option (gogoproto.goproto_registration) = true; +option (gogoproto.messagename_all) = true; + +message Balance { + option (gogoproto.goproto_stringer) = false; + uint32 Type = 1 [(gogoproto.casttype) = "Type"]; + uint64 Amount = 2; +} \ No newline at end of file diff --git a/protobuf/exec.proto b/protobuf/exec.proto index 172f540b..fde24149 100644 --- a/protobuf/exec.proto +++ b/protobuf/exec.proto @@ -5,7 +5,7 @@ package exec; option go_package = "github.com/hyperledger/burrow/execution/exec"; import "github.com/gogo/protobuf/gogoproto/gogo.proto"; -import "github.com/tendermint/tendermint/abci/types/types.proto"; +//import "github.com/tendermint/tendermint/abci/types/types.proto"; import "errors.proto"; import "names.proto"; diff --git a/protobuf/payload.proto b/protobuf/payload.proto index 1e75fdf4..55938021 100644 --- a/protobuf/payload.proto +++ b/protobuf/payload.proto @@ -20,12 +20,14 @@ option (gogoproto.goproto_registration) = true; // Enable generation of XXX_MessageName methods for grpc-go/status. option (gogoproto.messagename_all) = true; -message AnyPayload { +message Any { CallTx CallTx = 1; SendTx SendTx = 2; NameTx NameTx = 3; - PermissionsTx PermissionsTx = 4; - GovernanceTx GovernanceTx = 5; + PermsTx PermsTx = 4; + GovTx GovTx = 5; + BondTx BondTx = 6; + UnbondTx UnbondTx = 7; } // An input to a transaction that may carry an Amount as a charge and whose sequence number must be one greater than @@ -76,7 +78,7 @@ message SendTx { } // An update to the on-chain permissions -message PermissionsTx { +message PermsTx { option (gogoproto.goproto_stringer) = false; // The permission moderator TxInput Input = 1; @@ -114,7 +116,7 @@ message UnbondTx { uint64 Height = 3; } -message GovernanceTx { +message GovTx { option (gogoproto.goproto_stringer) = false; option (gogoproto.goproto_getters) = false; diff --git a/protobuf/rpcquery.proto b/protobuf/rpcquery.proto index bbb51225..fc8b6626 100644 --- a/protobuf/rpcquery.proto +++ b/protobuf/rpcquery.proto @@ -8,6 +8,7 @@ import "github.com/gogo/protobuf/gogoproto/gogo.proto"; import "names.proto"; import "acm.proto"; +import "validator.proto"; option (gogoproto.marshaler_all) = true; option (gogoproto.unmarshaler_all) = true; @@ -20,6 +21,7 @@ service Query { rpc ListAccounts (ListAccountsParam) returns (stream acm.ConcreteAccount); rpc GetName (GetNameParam) returns (names.Entry); rpc ListNames (ListNamesParam) returns (stream names.Entry); + rpc GetValidatorSet (GetValidatorSetParam) returns (ValidatorSet); } message GetAccountParam { @@ -38,3 +40,16 @@ message ListNamesParam { string Query = 1; } +message GetValidatorSetParam { + bool IncludeHistory = 1; +} + +message ValidatorSet { + uint64 height = 1; + repeated validator.Validator Set = 2; + repeated ValidatorSetDeltas History = 3; +} + +message ValidatorSetDeltas { + repeated validator.Validator Validators = 2; +} \ No newline at end of file diff --git a/protobuf/rpctransact.proto b/protobuf/rpctransact.proto index b2753a17..64b77821 100644 --- a/protobuf/rpctransact.proto +++ b/protobuf/rpctransact.proto @@ -32,7 +32,7 @@ service Transact { // Sign transaction server-side rpc SignTx (TxEnvelopeParam) returns (TxEnvelope); // Formulate a transaction from a Payload and retrun the envelop with the Tx bytes ready to sign - rpc FormulateTx (PayloadParam) returns (TxEnvelope); + rpc FormulateTx (payload.Any) returns (TxEnvelope); // Formulate and sign a CallTx transaction signed server-side and wait for it to be included in a block, retrieving response rpc CallTxSync (payload.CallTx) returns (exec.TxExecution); @@ -61,12 +61,6 @@ message CallCodeParam { bytes Data = 3; } -message PayloadParam { - payload.CallTx CallTx = 1; - payload.SendTx SendTx = 2; - payload.NameTx NameTx = 3; -} - message TxEnvelope { txs.Envelope Envelope = 1 [(gogoproto.customtype) = "github.com/hyperledger/burrow/txs.Envelope"]; } @@ -75,6 +69,6 @@ message TxEnvelopeParam { // An existing Envelope - either signed or unsigned - if the latter will be signed server-side txs.Envelope Envelope = 1 [(gogoproto.customtype) = "github.com/hyperledger/burrow/txs.Envelope"]; // If no Envelope provided then one will be generated from the provided payload and signed server-side - PayloadParam Payload = 2; + payload.Any Payload = 2; } diff --git a/protobuf/spec.proto b/protobuf/spec.proto index 7f0c6abe..03a2090b 100644 --- a/protobuf/spec.proto +++ b/protobuf/spec.proto @@ -1,35 +1,28 @@ // Needed to proto2 rather than proto3 to get pointer field for PermArg -syntax = 'proto2'; +syntax = 'proto3'; option go_package = "github.com/hyperledger/burrow/genesis/spec"; import "github.com/gogo/protobuf/gogoproto/gogo.proto"; import "crypto.proto"; +import "balance.proto"; package spec; -// Enable custom Marshal method. option (gogoproto.marshaler_all) = true; -// Enable custom Unmarshal method. option (gogoproto.unmarshaler_all) = true; -// Enable custom Size method (Required by Marshal and Unmarshal). option (gogoproto.sizer_all) = true; -// Enable registration with golang/protobuf for the grpc-gateway. option (gogoproto.goproto_registration) = true; -// Enable generation of XXX_MessageName methods for grpc-go/status. option (gogoproto.messagename_all) = true; message TemplateAccount { - option (gogoproto.goproto_unrecognized) = false; - - optional string Name = 1 [(gogoproto.nullable) = false]; - optional bytes Address = 2 [(gogoproto.customtype) = "github.com/hyperledger/burrow/crypto.Address", (gogoproto.jsontag) = ",omitempty", (gogoproto.moretags) = "toml:\",omitempty\""]; - optional bytes NodeAddress = 3 [(gogoproto.customtype) = "github.com/hyperledger/burrow/crypto.Address", (gogoproto.jsontag) = ",omitempty", (gogoproto.moretags) = "toml:\",omitempty\""]; - optional crypto.PublicKey PublicKey = 4 [(gogoproto.jsontag) = ",omitempty", (gogoproto.moretags) = "toml:\",omitempty\""]; - optional uint64 Amount = 5 [(gogoproto.jsontag) = ",omitempty", (gogoproto.moretags) = "toml:\",omitempty\""]; - optional uint64 Power = 6 [(gogoproto.jsontag) = ",omitempty", (gogoproto.moretags) = "toml:\",omitempty\""]; - repeated string Permissions = 7 [(gogoproto.jsontag) = ",omitempty", (gogoproto.moretags) = "toml:\",omitempty\""]; - repeated string Roles = 8 [(gogoproto.jsontag) = ",omitempty", (gogoproto.moretags) = "toml:\",omitempty\""]; + string Name = 1; + bytes Address = 2 [(gogoproto.customtype) = "github.com/hyperledger/burrow/crypto.Address", (gogoproto.jsontag) = ",omitempty", (gogoproto.moretags) = "toml:\",omitempty\""]; + bytes NodeAddress = 3 [(gogoproto.customtype) = "github.com/hyperledger/burrow/crypto.Address", (gogoproto.jsontag) = ",omitempty", (gogoproto.moretags) = "toml:\",omitempty\""]; + crypto.PublicKey PublicKey = 4 [(gogoproto.jsontag) = ",omitempty", (gogoproto.moretags) = "toml:\",omitempty\""]; + repeated balance.Balance Amounts = 5 [(gogoproto.nullable) = false, (gogoproto.jsontag) = ",omitempty", (gogoproto.moretags) = "toml:\",omitempty\""]; + repeated string Permissions = 6 [(gogoproto.jsontag) = ",omitempty", (gogoproto.moretags) = "toml:\",omitempty\""]; + repeated string Roles = 7 [(gogoproto.jsontag) = ",omitempty", (gogoproto.moretags) = "toml:\",omitempty\""]; } diff --git a/protobuf/validator.proto b/protobuf/validator.proto new file mode 100644 index 00000000..dc621ab7 --- /dev/null +++ b/protobuf/validator.proto @@ -0,0 +1,22 @@ +syntax = 'proto3'; + +package validator; + +option go_package = "github.com/hyperledger/burrow/acm/validator"; + +import "github.com/gogo/protobuf/gogoproto/gogo.proto"; + +import "crypto.proto"; + +option (gogoproto.marshaler_all) = true; +option (gogoproto.unmarshaler_all) = true; +option (gogoproto.sizer_all) = true; +option (gogoproto.goproto_registration) = true; +option (gogoproto.messagename_all) = true; + +message Validator { + option (gogoproto.goproto_stringer) = false; + bytes Address = 1 [(gogoproto.customtype) = "github.com/hyperledger/burrow/crypto.Address"]; + crypto.PublicKey PublicKey = 2 [(gogoproto.nullable) = false]; + uint64 Power = 3; +} diff --git a/rpc/result.go b/rpc/result.go index af777d94..35d21892 100644 --- a/rpc/result.go +++ b/rpc/result.go @@ -18,6 +18,7 @@ import ( "time" "github.com/hyperledger/burrow/acm" + "github.com/hyperledger/burrow/acm/validator" "github.com/hyperledger/burrow/binary" "github.com/hyperledger/burrow/crypto" "github.com/hyperledger/burrow/execution/names" @@ -96,7 +97,7 @@ func (b *Block) UnmarshalJSON(data []byte) (err error) { type ResultStatus struct { NodeInfo p2p.NodeInfo GenesisHash binary.HexBytes - PubKey crypto.PublicKey + PublicKey crypto.PublicKey LatestBlockHash binary.HexBytes LatestBlockHeight uint64 LatestBlockTime int64 @@ -130,6 +131,7 @@ type Peer struct { } type ResultNetInfo struct { + ThisNode p2p.NodeInfo Listening bool Listeners []string Peers []*Peer @@ -137,8 +139,8 @@ type ResultNetInfo struct { type ResultListValidators struct { BlockHeight uint64 - BondedValidators []*acm.ConcreteValidator - UnbondingValidators []*acm.ConcreteValidator + BondedValidators []*validator.Validator + UnbondingValidators []*validator.Validator } type ResultDumpConsensusState struct { diff --git a/rpc/rpcevents/execution_events_server.go b/rpc/rpcevents/execution_events_server.go index 2b042c77..d8f48e14 100644 --- a/rpc/rpcevents/execution_events_server.go +++ b/rpc/rpcevents/execution_events_server.go @@ -7,7 +7,7 @@ import ( "io" "github.com/gogo/protobuf/proto" - bcm "github.com/hyperledger/burrow/blockchain" + bcm "github.com/hyperledger/burrow/bcm" "github.com/hyperledger/burrow/event" "github.com/hyperledger/burrow/event/query" "github.com/hyperledger/burrow/execution/exec" @@ -29,12 +29,12 @@ type Provider interface { type executionEventsServer struct { eventsProvider Provider subscribable event.Subscribable - tip bcm.TipInfo + tip bcm.BlockchainInfo logger *logging.Logger } func NewExecutionEventsServer(eventsProvider Provider, subscribable event.Subscribable, - tip bcm.TipInfo, logger *logging.Logger) ExecutionEventsServer { + tip bcm.BlockchainInfo, logger *logging.Logger) ExecutionEventsServer { return &executionEventsServer{ eventsProvider: eventsProvider, diff --git a/rpc/rpcquery/query_server.go b/rpc/rpcquery/query_server.go index edcb968b..debdc05b 100644 --- a/rpc/rpcquery/query_server.go +++ b/rpc/rpcquery/query_server.go @@ -5,24 +5,36 @@ import ( "github.com/hyperledger/burrow/acm" "github.com/hyperledger/burrow/acm/state" + "github.com/hyperledger/burrow/bcm" + "github.com/hyperledger/burrow/consensus/tendermint" "github.com/hyperledger/burrow/event/query" "github.com/hyperledger/burrow/execution/names" + "github.com/hyperledger/burrow/logging" ) type queryServer struct { - accounts state.IterableReader - nameReg names.IterableReader + accounts state.IterableReader + nameReg names.IterableReader + blockchain bcm.BlockchainInfo + nodeView *tendermint.NodeView + logger *logging.Logger } var _ QueryServer = &queryServer{} -func NewQueryServer(state state.IterableReader, nameReg names.IterableReader) *queryServer { +func NewQueryServer(state state.IterableReader, nameReg names.IterableReader, blockchain bcm.BlockchainInfo, + nodeView *tendermint.NodeView, logger *logging.Logger) *queryServer { return &queryServer{ - accounts: state, - nameReg: nameReg, + accounts: state, + nameReg: nameReg, + blockchain: blockchain, + nodeView: nodeView, + logger: logger, } } +// Account state + func (qs *queryServer) GetAccount(ctx context.Context, param *GetAccountParam) (*acm.ConcreteAccount, error) { acc, err := qs.accounts.GetAccount(param.Address) if err != nil { @@ -74,3 +86,20 @@ func (qs *queryServer) ListNames(param *ListNamesParam, stream Query_ListNamesSe } return streamErr } + +func (qs *queryServer) GetValidatorSet(ctx context.Context, param *GetValidatorSetParam) (*ValidatorSet, error) { + set, deltas, height := qs.blockchain.ValidatorsHistory() + vs := &ValidatorSet{ + Height: height, + Set: set.Validators(), + } + if param.IncludeHistory { + vs.History = make([]*ValidatorSetDeltas, len(deltas)) + for i, d := range deltas { + vs.History[i] = &ValidatorSetDeltas{ + Validators: d.Validators(), + } + } + } + return vs, nil +} diff --git a/rpc/rpcquery/rpcquery.pb.go b/rpc/rpcquery/rpcquery.pb.go index ce9b9f17..ec9b8171 100644 --- a/rpc/rpcquery/rpcquery.pb.go +++ b/rpc/rpcquery/rpcquery.pb.go @@ -12,6 +12,9 @@ ListAccountsParam GetNameParam ListNamesParam + GetValidatorSetParam + ValidatorSet + ValidatorSetDeltas */ package rpcquery @@ -22,6 +25,7 @@ import math "math" import _ "github.com/gogo/protobuf/gogoproto" import names "github.com/hyperledger/burrow/execution/names" import acm "github.com/hyperledger/burrow/acm" +import validator "github.com/hyperledger/burrow/acm/validator" import github_com_hyperledger_burrow_crypto "github.com/hyperledger/burrow/crypto" @@ -114,6 +118,82 @@ func (m *ListNamesParam) GetQuery() string { func (*ListNamesParam) XXX_MessageName() string { return "rpcquery.ListNamesParam" } + +type GetValidatorSetParam struct { + IncludeHistory bool `protobuf:"varint,1,opt,name=IncludeHistory,proto3" json:"IncludeHistory,omitempty"` +} + +func (m *GetValidatorSetParam) Reset() { *m = GetValidatorSetParam{} } +func (m *GetValidatorSetParam) String() string { return proto.CompactTextString(m) } +func (*GetValidatorSetParam) ProtoMessage() {} +func (*GetValidatorSetParam) Descriptor() ([]byte, []int) { return fileDescriptorRpcquery, []int{4} } + +func (m *GetValidatorSetParam) GetIncludeHistory() bool { + if m != nil { + return m.IncludeHistory + } + return false +} + +func (*GetValidatorSetParam) XXX_MessageName() string { + return "rpcquery.GetValidatorSetParam" +} + +type ValidatorSet struct { + Height uint64 `protobuf:"varint,1,opt,name=height,proto3" json:"height,omitempty"` + Set []*validator.Validator `protobuf:"bytes,2,rep,name=Set" json:"Set,omitempty"` + History []*ValidatorSetDeltas `protobuf:"bytes,3,rep,name=History" json:"History,omitempty"` +} + +func (m *ValidatorSet) Reset() { *m = ValidatorSet{} } +func (m *ValidatorSet) String() string { return proto.CompactTextString(m) } +func (*ValidatorSet) ProtoMessage() {} +func (*ValidatorSet) Descriptor() ([]byte, []int) { return fileDescriptorRpcquery, []int{5} } + +func (m *ValidatorSet) GetHeight() uint64 { + if m != nil { + return m.Height + } + return 0 +} + +func (m *ValidatorSet) GetSet() []*validator.Validator { + if m != nil { + return m.Set + } + return nil +} + +func (m *ValidatorSet) GetHistory() []*ValidatorSetDeltas { + if m != nil { + return m.History + } + return nil +} + +func (*ValidatorSet) XXX_MessageName() string { + return "rpcquery.ValidatorSet" +} + +type ValidatorSetDeltas struct { + Validators []*validator.Validator `protobuf:"bytes,2,rep,name=Validators" json:"Validators,omitempty"` +} + +func (m *ValidatorSetDeltas) Reset() { *m = ValidatorSetDeltas{} } +func (m *ValidatorSetDeltas) String() string { return proto.CompactTextString(m) } +func (*ValidatorSetDeltas) ProtoMessage() {} +func (*ValidatorSetDeltas) Descriptor() ([]byte, []int) { return fileDescriptorRpcquery, []int{6} } + +func (m *ValidatorSetDeltas) GetValidators() []*validator.Validator { + if m != nil { + return m.Validators + } + return nil +} + +func (*ValidatorSetDeltas) XXX_MessageName() string { + return "rpcquery.ValidatorSetDeltas" +} func init() { proto.RegisterType((*GetAccountParam)(nil), "rpcquery.GetAccountParam") golang_proto.RegisterType((*GetAccountParam)(nil), "rpcquery.GetAccountParam") @@ -123,6 +203,12 @@ func init() { golang_proto.RegisterType((*GetNameParam)(nil), "rpcquery.GetNameParam") proto.RegisterType((*ListNamesParam)(nil), "rpcquery.ListNamesParam") golang_proto.RegisterType((*ListNamesParam)(nil), "rpcquery.ListNamesParam") + proto.RegisterType((*GetValidatorSetParam)(nil), "rpcquery.GetValidatorSetParam") + golang_proto.RegisterType((*GetValidatorSetParam)(nil), "rpcquery.GetValidatorSetParam") + proto.RegisterType((*ValidatorSet)(nil), "rpcquery.ValidatorSet") + golang_proto.RegisterType((*ValidatorSet)(nil), "rpcquery.ValidatorSet") + proto.RegisterType((*ValidatorSetDeltas)(nil), "rpcquery.ValidatorSetDeltas") + golang_proto.RegisterType((*ValidatorSetDeltas)(nil), "rpcquery.ValidatorSetDeltas") } // Reference imports to suppress errors if they are not otherwise used. @@ -140,6 +226,7 @@ type QueryClient interface { ListAccounts(ctx context.Context, in *ListAccountsParam, opts ...grpc.CallOption) (Query_ListAccountsClient, error) GetName(ctx context.Context, in *GetNameParam, opts ...grpc.CallOption) (*names.Entry, error) ListNames(ctx context.Context, in *ListNamesParam, opts ...grpc.CallOption) (Query_ListNamesClient, error) + GetValidatorSet(ctx context.Context, in *GetValidatorSetParam, opts ...grpc.CallOption) (*ValidatorSet, error) } type queryClient struct { @@ -232,6 +319,15 @@ func (x *queryListNamesClient) Recv() (*names.Entry, error) { return m, nil } +func (c *queryClient) GetValidatorSet(ctx context.Context, in *GetValidatorSetParam, opts ...grpc.CallOption) (*ValidatorSet, error) { + out := new(ValidatorSet) + err := grpc.Invoke(ctx, "/rpcquery.Query/GetValidatorSet", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + // Server API for Query service type QueryServer interface { @@ -239,6 +335,7 @@ type QueryServer interface { ListAccounts(*ListAccountsParam, Query_ListAccountsServer) error GetName(context.Context, *GetNameParam) (*names.Entry, error) ListNames(*ListNamesParam, Query_ListNamesServer) error + GetValidatorSet(context.Context, *GetValidatorSetParam) (*ValidatorSet, error) } func RegisterQueryServer(s *grpc.Server, srv QueryServer) { @@ -323,6 +420,24 @@ func (x *queryListNamesServer) Send(m *names.Entry) error { return x.ServerStream.SendMsg(m) } +func _Query_GetValidatorSet_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(GetValidatorSetParam) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(QueryServer).GetValidatorSet(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/rpcquery.Query/GetValidatorSet", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(QueryServer).GetValidatorSet(ctx, req.(*GetValidatorSetParam)) + } + return interceptor(ctx, in, info, handler) +} + var _Query_serviceDesc = grpc.ServiceDesc{ ServiceName: "rpcquery.Query", HandlerType: (*QueryServer)(nil), @@ -335,6 +450,10 @@ var _Query_serviceDesc = grpc.ServiceDesc{ MethodName: "GetName", Handler: _Query_GetName_Handler, }, + { + MethodName: "GetValidatorSet", + Handler: _Query_GetValidatorSet_Handler, + }, }, Streams: []grpc.StreamDesc{ { @@ -449,6 +568,111 @@ func (m *ListNamesParam) MarshalTo(dAtA []byte) (int, error) { return i, nil } +func (m *GetValidatorSetParam) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalTo(dAtA) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *GetValidatorSetParam) MarshalTo(dAtA []byte) (int, error) { + var i int + _ = i + var l int + _ = l + if m.IncludeHistory { + dAtA[i] = 0x8 + i++ + if m.IncludeHistory { + dAtA[i] = 1 + } else { + dAtA[i] = 0 + } + i++ + } + return i, nil +} + +func (m *ValidatorSet) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalTo(dAtA) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *ValidatorSet) MarshalTo(dAtA []byte) (int, error) { + var i int + _ = i + var l int + _ = l + if m.Height != 0 { + dAtA[i] = 0x8 + i++ + i = encodeVarintRpcquery(dAtA, i, uint64(m.Height)) + } + if len(m.Set) > 0 { + for _, msg := range m.Set { + dAtA[i] = 0x12 + i++ + i = encodeVarintRpcquery(dAtA, i, uint64(msg.Size())) + n, err := msg.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n + } + } + if len(m.History) > 0 { + for _, msg := range m.History { + dAtA[i] = 0x1a + i++ + i = encodeVarintRpcquery(dAtA, i, uint64(msg.Size())) + n, err := msg.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n + } + } + return i, nil +} + +func (m *ValidatorSetDeltas) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalTo(dAtA) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *ValidatorSetDeltas) MarshalTo(dAtA []byte) (int, error) { + var i int + _ = i + var l int + _ = l + if len(m.Validators) > 0 { + for _, msg := range m.Validators { + dAtA[i] = 0x12 + i++ + i = encodeVarintRpcquery(dAtA, i, uint64(msg.Size())) + n, err := msg.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n + } + } + return i, nil +} + func encodeVarintRpcquery(dAtA []byte, offset int, v uint64) int { for v >= 1<<7 { dAtA[offset] = uint8(v&0x7f | 0x80) @@ -496,6 +720,48 @@ func (m *ListNamesParam) Size() (n int) { return n } +func (m *GetValidatorSetParam) Size() (n int) { + var l int + _ = l + if m.IncludeHistory { + n += 2 + } + return n +} + +func (m *ValidatorSet) Size() (n int) { + var l int + _ = l + if m.Height != 0 { + n += 1 + sovRpcquery(uint64(m.Height)) + } + if len(m.Set) > 0 { + for _, e := range m.Set { + l = e.Size() + n += 1 + l + sovRpcquery(uint64(l)) + } + } + if len(m.History) > 0 { + for _, e := range m.History { + l = e.Size() + n += 1 + l + sovRpcquery(uint64(l)) + } + } + return n +} + +func (m *ValidatorSetDeltas) Size() (n int) { + var l int + _ = l + if len(m.Validators) > 0 { + for _, e := range m.Validators { + l = e.Size() + n += 1 + l + sovRpcquery(uint64(l)) + } + } + return n +} + func sovRpcquery(x uint64) (n int) { for { n++ @@ -826,6 +1092,288 @@ func (m *ListNamesParam) Unmarshal(dAtA []byte) error { } return nil } +func (m *GetValidatorSetParam) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowRpcquery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: GetValidatorSetParam: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: GetValidatorSetParam: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field IncludeHistory", wireType) + } + var v int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowRpcquery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + m.IncludeHistory = bool(v != 0) + default: + iNdEx = preIndex + skippy, err := skipRpcquery(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthRpcquery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *ValidatorSet) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowRpcquery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: ValidatorSet: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ValidatorSet: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Height", wireType) + } + m.Height = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowRpcquery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Height |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Set", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowRpcquery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthRpcquery + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Set = append(m.Set, &validator.Validator{}) + if err := m.Set[len(m.Set)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field History", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowRpcquery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthRpcquery + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.History = append(m.History, &ValidatorSetDeltas{}) + if err := m.History[len(m.History)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipRpcquery(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthRpcquery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *ValidatorSetDeltas) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowRpcquery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: ValidatorSetDeltas: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ValidatorSetDeltas: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Validators", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowRpcquery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthRpcquery + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Validators = append(m.Validators, &validator.Validator{}) + if err := m.Validators[len(m.Validators)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipRpcquery(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthRpcquery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} func skipRpcquery(dAtA []byte) (n int, err error) { l := len(dAtA) iNdEx := 0 @@ -935,27 +1483,36 @@ func init() { proto.RegisterFile("rpcquery.proto", fileDescriptorRpcquery) } func init() { golang_proto.RegisterFile("rpcquery.proto", fileDescriptorRpcquery) } var fileDescriptorRpcquery = []byte{ - // 349 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x7c, 0x92, 0xcd, 0x4a, 0xc3, 0x40, - 0x14, 0x85, 0x1d, 0x50, 0x6b, 0xaf, 0xa1, 0xe2, 0x50, 0xa4, 0x46, 0x48, 0x25, 0x0b, 0x51, 0xd1, - 0xa4, 0xf8, 0xb3, 0x14, 0x6c, 0x8b, 0x74, 0x23, 0x45, 0xbb, 0x74, 0x97, 0x4c, 0xc7, 0xb4, 0x60, - 0x32, 0xf1, 0x66, 0x82, 0xe4, 0xed, 0x5c, 0x76, 0xe9, 0xda, 0x45, 0x91, 0xf6, 0x11, 0x7c, 0x01, - 0xc9, 0x24, 0xe9, 0x8f, 0x4a, 0x77, 0xf7, 0x84, 0x7b, 0xce, 0x99, 0x6f, 0x26, 0x50, 0xc1, 0x90, - 0xbd, 0xc6, 0x1c, 0x13, 0x2b, 0x44, 0x21, 0x05, 0xdd, 0x2a, 0xb4, 0x7e, 0xee, 0x0d, 0xe5, 0x20, - 0x76, 0x2d, 0x26, 0x7c, 0xdb, 0x13, 0x9e, 0xb0, 0xd5, 0x82, 0x1b, 0x3f, 0x2b, 0xa5, 0x84, 0x9a, - 0x32, 0xa3, 0xbe, 0x1d, 0x38, 0x3e, 0x8f, 0x72, 0x51, 0x76, 0x98, 0x9f, 0x8d, 0xa6, 0x03, 0x3b, - 0x1d, 0x2e, 0x9b, 0x8c, 0x89, 0x38, 0x90, 0x0f, 0x0e, 0x3a, 0x3e, 0xed, 0x42, 0xa9, 0xd9, 0xef, - 0x23, 0x8f, 0xa2, 0x1a, 0x39, 0x24, 0xc7, 0x5a, 0xeb, 0x6a, 0x34, 0xae, 0xaf, 0x7d, 0x8e, 0xeb, - 0x67, 0x0b, 0x95, 0x83, 0x24, 0xe4, 0xf8, 0xc2, 0xfb, 0x1e, 0x47, 0xdb, 0x8d, 0x11, 0xc5, 0x9b, - 0xcd, 0x30, 0x09, 0xa5, 0xb0, 0x72, 0x6f, 0xaf, 0x08, 0x31, 0x4f, 0x60, 0xf7, 0x7e, 0x18, 0x15, - 0x1d, 0x51, 0x56, 0x52, 0x85, 0x8d, 0xc7, 0x94, 0x43, 0x55, 0x94, 0x7b, 0x99, 0x30, 0x4d, 0xd0, - 0x3a, 0x5c, 0x76, 0x1d, 0x9f, 0x67, 0x5b, 0x14, 0xd6, 0x53, 0x91, 0x2f, 0xa9, 0xd9, 0x3c, 0x82, - 0x4a, 0x1a, 0x97, 0xce, 0xab, 0xb2, 0x2e, 0xbe, 0x49, 0xfe, 0x99, 0xde, 0x00, 0xcc, 0x19, 0xe9, - 0xbe, 0x35, 0xbb, 0xd3, 0x5f, 0xe4, 0x7a, 0xd5, 0x4a, 0x2f, 0xa6, 0x2d, 0x02, 0x86, 0x5c, 0xf2, - 0xc2, 0xd0, 0x06, 0x6d, 0xf1, 0xfc, 0xf4, 0x60, 0x1e, 0xf0, 0x87, 0xeb, 0xff, 0x88, 0x06, 0xa1, - 0x36, 0x94, 0x72, 0x32, 0xba, 0xb7, 0x74, 0x80, 0x19, 0xac, 0xae, 0x59, 0xd9, 0x1b, 0xdd, 0x05, - 0x12, 0x13, 0x7a, 0x0d, 0xe5, 0x19, 0x26, 0xad, 0x2d, 0x57, 0xce, 0xd9, 0x97, 0x4d, 0x0d, 0xd2, - 0xba, 0x1d, 0x4d, 0x0c, 0xf2, 0x31, 0x31, 0xc8, 0xd7, 0xc4, 0x20, 0xef, 0x53, 0x83, 0x8c, 0xa6, - 0x06, 0x79, 0x3a, 0x5d, 0xfd, 0x72, 0x18, 0x32, 0xbb, 0x28, 0x70, 0x37, 0xd5, 0x8f, 0x71, 0xf9, - 0x13, 0x00, 0x00, 0xff, 0xff, 0xfa, 0xef, 0x21, 0x21, 0x7b, 0x02, 0x00, 0x00, + // 487 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x7c, 0x53, 0x4f, 0x6f, 0xd3, 0x30, + 0x1c, 0xc5, 0xeb, 0x58, 0xd7, 0xdf, 0xaa, 0x4e, 0x58, 0x55, 0x55, 0x02, 0xca, 0xa6, 0x1c, 0xaa, + 0x81, 0x20, 0x99, 0xc6, 0xe0, 0x06, 0x62, 0x1b, 0xa8, 0x0c, 0xa1, 0x09, 0x32, 0x89, 0x03, 0x37, + 0xd7, 0x31, 0x69, 0xa4, 0x26, 0x0e, 0x8e, 0x03, 0xea, 0x17, 0xe0, 0x63, 0x21, 0x8e, 0x3d, 0x72, + 0xe6, 0x30, 0xa1, 0xee, 0x8b, 0xa0, 0x38, 0xce, 0xbf, 0x75, 0xea, 0xcd, 0xcf, 0x79, 0xef, 0xf7, + 0xec, 0xbc, 0x67, 0xe8, 0x89, 0x98, 0x7e, 0x4b, 0x99, 0x98, 0xdb, 0xb1, 0xe0, 0x92, 0xe3, 0xed, + 0x02, 0x1b, 0x4f, 0xfd, 0x40, 0x4e, 0xd3, 0x89, 0x4d, 0x79, 0xe8, 0xf8, 0xdc, 0xe7, 0x8e, 0x22, + 0x4c, 0xd2, 0xaf, 0x0a, 0x29, 0xa0, 0x56, 0xb9, 0xd0, 0xd8, 0x89, 0x48, 0xc8, 0x12, 0x0d, 0x3a, + 0x84, 0x86, 0x7a, 0xb9, 0xfb, 0x9d, 0xcc, 0x02, 0x8f, 0x48, 0x2e, 0xf2, 0x0d, 0x8b, 0xc0, 0xee, + 0x98, 0xc9, 0x13, 0x4a, 0x79, 0x1a, 0xc9, 0x8f, 0x44, 0x90, 0x10, 0x5f, 0x40, 0xfb, 0xc4, 0xf3, + 0x04, 0x4b, 0x92, 0x21, 0xda, 0x47, 0x07, 0xdd, 0xd3, 0xe3, 0xc5, 0xd5, 0xde, 0x9d, 0xbf, 0x57, + 0x7b, 0x4f, 0x6a, 0x67, 0x98, 0xce, 0x63, 0x26, 0x66, 0xcc, 0xf3, 0x99, 0x70, 0x26, 0xa9, 0x10, + 0xfc, 0x87, 0x43, 0xc5, 0x3c, 0x96, 0xdc, 0xd6, 0x5a, 0xb7, 0x18, 0x62, 0x3d, 0x82, 0x7b, 0x1f, + 0x82, 0xa4, 0xf0, 0x48, 0x72, 0x93, 0x3e, 0xdc, 0xfd, 0x94, 0x5d, 0x4c, 0x59, 0x74, 0xdc, 0x1c, + 0x58, 0x16, 0x74, 0xc7, 0x4c, 0x5e, 0x90, 0x90, 0xe5, 0x2c, 0x0c, 0x9b, 0x19, 0xd0, 0x24, 0xb5, + 0xb6, 0x46, 0xd0, 0xcb, 0xc6, 0x65, 0xeb, 0xb5, 0xb3, 0x5e, 0x41, 0x7f, 0xcc, 0xe4, 0xe7, 0xe2, + 0xbe, 0x97, 0x4c, 0x5f, 0x6f, 0x04, 0xbd, 0xf3, 0x88, 0xce, 0x52, 0x8f, 0xbd, 0x0b, 0x12, 0xc9, + 0xb5, 0x6c, 0xdb, 0xbd, 0xb1, 0x6b, 0xfd, 0x44, 0xd0, 0xad, 0xab, 0xf1, 0x00, 0xb6, 0xa6, 0x2c, + 0xf0, 0xa7, 0x52, 0x09, 0x36, 0x5d, 0x8d, 0xf0, 0x08, 0x5a, 0x97, 0x4c, 0x0e, 0x37, 0xf6, 0x5b, + 0x07, 0x3b, 0x47, 0x7d, 0xbb, 0xfa, 0xc3, 0xa5, 0xda, 0xcd, 0x08, 0xf8, 0x05, 0xb4, 0x0b, 0xc7, + 0x96, 0xe2, 0x3e, 0xb4, 0xcb, 0xb8, 0xeb, 0x46, 0x6f, 0xd8, 0x4c, 0x92, 0xc4, 0x2d, 0xc8, 0xd6, + 0x7b, 0xc0, 0xab, 0x9f, 0xf1, 0x31, 0x40, 0xb9, 0x9b, 0xac, 0x35, 0xaf, 0xf1, 0x8e, 0x7e, 0x6d, + 0xe8, 0x7f, 0x85, 0x5f, 0x02, 0x54, 0xc1, 0xe3, 0xfb, 0xd5, 0x51, 0x6e, 0xd4, 0xc1, 0xe8, 0xdb, + 0x59, 0x7d, 0xce, 0x78, 0x44, 0x05, 0x93, 0xac, 0x10, 0x9c, 0x41, 0xb7, 0x1e, 0x2a, 0x7e, 0x50, + 0x0d, 0x58, 0x09, 0xfb, 0xf6, 0x11, 0x87, 0x08, 0x3b, 0xd0, 0xd6, 0x71, 0xe3, 0x41, 0xe3, 0x00, + 0x65, 0x03, 0x8c, 0xae, 0x9d, 0x37, 0xf9, 0x6d, 0x24, 0xc5, 0x1c, 0x3f, 0x87, 0x4e, 0x99, 0x3d, + 0x1e, 0x36, 0x2d, 0xab, 0x42, 0x34, 0x45, 0x87, 0x08, 0x9f, 0xab, 0x92, 0x37, 0xc2, 0x34, 0x1b, + 0x7e, 0x2b, 0x2d, 0x31, 0x06, 0xb7, 0x67, 0x73, 0xfa, 0x7a, 0xb1, 0x34, 0xd1, 0x9f, 0xa5, 0x89, + 0xfe, 0x2d, 0x4d, 0xf4, 0xfb, 0xda, 0x44, 0x8b, 0x6b, 0x13, 0x7d, 0x79, 0xbc, 0xfe, 0x65, 0x88, + 0x98, 0x3a, 0xc5, 0xb8, 0xc9, 0x96, 0x7a, 0x78, 0xcf, 0xfe, 0x07, 0x00, 0x00, 0xff, 0xff, 0xfd, + 0xa4, 0xb6, 0xf9, 0xec, 0x03, 0x00, 0x00, } diff --git a/rpc/rpctransact/rpctransact.pb.go b/rpc/rpctransact/rpctransact.pb.go index 903e977b..98861547 100644 --- a/rpc/rpctransact/rpctransact.pb.go +++ b/rpc/rpctransact/rpctransact.pb.go @@ -9,7 +9,6 @@ It has these top-level messages: CallCodeParam - PayloadParam TxEnvelope TxEnvelopeParam */ @@ -73,42 +72,6 @@ func (*CallCodeParam) XXX_MessageName() string { return "rpctransact.CallCodeParam" } -type PayloadParam struct { - CallTx *payload.CallTx `protobuf:"bytes,1,opt,name=CallTx" json:"CallTx,omitempty"` - SendTx *payload.SendTx `protobuf:"bytes,2,opt,name=SendTx" json:"SendTx,omitempty"` - NameTx *payload.NameTx `protobuf:"bytes,3,opt,name=NameTx" json:"NameTx,omitempty"` -} - -func (m *PayloadParam) Reset() { *m = PayloadParam{} } -func (m *PayloadParam) String() string { return proto.CompactTextString(m) } -func (*PayloadParam) ProtoMessage() {} -func (*PayloadParam) Descriptor() ([]byte, []int) { return fileDescriptorRpctransact, []int{1} } - -func (m *PayloadParam) GetCallTx() *payload.CallTx { - if m != nil { - return m.CallTx - } - return nil -} - -func (m *PayloadParam) GetSendTx() *payload.SendTx { - if m != nil { - return m.SendTx - } - return nil -} - -func (m *PayloadParam) GetNameTx() *payload.NameTx { - if m != nil { - return m.NameTx - } - return nil -} - -func (*PayloadParam) XXX_MessageName() string { - return "rpctransact.PayloadParam" -} - type TxEnvelope struct { Envelope *github_com_hyperledger_burrow_txs.Envelope `protobuf:"bytes,1,opt,name=Envelope,customtype=github.com/hyperledger/burrow/txs.Envelope" json:"Envelope,omitempty"` } @@ -116,7 +79,7 @@ type TxEnvelope struct { func (m *TxEnvelope) Reset() { *m = TxEnvelope{} } func (m *TxEnvelope) String() string { return proto.CompactTextString(m) } func (*TxEnvelope) ProtoMessage() {} -func (*TxEnvelope) Descriptor() ([]byte, []int) { return fileDescriptorRpctransact, []int{2} } +func (*TxEnvelope) Descriptor() ([]byte, []int) { return fileDescriptorRpctransact, []int{1} } func (*TxEnvelope) XXX_MessageName() string { return "rpctransact.TxEnvelope" @@ -126,15 +89,15 @@ type TxEnvelopeParam struct { // An existing Envelope - either signed or unsigned - if the latter will be signed server-side Envelope *github_com_hyperledger_burrow_txs.Envelope `protobuf:"bytes,1,opt,name=Envelope,customtype=github.com/hyperledger/burrow/txs.Envelope" json:"Envelope,omitempty"` // If no Envelope provided then one will be generated from the provided payload and signed server-side - Payload *PayloadParam `protobuf:"bytes,2,opt,name=Payload" json:"Payload,omitempty"` + Payload *payload.Any `protobuf:"bytes,2,opt,name=Payload" json:"Payload,omitempty"` } func (m *TxEnvelopeParam) Reset() { *m = TxEnvelopeParam{} } func (m *TxEnvelopeParam) String() string { return proto.CompactTextString(m) } func (*TxEnvelopeParam) ProtoMessage() {} -func (*TxEnvelopeParam) Descriptor() ([]byte, []int) { return fileDescriptorRpctransact, []int{3} } +func (*TxEnvelopeParam) Descriptor() ([]byte, []int) { return fileDescriptorRpctransact, []int{2} } -func (m *TxEnvelopeParam) GetPayload() *PayloadParam { +func (m *TxEnvelopeParam) GetPayload() *payload.Any { if m != nil { return m.Payload } @@ -147,8 +110,6 @@ func (*TxEnvelopeParam) XXX_MessageName() string { func init() { proto.RegisterType((*CallCodeParam)(nil), "rpctransact.CallCodeParam") golang_proto.RegisterType((*CallCodeParam)(nil), "rpctransact.CallCodeParam") - proto.RegisterType((*PayloadParam)(nil), "rpctransact.PayloadParam") - golang_proto.RegisterType((*PayloadParam)(nil), "rpctransact.PayloadParam") proto.RegisterType((*TxEnvelope)(nil), "rpctransact.TxEnvelope") golang_proto.RegisterType((*TxEnvelope)(nil), "rpctransact.TxEnvelope") proto.RegisterType((*TxEnvelopeParam)(nil), "rpctransact.TxEnvelopeParam") @@ -174,7 +135,7 @@ type TransactClient interface { // Sign transaction server-side SignTx(ctx context.Context, in *TxEnvelopeParam, opts ...grpc.CallOption) (*TxEnvelope, error) // Formulate a transaction from a Payload and retrun the envelop with the Tx bytes ready to sign - FormulateTx(ctx context.Context, in *PayloadParam, opts ...grpc.CallOption) (*TxEnvelope, error) + FormulateTx(ctx context.Context, in *payload.Any, opts ...grpc.CallOption) (*TxEnvelope, error) // Formulate and sign a CallTx transaction signed server-side and wait for it to be included in a block, retrieving response CallTxSync(ctx context.Context, in *payload.CallTx, opts ...grpc.CallOption) (*exec.TxExecution, error) // Formulate and sign a CallTx transaction signed server-side @@ -229,7 +190,7 @@ func (c *transactClient) SignTx(ctx context.Context, in *TxEnvelopeParam, opts . return out, nil } -func (c *transactClient) FormulateTx(ctx context.Context, in *PayloadParam, opts ...grpc.CallOption) (*TxEnvelope, error) { +func (c *transactClient) FormulateTx(ctx context.Context, in *payload.Any, opts ...grpc.CallOption) (*TxEnvelope, error) { out := new(TxEnvelope) err := grpc.Invoke(ctx, "/rpctransact.Transact/FormulateTx", in, out, c.cc, opts...) if err != nil { @@ -321,7 +282,7 @@ type TransactServer interface { // Sign transaction server-side SignTx(context.Context, *TxEnvelopeParam) (*TxEnvelope, error) // Formulate a transaction from a Payload and retrun the envelop with the Tx bytes ready to sign - FormulateTx(context.Context, *PayloadParam) (*TxEnvelope, error) + FormulateTx(context.Context, *payload.Any) (*TxEnvelope, error) // Formulate and sign a CallTx transaction signed server-side and wait for it to be included in a block, retrieving response CallTxSync(context.Context, *payload.CallTx) (*exec.TxExecution, error) // Formulate and sign a CallTx transaction signed server-side @@ -400,7 +361,7 @@ func _Transact_SignTx_Handler(srv interface{}, ctx context.Context, dec func(int } func _Transact_FormulateTx_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(PayloadParam) + in := new(payload.Any) if err := dec(in); err != nil { return nil, err } @@ -412,7 +373,7 @@ func _Transact_FormulateTx_Handler(srv interface{}, ctx context.Context, dec fun FullMethod: "/rpctransact.Transact/FormulateTx", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(TransactServer).FormulateTx(ctx, req.(*PayloadParam)) + return srv.(TransactServer).FormulateTx(ctx, req.(*payload.Any)) } return interceptor(ctx, in, info, handler) } @@ -656,54 +617,6 @@ func (m *CallCodeParam) MarshalTo(dAtA []byte) (int, error) { return i, nil } -func (m *PayloadParam) Marshal() (dAtA []byte, err error) { - size := m.Size() - dAtA = make([]byte, size) - n, err := m.MarshalTo(dAtA) - if err != nil { - return nil, err - } - return dAtA[:n], nil -} - -func (m *PayloadParam) MarshalTo(dAtA []byte) (int, error) { - var i int - _ = i - var l int - _ = l - if m.CallTx != nil { - dAtA[i] = 0xa - i++ - i = encodeVarintRpctransact(dAtA, i, uint64(m.CallTx.Size())) - n2, err := m.CallTx.MarshalTo(dAtA[i:]) - if err != nil { - return 0, err - } - i += n2 - } - if m.SendTx != nil { - dAtA[i] = 0x12 - i++ - i = encodeVarintRpctransact(dAtA, i, uint64(m.SendTx.Size())) - n3, err := m.SendTx.MarshalTo(dAtA[i:]) - if err != nil { - return 0, err - } - i += n3 - } - if m.NameTx != nil { - dAtA[i] = 0x1a - i++ - i = encodeVarintRpctransact(dAtA, i, uint64(m.NameTx.Size())) - n4, err := m.NameTx.MarshalTo(dAtA[i:]) - if err != nil { - return 0, err - } - i += n4 - } - return i, nil -} - func (m *TxEnvelope) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) @@ -723,11 +636,11 @@ func (m *TxEnvelope) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintRpctransact(dAtA, i, uint64(m.Envelope.Size())) - n5, err := m.Envelope.MarshalTo(dAtA[i:]) + n2, err := m.Envelope.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n5 + i += n2 } return i, nil } @@ -751,21 +664,21 @@ func (m *TxEnvelopeParam) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintRpctransact(dAtA, i, uint64(m.Envelope.Size())) - n6, err := m.Envelope.MarshalTo(dAtA[i:]) + n3, err := m.Envelope.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n6 + i += n3 } if m.Payload != nil { dAtA[i] = 0x12 i++ i = encodeVarintRpctransact(dAtA, i, uint64(m.Payload.Size())) - n7, err := m.Payload.MarshalTo(dAtA[i:]) + n4, err := m.Payload.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n7 + i += n4 } return i, nil } @@ -795,24 +708,6 @@ func (m *CallCodeParam) Size() (n int) { return n } -func (m *PayloadParam) Size() (n int) { - var l int - _ = l - if m.CallTx != nil { - l = m.CallTx.Size() - n += 1 + l + sovRpctransact(uint64(l)) - } - if m.SendTx != nil { - l = m.SendTx.Size() - n += 1 + l + sovRpctransact(uint64(l)) - } - if m.NameTx != nil { - l = m.NameTx.Size() - n += 1 + l + sovRpctransact(uint64(l)) - } - return n -} - func (m *TxEnvelope) Size() (n int) { var l int _ = l @@ -992,155 +887,6 @@ func (m *CallCodeParam) Unmarshal(dAtA []byte) error { } return nil } -func (m *PayloadParam) Unmarshal(dAtA []byte) error { - l := len(dAtA) - iNdEx := 0 - for iNdEx < l { - preIndex := iNdEx - var wire uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowRpctransact - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - wire |= (uint64(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - fieldNum := int32(wire >> 3) - wireType := int(wire & 0x7) - if wireType == 4 { - return fmt.Errorf("proto: PayloadParam: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: PayloadParam: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field CallTx", wireType) - } - var msglen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowRpctransact - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - msglen |= (int(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - if msglen < 0 { - return ErrInvalidLengthRpctransact - } - postIndex := iNdEx + msglen - if postIndex > l { - return io.ErrUnexpectedEOF - } - if m.CallTx == nil { - m.CallTx = &payload.CallTx{} - } - if err := m.CallTx.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - case 2: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field SendTx", wireType) - } - var msglen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowRpctransact - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - msglen |= (int(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - if msglen < 0 { - return ErrInvalidLengthRpctransact - } - postIndex := iNdEx + msglen - if postIndex > l { - return io.ErrUnexpectedEOF - } - if m.SendTx == nil { - m.SendTx = &payload.SendTx{} - } - if err := m.SendTx.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - case 3: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field NameTx", wireType) - } - var msglen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowRpctransact - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - msglen |= (int(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - if msglen < 0 { - return ErrInvalidLengthRpctransact - } - postIndex := iNdEx + msglen - if postIndex > l { - return io.ErrUnexpectedEOF - } - if m.NameTx == nil { - m.NameTx = &payload.NameTx{} - } - if err := m.NameTx.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - default: - iNdEx = preIndex - skippy, err := skipRpctransact(dAtA[iNdEx:]) - if err != nil { - return err - } - if skippy < 0 { - return ErrInvalidLengthRpctransact - } - if (iNdEx + skippy) > l { - return io.ErrUnexpectedEOF - } - iNdEx += skippy - } - } - - if iNdEx > l { - return io.ErrUnexpectedEOF - } - return nil -} func (m *TxEnvelope) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 @@ -1313,7 +1059,7 @@ func (m *TxEnvelopeParam) Unmarshal(dAtA []byte) error { return io.ErrUnexpectedEOF } if m.Payload == nil { - m.Payload = &PayloadParam{} + m.Payload = &payload.Any{} } if err := m.Payload.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { return err @@ -1449,40 +1195,37 @@ func init() { proto.RegisterFile("rpctransact.proto", fileDescriptorRpctransact) func init() { golang_proto.RegisterFile("rpctransact.proto", fileDescriptorRpctransact) } var fileDescriptorRpctransact = []byte{ - // 552 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb4, 0x54, 0xcd, 0x6e, 0xd3, 0x40, - 0x10, 0xc6, 0xfc, 0x84, 0x76, 0x92, 0x28, 0x74, 0x2f, 0x84, 0x08, 0x25, 0x28, 0x17, 0x10, 0x6a, - 0xed, 0xa8, 0xe5, 0x88, 0x40, 0x49, 0x68, 0x8f, 0xa8, 0x72, 0x2c, 0x24, 0xb8, 0x6d, 0xec, 0xc5, - 0x8d, 0x64, 0x7b, 0xad, 0xf5, 0x06, 0x36, 0x8f, 0xc0, 0x89, 0x67, 0xe8, 0x9b, 0x70, 0xcc, 0x91, - 0x73, 0x0f, 0x11, 0x4a, 0x5f, 0x04, 0xed, 0x4f, 0x60, 0x6d, 0x9a, 0x96, 0x4b, 0x6f, 0xe3, 0x6f, - 0x66, 0xbe, 0x99, 0xef, 0xd3, 0x8e, 0x61, 0x8f, 0xe5, 0x21, 0x67, 0x38, 0x2b, 0x70, 0xc8, 0xdd, - 0x9c, 0x51, 0x4e, 0x51, 0xdd, 0x82, 0x3a, 0x07, 0xf1, 0x8c, 0x9f, 0xcd, 0xa7, 0x6e, 0x48, 0x53, - 0x2f, 0xa6, 0x31, 0xf5, 0x54, 0xcd, 0x74, 0xfe, 0x59, 0x7d, 0xa9, 0x0f, 0x15, 0xe9, 0xde, 0x0e, - 0x10, 0x41, 0x42, 0x13, 0x37, 0x73, 0xbc, 0x48, 0x28, 0x8e, 0xcc, 0xe7, 0x2e, 0x17, 0x85, 0x0e, - 0xfb, 0xdf, 0x1d, 0x68, 0x8e, 0x71, 0x92, 0x8c, 0x69, 0x44, 0x4e, 0x31, 0xc3, 0x29, 0xfa, 0x00, - 0xf5, 0x13, 0x46, 0xd3, 0x61, 0x14, 0x31, 0x52, 0x14, 0x6d, 0xe7, 0x99, 0xf3, 0xa2, 0x31, 0x7a, - 0xb5, 0x5c, 0xf5, 0xee, 0x5c, 0xac, 0x7a, 0xfb, 0xd6, 0x0e, 0x67, 0x8b, 0x9c, 0xb0, 0x84, 0x44, - 0x31, 0x61, 0xde, 0x74, 0xce, 0x18, 0xfd, 0xea, 0x85, 0x6c, 0x91, 0x73, 0xea, 0x9a, 0x5e, 0xdf, - 0x26, 0x42, 0x08, 0xee, 0xcb, 0x21, 0xed, 0xbb, 0x92, 0xd0, 0x57, 0xb1, 0xc4, 0xde, 0x61, 0x8e, - 0xdb, 0xf7, 0x34, 0x26, 0xe3, 0xfe, 0x37, 0x07, 0x1a, 0xa7, 0x7a, 0x5d, 0xbd, 0xd0, 0x73, 0xa8, - 0xc9, 0x0d, 0x03, 0xa1, 0x76, 0xa9, 0x1f, 0xb6, 0xdc, 0x8d, 0x1a, 0x0d, 0xfb, 0x26, 0x2d, 0x0b, - 0x27, 0x24, 0x8b, 0x02, 0xa1, 0x66, 0xd8, 0x85, 0x1a, 0xf6, 0x4d, 0x5a, 0x16, 0xbe, 0xc7, 0x29, - 0x09, 0x84, 0x1a, 0x6c, 0x17, 0x6a, 0xd8, 0x37, 0xe9, 0x7e, 0x0c, 0x10, 0x88, 0xe3, 0xec, 0x0b, - 0x49, 0x68, 0x4e, 0xd0, 0x47, 0xd8, 0xd9, 0xc4, 0x66, 0x95, 0xa6, 0x2b, 0x9d, 0xdc, 0x80, 0x23, - 0xf7, 0x62, 0xd5, 0x7b, 0x79, 0xbd, 0x43, 0x76, 0xbd, 0xff, 0x87, 0xae, 0x7f, 0xee, 0x40, 0xeb, - 0xef, 0x24, 0xad, 0xfb, 0xf6, 0xc6, 0xa1, 0x23, 0x78, 0x68, 0x2c, 0x36, 0x56, 0x3d, 0x71, 0xed, - 0xc7, 0x67, 0xdb, 0xef, 0x6f, 0x2a, 0x0f, 0xcf, 0x1f, 0xc0, 0x4e, 0x60, 0x4a, 0xd0, 0x08, 0x5a, - 0x23, 0x46, 0x71, 0x14, 0xe2, 0x82, 0x07, 0x62, 0xb2, 0xc8, 0x42, 0xf4, 0xb4, 0xc4, 0x51, 0x51, - 0xd3, 0xd9, 0x73, 0xd5, 0x7b, 0x0c, 0xc4, 0xb1, 0x20, 0xe1, 0x9c, 0xcf, 0x68, 0x86, 0xde, 0xc0, - 0x23, 0x8b, 0x63, 0x58, 0xdc, 0x4c, 0xd2, 0x50, 0x06, 0xf8, 0x24, 0x24, 0xb3, 0x9c, 0xa3, 0xb7, - 0x50, 0x9b, 0xcc, 0xe2, 0x2c, 0x10, 0x37, 0x74, 0x3d, 0xde, 0x92, 0x45, 0x43, 0xa8, 0x9f, 0x50, - 0x96, 0xce, 0x13, 0xcc, 0x49, 0x20, 0xd0, 0x76, 0x13, 0xb6, 0x53, 0x0c, 0x00, 0xf4, 0xeb, 0x53, - 0x16, 0x54, 0x9f, 0xe6, 0x55, 0xaa, 0xf7, 0xa1, 0xae, 0x93, 0x5a, 0xf0, 0x3f, 0x2d, 0x65, 0x8d, - 0x1e, 0xec, 0x1a, 0xfe, 0x59, 0xfa, 0x5f, 0xf4, 0xaf, 0x35, 0xbd, 0x3c, 0x2f, 0xd9, 0xd2, 0x29, - 0x2d, 0x5e, 0xba, 0xf4, 0xab, 0xba, 0x07, 0x00, 0xfa, 0x46, 0x2a, 0x72, 0x34, 0xb8, 0x45, 0x8e, - 0x4e, 0x56, 0xe5, 0x98, 0x96, 0xb2, 0x9c, 0x01, 0x80, 0x3e, 0xad, 0x0a, 0xbf, 0x06, 0xb7, 0xf0, - 0xeb, 0x64, 0x95, 0xdf, 0xb4, 0x94, 0xf8, 0x47, 0xe3, 0xe5, 0xba, 0xeb, 0xfc, 0x5c, 0x77, 0x9d, - 0x5f, 0xeb, 0xae, 0xf3, 0xe3, 0xb2, 0xeb, 0x2c, 0x2f, 0xbb, 0xce, 0xa7, 0x83, 0xeb, 0x8f, 0x84, - 0xe5, 0xa1, 0x67, 0xb9, 0x34, 0xad, 0xa9, 0x5f, 0xe3, 0xd1, 0xef, 0x00, 0x00, 0x00, 0xff, 0xff, - 0x0f, 0x15, 0x24, 0xfe, 0x91, 0x05, 0x00, 0x00, + // 506 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb4, 0x54, 0xcf, 0x6f, 0xd3, 0x30, + 0x18, 0x25, 0xfc, 0x18, 0xdb, 0x97, 0x56, 0x65, 0xbe, 0x50, 0x55, 0x28, 0x45, 0x3d, 0x20, 0x84, + 0xb6, 0xa4, 0x2a, 0x3b, 0x22, 0x50, 0x53, 0xb6, 0x23, 0x9a, 0xd2, 0x08, 0x09, 0x6e, 0xae, 0x63, + 0xb2, 0x48, 0x49, 0x1c, 0x39, 0x0e, 0x24, 0x7f, 0x05, 0x97, 0xfd, 0x41, 0x1c, 0x7b, 0xe4, 0xbc, + 0x43, 0x85, 0xba, 0x7f, 0x04, 0xc5, 0x4e, 0x47, 0xd2, 0xae, 0x2b, 0x97, 0xdd, 0x9e, 0xdf, 0x97, + 0xf7, 0xfc, 0x3d, 0x7f, 0x76, 0xe0, 0x90, 0x27, 0x44, 0x70, 0x1c, 0xa7, 0x98, 0x08, 0x33, 0xe1, + 0x4c, 0x30, 0xa4, 0xd7, 0xa8, 0xde, 0xb1, 0x1f, 0x88, 0x8b, 0x6c, 0x66, 0x12, 0x16, 0x59, 0x3e, + 0xf3, 0x99, 0x25, 0xbf, 0x99, 0x65, 0xdf, 0xe4, 0x4a, 0x2e, 0x24, 0x52, 0xda, 0x1e, 0xd0, 0x9c, + 0x92, 0x0a, 0xb7, 0x13, 0x5c, 0x84, 0x0c, 0x7b, 0xd5, 0xf2, 0x40, 0xe4, 0xa9, 0x82, 0x83, 0x9f, + 0x1a, 0xb4, 0x27, 0x38, 0x0c, 0x27, 0xcc, 0xa3, 0xe7, 0x98, 0xe3, 0x08, 0x7d, 0x06, 0xfd, 0x8c, + 0xb3, 0x68, 0xec, 0x79, 0x9c, 0xa6, 0x69, 0x57, 0x7b, 0xa9, 0xbd, 0x6e, 0xd9, 0x27, 0xf3, 0x45, + 0xff, 0xc1, 0xd5, 0xa2, 0x7f, 0x54, 0xeb, 0xe1, 0xa2, 0x48, 0x28, 0x0f, 0xa9, 0xe7, 0x53, 0x6e, + 0xcd, 0x32, 0xce, 0xd9, 0x0f, 0x8b, 0xf0, 0x22, 0x11, 0xcc, 0xac, 0xb4, 0x4e, 0xdd, 0x08, 0x21, + 0x78, 0x5c, 0x6e, 0xd2, 0x7d, 0x58, 0x1a, 0x3a, 0x12, 0x97, 0xdc, 0x47, 0x2c, 0x70, 0xf7, 0x91, + 0xe2, 0x4a, 0x3c, 0xf0, 0x01, 0xdc, 0xfc, 0x34, 0xfe, 0x4e, 0x43, 0x96, 0x50, 0xf4, 0x05, 0xf6, + 0x57, 0x58, 0xb6, 0xa2, 0x8f, 0xda, 0x66, 0xd9, 0xfd, 0x8a, 0xb4, 0xcd, 0xab, 0x45, 0xff, 0xcd, + 0xdd, 0x5d, 0xd5, 0xbf, 0x77, 0x6e, 0xec, 0x06, 0x97, 0x1a, 0x74, 0xfe, 0xed, 0xa4, 0xc2, 0xdf, + 0xdf, 0x76, 0xe8, 0x15, 0x3c, 0x3d, 0x57, 0x53, 0x90, 0x47, 0xa0, 0x8f, 0x5a, 0xe6, 0x6a, 0x2a, + 0xe3, 0xb8, 0x70, 0x56, 0xc5, 0xd1, 0xe5, 0x13, 0xd8, 0x77, 0xab, 0x99, 0x23, 0x1b, 0x3a, 0x36, + 0x67, 0xd8, 0x23, 0x38, 0x15, 0x6e, 0x3e, 0x2d, 0x62, 0x82, 0x5e, 0x98, 0xf5, 0x7b, 0xb2, 0x16, + 0xa0, 0x77, 0x68, 0xca, 0xb1, 0xbb, 0xf9, 0x69, 0x4e, 0x49, 0x26, 0x02, 0x16, 0xa3, 0xf7, 0xf0, + 0xac, 0xe6, 0x31, 0x4e, 0x77, 0x9b, 0xb4, 0x64, 0x66, 0x87, 0x12, 0x1a, 0x24, 0x02, 0x7d, 0x80, + 0xbd, 0x69, 0xe0, 0xc7, 0x6e, 0xbe, 0x43, 0xf5, 0x7c, 0x4b, 0x15, 0x9d, 0x80, 0x7e, 0xc6, 0x78, + 0x94, 0x85, 0x58, 0x50, 0x37, 0x47, 0x8d, 0xdc, 0xdb, 0x55, 0x43, 0x80, 0xf2, 0x62, 0x56, 0xa9, + 0x3b, 0x37, 0x22, 0x45, 0xde, 0x16, 0xf4, 0x08, 0x74, 0x55, 0x54, 0x19, 0x37, 0x24, 0xcd, 0x58, + 0x16, 0x1c, 0x54, 0xfe, 0x41, 0xf4, 0x5f, 0xf6, 0xef, 0x94, 0x7d, 0x79, 0x71, 0x4b, 0x49, 0xaf, + 0xd1, 0x78, 0xe3, 0x0d, 0xdd, 0xa6, 0x1e, 0x02, 0x4c, 0x69, 0xec, 0x6d, 0xc4, 0x51, 0xe4, 0x96, + 0x38, 0xaa, 0xb8, 0x1e, 0xa7, 0x92, 0x34, 0xe3, 0x0c, 0x01, 0x3e, 0xe1, 0x88, 0x6e, 0xf8, 0x2b, + 0x72, 0x8b, 0xbf, 0x2a, 0xae, 0xfb, 0x57, 0x92, 0x86, 0xbf, 0x3d, 0x99, 0x2f, 0x0d, 0xed, 0xf7, + 0xd2, 0xd0, 0xfe, 0x2c, 0x0d, 0xed, 0xd7, 0xb5, 0xa1, 0xcd, 0xaf, 0x0d, 0xed, 0xeb, 0xf1, 0xdd, + 0x4f, 0x81, 0x27, 0xc4, 0xaa, 0x9d, 0xd2, 0x6c, 0x4f, 0xfe, 0x74, 0xde, 0xfe, 0x0d, 0x00, 0x00, + 0xff, 0xff, 0xd4, 0x01, 0x16, 0xdf, 0xeb, 0x04, 0x00, 0x00, } diff --git a/rpc/rpctransact/transact_server.go b/rpc/rpctransact/transact_server.go index ab3a8c6e..d2e0a9b4 100644 --- a/rpc/rpctransact/transact_server.go +++ b/rpc/rpctransact/transact_server.go @@ -52,8 +52,8 @@ func (ts *transactServer) SignTx(ctx context.Context, param *TxEnvelopeParam) (* }, nil } -func (ts *transactServer) FormulateTx(ctx context.Context, param *PayloadParam) (*TxEnvelope, error) { - txEnv := param.Envelope(ts.transactor.Tip.ChainID()) +func (ts *transactServer) FormulateTx(ctx context.Context, param *payload.Any) (*TxEnvelope, error) { + txEnv := EnvelopeFromAny(ts.transactor.Tip.ChainID(), param) if txEnv == nil { return nil, fmt.Errorf("no payload provided to FormulateTx") } @@ -63,11 +63,11 @@ func (ts *transactServer) FormulateTx(ctx context.Context, param *PayloadParam) } func (ts *transactServer) CallTxSync(ctx context.Context, param *payload.CallTx) (*exec.TxExecution, error) { - return ts.BroadcastTxSync(ctx, txEnvelopeParam(param)) + return ts.BroadcastTxSync(ctx, &TxEnvelopeParam{Payload: param.Any()}) } func (ts *transactServer) CallTxAsync(ctx context.Context, param *payload.CallTx) (*txs.Receipt, error) { - return ts.BroadcastTxAsync(ctx, txEnvelopeParam(param)) + return ts.BroadcastTxAsync(ctx, &TxEnvelopeParam{Payload: param.Any()}) } func (ts *transactServer) CallTxSim(ctx context.Context, param *payload.CallTx) (*exec.TxExecution, error) { @@ -82,19 +82,19 @@ func (ts *transactServer) CallCodeSim(ctx context.Context, param *CallCodeParam) } func (ts *transactServer) SendTxSync(ctx context.Context, param *payload.SendTx) (*exec.TxExecution, error) { - return ts.BroadcastTxSync(ctx, txEnvelopeParam(param)) + return ts.BroadcastTxSync(ctx, &TxEnvelopeParam{Payload: param.Any()}) } func (ts *transactServer) SendTxAsync(ctx context.Context, param *payload.SendTx) (*txs.Receipt, error) { - return ts.BroadcastTxAsync(ctx, txEnvelopeParam(param)) + return ts.BroadcastTxAsync(ctx, &TxEnvelopeParam{Payload: param.Any()}) } func (ts *transactServer) NameTxSync(ctx context.Context, param *payload.NameTx) (*exec.TxExecution, error) { - return ts.BroadcastTxSync(ctx, txEnvelopeParam(param)) + return ts.BroadcastTxSync(ctx, &TxEnvelopeParam{Payload: param.Any()}) } func (ts *transactServer) NameTxAsync(ctx context.Context, param *payload.NameTx) (*txs.Receipt, error) { - return ts.BroadcastTxAsync(ctx, txEnvelopeParam(param)) + return ts.BroadcastTxAsync(ctx, &TxEnvelopeParam{Payload: param.Any()}) } func (te *TxEnvelopeParam) GetEnvelope(chainID string) *txs.Envelope { @@ -105,44 +105,26 @@ func (te *TxEnvelopeParam) GetEnvelope(chainID string) *txs.Envelope { return te.Envelope } if te.Payload != nil { - return te.Payload.Envelope(chainID) + return EnvelopeFromAny(chainID, te.Payload) } return nil } -func (pp *PayloadParam) Envelope(chainID string) *txs.Envelope { - if pp.CallTx != nil { - return txs.Enclose(chainID, pp.CallTx) +func EnvelopeFromAny(chainID string, p *payload.Any) *txs.Envelope { + if p.CallTx != nil { + return txs.Enclose(chainID, p.CallTx) } - if pp.SendTx != nil { - return txs.Enclose(chainID, pp.SendTx) + if p.SendTx != nil { + return txs.Enclose(chainID, p.SendTx) } - if pp.NameTx != nil { - return txs.Enclose(chainID, pp.NameTx) + if p.NameTx != nil { + return txs.Enclose(chainID, p.NameTx) } - return nil -} - -func txEnvelopeParam(pl payload.Payload) *TxEnvelopeParam { - switch tx := pl.(type) { - case *payload.CallTx: - return &TxEnvelopeParam{ - Payload: &PayloadParam{ - CallTx: tx, - }, - } - case *payload.SendTx: - return &TxEnvelopeParam{ - Payload: &PayloadParam{ - SendTx: tx, - }, - } - case *payload.NameTx: - return &TxEnvelopeParam{ - Payload: &PayloadParam{ - NameTx: tx, - }, - } + if p.PermsTx != nil { + return txs.Enclose(chainID, p.PermsTx) + } + if p.GovTx != nil { + return txs.Enclose(chainID, p.GovTx) } return nil } diff --git a/rpc/service.go b/rpc/service.go index 42ebc1cf..3c266ad2 100644 --- a/rpc/service.go +++ b/rpc/service.go @@ -22,11 +22,11 @@ import ( "github.com/hyperledger/burrow/acm" "github.com/hyperledger/burrow/acm/state" + "github.com/hyperledger/burrow/acm/validator" + "github.com/hyperledger/burrow/bcm" "github.com/hyperledger/burrow/binary" - bcm "github.com/hyperledger/burrow/blockchain" - "github.com/hyperledger/burrow/consensus/tendermint/query" + "github.com/hyperledger/burrow/consensus/tendermint" "github.com/hyperledger/burrow/crypto" - "github.com/hyperledger/burrow/execution" "github.com/hyperledger/burrow/execution/names" "github.com/hyperledger/burrow/logging" "github.com/hyperledger/burrow/logging/structure" @@ -45,31 +45,24 @@ type Service struct { state state.IterableReader nameReg names.IterableReader blockchain bcm.BlockchainInfo - transactor *execution.Transactor - nodeView *query.NodeView + nodeView *tendermint.NodeView logger *logging.Logger } -func NewService(state state.IterableReader, nameReg names.IterableReader, - blockchain bcm.BlockchainInfo, transactor *execution.Transactor, nodeView *query.NodeView, - logger *logging.Logger) *Service { +// Service provides an internal query and information service with serialisable return types on which can accomodate +// a number of transport front ends +func NewService(state state.IterableReader, nameReg names.IterableReader, blockchain bcm.BlockchainInfo, + nodeView *tendermint.NodeView, logger *logging.Logger) *Service { return &Service{ state: state, nameReg: nameReg, blockchain: blockchain, - transactor: transactor, nodeView: nodeView, logger: logger.With(structure.ComponentKey, "Service"), } } -// Get a Transactor providing methods for delegating signing and the core BroadcastTx function for publishing -// transactions to the network -func (s *Service) Transactor() *execution.Transactor { - return s.transactor -} - func (s *Service) State() state.Reader { return s.state } @@ -117,7 +110,7 @@ func (s *Service) Status() (*ResultStatus, error) { return &ResultStatus{ NodeInfo: s.nodeView.NodeInfo(), GenesisHash: s.blockchain.GenesisHash(), - PubKey: publicKey, + PublicKey: publicKey, LatestBlockHash: latestBlockHash, LatestBlockHeight: latestHeight, LatestBlockTime: latestBlockTime, @@ -157,6 +150,7 @@ func (s *Service) NetInfo() (*ResultNetInfo, error) { return nil, err } return &ResultNetInfo{ + ThisNode: s.nodeView.NodeInfo(), Listening: listening, Listeners: listeners, Peers: peers.Peers, @@ -242,7 +236,7 @@ func (s *Service) GetAccountHumanReadable(address crypto.Address) (*ResultGetAcc if acc == nil { return &ResultGetAccountHumanReadable{}, nil } - perms, err := permission.BasePermissionsToStringList(acc.Permissions().Base) + perms := permission.BasePermissionsToStringList(acc.Permissions().Base) if acc == nil { return &ResultGetAccountHumanReadable{}, nil } @@ -323,10 +317,11 @@ func (s *Service) ListBlocks(minHeight, maxHeight uint64) (*ResultListBlocks, er } func (s *Service) ListValidators() (*ResultListValidators, error) { - concreteValidators := make([]*acm.ConcreteValidator, 0, s.blockchain.NumValidators()) - s.blockchain.IterateValidators(func(id crypto.Addressable, power *big.Int) (stop bool) { - concreteValidators = append(concreteValidators, &acm.ConcreteValidator{ - Address: id.Address(), + validators := make([]*validator.Validator, 0, s.blockchain.NumValidators()) + s.blockchain.Validators().Iterate(func(id crypto.Addressable, power *big.Int) (stop bool) { + address := id.Address() + validators = append(validators, &validator.Validator{ + Address: &address, PublicKey: id.PublicKey(), Power: power.Uint64(), }) @@ -334,7 +329,7 @@ func (s *Service) ListValidators() (*ResultListValidators, error) { }) return &ResultListValidators{ BlockHeight: s.blockchain.LastBlockHeight(), - BondedValidators: concreteValidators, + BondedValidators: validators, UnbondingValidators: nil, }, nil } diff --git a/txs/amino_codec.go b/txs/amino_codec.go index 9d85480b..2ff42331 100644 --- a/txs/amino_codec.go +++ b/txs/amino_codec.go @@ -18,9 +18,9 @@ func NewAminoCodec() *aminoCodec { registerTx(cdc, &payload.CallTx{}) registerTx(cdc, &payload.BondTx{}) registerTx(cdc, &payload.UnbondTx{}) - registerTx(cdc, &payload.PermissionsTx{}) + registerTx(cdc, &payload.PermsTx{}) registerTx(cdc, &payload.NameTx{}) - registerTx(cdc, &payload.GovernanceTx{}) + registerTx(cdc, &payload.GovTx{}) return &aminoCodec{cdc} } diff --git a/txs/payload/bond_tx.go b/txs/payload/bond_tx.go index 59585b6e..f81b2133 100644 --- a/txs/payload/bond_tx.go +++ b/txs/payload/bond_tx.go @@ -54,3 +54,9 @@ func (tx *BondTx) AddOutput(addr crypto.Address, amt uint64) error { }) return nil } + +func (tx *BondTx) Any() *Any { + return &Any{ + BondTx: tx, + } +} diff --git a/txs/payload/call_tx.go b/txs/payload/call_tx.go index 68638de3..9855e296 100644 --- a/txs/payload/call_tx.go +++ b/txs/payload/call_tx.go @@ -59,3 +59,9 @@ func (tx *CallTx) CreatesContractAddress() *crypto.Address { address := crypto.NewContractAddress(tx.Input.Address, tx.Input.Sequence) return &address } + +func (tx *CallTx) Any() *Any { + return &Any{ + CallTx: tx, + } +} diff --git a/txs/payload/gov_tx.go b/txs/payload/gov_tx.go new file mode 100644 index 00000000..eb4e5a1d --- /dev/null +++ b/txs/payload/gov_tx.go @@ -0,0 +1,23 @@ +package payload + +import ( + "fmt" +) + +func (tx *GovTx) Type() Type { + return TypeGovernance +} + +func (tx *GovTx) GetInputs() []*TxInput { + return tx.Inputs +} + +func (tx *GovTx) String() string { + return fmt.Sprintf("GovTx{%v -> %v}", tx.Inputs, tx.AccountUpdates) +} + +func (tx *GovTx) Any() *Any { + return &Any{ + GovTx: tx, + } +} diff --git a/txs/payload/governance_tx.go b/txs/payload/governance_tx.go deleted file mode 100644 index 5f8bfdeb..00000000 --- a/txs/payload/governance_tx.go +++ /dev/null @@ -1,17 +0,0 @@ -package payload - -import ( - "fmt" -) - -func (tx *GovernanceTx) Type() Type { - return TypeGovernance -} - -func (tx *GovernanceTx) GetInputs() []*TxInput { - return tx.Inputs -} - -func (tx *GovernanceTx) String() string { - return fmt.Sprintf("GovernanceTx{%v -> %v}", tx.Inputs, tx.AccountUpdates) -} diff --git a/txs/payload/name_tx.go b/txs/payload/name_tx.go index 334fa6df..13f85318 100644 --- a/txs/payload/name_tx.go +++ b/txs/payload/name_tx.go @@ -47,3 +47,9 @@ func (tx *NameTx) GetInputs() []*TxInput { func (tx *NameTx) String() string { return fmt.Sprintf("NameTx{%v -> %s: %s}", tx.Input, tx.Name, tx.Data) } + +func (tx *NameTx) Any() *Any { + return &Any{ + NameTx: tx, + } +} diff --git a/txs/payload/payload.go b/txs/payload/payload.go index f415d8f8..d55a8cad 100644 --- a/txs/payload/payload.go +++ b/txs/payload/payload.go @@ -1,5 +1,7 @@ package payload +import "fmt" + /* Payload (Transaction) is an atomic operation on the ledger state. @@ -13,7 +15,7 @@ Validation Txs: - UnbondTx Validator leaves Admin Txs: - - PermissionsTx + - PermsTx */ type Type uint32 @@ -42,8 +44,8 @@ var nameFromType = map[Type]string{ TypeName: "NameTx", TypeBond: "BondTx", TypeUnbond: "UnbondTx", - TypePermissions: "PermissionsTx", - TypeGovernance: "GovernanceTx", + TypePermissions: "PermsTx", + TypeGovernance: "GovTx", } var typeFromName = make(map[string]Type) @@ -88,24 +90,50 @@ type Payload interface { String() string GetInputs() []*TxInput Type() Type + Any() *Any // The serialised size in bytes Size() int } -func New(txType Type) Payload { +type UnknownTx struct { +} + +func (UnknownTx) String() string { + panic("implement me") +} + +func (UnknownTx) GetInputs() []*TxInput { + panic("implement me") +} + +func (UnknownTx) Type() Type { + panic("implement me") +} + +func (UnknownTx) Any() *Any { + panic("implement me") +} + +func (UnknownTx) Size() int { + panic("implement me") +} + +func New(txType Type) (Payload, error) { switch txType { case TypeSend: - return &SendTx{} + return &SendTx{}, nil case TypeCall: - return &CallTx{} + return &CallTx{}, nil case TypeName: - return &NameTx{} + return &NameTx{}, nil case TypeBond: - return &BondTx{} + return &BondTx{}, nil case TypeUnbond: - return &UnbondTx{} + return &UnbondTx{}, nil case TypePermissions: - return &PermissionsTx{} + return &PermsTx{}, nil + case TypeGovernance: + return &GovTx{}, nil } - return nil + return nil, fmt.Errorf("unknown payload type: %d", txType) } diff --git a/txs/payload/payload.pb.go b/txs/payload/payload.pb.go index a5e27c74..f1e5755e 100644 --- a/txs/payload/payload.pb.go +++ b/txs/payload/payload.pb.go @@ -8,16 +8,16 @@ payload.proto It has these top-level messages: - AnyPayload + Any TxInput TxOutput CallTx SendTx - PermissionsTx + PermsTx NameTx BondTx UnbondTx - GovernanceTx + GovTx */ package payload @@ -46,56 +46,72 @@ var _ = math.Inf // proto package needs to be updated. const _ = proto.GoGoProtoPackageIsVersion2 // please upgrade the proto package -type AnyPayload struct { - CallTx *CallTx `protobuf:"bytes,1,opt,name=CallTx" json:"CallTx,omitempty"` - SendTx *SendTx `protobuf:"bytes,2,opt,name=SendTx" json:"SendTx,omitempty"` - NameTx *NameTx `protobuf:"bytes,3,opt,name=NameTx" json:"NameTx,omitempty"` - PermissionsTx *PermissionsTx `protobuf:"bytes,4,opt,name=PermissionsTx" json:"PermissionsTx,omitempty"` - GovernanceTx *GovernanceTx `protobuf:"bytes,5,opt,name=GovernanceTx" json:"GovernanceTx,omitempty"` +type Any struct { + CallTx *CallTx `protobuf:"bytes,1,opt,name=CallTx" json:"CallTx,omitempty"` + SendTx *SendTx `protobuf:"bytes,2,opt,name=SendTx" json:"SendTx,omitempty"` + NameTx *NameTx `protobuf:"bytes,3,opt,name=NameTx" json:"NameTx,omitempty"` + PermsTx *PermsTx `protobuf:"bytes,4,opt,name=PermsTx" json:"PermsTx,omitempty"` + GovTx *GovTx `protobuf:"bytes,5,opt,name=GovTx" json:"GovTx,omitempty"` + BondTx *BondTx `protobuf:"bytes,6,opt,name=BondTx" json:"BondTx,omitempty"` + UnbondTx *UnbondTx `protobuf:"bytes,7,opt,name=UnbondTx" json:"UnbondTx,omitempty"` } -func (m *AnyPayload) Reset() { *m = AnyPayload{} } -func (m *AnyPayload) String() string { return proto.CompactTextString(m) } -func (*AnyPayload) ProtoMessage() {} -func (*AnyPayload) Descriptor() ([]byte, []int) { return fileDescriptorPayload, []int{0} } +func (m *Any) Reset() { *m = Any{} } +func (m *Any) String() string { return proto.CompactTextString(m) } +func (*Any) ProtoMessage() {} +func (*Any) Descriptor() ([]byte, []int) { return fileDescriptorPayload, []int{0} } -func (m *AnyPayload) GetCallTx() *CallTx { +func (m *Any) GetCallTx() *CallTx { if m != nil { return m.CallTx } return nil } -func (m *AnyPayload) GetSendTx() *SendTx { +func (m *Any) GetSendTx() *SendTx { if m != nil { return m.SendTx } return nil } -func (m *AnyPayload) GetNameTx() *NameTx { +func (m *Any) GetNameTx() *NameTx { if m != nil { return m.NameTx } return nil } -func (m *AnyPayload) GetPermissionsTx() *PermissionsTx { +func (m *Any) GetPermsTx() *PermsTx { if m != nil { - return m.PermissionsTx + return m.PermsTx } return nil } -func (m *AnyPayload) GetGovernanceTx() *GovernanceTx { +func (m *Any) GetGovTx() *GovTx { if m != nil { - return m.GovernanceTx + return m.GovTx } return nil } -func (*AnyPayload) XXX_MessageName() string { - return "payload.AnyPayload" +func (m *Any) GetBondTx() *BondTx { + if m != nil { + return m.BondTx + } + return nil +} + +func (m *Any) GetUnbondTx() *UnbondTx { + if m != nil { + return m.UnbondTx + } + return nil +} + +func (*Any) XXX_MessageName() string { + return "payload.Any" } // An input to a transaction that may carry an Amount as a charge and whose sequence number must be one greater than @@ -214,33 +230,33 @@ func (*SendTx) XXX_MessageName() string { } // An update to the on-chain permissions -type PermissionsTx struct { +type PermsTx struct { // The permission moderator Input *TxInput `protobuf:"bytes,1,opt,name=Input" json:"Input,omitempty"` // The modified permissions PermArgs permission.PermArgs `protobuf:"bytes,2,opt,name=PermArgs" json:"PermArgs"` } -func (m *PermissionsTx) Reset() { *m = PermissionsTx{} } -func (*PermissionsTx) ProtoMessage() {} -func (*PermissionsTx) Descriptor() ([]byte, []int) { return fileDescriptorPayload, []int{5} } +func (m *PermsTx) Reset() { *m = PermsTx{} } +func (*PermsTx) ProtoMessage() {} +func (*PermsTx) Descriptor() ([]byte, []int) { return fileDescriptorPayload, []int{5} } -func (m *PermissionsTx) GetInput() *TxInput { +func (m *PermsTx) GetInput() *TxInput { if m != nil { return m.Input } return nil } -func (m *PermissionsTx) GetPermArgs() permission.PermArgs { +func (m *PermsTx) GetPermArgs() permission.PermArgs { if m != nil { return m.PermArgs } return permission.PermArgs{} } -func (*PermissionsTx) XXX_MessageName() string { - return "payload.PermissionsTx" +func (*PermsTx) XXX_MessageName() string { + return "payload.PermsTx" } // A request to claim a globally unique name across the entire chain with some optional data storage leased for a fee @@ -318,21 +334,21 @@ func (*UnbondTx) XXX_MessageName() string { return "payload.UnbondTx" } -type GovernanceTx struct { +type GovTx struct { Inputs []*TxInput `protobuf:"bytes,1,rep,name=Inputs" json:"Inputs,omitempty"` AccountUpdates []*spec.TemplateAccount `protobuf:"bytes,2,rep,name=AccountUpdates" json:"AccountUpdates,omitempty"` } -func (m *GovernanceTx) Reset() { *m = GovernanceTx{} } -func (*GovernanceTx) ProtoMessage() {} -func (*GovernanceTx) Descriptor() ([]byte, []int) { return fileDescriptorPayload, []int{9} } +func (m *GovTx) Reset() { *m = GovTx{} } +func (*GovTx) ProtoMessage() {} +func (*GovTx) Descriptor() ([]byte, []int) { return fileDescriptorPayload, []int{9} } -func (*GovernanceTx) XXX_MessageName() string { - return "payload.GovernanceTx" +func (*GovTx) XXX_MessageName() string { + return "payload.GovTx" } func init() { - proto.RegisterType((*AnyPayload)(nil), "payload.AnyPayload") - golang_proto.RegisterType((*AnyPayload)(nil), "payload.AnyPayload") + proto.RegisterType((*Any)(nil), "payload.Any") + golang_proto.RegisterType((*Any)(nil), "payload.Any") proto.RegisterType((*TxInput)(nil), "payload.TxInput") golang_proto.RegisterType((*TxInput)(nil), "payload.TxInput") proto.RegisterType((*TxOutput)(nil), "payload.TxOutput") @@ -341,18 +357,18 @@ func init() { golang_proto.RegisterType((*CallTx)(nil), "payload.CallTx") proto.RegisterType((*SendTx)(nil), "payload.SendTx") golang_proto.RegisterType((*SendTx)(nil), "payload.SendTx") - proto.RegisterType((*PermissionsTx)(nil), "payload.PermissionsTx") - golang_proto.RegisterType((*PermissionsTx)(nil), "payload.PermissionsTx") + proto.RegisterType((*PermsTx)(nil), "payload.PermsTx") + golang_proto.RegisterType((*PermsTx)(nil), "payload.PermsTx") proto.RegisterType((*NameTx)(nil), "payload.NameTx") golang_proto.RegisterType((*NameTx)(nil), "payload.NameTx") proto.RegisterType((*BondTx)(nil), "payload.BondTx") golang_proto.RegisterType((*BondTx)(nil), "payload.BondTx") proto.RegisterType((*UnbondTx)(nil), "payload.UnbondTx") golang_proto.RegisterType((*UnbondTx)(nil), "payload.UnbondTx") - proto.RegisterType((*GovernanceTx)(nil), "payload.GovernanceTx") - golang_proto.RegisterType((*GovernanceTx)(nil), "payload.GovernanceTx") + proto.RegisterType((*GovTx)(nil), "payload.GovTx") + golang_proto.RegisterType((*GovTx)(nil), "payload.GovTx") } -func (m *AnyPayload) Marshal() (dAtA []byte, err error) { +func (m *Any) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) n, err := m.MarshalTo(dAtA) @@ -362,7 +378,7 @@ func (m *AnyPayload) Marshal() (dAtA []byte, err error) { return dAtA[:n], nil } -func (m *AnyPayload) MarshalTo(dAtA []byte) (int, error) { +func (m *Any) MarshalTo(dAtA []byte) (int, error) { var i int _ = i var l int @@ -397,26 +413,46 @@ func (m *AnyPayload) MarshalTo(dAtA []byte) (int, error) { } i += n3 } - if m.PermissionsTx != nil { + if m.PermsTx != nil { dAtA[i] = 0x22 i++ - i = encodeVarintPayload(dAtA, i, uint64(m.PermissionsTx.Size())) - n4, err := m.PermissionsTx.MarshalTo(dAtA[i:]) + i = encodeVarintPayload(dAtA, i, uint64(m.PermsTx.Size())) + n4, err := m.PermsTx.MarshalTo(dAtA[i:]) if err != nil { return 0, err } i += n4 } - if m.GovernanceTx != nil { + if m.GovTx != nil { dAtA[i] = 0x2a i++ - i = encodeVarintPayload(dAtA, i, uint64(m.GovernanceTx.Size())) - n5, err := m.GovernanceTx.MarshalTo(dAtA[i:]) + i = encodeVarintPayload(dAtA, i, uint64(m.GovTx.Size())) + n5, err := m.GovTx.MarshalTo(dAtA[i:]) if err != nil { return 0, err } i += n5 } + if m.BondTx != nil { + dAtA[i] = 0x32 + i++ + i = encodeVarintPayload(dAtA, i, uint64(m.BondTx.Size())) + n6, err := m.BondTx.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n6 + } + if m.UnbondTx != nil { + dAtA[i] = 0x3a + i++ + i = encodeVarintPayload(dAtA, i, uint64(m.UnbondTx.Size())) + n7, err := m.UnbondTx.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n7 + } return i, nil } @@ -438,11 +474,11 @@ func (m *TxInput) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintPayload(dAtA, i, uint64(m.Address.Size())) - n6, err := m.Address.MarshalTo(dAtA[i:]) + n8, err := m.Address.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n6 + i += n8 if m.Amount != 0 { dAtA[i] = 0x10 i++ @@ -474,11 +510,11 @@ func (m *TxOutput) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintPayload(dAtA, i, uint64(m.Address.Size())) - n7, err := m.Address.MarshalTo(dAtA[i:]) + n9, err := m.Address.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n7 + i += n9 if m.Amount != 0 { dAtA[i] = 0x10 i++ @@ -506,21 +542,21 @@ func (m *CallTx) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintPayload(dAtA, i, uint64(m.Input.Size())) - n8, err := m.Input.MarshalTo(dAtA[i:]) + n10, err := m.Input.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n8 + i += n10 } if m.Address != nil { dAtA[i] = 0x12 i++ i = encodeVarintPayload(dAtA, i, uint64(m.Address.Size())) - n9, err := m.Address.MarshalTo(dAtA[i:]) + n11, err := m.Address.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n9 + i += n11 } if m.GasLimit != 0 { dAtA[i] = 0x18 @@ -535,11 +571,11 @@ func (m *CallTx) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x2a i++ i = encodeVarintPayload(dAtA, i, uint64(m.Data.Size())) - n10, err := m.Data.MarshalTo(dAtA[i:]) + n12, err := m.Data.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n10 + i += n12 return i, nil } @@ -585,7 +621,7 @@ func (m *SendTx) MarshalTo(dAtA []byte) (int, error) { return i, nil } -func (m *PermissionsTx) Marshal() (dAtA []byte, err error) { +func (m *PermsTx) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) n, err := m.MarshalTo(dAtA) @@ -595,7 +631,7 @@ func (m *PermissionsTx) Marshal() (dAtA []byte, err error) { return dAtA[:n], nil } -func (m *PermissionsTx) MarshalTo(dAtA []byte) (int, error) { +func (m *PermsTx) MarshalTo(dAtA []byte) (int, error) { var i int _ = i var l int @@ -604,20 +640,20 @@ func (m *PermissionsTx) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintPayload(dAtA, i, uint64(m.Input.Size())) - n11, err := m.Input.MarshalTo(dAtA[i:]) + n13, err := m.Input.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n11 + i += n13 } dAtA[i] = 0x12 i++ i = encodeVarintPayload(dAtA, i, uint64(m.PermArgs.Size())) - n12, err := m.PermArgs.MarshalTo(dAtA[i:]) + n14, err := m.PermArgs.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n12 + i += n14 return i, nil } @@ -640,11 +676,11 @@ func (m *NameTx) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintPayload(dAtA, i, uint64(m.Input.Size())) - n13, err := m.Input.MarshalTo(dAtA[i:]) + n15, err := m.Input.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n13 + i += n15 } if len(m.Name) > 0 { dAtA[i] = 0x12 @@ -727,20 +763,20 @@ func (m *UnbondTx) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintPayload(dAtA, i, uint64(m.Input.Size())) - n14, err := m.Input.MarshalTo(dAtA[i:]) + n16, err := m.Input.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n14 + i += n16 } dAtA[i] = 0x12 i++ i = encodeVarintPayload(dAtA, i, uint64(m.Address.Size())) - n15, err := m.Address.MarshalTo(dAtA[i:]) + n17, err := m.Address.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n15 + i += n17 if m.Height != 0 { dAtA[i] = 0x18 i++ @@ -749,7 +785,7 @@ func (m *UnbondTx) MarshalTo(dAtA []byte) (int, error) { return i, nil } -func (m *GovernanceTx) Marshal() (dAtA []byte, err error) { +func (m *GovTx) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) n, err := m.MarshalTo(dAtA) @@ -759,7 +795,7 @@ func (m *GovernanceTx) Marshal() (dAtA []byte, err error) { return dAtA[:n], nil } -func (m *GovernanceTx) MarshalTo(dAtA []byte) (int, error) { +func (m *GovTx) MarshalTo(dAtA []byte) (int, error) { var i int _ = i var l int @@ -800,7 +836,7 @@ func encodeVarintPayload(dAtA []byte, offset int, v uint64) int { dAtA[offset] = uint8(v) return offset + 1 } -func (m *AnyPayload) Size() (n int) { +func (m *Any) Size() (n int) { var l int _ = l if m.CallTx != nil { @@ -815,12 +851,20 @@ func (m *AnyPayload) Size() (n int) { l = m.NameTx.Size() n += 1 + l + sovPayload(uint64(l)) } - if m.PermissionsTx != nil { - l = m.PermissionsTx.Size() + if m.PermsTx != nil { + l = m.PermsTx.Size() n += 1 + l + sovPayload(uint64(l)) } - if m.GovernanceTx != nil { - l = m.GovernanceTx.Size() + if m.GovTx != nil { + l = m.GovTx.Size() + n += 1 + l + sovPayload(uint64(l)) + } + if m.BondTx != nil { + l = m.BondTx.Size() + n += 1 + l + sovPayload(uint64(l)) + } + if m.UnbondTx != nil { + l = m.UnbondTx.Size() n += 1 + l + sovPayload(uint64(l)) } return n @@ -891,7 +935,7 @@ func (m *SendTx) Size() (n int) { return n } -func (m *PermissionsTx) Size() (n int) { +func (m *PermsTx) Size() (n int) { var l int _ = l if m.Input != nil { @@ -957,7 +1001,7 @@ func (m *UnbondTx) Size() (n int) { return n } -func (m *GovernanceTx) Size() (n int) { +func (m *GovTx) Size() (n int) { var l int _ = l if len(m.Inputs) > 0 { @@ -988,7 +1032,7 @@ func sovPayload(x uint64) (n int) { func sozPayload(x uint64) (n int) { return sovPayload(uint64((x << 1) ^ uint64((int64(x) >> 63)))) } -func (m *AnyPayload) Unmarshal(dAtA []byte) error { +func (m *Any) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -1011,10 +1055,10 @@ func (m *AnyPayload) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: AnyPayload: wiretype end group for non-group") + return fmt.Errorf("proto: Any: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: AnyPayload: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: Any: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: @@ -1118,7 +1162,7 @@ func (m *AnyPayload) Unmarshal(dAtA []byte) error { iNdEx = postIndex case 4: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field PermissionsTx", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field PermsTx", wireType) } var msglen int for shift := uint(0); ; shift += 7 { @@ -1142,16 +1186,82 @@ func (m *AnyPayload) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - if m.PermissionsTx == nil { - m.PermissionsTx = &PermissionsTx{} + if m.PermsTx == nil { + m.PermsTx = &PermsTx{} } - if err := m.PermissionsTx.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + if err := m.PermsTx.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { return err } iNdEx = postIndex case 5: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field GovernanceTx", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field GovTx", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPayload + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthPayload + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.GovTx == nil { + m.GovTx = &GovTx{} + } + if err := m.GovTx.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 6: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field BondTx", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPayload + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthPayload + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.BondTx == nil { + m.BondTx = &BondTx{} + } + if err := m.BondTx.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 7: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field UnbondTx", wireType) } var msglen int for shift := uint(0); ; shift += 7 { @@ -1175,10 +1285,10 @@ func (m *AnyPayload) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - if m.GovernanceTx == nil { - m.GovernanceTx = &GovernanceTx{} + if m.UnbondTx == nil { + m.UnbondTx = &UnbondTx{} } - if err := m.GovernanceTx.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + if err := m.UnbondTx.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { return err } iNdEx = postIndex @@ -1715,7 +1825,7 @@ func (m *SendTx) Unmarshal(dAtA []byte) error { } return nil } -func (m *PermissionsTx) Unmarshal(dAtA []byte) error { +func (m *PermsTx) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -1738,10 +1848,10 @@ func (m *PermissionsTx) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: PermissionsTx: wiretype end group for non-group") + return fmt.Errorf("proto: PermsTx: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: PermissionsTx: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: PermsTx: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: @@ -2232,7 +2342,7 @@ func (m *UnbondTx) Unmarshal(dAtA []byte) error { } return nil } -func (m *GovernanceTx) Unmarshal(dAtA []byte) error { +func (m *GovTx) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -2255,10 +2365,10 @@ func (m *GovernanceTx) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: GovernanceTx: wiretype end group for non-group") + return fmt.Errorf("proto: GovTx: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: GovernanceTx: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: GovTx: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: @@ -2453,46 +2563,47 @@ func init() { proto.RegisterFile("payload.proto", fileDescriptorPayload) } func init() { golang_proto.RegisterFile("payload.proto", fileDescriptorPayload) } var fileDescriptorPayload = []byte{ - // 652 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x55, 0xbf, 0x6f, 0xd3, 0x40, - 0x14, 0xee, 0x35, 0x6e, 0x62, 0x8e, 0x16, 0xca, 0x89, 0x56, 0x51, 0x86, 0x04, 0x75, 0x80, 0x22, - 0xa8, 0x83, 0xf8, 0x25, 0x51, 0x21, 0xa1, 0xb8, 0x88, 0xb6, 0x08, 0x85, 0xea, 0xea, 0x2e, 0x6c, - 0xfe, 0x71, 0x38, 0x16, 0xb1, 0xcf, 0xd8, 0x67, 0xb0, 0x37, 0x36, 0xd8, 0x59, 0x18, 0x3b, 0xf0, - 0x87, 0x30, 0x66, 0x64, 0x66, 0xa8, 0x50, 0xfa, 0x67, 0xb0, 0xa0, 0x3b, 0x9f, 0x5d, 0x27, 0x40, - 0x95, 0x82, 0xc4, 0x76, 0xef, 0x7d, 0xdf, 0xbb, 0xf7, 0xde, 0x77, 0xef, 0xd9, 0x70, 0x29, 0x34, - 0xb3, 0x21, 0x35, 0x1d, 0x2d, 0x8c, 0x28, 0xa3, 0xa8, 0x21, 0xcd, 0xd6, 0x86, 0xeb, 0xb1, 0x41, - 0x62, 0x69, 0x36, 0xf5, 0xbb, 0x2e, 0x75, 0x69, 0x57, 0xe0, 0x56, 0xf2, 0x52, 0x58, 0xc2, 0x10, - 0xa7, 0x3c, 0xae, 0xb5, 0x1c, 0x92, 0xc8, 0xf7, 0xe2, 0xd8, 0xa3, 0x81, 0xf4, 0xc0, 0x38, 0x24, - 0x76, 0x7e, 0x5e, 0x7b, 0x37, 0x0f, 0x61, 0x2f, 0xc8, 0xf6, 0xf2, 0xbb, 0xd1, 0x35, 0x58, 0xdf, - 0x32, 0x87, 0x43, 0x23, 0x6d, 0x82, 0x2b, 0x60, 0xfd, 0xfc, 0xed, 0x8b, 0x5a, 0x51, 0x44, 0xee, - 0xc6, 0x12, 0xe6, 0xc4, 0x7d, 0x12, 0x38, 0x46, 0xda, 0x9c, 0x9f, 0x22, 0xe6, 0x6e, 0x2c, 0x61, - 0x4e, 0xec, 0x9b, 0x3e, 0x31, 0xd2, 0x66, 0x6d, 0x8a, 0x98, 0xbb, 0xb1, 0x84, 0xd1, 0x43, 0xb8, - 0xb4, 0x57, 0x56, 0x1a, 0x1b, 0x69, 0x53, 0x11, 0xfc, 0xd5, 0x92, 0x3f, 0x81, 0xe2, 0x49, 0x32, - 0x7a, 0x00, 0x17, 0xb7, 0xe9, 0x1b, 0x12, 0x05, 0x66, 0x60, 0xf3, 0x64, 0x0b, 0x22, 0x78, 0xa5, - 0x0c, 0xae, 0x82, 0x78, 0x82, 0xba, 0xf6, 0x11, 0xc0, 0x86, 0x91, 0xee, 0x06, 0x61, 0xc2, 0x50, - 0x1f, 0x36, 0x7a, 0x8e, 0x13, 0x91, 0x38, 0x16, 0x02, 0x2c, 0xea, 0x77, 0x47, 0x47, 0x9d, 0xb9, - 0x6f, 0x47, 0x9d, 0x9b, 0x15, 0xd1, 0x07, 0x59, 0x48, 0xa2, 0x21, 0x71, 0x5c, 0x12, 0x75, 0xad, - 0x24, 0x8a, 0xe8, 0xdb, 0xae, 0x1d, 0x65, 0x21, 0xa3, 0x9a, 0x8c, 0xc5, 0xc5, 0x25, 0x68, 0x15, - 0xd6, 0x7b, 0x3e, 0x4d, 0x02, 0x26, 0x64, 0x52, 0xb0, 0xb4, 0x50, 0x0b, 0xaa, 0xfb, 0xe4, 0x75, - 0x42, 0x02, 0x9b, 0x08, 0x5d, 0x14, 0x5c, 0xda, 0x9b, 0xca, 0xa7, 0xc3, 0xce, 0xdc, 0x5a, 0x0a, - 0x55, 0x23, 0x7d, 0x9e, 0xb0, 0xff, 0x58, 0x95, 0xcc, 0xfc, 0x03, 0x14, 0x43, 0x80, 0xae, 0xc2, - 0x05, 0xa1, 0x8b, 0x9c, 0x86, 0xe5, 0x52, 0x4e, 0xa9, 0x17, 0xce, 0x61, 0xf4, 0xf4, 0xa4, 0xc0, - 0x79, 0x51, 0xe0, 0xad, 0xbf, 0x2f, 0xae, 0x05, 0xd5, 0x6d, 0x33, 0x7e, 0xe6, 0xf9, 0x1e, 0x2b, - 0xa4, 0x29, 0x6c, 0xb4, 0x0c, 0x6b, 0x4f, 0x08, 0x11, 0x93, 0xa1, 0x60, 0x7e, 0x44, 0xbb, 0x50, - 0x79, 0x6c, 0x32, 0x53, 0xbc, 0xf7, 0xa2, 0x7e, 0x4f, 0xea, 0xb2, 0x71, 0x7a, 0x6a, 0xcb, 0x0b, - 0xcc, 0x28, 0xd3, 0x76, 0x48, 0xaa, 0x67, 0x8c, 0xc4, 0x58, 0x5c, 0x21, 0xbb, 0xf7, 0x8a, 0xc1, - 0x46, 0xeb, 0xb0, 0x2e, 0xba, 0xe3, 0xa2, 0xd7, 0x7e, 0xdb, 0xbd, 0xc4, 0xd1, 0x0d, 0xd8, 0xc8, - 0x5f, 0x8a, 0xb7, 0xcf, 0xa9, 0x97, 0x2a, 0xd4, 0x1c, 0xc1, 0x05, 0x63, 0x53, 0xfd, 0x70, 0xd8, - 0x99, 0x13, 0xa9, 0x92, 0xa9, 0x89, 0x9f, 0x59, 0xee, 0xfb, 0x50, 0xe5, 0x81, 0xbd, 0xc8, 0x8d, - 0xe5, 0xfa, 0x5d, 0xd6, 0x2a, 0x5b, 0x5e, 0x60, 0xba, 0xc2, 0xe5, 0xc0, 0x25, 0x57, 0x76, 0x18, - 0x16, 0x1b, 0x39, 0x73, 0x3e, 0x04, 0x15, 0x1e, 0x21, 0x72, 0x9d, 0xc3, 0xe2, 0xcc, 0x7d, 0x42, - 0xf8, 0x5a, 0xee, 0xe3, 0xe7, 0x5f, 0x9f, 0x47, 0x66, 0x7c, 0x05, 0xeb, 0x3a, 0x3d, 0xa3, 0xa6, - 0x1b, 0x50, 0x3d, 0x08, 0x2c, 0x1e, 0x45, 0xff, 0x2c, 0x6a, 0x49, 0xa9, 0xa8, 0xfa, 0x19, 0x94, - 0x91, 0xb3, 0x77, 0xd8, 0x9f, 0x1e, 0xe0, 0x7f, 0xdf, 0xb0, 0x1d, 0xe2, 0xb9, 0x83, 0x62, 0x84, - 0xa5, 0x55, 0x29, 0xf3, 0x3d, 0x98, 0xfc, 0x62, 0x9d, 0x41, 0x9a, 0x2d, 0x78, 0xa1, 0x67, 0xdb, - 0x7c, 0x63, 0x0f, 0x42, 0xc7, 0x64, 0xa4, 0x98, 0xba, 0x15, 0x4d, 0x7c, 0xd8, 0x0d, 0xe2, 0x87, - 0x43, 0x93, 0x11, 0xc9, 0x11, 0x53, 0x00, 0xf0, 0x54, 0xc8, 0x49, 0x25, 0xfa, 0xa3, 0xd1, 0xb8, - 0x0d, 0xbe, 0x8e, 0xdb, 0xe0, 0xfb, 0xb8, 0x0d, 0xbe, 0x1c, 0xb7, 0xc1, 0xe8, 0xb8, 0x0d, 0x5e, - 0x5c, 0x3f, 0xbd, 0x71, 0x96, 0xc6, 0x5d, 0x59, 0x9f, 0x55, 0x17, 0xbf, 0x92, 0x3b, 0x3f, 0x03, - 0x00, 0x00, 0xff, 0xff, 0xac, 0xa5, 0xe3, 0x1c, 0xb1, 0x06, 0x00, 0x00, + // 665 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x55, 0x3b, 0x6f, 0xd4, 0x40, + 0x10, 0xce, 0xe6, 0x9c, 0xbb, 0x63, 0x09, 0x21, 0xac, 0x00, 0x9d, 0xae, 0xb8, 0x43, 0x11, 0x82, + 0xf0, 0x88, 0x0f, 0xf1, 0x2a, 0xd2, 0xa0, 0xbb, 0x20, 0x92, 0x20, 0x14, 0xd0, 0xc6, 0x69, 0xe8, + 0xfc, 0x58, 0x1c, 0x8b, 0xb3, 0xd7, 0xd8, 0x6b, 0xb0, 0x3b, 0x4a, 0x7a, 0x1a, 0xca, 0x14, 0x54, + 0xfc, 0x0a, 0xca, 0x94, 0xd4, 0x14, 0x11, 0x4a, 0x7e, 0x06, 0x0d, 0xda, 0xf1, 0xae, 0xef, 0x38, + 0x20, 0xba, 0x80, 0x44, 0xb7, 0x33, 0xdf, 0xb7, 0x9e, 0x99, 0x6f, 0x66, 0xd6, 0xf8, 0x4c, 0x6c, + 0x17, 0x43, 0x6e, 0x7b, 0x66, 0x9c, 0x70, 0xc1, 0x49, 0x43, 0x99, 0xed, 0x15, 0x3f, 0x10, 0xbb, + 0x99, 0x63, 0xba, 0x3c, 0xec, 0xf9, 0xdc, 0xe7, 0x3d, 0xc0, 0x9d, 0xec, 0x05, 0x58, 0x60, 0xc0, + 0xa9, 0xbc, 0xd7, 0x5e, 0x8c, 0x59, 0x12, 0x06, 0x69, 0x1a, 0xf0, 0x48, 0x79, 0x70, 0x1a, 0x33, + 0xb7, 0x3c, 0x2f, 0x7d, 0x9a, 0xc5, 0xb5, 0x7e, 0x54, 0x90, 0xab, 0xb8, 0xbe, 0x66, 0x0f, 0x87, + 0x56, 0xde, 0x42, 0x97, 0xd0, 0xf2, 0xe9, 0xdb, 0x67, 0x4d, 0x1d, 0xbd, 0x74, 0x53, 0x05, 0x4b, + 0xe2, 0x36, 0x8b, 0x3c, 0x2b, 0x6f, 0xcd, 0x4e, 0x10, 0x4b, 0x37, 0x55, 0xb0, 0x24, 0x6e, 0xd9, + 0x21, 0xb3, 0xf2, 0x56, 0x6d, 0x82, 0x58, 0xba, 0xa9, 0x82, 0xc9, 0x75, 0xdc, 0x78, 0xc6, 0x92, + 0x30, 0xb5, 0xf2, 0x96, 0x01, 0xcc, 0xc5, 0x8a, 0xa9, 0xfc, 0x54, 0x13, 0xc8, 0x65, 0x3c, 0xb7, + 0xce, 0x5f, 0x5b, 0x79, 0x6b, 0x0e, 0x98, 0x0b, 0x15, 0x13, 0xbc, 0xb4, 0x04, 0x65, 0xe8, 0x01, + 0x87, 0x1c, 0xeb, 0x13, 0xa1, 0x4b, 0x37, 0x55, 0x30, 0x59, 0xc1, 0xcd, 0x9d, 0xc8, 0x29, 0xa9, + 0x0d, 0xa0, 0x9e, 0xab, 0xa8, 0x1a, 0xa0, 0x15, 0x65, 0xe9, 0x3d, 0xc2, 0x0d, 0x2b, 0xdf, 0x8c, + 0xe2, 0x4c, 0x90, 0x2d, 0xdc, 0xe8, 0x7b, 0x5e, 0xc2, 0xd2, 0x14, 0x14, 0x9b, 0x1f, 0xdc, 0xdd, + 0x3f, 0xe8, 0xce, 0x7c, 0x3d, 0xe8, 0xde, 0x1c, 0x6b, 0xcf, 0x6e, 0x11, 0xb3, 0x64, 0xc8, 0x3c, + 0x9f, 0x25, 0x3d, 0x27, 0x4b, 0x12, 0xfe, 0xa6, 0xe7, 0x26, 0x45, 0x2c, 0xb8, 0xa9, 0xee, 0x52, + 0xfd, 0x11, 0x72, 0x11, 0xd7, 0xfb, 0x21, 0xcf, 0x22, 0x01, 0xba, 0x1a, 0x54, 0x59, 0xa4, 0x8d, + 0x9b, 0xdb, 0xec, 0x55, 0xc6, 0x22, 0x97, 0x81, 0x90, 0x06, 0xad, 0xec, 0x55, 0xe3, 0xc3, 0x5e, + 0x77, 0x66, 0x29, 0xc7, 0x4d, 0x2b, 0x7f, 0x9a, 0x89, 0xff, 0x98, 0x95, 0x8a, 0xfc, 0x1d, 0xe9, + 0xa9, 0x21, 0x57, 0xf0, 0x1c, 0xe8, 0xa2, 0xc6, 0x67, 0xd4, 0x42, 0xa5, 0x17, 0x2d, 0x61, 0xf2, + 0x78, 0x94, 0xe0, 0x2c, 0x24, 0x78, 0xeb, 0xef, 0x93, 0x6b, 0xe3, 0xe6, 0xba, 0x9d, 0x3e, 0x09, + 0xc2, 0x40, 0x68, 0x69, 0xb4, 0x4d, 0x16, 0x71, 0xed, 0x11, 0x63, 0x30, 0x50, 0x06, 0x95, 0x47, + 0xb2, 0x89, 0x8d, 0x87, 0xb6, 0xb0, 0x61, 0x72, 0xe6, 0x07, 0xf7, 0x94, 0x2e, 0x2b, 0xc7, 0x87, + 0x76, 0x82, 0xc8, 0x4e, 0x0a, 0x73, 0x83, 0xe5, 0x83, 0x42, 0xb0, 0x94, 0xc2, 0x27, 0x54, 0xf5, + 0x81, 0xde, 0x04, 0xb2, 0x8c, 0xeb, 0x50, 0x9d, 0x14, 0xbd, 0xf6, 0xdb, 0xea, 0x15, 0x4e, 0x6e, + 0xe0, 0x46, 0xd9, 0x29, 0x59, 0x7e, 0xed, 0xa7, 0x79, 0xd3, 0x3d, 0xa4, 0x9a, 0xb1, 0xda, 0x7c, + 0xb7, 0xd7, 0x9d, 0x81, 0x50, 0xbc, 0x5a, 0x91, 0xa9, 0x85, 0xbe, 0x8f, 0x9b, 0xf2, 0x4a, 0x3f, + 0xf1, 0x53, 0xb5, 0xa9, 0xe7, 0xcd, 0xb1, 0x97, 0x40, 0x63, 0x03, 0x43, 0x0a, 0x41, 0x2b, 0xae, + 0xaa, 0x2d, 0xd6, 0xcb, 0x3b, 0x75, 0x3c, 0x82, 0x0d, 0x79, 0x03, 0x62, 0x9d, 0xa2, 0x70, 0x96, + 0x3e, 0x90, 0xbc, 0x56, 0xfa, 0xe4, 0xf9, 0xd7, 0xc6, 0xa8, 0x88, 0x2f, 0xf5, 0xce, 0x9e, 0x40, + 0xcd, 0xd1, 0xfa, 0xf2, 0x3f, 0xcb, 0x59, 0x51, 0xc6, 0xf4, 0xfc, 0x88, 0x46, 0x8b, 0x3f, 0x75, + 0x85, 0x5b, 0x93, 0xa3, 0xfb, 0xef, 0xbb, 0xb5, 0xc1, 0x02, 0x7f, 0x57, 0x0f, 0xaf, 0xb2, 0xc6, + 0xd2, 0x7c, 0x8b, 0xd4, 0x73, 0x77, 0x02, 0x4d, 0xd6, 0xf0, 0x42, 0xdf, 0x75, 0xe5, 0x92, 0xee, + 0xc4, 0x9e, 0x2d, 0x98, 0x1e, 0xb4, 0x0b, 0x26, 0xbc, 0xfa, 0x16, 0x0b, 0xe3, 0xa1, 0x2d, 0x98, + 0xe2, 0x40, 0xfb, 0x11, 0x9d, 0xb8, 0x32, 0x4a, 0x61, 0xf0, 0x60, 0xff, 0xb0, 0x83, 0xbe, 0x1c, + 0x76, 0xd0, 0xb7, 0xc3, 0x0e, 0xfa, 0x7c, 0xd4, 0x41, 0xfb, 0x47, 0x1d, 0xf4, 0xfc, 0xda, 0xf1, + 0x15, 0x8b, 0x3c, 0xed, 0xa9, 0xfc, 0x9c, 0x3a, 0xfc, 0x67, 0xee, 0xfc, 0x08, 0x00, 0x00, 0xff, + 0xff, 0xf8, 0x92, 0x62, 0xb5, 0xce, 0x06, 0x00, 0x00, } diff --git a/txs/payload/permission_tx.go b/txs/payload/perms_tx.go similarity index 53% rename from txs/payload/permission_tx.go rename to txs/payload/perms_tx.go index d22984f9..5dbff87e 100644 --- a/txs/payload/permission_tx.go +++ b/txs/payload/perms_tx.go @@ -8,7 +8,7 @@ import ( "github.com/hyperledger/burrow/permission" ) -func NewPermissionsTx(st state.AccountGetter, from crypto.PublicKey, args permission.PermArgs) (*PermissionsTx, error) { +func NewPermsTx(st state.AccountGetter, from crypto.PublicKey, args permission.PermArgs) (*PermsTx, error) { addr := from.Address() acc, err := st.GetAccount(addr) if err != nil { @@ -19,30 +19,36 @@ func NewPermissionsTx(st state.AccountGetter, from crypto.PublicKey, args permis } sequence := acc.Sequence() + 1 - return NewPermissionsTxWithSequence(from, args, sequence), nil + return NewPermsTxWithSequence(from, args, sequence), nil } -func NewPermissionsTxWithSequence(from crypto.PublicKey, args permission.PermArgs, sequence uint64) *PermissionsTx { +func NewPermsTxWithSequence(from crypto.PublicKey, args permission.PermArgs, sequence uint64) *PermsTx { input := &TxInput{ Address: from.Address(), Amount: 1, // NOTE: amounts can't be 0 ... Sequence: sequence, } - return &PermissionsTx{ + return &PermsTx{ Input: input, PermArgs: args, } } -func (tx *PermissionsTx) Type() Type { +func (tx *PermsTx) Type() Type { return TypePermissions } -func (tx *PermissionsTx) GetInputs() []*TxInput { +func (tx *PermsTx) GetInputs() []*TxInput { return []*TxInput{tx.Input} } -func (tx *PermissionsTx) String() string { - return fmt.Sprintf("PermissionsTx{%v -> %v}", tx.Input, tx.PermArgs) +func (tx *PermsTx) String() string { + return fmt.Sprintf("PermsTx{%v -> %v}", tx.Input, tx.PermArgs) +} + +func (tx *PermsTx) Any() *Any { + return &Any{ + PermsTx: tx, + } } diff --git a/txs/payload/send_tx.go b/txs/payload/send_tx.go index f83fcf95..c67babef 100644 --- a/txs/payload/send_tx.go +++ b/txs/payload/send_tx.go @@ -55,3 +55,9 @@ func (tx *SendTx) AddOutput(addr crypto.Address, amt uint64) error { }) return nil } + +func (tx *SendTx) Any() *Any { + return &Any{ + SendTx: tx, + } +} diff --git a/txs/payload/unbond_tx.go b/txs/payload/unbond_tx.go index c6fe036f..c295cfad 100644 --- a/txs/payload/unbond_tx.go +++ b/txs/payload/unbond_tx.go @@ -24,3 +24,9 @@ func (tx *UnbondTx) GetInputs() []*TxInput { func (tx *UnbondTx) String() string { return fmt.Sprintf("UnbondTx{%v -> %s,%v}", tx.Input, tx.Address, tx.Height) } + +func (tx *UnbondTx) Any() *Any { + return &Any{ + UnbondTx: tx, + } +} diff --git a/txs/tx.go b/txs/tx.go index ee773c3c..45b15ca8 100644 --- a/txs/tx.go +++ b/txs/tx.go @@ -103,7 +103,7 @@ func (tx *Tx) UnmarshalJSON(data []byte) error { } tx.ChainID = w.ChainID // Now we know the Type we can deserialise the Payload - tx.Payload = payload.New(w.Type) + tx.Payload, err = payload.New(w.Type) return json.Unmarshal(w.Payload, tx.Payload) } diff --git a/txs/tx_test.go b/txs/tx_test.go index 4716bc28..b3d0d4a4 100644 --- a/txs/tx_test.go +++ b/txs/tx_test.go @@ -153,7 +153,7 @@ func TestUnbondTxSignable(t *testing.T) { } func TestPermissionsTxSignable(t *testing.T) { - permsTx := &payload.PermissionsTx{ + permsTx := &payload.PermsTx{ Input: &payload.TxInput{ Address: makePrivateAccount("input1").Address(), Amount: 12345, @@ -191,7 +191,7 @@ func TestTxWrapper_MarshalJSON(t *testing.T) { func TestNewPermissionsTxWithSequence(t *testing.T) { privateAccount := makePrivateAccount("shhhhh") args := permission.SetBaseArgs(privateAccount.PublicKey().Address(), permission.HasRole, true) - permTx := payload.NewPermissionsTxWithSequence(privateAccount.PublicKey(), args, 1) + permTx := payload.NewPermsTxWithSequence(privateAccount.PublicKey(), args, 1) testTxMarshalJSON(t, permTx) testTxSignVerify(t, permTx) } diff --git a/util/logging/cmd/main.go b/util/logging/cmd/main.go index cc6960b6..d0b8acda 100644 --- a/util/logging/cmd/main.go +++ b/util/logging/cmd/main.go @@ -17,7 +17,7 @@ package main import ( "fmt" - . "github.com/hyperledger/burrow/logging/config" + . "github.com/hyperledger/burrow/logging/logconfig" ) // Dump an example logging configuration -- GitLab