Skip to content

Commit

Permalink
native: implement HF-based update
Browse files Browse the repository at this point in the history
Close #3213.

Signed-off-by: Anna Shaleva <shaleva.ann@nspcc.ru>
  • Loading branch information
AnnaShaleva committed Apr 9, 2024
1 parent 927dbb6 commit b87ac96
Show file tree
Hide file tree
Showing 19 changed files with 418 additions and 107 deletions.
8 changes: 5 additions & 3 deletions pkg/compiler/native_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -288,7 +288,7 @@ func runNativeTestCases(t *testing.T, ctr interop.ContractMD, name string, nativ
})
}

func getMethod(t *testing.T, ctr interop.ContractMD, name string, params []string) interop.MethodAndPrice {
func getMethod(t *testing.T, ctr interop.ContractMD, name string, params []string) interop.HFSpecificMethodAndPrice {
paramLen := len(params)

switch {
Expand All @@ -308,8 +308,10 @@ func getMethod(t *testing.T, ctr interop.ContractMD, name string, params []strin
name = strings.TrimSuffix(name, "WithData")
}

md, ok := ctr.GetMethod(name, paramLen)
require.True(t, ok, ctr.Manifest.Name, name, paramLen)
latestHF := config.LatestHardfork()
cMD := ctr.HFSpecificContractMD(&latestHF)
md, ok := cMD.GetMethod(name, paramLen)
require.True(t, ok, cMD.Manifest.Name, name, paramLen)
return md
}

Expand Down
21 changes: 21 additions & 0 deletions pkg/config/hardfork.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,30 @@ func init() {
}
}

// Cmp returns the result of hardforks comparison. It returns:
//
// -1 if hf < other
// 0 if hf == other
// +1 if hf > other
func (hf Hardfork) Cmp(other Hardfork) int {
switch {
case hf == other:
return 0
case hf < other:
return -1
default:
return 1
}
}

// IsHardforkValid denotes whether the provided string represents a valid
// Hardfork name.
func IsHardforkValid(s string) bool {
_, ok := hardforks[s]
return ok
}

// LatestHardfork returns latest known hardfork.
func LatestHardfork() Hardfork {
return hfLast >> 1
}
37 changes: 32 additions & 5 deletions pkg/core/blockchain.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ import (

// Tuning parameters.
const (
version = "0.2.10"
version = "0.2.11"

// DefaultInitialGAS is the default amount of GAS emitted to the standby validators
// multisignature account during native GAS contract initialization.
Expand Down Expand Up @@ -341,16 +341,37 @@ func (bc *Blockchain) GetDesignatedByRole(r noderoles.Role) (keys.PublicKeys, ui
return res, h, err
}

// getCurrentHF returns latest currently enabled hardfork. In case if no hardforks is enabled, the
// default config.Hardfork(0) value is returned.
func (bc *Blockchain) getCurrentHF() config.Hardfork {
var (
height = bc.BlockHeight()
current config.Hardfork
)
// Rely on the fact that hardforks list is continuous.
for _, hf := range config.Hardforks {
enableHeight, ok := bc.config.Hardforks[hf.String()]
if !ok || height < enableHeight {
break
}
current = hf
}
return current
}

// SetOracle sets oracle module. It can safely be called on the running blockchain.
// To unregister Oracle service use SetOracle(nil).
func (bc *Blockchain) SetOracle(mod native.OracleService) {
// TODO: ensure Oracle script is updated when needed.
orc := bc.contracts.Oracle
currentHF := bc.getCurrentHF()
if mod != nil {
md, ok := orc.GetMethod(manifest.MethodVerify, -1)
orcMd := orc.HFSpecificContractMD(&currentHF)
md, ok := orcMd.GetMethod(manifest.MethodVerify, -1)
if !ok {
panic(fmt.Errorf("%s method not found", manifest.MethodVerify))
}
mod.UpdateNativeContract(orc.NEF.Script, orc.GetOracleResponseScript(),
mod.UpdateNativeContract(orcMd.NEF.Script, orc.GetOracleResponseScript(),
orc.Hash, md.MD.Offset)
keys, _, err := bc.GetDesignatedByRole(noderoles.Oracle)
if err != nil {
Expand Down Expand Up @@ -487,8 +508,10 @@ func (bc *Blockchain) init() error {
// Check autogenerated native contracts' manifests and NEFs against the stored ones.
// Need to be done after native Management cache initialization to be able to get
// contract state from DAO via high-level bc API.
var current = bc.getCurrentHF()
for _, c := range bc.contracts.Contracts {
md := c.Metadata()
hfMD := md.HFSpecificContractMD(&current)
storedCS := bc.GetContractState(md.Hash)
// Check that contract was deployed.
if !bc.isHardforkEnabled(c.ActiveIn(), bHeight) {
Expand All @@ -505,7 +528,7 @@ func (bc *Blockchain) init() error {
return fmt.Errorf("failed to check native %s state against autogenerated one: %w", md.Name, err)
}
autogenCS := &state.Contract{
ContractBase: md.ContractBase,
ContractBase: hfMD.ContractBase,
UpdateCounter: storedCS.UpdateCounter, // it can be restored only from the DB, so use the stored value.
}
autogenCSBytes, err := stackitem.SerializeConvertible(autogenCS)
Expand Down Expand Up @@ -2269,8 +2292,12 @@ func (bc *Blockchain) GetNativeContractScriptHash(name string) (util.Uint160, er
// GetNatives returns list of native contracts.
func (bc *Blockchain) GetNatives() []state.NativeContract {
res := make([]state.NativeContract, 0, len(bc.contracts.Contracts))
current := bc.getCurrentHF()
for _, c := range bc.contracts.Contracts {
res = append(res, c.Metadata().NativeContract)
md := c.Metadata().HFSpecificContractMD(&current)
res = append(res, state.NativeContract{
ContractBase: md.ContractBase,
})
}
return res
}
Expand Down
Loading

0 comments on commit b87ac96

Please sign in to comment.