Skip to content

Commit

Permalink
[cmd] Broken contract migration (#665)
Browse files Browse the repository at this point in the history
* add tracing for fees

* add migration for broken contracts

* Update cmd/util/ledger/migrations/broken_contract_migration.go

Co-authored-by: Peter Siemens <peterjsiemens@gmail.com>

* add migration to the list

Co-authored-by: Peter Siemens <peterjsiemens@gmail.com>
  • Loading branch information
ramtinms and psiemens committed Apr 27, 2021
1 parent 44d2290 commit 4e733ba
Show file tree
Hide file tree
Showing 9 changed files with 144 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ func extractExecutionState(dir string,
if migrate {
migrations = []ledger.Migration{
mgr.PruneMigration,
mgr.BrokenContractMigration,
mgr.StorageFormatV4Migration,
}
}
Expand Down
6 changes: 3 additions & 3 deletions cmd/util/ledger/migrations/accounts.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import (
)

func AddMissingKeysMigration(payloads []ledger.Payload) ([]ledger.Payload, error) {
l := newView(payloads)
l := NewView(payloads)
st := state.NewState(l)
sth := state.NewStateHolder(st)
a := state.NewAccounts(sth)
Expand Down Expand Up @@ -137,15 +137,15 @@ type view struct {
Ledger *led
}

func newView(payloads []ledger.Payload) *view {
func NewView(payloads []ledger.Payload) *view {
return &view{
Ledger: newLed(payloads),
}
}

func (v *view) NewChild() state.View {
payload := make([]ledger.Payload, 0)
ch := newView(payload)
ch := NewView(payload)
ch.Parent = v
return ch
}
Expand Down
85 changes: 85 additions & 0 deletions cmd/util/ledger/migrations/broken_contract_migration.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
package migrations

import (
"fmt"

"github.com/onflow/flow-go/fvm/state"
"github.com/onflow/flow-go/ledger"
"github.com/onflow/flow-go/model/flow"
)

// BrokenContractMigration fixes some of the early contracts that have been broken due to Cadence upgrades.
func BrokenContractMigration(payloads []ledger.Payload) ([]ledger.Payload, error) {
l := NewView(payloads)
st := state.NewState(l)
sth := state.NewStateHolder(st)
a := state.NewAccounts(sth)

err := migrateContractForAccount(a, "937cbdee135c656c")
if err != nil {
return nil, err
}

err = migrateContractForAccount(a, "7f560d7e3ff04a31")
if err != nil {
return nil, err
}

return l.Payloads(), nil
}

func migrateContractForAccount(accounts *state.Accounts, addressInHex string) error {
address := flow.HexToAddress(addressInHex)
ok, err := accounts.Exists(address)
if err != nil {
return err
}
if ok {
err = accounts.SetContract("TokenHolderKeyManager", address, GetKeyManagerContractContent())
if err != nil {
return err
}
} else {
// if not exist log and return gracefully
fmt.Println("warning account does not exist: ", addressInHex)
}
return nil
}

func GetKeyManagerContractContent() []byte {
return []byte(`import KeyManager from 0x840b99b76051d886
// The TokenHolderKeyManager contract is an implementation of
// the KeyManager interface intended for use by FLOW token holders.
//
// One instance is deployed to each token holder account.
// Deployment is executed a with signature from the administrator,
// allowing them to take possession of a KeyAdder resource
// upon initialization.
pub contract TokenHolderKeyManager: KeyManager {
access(contract) fun addPublicKey(_ publicKey: [UInt8]) {
self.account.addPublicKey(publicKey)
}
pub resource KeyAdder: KeyManager.KeyAdder {
pub let address: Address
pub fun addPublicKey(_ publicKey: [UInt8]) {
TokenHolderKeyManager.addPublicKey(publicKey)
}
init(address: Address) {
self.address = address
}
}
init(admin: AuthAccount, path: StoragePath) {
let keyAdder <- create KeyAdder(address: self.account.address)
admin.save(<- keyAdder, to: path)
}
}
`)
}
36 changes: 36 additions & 0 deletions cmd/util/ledger/migrations/broken_contract_migration_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package migrations_test

import (
"testing"

"github.com/onflow/flow-go/cmd/util/ledger/migrations"
"github.com/onflow/flow-go/fvm/state"
"github.com/onflow/flow-go/ledger"
"github.com/onflow/flow-go/model/flow"
"github.com/stretchr/testify/require"
)

func TestBrokenContractMigration(t *testing.T) {

address := flow.HexToAddress("937cbdee135c656c")
l := migrations.NewView(make([]ledger.Payload, 0))
st := state.NewState(l)
sth := state.NewStateHolder(st)
accounts := state.NewAccounts(sth)

err := accounts.Create(nil, address)
require.NoError(t, err)

err = accounts.SetContract("TokenHolderKeyManager", address, []byte("OLD CONTENT"))
require.NoError(t, err)

newPayloads, err := migrations.BrokenContractMigration(l.Payloads())
require.NoError(t, err)

st = state.NewState(migrations.NewView(newPayloads))
sth = state.NewStateHolder(st)
accounts = state.NewAccounts(sth)
content, err := accounts.GetContract("TokenHolderKeyManager", address)
require.NoError(t, err)
require.Equal(t, content, migrations.GetKeyManagerContractContent())
}
2 changes: 1 addition & 1 deletion cmd/util/ledger/migrations/contract_reporter.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ func (r ContractReporter) Report(payload []ledger.Payload) error {
}
}()

l := newView(payload)
l := NewView(payload)
st := state.NewState(l)
sth := state.NewStateHolder(st)
accounts := state.NewAccounts(sth)
Expand Down
2 changes: 1 addition & 1 deletion cmd/util/ledger/migrations/storage_reporter.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ func (r StorageReporter) Report(payload []ledger.Payload) error {
}
}()

l := newView(payload)
l := NewView(payload)
st := state.NewState(l)

for _, p := range payload {
Expand Down
10 changes: 10 additions & 0 deletions cmd/util/ledger/migrations/storage_v4.go
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,16 @@ var tokenForwardingLocationMainnet = common.AddressLocation{
Name: "TokenForwarding",
}

var tokenHolderKeyManagerLocationMainnet1 = common.AddressLocation{
Address: common.BytesToAddress([]byte{0x93, 0x7c, 0xbd, 0xee, 0x13, 0x5c, 0x65, 0x6c}),
Name: "TokenHolderKeyManager",
}

var tokenHolderKeyManagerLocationMainnet2 = common.AddressLocation{
Address: common.BytesToAddress([]byte{0x7f, 0x56, 0x0d, 0x7e, 0x3f, 0xf0, 0x4a, 0x31}),
Name: "TokenHolderKeyManager",
}

func isTokenForwardingLocation(location common.Location) bool {
return common.LocationsMatch(location, tokenForwardingLocationTestnet) ||
common.LocationsMatch(location, tokenForwardingLocationMainnet)
Expand Down
9 changes: 6 additions & 3 deletions fvm/transactionFeeDeductor.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"github.com/onflow/flow-go/fvm/programs"
"github.com/onflow/flow-go/fvm/state"
"github.com/onflow/flow-go/module/trace"
"github.com/opentracing/opentracing-go"
)

type TransactionFeeDeductor struct{}
Expand All @@ -20,12 +21,13 @@ func (d *TransactionFeeDeductor) Process(
sth *state.StateHolder,
programs *programs.Programs,
) error {
var span opentracing.Span
if ctx.Tracer != nil && proc.TraceSpan != nil {
span := ctx.Tracer.StartSpanFromParent(proc.TraceSpan, trace.FVMDeductTransactionFees)
span = ctx.Tracer.StartSpanFromParent(proc.TraceSpan, trace.FVMDeductTransactionFees)
defer span.Finish()
}

txErr, fatalErr := d.deductFees(vm, ctx, proc, sth, programs)
txErr, fatalErr := d.deductFees(vm, ctx, proc, sth, programs, span)
// TODO handle deduct fee failures, for now just return as error
if txErr != nil {
return txErr
Expand All @@ -39,9 +41,10 @@ func (d *TransactionFeeDeductor) deductFees(
proc *TransactionProcedure,
sth *state.StateHolder,
programs *programs.Programs,
span opentracing.Span,
) (errors.Error, error) {

feeTx := deductTransactionFeeTransaction(proc.Transaction.Payer, ctx.Chain.ServiceAddress())
feeTx.SetTraceSpan(span)
txErr, fatalErr := vm.invokeMetaTransaction(
*ctx,
feeTx,
Expand Down
1 change: 1 addition & 0 deletions module/trace/constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,7 @@ const (
FVMExecuteTransaction SpanName = "fvm.executeTransaction"
FVMDeductTransactionFees SpanName = "fvm.deductTransactionFees"
FVMFrozenAccountCheckTransaction SpanName = "fvm.frozenAccountCheckTransaction"
FVMInvokeMetaTransaction SpanName = "fvm.invokeMetaTransaction"

FVMEnvHash SpanName = "fvm.env.Hash"
FVMEnvValueExists SpanName = "fvm.env.valueExists"
Expand Down

0 comments on commit 4e733ba

Please sign in to comment.