mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-19 10:22:23 +00:00
ADDED LCP engine
This commit is contained in:
parent
197fcd5445
commit
5f8a201d68
13 changed files with 567 additions and 389 deletions
|
|
@ -167,6 +167,8 @@ func BytesToAddress(b []byte) Address {
|
||||||
return a
|
return a
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func StringToAddress(s string) Address { return BytesToAddress([]byte(s)) }
|
||||||
|
|
||||||
// BigToAddress returns Address with byte values of b.
|
// BigToAddress returns Address with byte values of b.
|
||||||
// If b is larger than len(h), b will be cropped from the left.
|
// If b is larger than len(h), b will be cropped from the left.
|
||||||
func BigToAddress(b *big.Int) Address { return BytesToAddress(b.Bytes()) }
|
func BigToAddress(b *big.Int) Address { return BytesToAddress(b.Bytes()) }
|
||||||
|
|
@ -219,7 +221,7 @@ func (a Address) Hex() string {
|
||||||
func (a Address) String() string {
|
func (a Address) String() string {
|
||||||
return a.Hex()
|
return a.Hex()
|
||||||
}
|
}
|
||||||
|
func (a Address) Str() string { return string(a[:]) }
|
||||||
// Format implements fmt.Formatter, forcing the byte slice to be formatted as is,
|
// Format implements fmt.Formatter, forcing the byte slice to be formatted as is,
|
||||||
// without going through the stringer interface used for logging.
|
// without going through the stringer interface used for logging.
|
||||||
func (a Address) Format(s fmt.State, c rune) {
|
func (a Address) Format(s fmt.State, c rune) {
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,11 @@ import (
|
||||||
"github.com/pavelkrolevets/go-ethereum/core/types"
|
"github.com/pavelkrolevets/go-ethereum/core/types"
|
||||||
"github.com/pavelkrolevets/go-ethereum/ethdb"
|
"github.com/pavelkrolevets/go-ethereum/ethdb"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
//types2 "github.com/pavelkrolevets/go-ethereum/core/types"
|
|
||||||
|
"strings"
|
||||||
|
"strconv"
|
||||||
|
"github.com/pavelkrolevets/go-ethereum/trie"
|
||||||
|
"fmt"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestEpochContextCountVotes(t *testing.T) {
|
func TestEpochContextCountVotes(t *testing.T) {
|
||||||
|
|
@ -30,7 +34,7 @@ func TestEpochContextCountVotes(t *testing.T) {
|
||||||
}
|
}
|
||||||
balance := int64(5)
|
balance := int64(5)
|
||||||
db := ethdb.NewMemDatabase()
|
db := ethdb.NewMemDatabase()
|
||||||
//bdb := trie.NewDatabase(db)
|
//dbd := trie.NewDatabase(db)
|
||||||
stateDB, _ := state.New(common.Hash{}, state.NewDatabase(db))
|
stateDB, _ := state.New(common.Hash{}, state.NewDatabase(db))
|
||||||
LCPContext, err := types.NewLCPContext(db)
|
LCPContext, err := types.NewLCPContext(db)
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
|
|
@ -44,12 +48,31 @@ func TestEpochContextCountVotes(t *testing.T) {
|
||||||
|
|
||||||
for candidate, electors := range voteMap {
|
for candidate, electors := range voteMap {
|
||||||
assert.Nil(t, LCPContext.BecomeCandidate(candidate))
|
assert.Nil(t, LCPContext.BecomeCandidate(candidate))
|
||||||
|
//for _, delegate := range electors{
|
||||||
|
// assert.Nil(t, LCPContext.BecomeDelegate(delegate))
|
||||||
|
// fmt.Println(delegate)
|
||||||
|
//}
|
||||||
|
//fmt.Println(electors)
|
||||||
for _, elector := range electors {
|
for _, elector := range electors {
|
||||||
stateDB.SetBalance(elector, big.NewInt(balance))
|
epochContext.statedb.SetBalance(elector, big.NewInt(balance))
|
||||||
|
//bal := epochContext.statedb.GetBalance(elector)
|
||||||
|
//fmt.Println(bal)
|
||||||
assert.Nil(t, LCPContext.Delegate(elector, candidate))
|
assert.Nil(t, LCPContext.Delegate(elector, candidate))
|
||||||
|
|
||||||
|
//delegateIterator := trie.NewIterator(epochContext.Context.DelegateTrie().PrefixIterator([]byte(candidate.Bytes())))
|
||||||
|
//existDelegator := delegateIterator.Next()
|
||||||
|
//fmt.Println(existDelegator)
|
||||||
|
//delegator := delegateIterator.Value
|
||||||
|
//fmt.Println(delegator)
|
||||||
|
|
||||||
|
//fmt.Println(elector)
|
||||||
|
//fmt.Println(epochContext.Context.VoteTrie().TryGet([]byte(elector.Bytes())))
|
||||||
|
//fmt.Println(epochContext.Context.DelegateTrie().TryGet([]byte(elector.Bytes())))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
result, err := epochContext.countVotes()
|
result, err := epochContext.countVotes()
|
||||||
|
//fmt.Println(result)
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
assert.Equal(t, len(voteMap), len(result))
|
assert.Equal(t, len(voteMap), len(result))
|
||||||
for candidate, electors := range voteMap {
|
for candidate, electors := range voteMap {
|
||||||
|
|
@ -58,300 +81,316 @@ func TestEpochContextCountVotes(t *testing.T) {
|
||||||
assert.Equal(t, balance*int64(len(electors)), voteCount.Int64())
|
assert.Equal(t, balance*int64(len(electors)), voteCount.Int64())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//
|
|
||||||
//func TestLookupValidator(t *testing.T) {
|
func TestLookupValidator(t *testing.T) {
|
||||||
// db, _ := ethdb.NewMemDatabase()
|
db:= ethdb.NewMemDatabase()
|
||||||
// dposCtx, _ := types.NewDposContext(db)
|
dposCtx, _ := types.NewLCPContext(db)
|
||||||
// mockEpochContext := &EpochContext{
|
mockEpochContext := &EpochContext{
|
||||||
// DposContext: dposCtx,
|
Context: dposCtx,
|
||||||
// }
|
}
|
||||||
// validators := []common.Address{
|
validators := []common.Address{
|
||||||
// common.StringToAddress("addr1"),
|
common.StringToAddress("addr1"),
|
||||||
// common.StringToAddress("addr2"),
|
common.StringToAddress("addr2"),
|
||||||
// common.StringToAddress("addr3"),
|
common.StringToAddress("addr3"),
|
||||||
// }
|
}
|
||||||
// mockEpochContext.DposContext.SetValidators(validators)
|
mockEpochContext.Context.SetPeriodBlock(1)
|
||||||
// for i, expected := range validators {
|
mockEpochContext.Context.SetEpochInterval(86400)
|
||||||
// got, _ := mockEpochContext.lookupValidator(int64(i) * blockInterval)
|
mockEpochContext.Context.SetMaxValidators(3)
|
||||||
// if got != expected {
|
blockInterval:=mockEpochContext.Context.GetPeriodBlock()
|
||||||
// t.Errorf("Failed to test lookup validator, %s was expected but got %s", expected.Str(), got.Str())
|
maxval:=mockEpochContext.Context.GetMaxValidators()
|
||||||
// }
|
epoch_int:= mockEpochContext.Context.GetEpochInterval()
|
||||||
// }
|
|
||||||
// _, err := mockEpochContext.lookupValidator(blockInterval - 1)
|
fmt.Println(blockInterval, maxval,epoch_int)
|
||||||
// if err != ErrInvalidMintBlockTime {
|
mockEpochContext.Context.SetValidators(validators)
|
||||||
// t.Errorf("Failed to test lookup validator. err '%v' was expected but got '%v'", ErrInvalidMintBlockTime, err)
|
for i, expected := range validators {
|
||||||
// }
|
fmt.Println(i, expected)
|
||||||
//}
|
got, _ := mockEpochContext.lookupValidator(int64(i) * blockInterval)
|
||||||
//
|
if got != expected {
|
||||||
//func TestEpochContextKickoutValidator(t *testing.T) {
|
t.Errorf("Failed to test lookup validator, %s was expected but got %s", expected.Str(), got.Str())
|
||||||
// db, _ := ethdb.NewMemDatabase()
|
}
|
||||||
// stateDB, _ := state.New(common.Hash{}, state.NewDatabase(db))
|
}
|
||||||
// dposContext, err := types.NewDposContext(db)
|
_, err := mockEpochContext.lookupValidator(blockInterval - 1)
|
||||||
// assert.Nil(t, err)
|
if err != ErrInvalidMintBlockTime {
|
||||||
// epochContext := &EpochContext{
|
t.Errorf("Failed to test lookup validator. err '%v' was expected but got '%v'", ErrInvalidMintBlockTime, err)
|
||||||
// TimeStamp: epochInterval,
|
}
|
||||||
// DposContext: dposContext,
|
}
|
||||||
// statedb: stateDB,
|
|
||||||
// }
|
func TestEpochContextKickoutValidator(t *testing.T) {
|
||||||
// atLeastMintCnt := epochInterval / blockInterval / maxValidatorSize / 2
|
db:= ethdb.NewMemDatabase()
|
||||||
// testEpoch := int64(1)
|
stateDB, _ := state.New(common.Hash{}, state.NewDatabase(db))
|
||||||
//
|
dposContext, err := types.NewLCPContext(db)
|
||||||
// // no validator can be kickout, because all validators mint enough block at least
|
assert.Nil(t, err)
|
||||||
// validators := []common.Address{}
|
|
||||||
// for i := 0; i < maxValidatorSize; i++ {
|
epochContext := &EpochContext{
|
||||||
// validator := common.StringToAddress("addr" + strconv.Itoa(i))
|
TimeStamp: epochInterval,
|
||||||
// validators = append(validators, validator)
|
Context: dposContext,
|
||||||
// assert.Nil(t, dposContext.BecomeCandidate(validator))
|
statedb: stateDB,
|
||||||
// setTestMintCnt(dposContext, testEpoch, validator, atLeastMintCnt)
|
}
|
||||||
// }
|
epochContext.Context.SetPeriodBlock(1)
|
||||||
// assert.Nil(t, dposContext.SetValidators(validators))
|
epochContext.Context.SetEpochInterval(86400)
|
||||||
// assert.Nil(t, dposContext.BecomeCandidate(common.StringToAddress("addr")))
|
epochContext.Context.SetMaxValidators(3)
|
||||||
// assert.Nil(t, epochContext.kickoutValidator(testEpoch))
|
|
||||||
// candidateMap := getCandidates(dposContext.CandidateTrie())
|
maxValidatorSize := int(epochContext.Context.GetMaxValidators())
|
||||||
// assert.Equal(t, maxValidatorSize +1, len(candidateMap))
|
atLeastMintCnt := epochInterval / blockInterval / int64(maxValidatorSize) / 2
|
||||||
//
|
testEpoch := int64(1)
|
||||||
// // atLeast a safeSize count candidate will reserve
|
|
||||||
// dposContext, err = types.NewDposContext(db)
|
// no validator can be kickout, because all validators mint enough block at least
|
||||||
// assert.Nil(t, err)
|
validators := []common.Address{}
|
||||||
// epochContext = &EpochContext{
|
for i := 0; i < int(maxValidatorSize); i++ {
|
||||||
// TimeStamp: epochInterval,
|
validator := common.StringToAddress("addr" + strconv.Itoa(i))
|
||||||
// DposContext: dposContext,
|
validators = append(validators, validator)
|
||||||
// statedb: stateDB,
|
assert.Nil(t, dposContext.BecomeCandidate(validator))
|
||||||
// }
|
setTestMintCnt(dposContext, testEpoch, validator, atLeastMintCnt)
|
||||||
// validators = []common.Address{}
|
}
|
||||||
// for i := 0; i < maxValidatorSize; i++ {
|
assert.Nil(t, dposContext.SetValidators(validators))
|
||||||
// validator := common.StringToAddress("addr" + strconv.Itoa(i))
|
assert.Nil(t, dposContext.BecomeCandidate(common.StringToAddress("addr")))
|
||||||
// validators = append(validators, validator)
|
assert.Nil(t, epochContext.kickoutValidator(testEpoch))
|
||||||
// assert.Nil(t, dposContext.BecomeCandidate(validator))
|
candidateMap := getCandidates(dposContext.CandidateTrie())
|
||||||
// setTestMintCnt(dposContext, testEpoch, validator, atLeastMintCnt-int64(i)-1)
|
assert.Equal(t, maxValidatorSize +1, len(candidateMap))
|
||||||
// }
|
|
||||||
// assert.Nil(t, dposContext.SetValidators(validators))
|
// atLeast a safeSize count candidate will reserve
|
||||||
// assert.Nil(t, epochContext.kickoutValidator(testEpoch))
|
dposContext, err = types.NewLCPContext(db)
|
||||||
// candidateMap = getCandidates(dposContext.CandidateTrie())
|
assert.Nil(t, err)
|
||||||
// assert.Equal(t, safeSize, len(candidateMap))
|
epochContext = &EpochContext{
|
||||||
// for i := maxValidatorSize - 1; i >= safeSize; i-- {
|
TimeStamp: epochInterval,
|
||||||
// assert.False(t, candidateMap[common.StringToAddress("addr"+strconv.Itoa(i))])
|
Context: dposContext,
|
||||||
// }
|
statedb: stateDB,
|
||||||
//
|
}
|
||||||
// // all validator will be kickout, because all validators didn't mint enough block at least
|
validators = []common.Address{}
|
||||||
// dposContext, err = types.NewDposContext(db)
|
for i := 0; i < int(maxValidatorSize); i++ {
|
||||||
// assert.Nil(t, err)
|
validator := common.StringToAddress("addr" + strconv.Itoa(i))
|
||||||
// epochContext = &EpochContext{
|
validators = append(validators, validator)
|
||||||
// TimeStamp: epochInterval,
|
assert.Nil(t, dposContext.BecomeCandidate(validator))
|
||||||
// DposContext: dposContext,
|
setTestMintCnt(dposContext, testEpoch, validator, atLeastMintCnt-int64(i)-1)
|
||||||
// statedb: stateDB,
|
}
|
||||||
// }
|
assert.Nil(t, dposContext.SetValidators(validators))
|
||||||
// validators = []common.Address{}
|
assert.Nil(t, epochContext.kickoutValidator(testEpoch))
|
||||||
// for i := 0; i < maxValidatorSize; i++ {
|
candidateMap = getCandidates(dposContext.CandidateTrie())
|
||||||
// validator := common.StringToAddress("addr" + strconv.Itoa(i))
|
assert.Equal(t, safeSize, len(candidateMap))
|
||||||
// validators = append(validators, validator)
|
for i := int(maxValidatorSize) - 1; i >= safeSize; i-- {
|
||||||
// assert.Nil(t, dposContext.BecomeCandidate(validator))
|
assert.False(t, candidateMap[common.StringToAddress("addr"+strconv.Itoa(i))])
|
||||||
// setTestMintCnt(dposContext, testEpoch, validator, atLeastMintCnt-1)
|
}
|
||||||
// }
|
|
||||||
// for i := maxValidatorSize; i < maxValidatorSize *2; i++ {
|
// all validator will be kickout, because all validators didn't mint enough block at least
|
||||||
// candidate := common.StringToAddress("addr" + strconv.Itoa(i))
|
dposContext, err = types.NewLCPContext(db)
|
||||||
// assert.Nil(t, dposContext.BecomeCandidate(candidate))
|
assert.Nil(t, err)
|
||||||
// }
|
epochContext = &EpochContext{
|
||||||
// assert.Nil(t, dposContext.SetValidators(validators))
|
TimeStamp: epochInterval,
|
||||||
// assert.Nil(t, epochContext.kickoutValidator(testEpoch))
|
Context: dposContext,
|
||||||
// candidateMap = getCandidates(dposContext.CandidateTrie())
|
statedb: stateDB,
|
||||||
// assert.Equal(t, maxValidatorSize, len(candidateMap))
|
}
|
||||||
//
|
validators = []common.Address{}
|
||||||
// // only one validator mint count is not enough
|
for i := 0; i < int(maxValidatorSize); i++ {
|
||||||
// dposContext, err = types.NewDposContext(db)
|
validator := common.StringToAddress("addr" + strconv.Itoa(i))
|
||||||
// assert.Nil(t, err)
|
validators = append(validators, validator)
|
||||||
// epochContext = &EpochContext{
|
assert.Nil(t, dposContext.BecomeCandidate(validator))
|
||||||
// TimeStamp: epochInterval,
|
setTestMintCnt(dposContext, testEpoch, validator, atLeastMintCnt-1)
|
||||||
// DposContext: dposContext,
|
}
|
||||||
// statedb: stateDB,
|
for i := int(maxValidatorSize); i < int(maxValidatorSize) *2; i++ {
|
||||||
// }
|
candidate := common.StringToAddress("addr" + strconv.Itoa(i))
|
||||||
// validators = []common.Address{}
|
assert.Nil(t, dposContext.BecomeCandidate(candidate))
|
||||||
// for i := 0; i < maxValidatorSize; i++ {
|
}
|
||||||
// validator := common.StringToAddress("addr" + strconv.Itoa(i))
|
assert.Nil(t, dposContext.SetValidators(validators))
|
||||||
// validators = append(validators, validator)
|
assert.Nil(t, epochContext.kickoutValidator(testEpoch))
|
||||||
// assert.Nil(t, dposContext.BecomeCandidate(validator))
|
candidateMap = getCandidates(dposContext.CandidateTrie())
|
||||||
// if i == 0 {
|
assert.Equal(t, maxValidatorSize, len(candidateMap))
|
||||||
// setTestMintCnt(dposContext, testEpoch, validator, atLeastMintCnt-1)
|
|
||||||
// } else {
|
// only one validator mint count is not enough
|
||||||
// setTestMintCnt(dposContext, testEpoch, validator, atLeastMintCnt)
|
dposContext, err = types.NewLCPContext(db)
|
||||||
// }
|
assert.Nil(t, err)
|
||||||
// }
|
epochContext = &EpochContext{
|
||||||
// assert.Nil(t, dposContext.BecomeCandidate(common.StringToAddress("addr")))
|
TimeStamp: epochInterval,
|
||||||
// assert.Nil(t, dposContext.SetValidators(validators))
|
Context: dposContext,
|
||||||
// assert.Nil(t, epochContext.kickoutValidator(testEpoch))
|
statedb: stateDB,
|
||||||
// candidateMap = getCandidates(dposContext.CandidateTrie())
|
}
|
||||||
// assert.Equal(t, maxValidatorSize, len(candidateMap))
|
validators = []common.Address{}
|
||||||
// assert.False(t, candidateMap[common.StringToAddress("addr"+strconv.Itoa(0))])
|
for i := 0; i < int(maxValidatorSize); i++ {
|
||||||
//
|
validator := common.StringToAddress("addr" + strconv.Itoa(i))
|
||||||
// // epochTime is not complete, all validators mint enough block at least
|
validators = append(validators, validator)
|
||||||
// dposContext, err = types.NewDposContext(db)
|
assert.Nil(t, dposContext.BecomeCandidate(validator))
|
||||||
// assert.Nil(t, err)
|
if i == 0 {
|
||||||
// epochContext = &EpochContext{
|
setTestMintCnt(dposContext, testEpoch, validator, atLeastMintCnt-1)
|
||||||
// TimeStamp: epochInterval / 2,
|
} else {
|
||||||
// DposContext: dposContext,
|
setTestMintCnt(dposContext, testEpoch, validator, atLeastMintCnt)
|
||||||
// statedb: stateDB,
|
}
|
||||||
// }
|
}
|
||||||
// validators = []common.Address{}
|
assert.Nil(t, dposContext.BecomeCandidate(common.StringToAddress("addr")))
|
||||||
// for i := 0; i < maxValidatorSize; i++ {
|
assert.Nil(t, dposContext.SetValidators(validators))
|
||||||
// validator := common.StringToAddress("addr" + strconv.Itoa(i))
|
assert.Nil(t, epochContext.kickoutValidator(testEpoch))
|
||||||
// validators = append(validators, validator)
|
candidateMap = getCandidates(dposContext.CandidateTrie())
|
||||||
// assert.Nil(t, dposContext.BecomeCandidate(validator))
|
assert.Equal(t, maxValidatorSize, len(candidateMap))
|
||||||
// setTestMintCnt(dposContext, testEpoch, validator, atLeastMintCnt/2)
|
assert.False(t, candidateMap[common.StringToAddress("addr"+strconv.Itoa(0))])
|
||||||
// }
|
|
||||||
// for i := maxValidatorSize; i < maxValidatorSize *2; i++ {
|
// epochTime is not complete, all validators mint enough block at least
|
||||||
// candidate := common.StringToAddress("addr" + strconv.Itoa(i))
|
dposContext, err = types.NewLCPContext(db)
|
||||||
// assert.Nil(t, dposContext.BecomeCandidate(candidate))
|
assert.Nil(t, err)
|
||||||
// }
|
epochContext = &EpochContext{
|
||||||
// assert.Nil(t, dposContext.SetValidators(validators))
|
TimeStamp: epochInterval / 2,
|
||||||
// assert.Nil(t, epochContext.kickoutValidator(testEpoch))
|
Context: dposContext,
|
||||||
// candidateMap = getCandidates(dposContext.CandidateTrie())
|
statedb: stateDB,
|
||||||
// assert.Equal(t, maxValidatorSize *2, len(candidateMap))
|
}
|
||||||
//
|
validators = []common.Address{}
|
||||||
// // epochTime is not complete, all validators didn't mint enough block at least
|
for i := 0; i < int(maxValidatorSize); i++ {
|
||||||
// dposContext, err = types.NewDposContext(db)
|
validator := common.StringToAddress("addr" + strconv.Itoa(i))
|
||||||
// assert.Nil(t, err)
|
validators = append(validators, validator)
|
||||||
// epochContext = &EpochContext{
|
assert.Nil(t, dposContext.BecomeCandidate(validator))
|
||||||
// TimeStamp: epochInterval / 2,
|
setTestMintCnt(dposContext, testEpoch, validator, atLeastMintCnt/2)
|
||||||
// DposContext: dposContext,
|
}
|
||||||
// statedb: stateDB,
|
for i := int(maxValidatorSize); i < int(maxValidatorSize) *2; i++ {
|
||||||
// }
|
candidate := common.StringToAddress("addr" + strconv.Itoa(i))
|
||||||
// validators = []common.Address{}
|
assert.Nil(t, dposContext.BecomeCandidate(candidate))
|
||||||
// for i := 0; i < maxValidatorSize; i++ {
|
}
|
||||||
// validator := common.StringToAddress("addr" + strconv.Itoa(i))
|
assert.Nil(t, dposContext.SetValidators(validators))
|
||||||
// validators = append(validators, validator)
|
assert.Nil(t, epochContext.kickoutValidator(testEpoch))
|
||||||
// assert.Nil(t, dposContext.BecomeCandidate(validator))
|
candidateMap = getCandidates(dposContext.CandidateTrie())
|
||||||
// setTestMintCnt(dposContext, testEpoch, validator, atLeastMintCnt/2-1)
|
assert.Equal(t, maxValidatorSize *2, len(candidateMap))
|
||||||
// }
|
|
||||||
// for i := maxValidatorSize; i < maxValidatorSize *2; i++ {
|
// epochTime is not complete, all validators didn't mint enough block at least
|
||||||
// candidate := common.StringToAddress("addr" + strconv.Itoa(i))
|
dposContext, err = types.NewLCPContext(db)
|
||||||
// assert.Nil(t, dposContext.BecomeCandidate(candidate))
|
assert.Nil(t, err)
|
||||||
// }
|
epochContext = &EpochContext{
|
||||||
// assert.Nil(t, dposContext.SetValidators(validators))
|
TimeStamp: epochInterval / 2,
|
||||||
// assert.Nil(t, epochContext.kickoutValidator(testEpoch))
|
Context: dposContext,
|
||||||
// candidateMap = getCandidates(dposContext.CandidateTrie())
|
statedb: stateDB,
|
||||||
// assert.Equal(t, maxValidatorSize, len(candidateMap))
|
}
|
||||||
//
|
validators = []common.Address{}
|
||||||
// dposContext, err = types.NewDposContext(db)
|
for i := 0; i < int(maxValidatorSize); i++ {
|
||||||
// assert.Nil(t, err)
|
validator := common.StringToAddress("addr" + strconv.Itoa(i))
|
||||||
// epochContext = &EpochContext{
|
validators = append(validators, validator)
|
||||||
// TimeStamp: epochInterval / 2,
|
assert.Nil(t, dposContext.BecomeCandidate(validator))
|
||||||
// DposContext: dposContext,
|
setTestMintCnt(dposContext, testEpoch, validator, atLeastMintCnt/2-1)
|
||||||
// statedb: stateDB,
|
}
|
||||||
// }
|
for i := int(maxValidatorSize); i < int(maxValidatorSize) *2; i++ {
|
||||||
// assert.NotNil(t, epochContext.kickoutValidator(testEpoch))
|
candidate := common.StringToAddress("addr" + strconv.Itoa(i))
|
||||||
// dposContext.SetValidators([]common.Address{})
|
assert.Nil(t, dposContext.BecomeCandidate(candidate))
|
||||||
// assert.NotNil(t, epochContext.kickoutValidator(testEpoch))
|
}
|
||||||
//}
|
assert.Nil(t, dposContext.SetValidators(validators))
|
||||||
//
|
assert.Nil(t, epochContext.kickoutValidator(testEpoch))
|
||||||
//func setTestMintCnt(dposContext *types.DposContext, epoch int64, validator common.Address, count int64) {
|
candidateMap = getCandidates(dposContext.CandidateTrie())
|
||||||
// for i := int64(0); i < count; i++ {
|
assert.Equal(t, maxValidatorSize, len(candidateMap))
|
||||||
// updateMintCnt(epoch*epochInterval, epoch*epochInterval+blockInterval, validator, dposContext)
|
|
||||||
// }
|
dposContext, err = types.NewLCPContext(db)
|
||||||
//}
|
assert.Nil(t, err)
|
||||||
//
|
epochContext = &EpochContext{
|
||||||
//func getCandidates(candidateTrie *trie.Trie) map[common.Address]bool {
|
TimeStamp: epochInterval / 2,
|
||||||
// candidateMap := map[common.Address]bool{}
|
Context: dposContext,
|
||||||
// iter := trie.NewIterator(candidateTrie.NodeIterator(nil))
|
statedb: stateDB,
|
||||||
// for iter.Next() {
|
}
|
||||||
// candidateMap[common.BytesToAddress(iter.Value)] = true
|
assert.NotNil(t, epochContext.kickoutValidator(testEpoch))
|
||||||
// }
|
dposContext.SetValidators([]common.Address{})
|
||||||
// return candidateMap
|
assert.NotNil(t, epochContext.kickoutValidator(testEpoch))
|
||||||
//}
|
}
|
||||||
//
|
|
||||||
//func TestEpochContextTryElect(t *testing.T) {
|
func setTestMintCnt(dposContext *types.LCPContext, epoch int64, validator common.Address, count int64) {
|
||||||
// db, _ := ethdb.NewMemDatabase()
|
for i := int64(0); i < count; i++ {
|
||||||
// stateDB, _ := state.New(common.Hash{}, state.NewDatabase(db))
|
updateMintCnt(epoch*epochInterval, epoch*epochInterval+blockInterval, validator, dposContext)
|
||||||
// dposContext, err := types.NewDposContext(db)
|
}
|
||||||
// assert.Nil(t, err)
|
}
|
||||||
// epochContext := &EpochContext{
|
|
||||||
// TimeStamp: epochInterval,
|
func getCandidates(candidateTrie *trie.Trie) map[common.Address]bool {
|
||||||
// DposContext: dposContext,
|
candidateMap := map[common.Address]bool{}
|
||||||
// statedb: stateDB,
|
iter := trie.NewIterator(candidateTrie.NodeIterator(nil))
|
||||||
// }
|
for iter.Next() {
|
||||||
// atLeastMintCnt := epochInterval / blockInterval / maxValidatorSize / 2
|
candidateMap[common.BytesToAddress(iter.Value)] = true
|
||||||
// testEpoch := int64(1)
|
}
|
||||||
// validators := []common.Address{}
|
return candidateMap
|
||||||
// for i := 0; i < maxValidatorSize; i++ {
|
}
|
||||||
// validator := common.StringToAddress("addr" + strconv.Itoa(i))
|
|
||||||
// validators = append(validators, validator)
|
func TestEpochContextTryElect(t *testing.T) {
|
||||||
// assert.Nil(t, dposContext.BecomeCandidate(validator))
|
db := ethdb.NewMemDatabase()
|
||||||
// assert.Nil(t, dposContext.Delegate(validator, validator))
|
stateDB, _ := state.New(common.Hash{}, state.NewDatabase(db))
|
||||||
// stateDB.SetBalance(validator, big.NewInt(1))
|
dposContext, err := types.NewLCPContext(db)
|
||||||
// setTestMintCnt(dposContext, testEpoch, validator, atLeastMintCnt-1)
|
assert.Nil(t, err)
|
||||||
// }
|
epochContext := &EpochContext{
|
||||||
// dposContext.BecomeCandidate(common.StringToAddress("more"))
|
TimeStamp: epochInterval,
|
||||||
// assert.Nil(t, dposContext.SetValidators(validators))
|
Context: dposContext,
|
||||||
//
|
statedb: stateDB,
|
||||||
// // genesisEpoch == parentEpoch do not kickout
|
}
|
||||||
// genesis := &types.Header{
|
maxValidatorSize:= int(epochContext.Context.GetMaxValidators())
|
||||||
// Time: big.NewInt(0),
|
atLeastMintCnt := epochInterval / blockInterval / int64(maxValidatorSize) / 2
|
||||||
// }
|
testEpoch := int64(1)
|
||||||
// parent := &types.Header{
|
validators := []common.Address{}
|
||||||
// Time: big.NewInt(epochInterval - blockInterval),
|
for i := 0; i < maxValidatorSize; i++ {
|
||||||
// }
|
validator := common.StringToAddress("addr" + strconv.Itoa(i))
|
||||||
// oldHash := dposContext.EpochTrie().Hash()
|
validators = append(validators, validator)
|
||||||
// assert.Nil(t, epochContext.tryElect(genesis, parent))
|
assert.Nil(t, dposContext.BecomeCandidate(validator))
|
||||||
// result, err := dposContext.GetValidators()
|
assert.Nil(t, dposContext.Delegate(validator, validator))
|
||||||
// assert.Nil(t, err)
|
stateDB.SetBalance(validator, big.NewInt(1))
|
||||||
// assert.Equal(t, maxValidatorSize, len(result))
|
setTestMintCnt(dposContext, testEpoch, validator, atLeastMintCnt-1)
|
||||||
// for _, validator := range result {
|
}
|
||||||
// assert.True(t, strings.Contains(validator.Str(), "addr"))
|
dposContext.BecomeCandidate(common.StringToAddress("more"))
|
||||||
// }
|
assert.Nil(t, dposContext.SetValidators(validators))
|
||||||
// assert.NotEqual(t, oldHash, dposContext.EpochTrie().Hash())
|
|
||||||
//
|
// genesisEpoch == parentEpoch do not kickout
|
||||||
// // genesisEpoch != parentEpoch and have none mintCnt do not kickout
|
genesis := &types.Header{
|
||||||
// genesis = &types.Header{
|
Time: big.NewInt(0),
|
||||||
// Time: big.NewInt(-epochInterval),
|
}
|
||||||
// }
|
parent := &types.Header{
|
||||||
// parent = &types.Header{
|
Time: big.NewInt(epochInterval - blockInterval),
|
||||||
// Difficulty: big.NewInt(1),
|
}
|
||||||
// Time: big.NewInt(epochInterval - blockInterval),
|
oldHash := dposContext.EpochTrie().Hash()
|
||||||
// }
|
assert.Nil(t, epochContext.tryElect(genesis, parent))
|
||||||
// epochContext.TimeStamp = epochInterval
|
result, err := dposContext.GetValidators()
|
||||||
// oldHash = dposContext.EpochTrie().Hash()
|
assert.Nil(t, err)
|
||||||
// assert.Nil(t, epochContext.tryElect(genesis, parent))
|
assert.Equal(t, maxValidatorSize, len(result))
|
||||||
// result, err = dposContext.GetValidators()
|
for _, validator := range result {
|
||||||
// assert.Nil(t, err)
|
assert.True(t, strings.Contains(validator.Str(), "addr"))
|
||||||
// assert.Equal(t, maxValidatorSize, len(result))
|
}
|
||||||
// for _, validator := range result {
|
assert.NotEqual(t, oldHash, dposContext.EpochTrie().Hash())
|
||||||
// assert.True(t, strings.Contains(validator.Str(), "addr"))
|
|
||||||
// }
|
// genesisEpoch != parentEpoch and have none mintCnt do not kickout
|
||||||
// assert.NotEqual(t, oldHash, dposContext.EpochTrie().Hash())
|
genesis = &types.Header{
|
||||||
//
|
Time: big.NewInt(-epochInterval),
|
||||||
// // genesisEpoch != parentEpoch kickout
|
}
|
||||||
// genesis = &types.Header{
|
parent = &types.Header{
|
||||||
// Time: big.NewInt(0),
|
Difficulty: big.NewInt(1),
|
||||||
// }
|
Time: big.NewInt(epochInterval - blockInterval),
|
||||||
// parent = &types.Header{
|
}
|
||||||
// Time: big.NewInt(epochInterval*2 - blockInterval),
|
epochContext.TimeStamp = epochInterval
|
||||||
// }
|
oldHash = dposContext.EpochTrie().Hash()
|
||||||
// epochContext.TimeStamp = epochInterval * 2
|
assert.Nil(t, epochContext.tryElect(genesis, parent))
|
||||||
// oldHash = dposContext.EpochTrie().Hash()
|
result, err = dposContext.GetValidators()
|
||||||
// assert.Nil(t, epochContext.tryElect(genesis, parent))
|
assert.Nil(t, err)
|
||||||
// result, err = dposContext.GetValidators()
|
assert.Equal(t, maxValidatorSize, len(result))
|
||||||
// assert.Nil(t, err)
|
for _, validator := range result {
|
||||||
// assert.Equal(t, safeSize, len(result))
|
assert.True(t, strings.Contains(validator.Str(), "addr"))
|
||||||
// moreCnt := 0
|
}
|
||||||
// for _, validator := range result {
|
assert.NotEqual(t, oldHash, dposContext.EpochTrie().Hash())
|
||||||
// if strings.Contains(validator.Str(), "more") {
|
|
||||||
// moreCnt++
|
// genesisEpoch != parentEpoch kickout
|
||||||
// }
|
genesis = &types.Header{
|
||||||
// }
|
Time: big.NewInt(0),
|
||||||
// assert.Equal(t, 1, moreCnt)
|
}
|
||||||
// assert.NotEqual(t, oldHash, dposContext.EpochTrie().Hash())
|
parent = &types.Header{
|
||||||
//
|
Time: big.NewInt(epochInterval*2 - blockInterval),
|
||||||
// // parentEpoch == currentEpoch do not elect
|
}
|
||||||
// genesis = &types.Header{
|
epochContext.TimeStamp = epochInterval * 2
|
||||||
// Time: big.NewInt(0),
|
oldHash = dposContext.EpochTrie().Hash()
|
||||||
// }
|
assert.Nil(t, epochContext.tryElect(genesis, parent))
|
||||||
// parent = &types.Header{
|
result, err = dposContext.GetValidators()
|
||||||
// Time: big.NewInt(epochInterval),
|
assert.Nil(t, err)
|
||||||
// }
|
assert.Equal(t, safeSize, len(result))
|
||||||
// epochContext.TimeStamp = epochInterval + blockInterval
|
moreCnt := 0
|
||||||
// oldHash = dposContext.EpochTrie().Hash()
|
for _, validator := range result {
|
||||||
// assert.Nil(t, epochContext.tryElect(genesis, parent))
|
if strings.Contains(validator.Str(), "more") {
|
||||||
// result, err = dposContext.GetValidators()
|
moreCnt++
|
||||||
// assert.Nil(t, err)
|
}
|
||||||
// assert.Equal(t, safeSize, len(result))
|
}
|
||||||
// assert.Equal(t, oldHash, dposContext.EpochTrie().Hash())
|
assert.Equal(t, 1, moreCnt)
|
||||||
//}
|
assert.NotEqual(t, oldHash, dposContext.EpochTrie().Hash())
|
||||||
|
|
||||||
|
// parentEpoch == currentEpoch do not elect
|
||||||
|
genesis = &types.Header{
|
||||||
|
Time: big.NewInt(0),
|
||||||
|
}
|
||||||
|
parent = &types.Header{
|
||||||
|
Time: big.NewInt(epochInterval),
|
||||||
|
}
|
||||||
|
epochContext.TimeStamp = epochInterval + blockInterval
|
||||||
|
oldHash = dposContext.EpochTrie().Hash()
|
||||||
|
assert.Nil(t, epochContext.tryElect(genesis, parent))
|
||||||
|
result, err = dposContext.GetValidators()
|
||||||
|
assert.Nil(t, err)
|
||||||
|
assert.Equal(t, safeSize, len(result))
|
||||||
|
assert.Equal(t, oldHash, dposContext.EpochTrie().Hash())
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -52,6 +52,7 @@ func (ec *EpochContext) countVotes() (votes map[common.Address]*big.Int, err err
|
||||||
}
|
}
|
||||||
delegatorAddr := common.BytesToAddress(delegator)
|
delegatorAddr := common.BytesToAddress(delegator)
|
||||||
weight := statedb.GetBalance(delegatorAddr)
|
weight := statedb.GetBalance(delegatorAddr)
|
||||||
|
//fmt.Println(weight)
|
||||||
score.Add(score, weight)
|
score.Add(score, weight)
|
||||||
votes[candidateAddr] = score
|
votes[candidateAddr] = score
|
||||||
existDelegator = delegateIterator.Next()
|
existDelegator = delegateIterator.Next()
|
||||||
|
|
@ -132,11 +133,13 @@ func (ec *EpochContext) kickoutValidator(epoch int64) error {
|
||||||
|
|
||||||
func (ec *EpochContext) lookupValidator(now int64) (validator common.Address, err error) {
|
func (ec *EpochContext) lookupValidator(now int64) (validator common.Address, err error) {
|
||||||
validator = common.Address{}
|
validator = common.Address{}
|
||||||
offset := now % ec.Context.GetEpochInterval()
|
epoch_interval:=ec.Context.GetEpochInterval()
|
||||||
|
offset := now % epoch_interval
|
||||||
|
block_period:=ec.Context.GetPeriodBlock()
|
||||||
if offset%ec.Context.GetPeriodBlock() != 0 {
|
if offset%ec.Context.GetPeriodBlock() != 0 {
|
||||||
return common.Address{}, ErrInvalidMintBlockTime
|
return common.Address{}, ErrInvalidMintBlockTime
|
||||||
}
|
}
|
||||||
offset /= ec.Context.GetPeriodBlock()
|
offset /= block_period
|
||||||
|
|
||||||
validators, err := ec.Context.GetValidators()
|
validators, err := ec.Context.GetValidators()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
||||||
|
|
@ -86,7 +86,7 @@ func genValueTx(nbytes int) func(int, *BlockGen) {
|
||||||
toaddr := common.Address{}
|
toaddr := common.Address{}
|
||||||
data := make([]byte, nbytes)
|
data := make([]byte, nbytes)
|
||||||
gas, _ := IntrinsicGas(data, false, false)
|
gas, _ := IntrinsicGas(data, false, false)
|
||||||
tx, _ := types.SignTx(types.NewTransaction(gen.TxNonce(benchRootAddr), toaddr, big.NewInt(1), gas, nil, data), types.HomesteadSigner{}, benchRootKey)
|
tx, _ := types.SignTx(types.NewTransaction(0, gen.TxNonce(benchRootAddr), toaddr, big.NewInt(1), gas, nil, data), types.HomesteadSigner{}, benchRootKey)
|
||||||
gen.AddTx(tx)
|
gen.AddTx(tx)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -119,6 +119,7 @@ func genTxRing(naccounts int) func(int, *BlockGen) {
|
||||||
}
|
}
|
||||||
to := (from + 1) % naccounts
|
to := (from + 1) % naccounts
|
||||||
tx := types.NewTransaction(
|
tx := types.NewTransaction(
|
||||||
|
0,
|
||||||
gen.TxNonce(ringAddrs[from]),
|
gen.TxNonce(ringAddrs[from]),
|
||||||
ringAddrs[to],
|
ringAddrs[to],
|
||||||
benchRootFunds,
|
benchRootFunds,
|
||||||
|
|
|
||||||
|
|
@ -620,7 +620,7 @@ func TestFastVsFullChains(t *testing.T) {
|
||||||
// If the block number is multiple of 3, send a few bonus transactions to the miner
|
// If the block number is multiple of 3, send a few bonus transactions to the miner
|
||||||
if i%3 == 2 {
|
if i%3 == 2 {
|
||||||
for j := 0; j < i%4+1; j++ {
|
for j := 0; j < i%4+1; j++ {
|
||||||
tx, err := types.SignTx(types.NewTransaction(block.TxNonce(address), common.Address{0x00}, big.NewInt(1000), params.TxGas, nil, nil), signer, key)
|
tx, err := types.SignTx(types.NewTransaction(0, block.TxNonce(address), common.Address{0x00}, big.NewInt(1000), params.TxGas, nil, nil), signer, key)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
@ -793,8 +793,8 @@ func TestChainTxReorgs(t *testing.T) {
|
||||||
// Create two transactions shared between the chains:
|
// Create two transactions shared between the chains:
|
||||||
// - postponed: transaction included at a later block in the forked chain
|
// - postponed: transaction included at a later block in the forked chain
|
||||||
// - swapped: transaction included at the same block number in the forked chain
|
// - swapped: transaction included at the same block number in the forked chain
|
||||||
postponed, _ := types.SignTx(types.NewTransaction(0, addr1, big.NewInt(1000), params.TxGas, nil, nil), signer, key1)
|
postponed, _ := types.SignTx(types.NewTransaction(types.Binary,0, addr1, big.NewInt(1000), params.TxGas, nil, nil), signer, key1)
|
||||||
swapped, _ := types.SignTx(types.NewTransaction(1, addr1, big.NewInt(1000), params.TxGas, nil, nil), signer, key1)
|
swapped, _ := types.SignTx(types.NewTransaction(types.Binary, 1, addr1, big.NewInt(1000), params.TxGas, nil, nil), signer, key1)
|
||||||
|
|
||||||
// Create two transactions that will be dropped by the forked chain:
|
// Create two transactions that will be dropped by the forked chain:
|
||||||
// - pastDrop: transaction dropped retroactively from a past block
|
// - pastDrop: transaction dropped retroactively from a past block
|
||||||
|
|
@ -810,13 +810,13 @@ func TestChainTxReorgs(t *testing.T) {
|
||||||
chain, _ := GenerateChain(gspec.Config, genesis, ethash.NewFaker(), db, 3, func(i int, gen *BlockGen) {
|
chain, _ := GenerateChain(gspec.Config, genesis, ethash.NewFaker(), db, 3, func(i int, gen *BlockGen) {
|
||||||
switch i {
|
switch i {
|
||||||
case 0:
|
case 0:
|
||||||
pastDrop, _ = types.SignTx(types.NewTransaction(gen.TxNonce(addr2), addr2, big.NewInt(1000), params.TxGas, nil, nil), signer, key2)
|
pastDrop, _ = types.SignTx(types.NewTransaction(types.Binary, gen.TxNonce(addr2), addr2, big.NewInt(1000), params.TxGas, nil, nil), signer, key2)
|
||||||
|
|
||||||
gen.AddTx(pastDrop) // This transaction will be dropped in the fork from below the split point
|
gen.AddTx(pastDrop) // This transaction will be dropped in the fork from below the split point
|
||||||
gen.AddTx(postponed) // This transaction will be postponed till block #3 in the fork
|
gen.AddTx(postponed) // This transaction will be postponed till block #3 in the fork
|
||||||
|
|
||||||
case 2:
|
case 2:
|
||||||
freshDrop, _ = types.SignTx(types.NewTransaction(gen.TxNonce(addr2), addr2, big.NewInt(1000), params.TxGas, nil, nil), signer, key2)
|
freshDrop, _ = types.SignTx(types.NewTransaction(types.Binary, gen.TxNonce(addr2), addr2, big.NewInt(1000), params.TxGas, nil, nil), signer, key2)
|
||||||
|
|
||||||
gen.AddTx(freshDrop) // This transaction will be dropped in the fork from exactly at the split point
|
gen.AddTx(freshDrop) // This transaction will be dropped in the fork from exactly at the split point
|
||||||
gen.AddTx(swapped) // This transaction will be swapped out at the exact height
|
gen.AddTx(swapped) // This transaction will be swapped out at the exact height
|
||||||
|
|
@ -835,18 +835,18 @@ func TestChainTxReorgs(t *testing.T) {
|
||||||
chain, _ = GenerateChain(gspec.Config, genesis, ethash.NewFaker(), db, 5, func(i int, gen *BlockGen) {
|
chain, _ = GenerateChain(gspec.Config, genesis, ethash.NewFaker(), db, 5, func(i int, gen *BlockGen) {
|
||||||
switch i {
|
switch i {
|
||||||
case 0:
|
case 0:
|
||||||
pastAdd, _ = types.SignTx(types.NewTransaction(gen.TxNonce(addr3), addr3, big.NewInt(1000), params.TxGas, nil, nil), signer, key3)
|
pastAdd, _ = types.SignTx(types.NewTransaction(types.Binary,gen.TxNonce(addr3), addr3, big.NewInt(1000), params.TxGas, nil, nil), signer, key3)
|
||||||
gen.AddTx(pastAdd) // This transaction needs to be injected during reorg
|
gen.AddTx(pastAdd) // This transaction needs to be injected during reorg
|
||||||
|
|
||||||
case 2:
|
case 2:
|
||||||
gen.AddTx(postponed) // This transaction was postponed from block #1 in the original chain
|
gen.AddTx(postponed) // This transaction was postponed from block #1 in the original chain
|
||||||
gen.AddTx(swapped) // This transaction was swapped from the exact current spot in the original chain
|
gen.AddTx(swapped) // This transaction was swapped from the exact current spot in the original chain
|
||||||
|
|
||||||
freshAdd, _ = types.SignTx(types.NewTransaction(gen.TxNonce(addr3), addr3, big.NewInt(1000), params.TxGas, nil, nil), signer, key3)
|
freshAdd, _ = types.SignTx(types.NewTransaction(types.Binary,gen.TxNonce(addr3), addr3, big.NewInt(1000), params.TxGas, nil, nil), signer, key3)
|
||||||
gen.AddTx(freshAdd) // This transaction will be added exactly at reorg time
|
gen.AddTx(freshAdd) // This transaction will be added exactly at reorg time
|
||||||
|
|
||||||
case 3:
|
case 3:
|
||||||
futureAdd, _ = types.SignTx(types.NewTransaction(gen.TxNonce(addr3), addr3, big.NewInt(1000), params.TxGas, nil, nil), signer, key3)
|
futureAdd, _ = types.SignTx(types.NewTransaction(types.Binary, gen.TxNonce(addr3), addr3, big.NewInt(1000), params.TxGas, nil, nil), signer, key3)
|
||||||
gen.AddTx(futureAdd) // This transaction will be added after a full reorg
|
gen.AddTx(futureAdd) // This transaction will be added after a full reorg
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
@ -903,7 +903,7 @@ func TestLogReorgs(t *testing.T) {
|
||||||
blockchain.SubscribeRemovedLogsEvent(rmLogsCh)
|
blockchain.SubscribeRemovedLogsEvent(rmLogsCh)
|
||||||
chain, _ := GenerateChain(params.TestChainConfig, genesis, ethash.NewFaker(), db, 2, func(i int, gen *BlockGen) {
|
chain, _ := GenerateChain(params.TestChainConfig, genesis, ethash.NewFaker(), db, 2, func(i int, gen *BlockGen) {
|
||||||
if i == 1 {
|
if i == 1 {
|
||||||
tx, err := types.SignTx(types.NewContractCreation(gen.TxNonce(addr1), new(big.Int), 1000000, new(big.Int), code), signer, key1)
|
tx, err := types.SignTx(types.NewContractCreation(types.Binary, gen.TxNonce(addr1), new(big.Int), 1000000, new(big.Int), code), signer, key1)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed to create tx: %v", err)
|
t.Fatalf("failed to create tx: %v", err)
|
||||||
}
|
}
|
||||||
|
|
@ -952,7 +952,7 @@ func TestReorgSideEvent(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
replacementBlocks, _ := GenerateChain(gspec.Config, genesis, ethash.NewFaker(), db, 4, func(i int, gen *BlockGen) {
|
replacementBlocks, _ := GenerateChain(gspec.Config, genesis, ethash.NewFaker(), db, 4, func(i int, gen *BlockGen) {
|
||||||
tx, err := types.SignTx(types.NewContractCreation(gen.TxNonce(addr1), new(big.Int), 1000000, new(big.Int), nil), signer, key1)
|
tx, err := types.SignTx(types.NewContractCreation(types.Binary, gen.TxNonce(addr1), new(big.Int), 1000000, new(big.Int), nil), signer, key1)
|
||||||
if i == 2 {
|
if i == 2 {
|
||||||
gen.OffsetTime(-9)
|
gen.OffsetTime(-9)
|
||||||
}
|
}
|
||||||
|
|
@ -1080,7 +1080,7 @@ func TestEIP155Transition(t *testing.T) {
|
||||||
tx *types.Transaction
|
tx *types.Transaction
|
||||||
err error
|
err error
|
||||||
basicTx = func(signer types.Signer) (*types.Transaction, error) {
|
basicTx = func(signer types.Signer) (*types.Transaction, error) {
|
||||||
return types.SignTx(types.NewTransaction(block.TxNonce(address), common.Address{}, new(big.Int), 21000, new(big.Int), nil), signer, key)
|
return types.SignTx(types.NewTransaction(types.Binary, block.TxNonce(address), common.Address{}, new(big.Int), 21000, new(big.Int), nil), signer, key)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
switch i {
|
switch i {
|
||||||
|
|
@ -1143,7 +1143,7 @@ func TestEIP155Transition(t *testing.T) {
|
||||||
tx *types.Transaction
|
tx *types.Transaction
|
||||||
err error
|
err error
|
||||||
basicTx = func(signer types.Signer) (*types.Transaction, error) {
|
basicTx = func(signer types.Signer) (*types.Transaction, error) {
|
||||||
return types.SignTx(types.NewTransaction(block.TxNonce(address), common.Address{}, new(big.Int), 21000, new(big.Int), nil), signer, key)
|
return types.SignTx(types.NewTransaction(types.Binary, block.TxNonce(address), common.Address{}, new(big.Int), 21000, new(big.Int), nil), signer, key)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
if i == 0 {
|
if i == 0 {
|
||||||
|
|
@ -1190,11 +1190,11 @@ func TestEIP161AccountRemoval(t *testing.T) {
|
||||||
)
|
)
|
||||||
switch i {
|
switch i {
|
||||||
case 0:
|
case 0:
|
||||||
tx, err = types.SignTx(types.NewTransaction(block.TxNonce(address), theAddr, new(big.Int), 21000, new(big.Int), nil), signer, key)
|
tx, err = types.SignTx(types.NewTransaction(types.Binary, block.TxNonce(address), theAddr, new(big.Int), 21000, new(big.Int), nil), signer, key)
|
||||||
case 1:
|
case 1:
|
||||||
tx, err = types.SignTx(types.NewTransaction(block.TxNonce(address), theAddr, new(big.Int), 21000, new(big.Int), nil), signer, key)
|
tx, err = types.SignTx(types.NewTransaction(types.Binary, block.TxNonce(address), theAddr, new(big.Int), 21000, new(big.Int), nil), signer, key)
|
||||||
case 2:
|
case 2:
|
||||||
tx, err = types.SignTx(types.NewTransaction(block.TxNonce(address), theAddr, new(big.Int), 21000, new(big.Int), nil), signer, key)
|
tx, err = types.SignTx(types.NewTransaction(types.Binary, block.TxNonce(address), theAddr, new(big.Int), 21000, new(big.Int), nil), signer, key)
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
|
|
@ -1403,7 +1403,7 @@ func benchmarkLargeNumberOfValueToNonexisting(b *testing.B, numTxs, numBlocks in
|
||||||
uniq := uint64(i*numTxs + txi)
|
uniq := uint64(i*numTxs + txi)
|
||||||
recipient := recipientFn(uniq)
|
recipient := recipientFn(uniq)
|
||||||
//recipient := common.BigToAddress(big.NewInt(0).SetUint64(1337 + uniq))
|
//recipient := common.BigToAddress(big.NewInt(0).SetUint64(1337 + uniq))
|
||||||
tx, err := types.SignTx(types.NewTransaction(uniq, recipient, big.NewInt(1), params.TxGas, big.NewInt(1), nil), signer, testBankKey)
|
tx, err := types.SignTx(types.NewTransaction(types.Binary,uniq, recipient, big.NewInt(1), params.TxGas, big.NewInt(1), nil), signer, testBankKey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
b.Error(err)
|
b.Error(err)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -92,7 +92,7 @@ func (b *BlockGen) AddTxWithChain(bc *BlockChain, tx *types.Transaction) {
|
||||||
b.SetCoinbase(common.Address{})
|
b.SetCoinbase(common.Address{})
|
||||||
}
|
}
|
||||||
b.statedb.Prepare(tx.Hash(), common.Hash{}, len(b.txs))
|
b.statedb.Prepare(tx.Hash(), common.Hash{}, len(b.txs))
|
||||||
receipt, _, err := ApplyTransaction(b.config, bc, &b.header.Coinbase, b.gasPool, b.statedb, b.header, tx, &b.header.GasUsed, vm.Config{})
|
receipt, _, err := ApplyTransaction(b.config,nil, bc, &b.header.Coinbase, b.gasPool, b.statedb, b.header, tx, &b.header.GasUsed, vm.Config{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -54,13 +54,13 @@ func ExampleGenerateChain() {
|
||||||
switch i {
|
switch i {
|
||||||
case 0:
|
case 0:
|
||||||
// In block 1, addr1 sends addr2 some ether.
|
// In block 1, addr1 sends addr2 some ether.
|
||||||
tx, _ := types.SignTx(types.NewTransaction(gen.TxNonce(addr1), addr2, big.NewInt(10000), params.TxGas, nil, nil), signer, key1)
|
tx, _ := types.SignTx(types.NewTransaction(types.Binary, gen.TxNonce(addr1), addr2, big.NewInt(10000), params.TxGas, nil, nil), signer, key1)
|
||||||
gen.AddTx(tx)
|
gen.AddTx(tx)
|
||||||
case 1:
|
case 1:
|
||||||
// In block 2, addr1 sends some more ether to addr2.
|
// In block 2, addr1 sends some more ether to addr2.
|
||||||
// addr2 passes it on to addr3.
|
// addr2 passes it on to addr3.
|
||||||
tx1, _ := types.SignTx(types.NewTransaction(gen.TxNonce(addr1), addr2, big.NewInt(1000), params.TxGas, nil, nil), signer, key1)
|
tx1, _ := types.SignTx(types.NewTransaction(types.Binary, gen.TxNonce(addr1), addr2, big.NewInt(1000), params.TxGas, nil, nil), signer, key1)
|
||||||
tx2, _ := types.SignTx(types.NewTransaction(gen.TxNonce(addr2), addr3, big.NewInt(1000), params.TxGas, nil, nil), signer, key2)
|
tx2, _ := types.SignTx(types.NewTransaction(types.Binary, gen.TxNonce(addr2), addr3, big.NewInt(1000), params.TxGas, nil, nil), signer, key2)
|
||||||
gen.AddTx(tx1)
|
gen.AddTx(tx1)
|
||||||
gen.AddTx(tx2)
|
gen.AddTx(tx2)
|
||||||
case 2:
|
case 2:
|
||||||
|
|
|
||||||
|
|
@ -24,26 +24,51 @@ import (
|
||||||
"github.com/davecgh/go-spew/spew"
|
"github.com/davecgh/go-spew/spew"
|
||||||
"github.com/pavelkrolevets/go-ethereum/common"
|
"github.com/pavelkrolevets/go-ethereum/common"
|
||||||
"github.com/pavelkrolevets/go-ethereum/consensus/ethash"
|
"github.com/pavelkrolevets/go-ethereum/consensus/ethash"
|
||||||
"github.com/pavelkrolevets/go-ethereum/core/rawdb"
|
|
||||||
"github.com/pavelkrolevets/go-ethereum/core/vm"
|
"github.com/pavelkrolevets/go-ethereum/core/vm"
|
||||||
"github.com/pavelkrolevets/go-ethereum/ethdb"
|
"github.com/pavelkrolevets/go-ethereum/ethdb"
|
||||||
"github.com/pavelkrolevets/go-ethereum/params"
|
"github.com/pavelkrolevets/go-ethereum/params"
|
||||||
|
"github.com/pavelkrolevets/go-ethereum/core/types"
|
||||||
|
"github.com/pavelkrolevets/go-ethereum/core/state"
|
||||||
)
|
)
|
||||||
|
|
||||||
//func TestDefaultGenesisBlock(t *testing.T) {
|
type bproc struct{}
|
||||||
// block := DefaultGenesisBlock().ToBlock(nil)
|
|
||||||
// if block.Hash() != params.MainnetGenesisHash {
|
func (bproc) ValidateBody(*types.Block) error { return nil }
|
||||||
// t.Errorf("wrong mainnet genesis hash, got %v, want %v", block.Hash(), params.MainnetGenesisHash)
|
func (bproc) ValidateState(block, parent *types.Block, state *state.StateDB, receipts types.Receipts, usedGas *big.Int) error {
|
||||||
// }
|
return nil
|
||||||
// block = DefaultTestnetGenesisBlock().ToBlock(nil)
|
}
|
||||||
// if block.Hash() != params.TestnetGenesisHash {
|
func (bproc) Process(block *types.Block, statedb *state.StateDB, cfg vm.Config) (types.Receipts, []*types.Log, *big.Int, error) {
|
||||||
// t.Errorf("wrong testnet genesis hash, got %v, want %v", block.Hash(), params.TestnetGenesisHash)
|
return nil, nil, new(big.Int), nil
|
||||||
// }
|
}
|
||||||
//}
|
|
||||||
|
func (bproc) ValidateDposState(block *types.Block) error { return nil }
|
||||||
|
|
||||||
|
func makeBlockChainWithDiff(genesis *types.Block, d []int, seed byte) []*types.Block {
|
||||||
|
var chain []*types.Block
|
||||||
|
for i, difficulty := range d {
|
||||||
|
header := &types.Header{
|
||||||
|
Coinbase: common.Address{seed},
|
||||||
|
Number: big.NewInt(int64(i + 1)),
|
||||||
|
Difficulty: big.NewInt(int64(difficulty)),
|
||||||
|
UncleHash: types.EmptyUncleHash,
|
||||||
|
TxHash: types.EmptyRootHash,
|
||||||
|
ReceiptHash: types.EmptyRootHash,
|
||||||
|
Time: big.NewInt(int64(i) + 1),
|
||||||
|
}
|
||||||
|
if i == 0 {
|
||||||
|
header.ParentHash = genesis.Hash()
|
||||||
|
} else {
|
||||||
|
header.ParentHash = chain[i-1].Hash()
|
||||||
|
}
|
||||||
|
block := types.NewBlockWithHeader(header)
|
||||||
|
chain = append(chain, block)
|
||||||
|
}
|
||||||
|
return chain
|
||||||
|
}
|
||||||
|
|
||||||
func TestSetupGenesis(t *testing.T) {
|
func TestSetupGenesis(t *testing.T) {
|
||||||
var (
|
var (
|
||||||
customghash = common.HexToHash("0x89c99d90b79719238d2645c7642f2c9295246e80775b38cfd162b696817fbd50")
|
customghash = common.HexToHash("0xa4813c30e66d854572733941743e6736f20c0487d32c6b2fe1233946b036f6f5")
|
||||||
customg = Genesis{
|
customg = Genesis{
|
||||||
Config: ¶ms.ChainConfig{HomesteadBlock: big.NewInt(3)},
|
Config: ¶ms.ChainConfig{HomesteadBlock: big.NewInt(3)},
|
||||||
Alloc: GenesisAlloc{
|
Alloc: GenesisAlloc{
|
||||||
|
|
@ -60,31 +85,6 @@ func TestSetupGenesis(t *testing.T) {
|
||||||
wantHash common.Hash
|
wantHash common.Hash
|
||||||
wantErr error
|
wantErr error
|
||||||
}{
|
}{
|
||||||
{
|
|
||||||
name: "genesis without ChainConfig",
|
|
||||||
fn: func(db ethdb.Database) (*params.ChainConfig, common.Hash, error) {
|
|
||||||
return SetupGenesisBlock(db, new(Genesis))
|
|
||||||
},
|
|
||||||
wantErr: errGenesisNoConfig,
|
|
||||||
wantConfig: params.LcpChainConfig,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "no block in DB, genesis == nil",
|
|
||||||
fn: func(db ethdb.Database) (*params.ChainConfig, common.Hash, error) {
|
|
||||||
return SetupGenesisBlock(db, nil)
|
|
||||||
},
|
|
||||||
wantHash: params.MainnetGenesisHash,
|
|
||||||
wantConfig: params.LcpChainConfig,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "mainnet block in DB, genesis == nil",
|
|
||||||
fn: func(db ethdb.Database) (*params.ChainConfig, common.Hash, error) {
|
|
||||||
DefaultGenesisBlock().MustCommit(db)
|
|
||||||
return SetupGenesisBlock(db, nil)
|
|
||||||
},
|
|
||||||
wantHash: params.MainnetGenesisHash,
|
|
||||||
wantConfig: params.LcpChainConfig,
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
name: "custom block in DB, genesis == nil",
|
name: "custom block in DB, genesis == nil",
|
||||||
fn: func(db ethdb.Database) (*params.ChainConfig, common.Hash, error) {
|
fn: func(db ethdb.Database) (*params.ChainConfig, common.Hash, error) {
|
||||||
|
|
@ -94,16 +94,6 @@ func TestSetupGenesis(t *testing.T) {
|
||||||
wantHash: customghash,
|
wantHash: customghash,
|
||||||
wantConfig: customg.Config,
|
wantConfig: customg.Config,
|
||||||
},
|
},
|
||||||
{
|
|
||||||
name: "custom block in DB, genesis == testnet",
|
|
||||||
fn: func(db ethdb.Database) (*params.ChainConfig, common.Hash, error) {
|
|
||||||
customg.MustCommit(db)
|
|
||||||
return SetupGenesisBlock(db, DefaultTestnetGenesisBlock())
|
|
||||||
},
|
|
||||||
wantErr: &GenesisMismatchError{Stored: customghash, New: params.TestnetGenesisHash},
|
|
||||||
wantHash: params.TestnetGenesisHash,
|
|
||||||
wantConfig: params.TestnetChainConfig,
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
name: "compatible config in DB",
|
name: "compatible config in DB",
|
||||||
fn: func(db ethdb.Database) (*params.ChainConfig, common.Hash, error) {
|
fn: func(db ethdb.Database) (*params.ChainConfig, common.Hash, error) {
|
||||||
|
|
@ -119,12 +109,10 @@ func TestSetupGenesis(t *testing.T) {
|
||||||
// Commit the 'old' genesis block with Homestead transition at #2.
|
// Commit the 'old' genesis block with Homestead transition at #2.
|
||||||
// Advance to block #4, past the homestead transition block of customg.
|
// Advance to block #4, past the homestead transition block of customg.
|
||||||
genesis := oldcustomg.MustCommit(db)
|
genesis := oldcustomg.MustCommit(db)
|
||||||
|
|
||||||
bc, _ := NewBlockChain(db,nil, oldcustomg.Config, ethash.NewFullFaker(), vm.Config{})
|
bc, _ := NewBlockChain(db,nil, oldcustomg.Config, ethash.NewFullFaker(), vm.Config{})
|
||||||
defer bc.Stop()
|
defer bc.Stop()
|
||||||
|
bc.SetValidator(bproc{})
|
||||||
blocks, _ := GenerateChain(oldcustomg.Config, genesis, ethash.NewFaker(), db, 4, nil)
|
bc.InsertChain(makeBlockChainWithDiff(genesis, []int{2, 3, 4, 5}, 0))
|
||||||
bc.InsertChain(blocks)
|
|
||||||
bc.CurrentBlock()
|
bc.CurrentBlock()
|
||||||
// This should return a compatibility error.
|
// This should return a compatibility error.
|
||||||
return SetupGenesisBlock(db, &customg)
|
return SetupGenesisBlock(db, &customg)
|
||||||
|
|
@ -155,7 +143,7 @@ func TestSetupGenesis(t *testing.T) {
|
||||||
t.Errorf("%s: returned hash %s, want %s", test.name, hash.Hex(), test.wantHash.Hex())
|
t.Errorf("%s: returned hash %s, want %s", test.name, hash.Hex(), test.wantHash.Hex())
|
||||||
} else if err == nil {
|
} else if err == nil {
|
||||||
// Check database content.
|
// Check database content.
|
||||||
stored := rawdb.ReadBlock(db, test.wantHash, 0)
|
stored := GetBlock(db, test.wantHash, 0)
|
||||||
if stored.Hash() != test.wantHash {
|
if stored.Hash() != test.wantHash {
|
||||||
t.Errorf("%s: block in DB has hash %s, want %s", test.name, stored.Hash(), test.wantHash)
|
t.Errorf("%s: block in DB has hash %s, want %s", test.name, stored.Hash(), test.wantHash)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -68,7 +68,7 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg
|
||||||
// Iterate over and process the individual transactions
|
// Iterate over and process the individual transactions
|
||||||
for i, tx := range block.Transactions() {
|
for i, tx := range block.Transactions() {
|
||||||
statedb.Prepare(tx.Hash(), block.Hash(), i)
|
statedb.Prepare(tx.Hash(), block.Hash(), i)
|
||||||
receipt, _, err := ApplyTransaction(p.config, p.bc, nil, gp, statedb, header, tx, usedGas, cfg)
|
receipt, _, err := ApplyTransaction(p.config, nil, p.bc, nil, gp, statedb, header, tx, usedGas, cfg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, 0, err
|
return nil, nil, 0, err
|
||||||
}
|
}
|
||||||
|
|
@ -85,7 +85,7 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg
|
||||||
// and uses the input parameters for its environment. It returns the receipt
|
// and uses the input parameters for its environment. It returns the receipt
|
||||||
// for the transaction, gas used and an error if the transaction failed,
|
// for the transaction, gas used and an error if the transaction failed,
|
||||||
// indicating the block was invalid.
|
// indicating the block was invalid.
|
||||||
func ApplyTransaction(config *params.ChainConfig, bc ChainContext, author *common.Address, gp *GasPool, statedb *state.StateDB, header *types.Header, tx *types.Transaction, usedGas *uint64, cfg vm.Config) (*types.Receipt, uint64, error) {
|
func ApplyTransaction(config *params.ChainConfig, lcpContext *types.LCPContext, bc ChainContext, author *common.Address, gp *GasPool, statedb *state.StateDB, header *types.Header, tx *types.Transaction, usedGas *uint64, cfg vm.Config) (*types.Receipt, uint64, error) {
|
||||||
msg, err := tx.AsMessage(types.MakeSigner(config, header.Number))
|
msg, err := tx.AsMessage(types.MakeSigner(config, header.Number))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, 0, err
|
return nil, 0, err
|
||||||
|
|
@ -100,6 +100,11 @@ func ApplyTransaction(config *params.ChainConfig, bc ChainContext, author *commo
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, 0, err
|
return nil, 0, err
|
||||||
}
|
}
|
||||||
|
if msg.Type() != types.Binary {
|
||||||
|
if err = applyLcpMessage(lcpContext, msg); err != nil {
|
||||||
|
return nil, 0, err
|
||||||
|
}
|
||||||
|
}
|
||||||
// Update the state with pending changes
|
// Update the state with pending changes
|
||||||
var root []byte
|
var root []byte
|
||||||
if config.IsByzantium(header.Number) {
|
if config.IsByzantium(header.Number) {
|
||||||
|
|
@ -124,3 +129,19 @@ func ApplyTransaction(config *params.ChainConfig, bc ChainContext, author *commo
|
||||||
|
|
||||||
return receipt, gas, err
|
return receipt, gas, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func applyLcpMessage(lcpContext *types.LCPContext, msg types.Message) error {
|
||||||
|
switch msg.Type() {
|
||||||
|
case types.LoginCandidate:
|
||||||
|
lcpContext.BecomeCandidate(msg.From())
|
||||||
|
case types.LogoutCandidate:
|
||||||
|
lcpContext.KickoutCandidate(msg.From())
|
||||||
|
case types.Delegate:
|
||||||
|
lcpContext.Delegate(msg.From(), *(msg.To()))
|
||||||
|
case types.UnDelegate:
|
||||||
|
lcpContext.UnDelegate(msg.From(), *(msg.To()))
|
||||||
|
default:
|
||||||
|
return types.ErrInvalidType
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -338,7 +338,7 @@ func (b *Block) Body() *Body { return &Body{b.transactions, b.uncles} }
|
||||||
func (b *Block) HashNoNonce() common.Hash {
|
func (b *Block) HashNoNonce() common.Hash {
|
||||||
return b.header.HashNoNonce()
|
return b.header.HashNoNonce()
|
||||||
}
|
}
|
||||||
|
func (b *Block) LcpCtx() *LCPContext { return b.LCPContext }
|
||||||
// Size returns the true RLP encoded storage size of the block, either by encoding
|
// Size returns the true RLP encoded storage size of the block, either by encoding
|
||||||
// and returning it, or returning a previsouly cached value.
|
// and returning it, or returning a previsouly cached value.
|
||||||
func (b *Block) Size() common.StorageSize {
|
func (b *Block) Size() common.StorageSize {
|
||||||
|
|
|
||||||
|
|
@ -333,7 +333,10 @@ func (d *LCPContext) BecomeCandidate(candidateAddr common.Address) error {
|
||||||
candidate := candidateAddr.Bytes()
|
candidate := candidateAddr.Bytes()
|
||||||
return d.candidateTrie.TryUpdate(candidate, candidate)
|
return d.candidateTrie.TryUpdate(candidate, candidate)
|
||||||
}
|
}
|
||||||
|
func (d *LCPContext) BecomeDelegate(delegateAdr common.Address) error {
|
||||||
|
delegate := delegateAdr.Bytes()
|
||||||
|
return d.delegateTrie.TryUpdate(delegate, delegate)
|
||||||
|
}
|
||||||
func (d *LCPContext) Delegate(delegatorAddr, candidateAddr common.Address) error {
|
func (d *LCPContext) Delegate(delegatorAddr, candidateAddr common.Address) error {
|
||||||
delegator, candidate := delegatorAddr.Bytes(), candidateAddr.Bytes()
|
delegator, candidate := delegatorAddr.Bytes(), candidateAddr.Bytes()
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -27,14 +27,40 @@ import (
|
||||||
"github.com/pavelkrolevets/go-ethereum/common/hexutil"
|
"github.com/pavelkrolevets/go-ethereum/common/hexutil"
|
||||||
"github.com/pavelkrolevets/go-ethereum/crypto"
|
"github.com/pavelkrolevets/go-ethereum/crypto"
|
||||||
"github.com/pavelkrolevets/go-ethereum/rlp"
|
"github.com/pavelkrolevets/go-ethereum/rlp"
|
||||||
|
"fmt"
|
||||||
)
|
)
|
||||||
|
|
||||||
//go:generate gencodec -type txdata -field-override txdataMarshaling -out gen_tx_json.go
|
//go:generate gencodec -type txdata -field-override txdataMarshaling -out gen_tx_json.go
|
||||||
|
|
||||||
|
// transaction type
|
||||||
|
type TxType uint8
|
||||||
|
|
||||||
|
const (
|
||||||
|
Binary TxType = iota
|
||||||
|
LoginCandidate
|
||||||
|
LogoutCandidate
|
||||||
|
Delegate
|
||||||
|
UnDelegate
|
||||||
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
ErrInvalidSig = errors.New("invalid transaction v, r, s values")
|
ErrInvalidSig = errors.New("invalid transaction v, r, s values")
|
||||||
|
errNoSigner = errors.New("missing signing methods")
|
||||||
|
ErrInvalidType = errors.New("invalid transaction type")
|
||||||
|
ErrInvalidAddress = errors.New("invalid transaction payload address")
|
||||||
|
ErrInvalidAction = errors.New("invalid transaction payload action")
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// deriveSigner makes a *best* guess about which signer to use.
|
||||||
|
func deriveSigner(V *big.Int) Signer {
|
||||||
|
if V.Sign() != 0 && isProtectedV(V) {
|
||||||
|
return NewEIP155Signer(deriveChainId(V))
|
||||||
|
} else {
|
||||||
|
return HomesteadSigner{}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
type Transaction struct {
|
type Transaction struct {
|
||||||
data txdata
|
data txdata
|
||||||
// caches
|
// caches
|
||||||
|
|
@ -44,6 +70,7 @@ type Transaction struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
type txdata struct {
|
type txdata struct {
|
||||||
|
Type TxType `json:"type" gencodec:"required"`
|
||||||
AccountNonce uint64 `json:"nonce" gencodec:"required"`
|
AccountNonce uint64 `json:"nonce" gencodec:"required"`
|
||||||
Price *big.Int `json:"gasPrice" gencodec:"required"`
|
Price *big.Int `json:"gasPrice" gencodec:"required"`
|
||||||
GasLimit uint64 `json:"gas" gencodec:"required"`
|
GasLimit uint64 `json:"gas" gencodec:"required"`
|
||||||
|
|
@ -66,20 +93,25 @@ type txdataMarshaling struct {
|
||||||
GasLimit hexutil.Uint64
|
GasLimit hexutil.Uint64
|
||||||
Amount *hexutil.Big
|
Amount *hexutil.Big
|
||||||
Payload hexutil.Bytes
|
Payload hexutil.Bytes
|
||||||
|
Type TxType
|
||||||
V *hexutil.Big
|
V *hexutil.Big
|
||||||
R *hexutil.Big
|
R *hexutil.Big
|
||||||
S *hexutil.Big
|
S *hexutil.Big
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewTransaction(nonce uint64, to common.Address, amount *big.Int, gasLimit uint64, gasPrice *big.Int, data []byte) *Transaction {
|
func NewTransaction(txType TxType, nonce uint64, to common.Address, amount *big.Int, gasLimit uint64, gasPrice *big.Int, data []byte) *Transaction {
|
||||||
return newTransaction(nonce, &to, amount, gasLimit, gasPrice, data)
|
// compatible with raw transaction with to address is empty
|
||||||
|
if txType != Binary && (to == common.Address{}) {
|
||||||
|
return newTransaction(txType, nonce, nil, amount, gasLimit, gasPrice, data)
|
||||||
|
}
|
||||||
|
return newTransaction(txType, nonce, &to, amount, gasLimit, gasPrice, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewContractCreation(nonce uint64, amount *big.Int, gasLimit uint64, gasPrice *big.Int, data []byte) *Transaction {
|
func NewContractCreation(txType TxType, nonce uint64, amount *big.Int, gasLimit uint64, gasPrice *big.Int, data []byte) *Transaction {
|
||||||
return newTransaction(nonce, nil, amount, gasLimit, gasPrice, data)
|
return newTransaction(txType, nonce, nil, amount, gasLimit, gasPrice, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
func newTransaction(nonce uint64, to *common.Address, amount *big.Int, gasLimit uint64, gasPrice *big.Int, data []byte) *Transaction {
|
func newTransaction(txType TxType, nonce uint64, to *common.Address, amount *big.Int, gasLimit uint64, gasPrice *big.Int, data []byte) *Transaction {
|
||||||
if len(data) > 0 {
|
if len(data) > 0 {
|
||||||
data = common.CopyBytes(data)
|
data = common.CopyBytes(data)
|
||||||
}
|
}
|
||||||
|
|
@ -90,6 +122,7 @@ func newTransaction(nonce uint64, to *common.Address, amount *big.Int, gasLimit
|
||||||
Amount: new(big.Int),
|
Amount: new(big.Int),
|
||||||
GasLimit: gasLimit,
|
GasLimit: gasLimit,
|
||||||
Price: new(big.Int),
|
Price: new(big.Int),
|
||||||
|
Type: txType,
|
||||||
V: new(big.Int),
|
V: new(big.Int),
|
||||||
R: new(big.Int),
|
R: new(big.Int),
|
||||||
S: new(big.Int),
|
S: new(big.Int),
|
||||||
|
|
@ -109,6 +142,22 @@ func (tx *Transaction) ChainId() *big.Int {
|
||||||
return deriveChainId(tx.data.V)
|
return deriveChainId(tx.data.V)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Valid the transaction when the type isn't the binary
|
||||||
|
func (tx *Transaction) Validate() error {
|
||||||
|
if tx.Type() != Binary {
|
||||||
|
if tx.Value().Uint64() != 0 {
|
||||||
|
return errors.New("transaction value should be 0")
|
||||||
|
}
|
||||||
|
if tx.To() == nil && tx.Type() != LoginCandidate && tx.Type() != LogoutCandidate {
|
||||||
|
return errors.New("receipient was required")
|
||||||
|
}
|
||||||
|
if tx.Data() != nil {
|
||||||
|
return errors.New("payload should be empty")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// Protected returns whether the transaction is protected from replay protection.
|
// Protected returns whether the transaction is protected from replay protection.
|
||||||
func (tx *Transaction) Protected() bool {
|
func (tx *Transaction) Protected() bool {
|
||||||
return isProtectedV(tx.data.V)
|
return isProtectedV(tx.data.V)
|
||||||
|
|
@ -173,6 +222,7 @@ func (tx *Transaction) GasPrice() *big.Int { return new(big.Int).Set(tx.data.Pri
|
||||||
func (tx *Transaction) Value() *big.Int { return new(big.Int).Set(tx.data.Amount) }
|
func (tx *Transaction) Value() *big.Int { return new(big.Int).Set(tx.data.Amount) }
|
||||||
func (tx *Transaction) Nonce() uint64 { return tx.data.AccountNonce }
|
func (tx *Transaction) Nonce() uint64 { return tx.data.AccountNonce }
|
||||||
func (tx *Transaction) CheckNonce() bool { return true }
|
func (tx *Transaction) CheckNonce() bool { return true }
|
||||||
|
func (tx *Transaction) Type() TxType { return tx.data.Type }
|
||||||
|
|
||||||
// To returns the recipient address of the transaction.
|
// To returns the recipient address of the transaction.
|
||||||
// It returns nil if the transaction is a contract creation.
|
// It returns nil if the transaction is a contract creation.
|
||||||
|
|
@ -220,7 +270,9 @@ func (tx *Transaction) AsMessage(s Signer) (Message, error) {
|
||||||
to: tx.data.Recipient,
|
to: tx.data.Recipient,
|
||||||
amount: tx.data.Amount,
|
amount: tx.data.Amount,
|
||||||
data: tx.data.Payload,
|
data: tx.data.Payload,
|
||||||
|
txType: tx.data.Type,
|
||||||
checkNonce: true,
|
checkNonce: true,
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var err error
|
var err error
|
||||||
|
|
@ -251,6 +303,60 @@ func (tx *Transaction) RawSignatureValues() (*big.Int, *big.Int, *big.Int) {
|
||||||
return tx.data.V, tx.data.R, tx.data.S
|
return tx.data.V, tx.data.R, tx.data.S
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (tx *Transaction) String() string {
|
||||||
|
var from, to string
|
||||||
|
if tx.data.V != nil {
|
||||||
|
// make a best guess about the signer and use that to derive
|
||||||
|
// the sender.
|
||||||
|
signer := deriveSigner(tx.data.V)
|
||||||
|
if f, err := Sender(signer, tx); err != nil { // derive but don't cache
|
||||||
|
from = "[invalid sender: invalid sig]"
|
||||||
|
} else {
|
||||||
|
from = fmt.Sprintf("%x", f[:])
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
from = "[invalid sender: nil V field]"
|
||||||
|
}
|
||||||
|
|
||||||
|
if tx.data.Recipient == nil {
|
||||||
|
to = "[contract creation]"
|
||||||
|
} else {
|
||||||
|
to = fmt.Sprintf("%x", tx.data.Recipient[:])
|
||||||
|
}
|
||||||
|
enc, _ := rlp.EncodeToBytes(&tx.data)
|
||||||
|
return fmt.Sprintf(`
|
||||||
|
TX(%x)
|
||||||
|
Type: %d
|
||||||
|
Contract: %v
|
||||||
|
From: %s
|
||||||
|
To: %s
|
||||||
|
Nonce: %v
|
||||||
|
GasPrice: %#x
|
||||||
|
GasLimit %#x
|
||||||
|
Value: %#x
|
||||||
|
Data: 0x%x
|
||||||
|
V: %#x
|
||||||
|
R: %#x
|
||||||
|
S: %#x
|
||||||
|
Hex: %x
|
||||||
|
`,
|
||||||
|
tx.Hash(),
|
||||||
|
tx.Type(),
|
||||||
|
tx.data.Recipient == nil,
|
||||||
|
from,
|
||||||
|
to,
|
||||||
|
tx.data.AccountNonce,
|
||||||
|
tx.data.Price,
|
||||||
|
tx.data.GasLimit,
|
||||||
|
tx.data.Amount,
|
||||||
|
tx.data.Payload,
|
||||||
|
tx.data.V,
|
||||||
|
tx.data.R,
|
||||||
|
tx.data.S,
|
||||||
|
enc,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
// Transactions is a Transaction slice type for basic sorting.
|
// Transactions is a Transaction slice type for basic sorting.
|
||||||
type Transactions []*Transaction
|
type Transactions []*Transaction
|
||||||
|
|
||||||
|
|
@ -387,6 +493,7 @@ type Message struct {
|
||||||
gasPrice *big.Int
|
gasPrice *big.Int
|
||||||
data []byte
|
data []byte
|
||||||
checkNonce bool
|
checkNonce bool
|
||||||
|
txType TxType
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewMessage(from common.Address, to *common.Address, nonce uint64, amount *big.Int, gasLimit uint64, gasPrice *big.Int, data []byte, checkNonce bool) Message {
|
func NewMessage(from common.Address, to *common.Address, nonce uint64, amount *big.Int, gasLimit uint64, gasPrice *big.Int, data []byte, checkNonce bool) Message {
|
||||||
|
|
@ -399,6 +506,7 @@ func NewMessage(from common.Address, to *common.Address, nonce uint64, amount *b
|
||||||
gasPrice: gasPrice,
|
gasPrice: gasPrice,
|
||||||
data: data,
|
data: data,
|
||||||
checkNonce: checkNonce,
|
checkNonce: checkNonce,
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -410,3 +518,4 @@ func (m Message) Gas() uint64 { return m.gasLimit }
|
||||||
func (m Message) Nonce() uint64 { return m.nonce }
|
func (m Message) Nonce() uint64 { return m.nonce }
|
||||||
func (m Message) Data() []byte { return m.data }
|
func (m Message) Data() []byte { return m.data }
|
||||||
func (m Message) CheckNonce() bool { return m.checkNonce }
|
func (m Message) CheckNonce() bool { return m.checkNonce }
|
||||||
|
func (m Message) Type() TxType { return m.txType }
|
||||||
12
trie/trie.go
12
trie/trie.go
|
|
@ -142,6 +142,9 @@ func (t *Trie) PrefixIterator(prefix []byte) NodeIterator {
|
||||||
// NodeIterator returns an iterator that returns nodes of the trie. Iteration starts at
|
// NodeIterator returns an iterator that returns nodes of the trie. Iteration starts at
|
||||||
// the key after the given start key.
|
// the key after the given start key.
|
||||||
func (t *Trie) NodeIterator(start []byte) NodeIterator {
|
func (t *Trie) NodeIterator(start []byte) NodeIterator {
|
||||||
|
if t.prefix != nil {
|
||||||
|
start = append(t.prefix, start...)
|
||||||
|
}
|
||||||
return newNodeIterator(t, start)
|
return newNodeIterator(t, start)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -159,6 +162,9 @@ func (t *Trie) Get(key []byte) []byte {
|
||||||
// The value bytes must not be modified by the caller.
|
// The value bytes must not be modified by the caller.
|
||||||
// If a node was not found in the database, a MissingNodeError is returned.
|
// If a node was not found in the database, a MissingNodeError is returned.
|
||||||
func (t *Trie) TryGet(key []byte) ([]byte, error) {
|
func (t *Trie) TryGet(key []byte) ([]byte, error) {
|
||||||
|
if t.prefix != nil {
|
||||||
|
key = append(t.prefix, key...)
|
||||||
|
}
|
||||||
key = keybytesToHex(key)
|
key = keybytesToHex(key)
|
||||||
value, newroot, didResolve, err := t.tryGet(t.root, key, 0)
|
value, newroot, didResolve, err := t.tryGet(t.root, key, 0)
|
||||||
if err == nil && didResolve {
|
if err == nil && didResolve {
|
||||||
|
|
@ -226,6 +232,9 @@ func (t *Trie) Update(key, value []byte) {
|
||||||
//
|
//
|
||||||
// If a node was not found in the database, a MissingNodeError is returned.
|
// If a node was not found in the database, a MissingNodeError is returned.
|
||||||
func (t *Trie) TryUpdate(key, value []byte) error {
|
func (t *Trie) TryUpdate(key, value []byte) error {
|
||||||
|
if t.prefix != nil {
|
||||||
|
key = append(t.prefix, key...)
|
||||||
|
}
|
||||||
k := keybytesToHex(key)
|
k := keybytesToHex(key)
|
||||||
if len(value) != 0 {
|
if len(value) != 0 {
|
||||||
_, n, err := t.insert(t.root, nil, k, valueNode(value))
|
_, n, err := t.insert(t.root, nil, k, valueNode(value))
|
||||||
|
|
@ -322,6 +331,9 @@ func (t *Trie) Delete(key []byte) {
|
||||||
// TryDelete removes any existing value for key from the trie.
|
// TryDelete removes any existing value for key from the trie.
|
||||||
// If a node was not found in the database, a MissingNodeError is returned.
|
// If a node was not found in the database, a MissingNodeError is returned.
|
||||||
func (t *Trie) TryDelete(key []byte) error {
|
func (t *Trie) TryDelete(key []byte) error {
|
||||||
|
if t.prefix != nil {
|
||||||
|
key = append(t.prefix, key...)
|
||||||
|
}
|
||||||
k := keybytesToHex(key)
|
k := keybytesToHex(key)
|
||||||
_, n, err := t.delete(t.root, nil, k)
|
_, n, err := t.delete(t.root, nil, k)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue