Skip to content

Commit

Permalink
Fix scratch data [#3601]
Browse files Browse the repository at this point in the history
  • Loading branch information
firelizzard18 committed May 27, 2024
1 parent 273f5fa commit c56feb0
Show file tree
Hide file tree
Showing 5 changed files with 84 additions and 5 deletions.
11 changes: 8 additions & 3 deletions internal/core/execute/v2/chain/state_operation.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,19 +25,20 @@ type addDataEntry struct {
liteStateRec protocol.Account
hash []byte
entry protocol.DataEntry
scratch bool
}

// UpdateData will cache a data associated with a DataAccount chain.
// the cache data will not be stored directly in the state but can be used
// upstream for storing a chain in the state database.
func (m *stateCache) UpdateData(record protocol.Account, entryHash []byte, dataEntry protocol.DataEntry) {
func (m *stateCache) UpdateData(record protocol.Account, entryHash []byte, dataEntry protocol.DataEntry, scratch bool) {
var stateRec protocol.Account

if record.Type() == protocol.AccountTypeLiteDataAccount {
stateRec = record
}

m.operations = append(m.operations, &addDataEntry{record.GetUrl(), stateRec, entryHash, dataEntry})
m.operations = append(m.operations, &addDataEntry{record.GetUrl(), stateRec, entryHash, dataEntry, scratch})
}

func (op *addDataEntry) Execute(st *stateCache) ([]protocol.Account, error) {
Expand All @@ -62,5 +63,9 @@ func (op *addDataEntry) Execute(st *stateCache) ([]protocol.Account, error) {
}

// Add TX to main chain
return nil, st.State.ChainUpdates.AddChainEntry(st.batch, record.MainChain(), st.txHash[:], 0, 0)
chain := record.MainChain()
if op.scratch {
chain = record.ScratchChain()
}
return nil, st.State.ChainUpdates.AddChainEntry(st.batch, chain, st.txHash[:], 0, 0)
}
2 changes: 1 addition & 1 deletion internal/core/execute/v2/chain/synthetic_write_data.go
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ func executeWriteLiteDataAccount(st *StateManager, entry protocol.DataEntry) (pr
result.AccountUrl = u
}

st.UpdateData(account, result.EntryHash[:], entry)
st.UpdateData(account, result.EntryHash[:], entry, false)

return result, nil
}
8 changes: 7 additions & 1 deletion internal/core/execute/v2/chain/write_data.go
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,13 @@ func executeWriteFullDataAccount(st *StateManager, entry protocol.DataEntry, scr
result.AccountID = st.OriginUrl.AccountID()
result.AccountUrl = st.OriginUrl

st.UpdateData(st.Origin, result.EntryHash[:], entry)
if !st.Globals.ExecutorVersion.V2VandenbergEnabled() {
// There was an error in previous versions that needs to be preserved to
// avoid consensus failure
scratch = false
}

st.UpdateData(st.Origin, result.EntryHash[:], entry, scratch)
return result, nil
}

Expand Down
22 changes: 22 additions & 0 deletions pkg/build/account.go
Original file line number Diff line number Diff line change
Expand Up @@ -419,3 +419,25 @@ func (b *TokenAccountBuilder) Add(amount any) *TokenAccountBuilder {
})
return b
}

type DataAccountBuilder struct {
AccountBuilder[*protocol.DataAccount]
}

func (b *IdentityBuilder) Data(path string) *DataAccountBuilder {
return &DataAccountBuilder{AccountBuilder[*protocol.DataAccount]{b.child(path)}}
}

func (b *DataAccountBuilder) Identity() *IdentityBuilder {
return &IdentityBuilder{AccountBuilder[*protocol.ADI]{b.parent()}}
}

func (b *DataAccountBuilder) Create() *DataAccountBuilder {
b.AccountBuilder.Create(&protocol.DataAccount{})
return b
}

func (b *DataAccountBuilder) Update(fn func(acct *protocol.DataAccount)) *DataAccountBuilder {
b.AccountBuilder.Update(fn)
return b
}
46 changes: 46 additions & 0 deletions test/e2e/txn_write_data2_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (

"github.com/stretchr/testify/require"
"gitlab.com/accumulatenetwork/accumulate/internal/core"
"gitlab.com/accumulatenetwork/accumulate/pkg/api/v3"
"gitlab.com/accumulatenetwork/accumulate/pkg/build"
"gitlab.com/accumulatenetwork/accumulate/pkg/types/messaging"
"gitlab.com/accumulatenetwork/accumulate/pkg/url"
Expand Down Expand Up @@ -308,3 +309,48 @@ func Test64ByteHeader(t *testing.T) {
sim.StepUntil(
Txn(st.TxID).Succeeds())
}

func TestWriteDataScratch(t *testing.T) {
alice := build.
Identity("alice").Create("book").
Data("data").Create().Identity().
Book("book").Page(1).Create().AddCredits(1e9).Book().Identity()
aliceKey := alice.Book("book").Page(1).
GenerateKey(SignatureTypeED25519)

// Initialize
g := new(core.GlobalValues)
g.ExecutorVersion = ExecutorVersionLatest
sim := NewSim(t,
simulator.SimpleNetwork(t.Name(), 1, 1),
simulator.Genesis(GenesisTime).With(alice),
)

st := sim.BuildAndSubmitTxnSuccessfully(
build.Transaction().For(alice, "data").
WriteData().DoubleHash("foo").Scratch().
SignWith(alice, "book", "1").Version(1).Timestamp(1).PrivateKey(aliceKey))
require.NoError(t, st.AsError())
sim.StepUntil(
Txn(st.TxID).Succeeds())

// The transaction is on the scratch chain
r := sim.QueryMainChainEntries(alice.Url().JoinPath("data"), &api.ChainQuery{Name: "scratch", Range: &api.RangeOptions{
Start: 0,
Count: api.Ptr[uint64](1),
FromEnd: true,
Expand: api.Ptr(true),
}})
require.Len(t, r.Records, 1)
require.Equal(t, st.TxID.String(), r.Records[0].Value.ID.String())
require.IsType(t, (*WriteData)(nil), r.Records[0].Value.Message.Transaction.Body)

// Not the main chain
r = sim.QueryMainChainEntries(alice.Url().JoinPath("data"), &api.ChainQuery{Name: "main", Range: &api.RangeOptions{
Start: 0,
Expand: api.Ptr(true),
}})
for _, r := range r.Records {
require.NotEqual(t, st.TxID.String(), r.Value.ID.String())
}
}

0 comments on commit c56feb0

Please sign in to comment.