-
Notifications
You must be signed in to change notification settings - Fork 142
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add StateUpdate payload #345
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -84,7 +84,7 @@ func NewChainStore(file string) (*ChainStore, error) { | |
}, nil | ||
} | ||
|
||
func (bd *ChainStore) InitLedgerStoreWithGenesisBlock(genesisBlock *Block, defaultBookKeeper []*crypto.PubKey) (uint32, error) { | ||
func (bd *ChainStore) InitLedgerStoreWithGenesisBlock(genesisBlock *Block, defaultBookKeeper []*crypto.PubKey, defaultStateUpdater []*crypto.PubKey) (uint32, error) { | ||
|
||
hash := genesisBlock.Hash() | ||
bd.headerIndex[0] = hash | ||
|
@@ -238,6 +238,24 @@ func (bd *ChainStore) InitLedgerStoreWithGenesisBlock(genesisBlock *Block, defau | |
bd.st.Put(bkListKey.Bytes(), bkListValue.Bytes()) | ||
/////////////////////////////////////////////////// | ||
|
||
/////////////////////////////////////////////////// | ||
// process defaultStateUpdater | ||
/////////////////////////////////////////////////// | ||
// StateUpdater key | ||
suKey := bytes.NewBuffer(nil) | ||
suKey.WriteByte(byte(CA_StateUpdater)) | ||
|
||
// StateUpdater value | ||
suValue := bytes.NewBuffer(nil) | ||
serialization.WriteVarUint(suValue, uint64(len(defaultStateUpdater))) | ||
for k := 0; k < len(defaultStateUpdater); k++ { | ||
defaultStateUpdater[k].Serialize(suValue) | ||
} | ||
|
||
// StateUpdater put value | ||
bd.st.Put(suKey.Bytes(), suValue.Bytes()) | ||
/////////////////////////////////////////////////// | ||
|
||
// persist genesis block | ||
bd.persist(genesisBlock) | ||
|
||
|
@@ -660,6 +678,35 @@ func (self *ChainStore) GetBookKeeperList() ([]*crypto.PubKey, []*crypto.PubKey, | |
return currBookKeeper, nextBookKeeper, nil | ||
} | ||
|
||
func (self *ChainStore) GetStateUpdater() ([]*crypto.PubKey, error) { | ||
prefix := []byte{byte(CA_StateUpdater)} | ||
suValue, err_get := self.st.Get(prefix) | ||
if err_get != nil { | ||
return nil, err_get | ||
} | ||
|
||
r := bytes.NewReader(suValue) | ||
|
||
// read length | ||
count, err := serialization.ReadVarUint(r, 0) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
var stateUpdater = make([]*crypto.PubKey, count) | ||
for i := uint64(0); i < count; i++ { | ||
bk := new(crypto.PubKey) | ||
err := bk.DeSerialize(r) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
stateUpdater[i] = bk | ||
} | ||
|
||
return stateUpdater, nil | ||
} | ||
|
||
func (bd *ChainStore) persist(b *Block) error { | ||
utxoUnspents := make(map[Uint160]map[Uint256][]*tx.UTXOUnspent) | ||
unspents := make(map[Uint256][]uint16) | ||
|
@@ -746,6 +793,7 @@ func (bd *ChainStore) persist(b *Block) error { | |
b.Transactions[i].TxType == tx.IssueAsset || | ||
b.Transactions[i].TxType == tx.TransferAsset || | ||
b.Transactions[i].TxType == tx.Record || | ||
b.Transactions[i].TxType == tx.StateUpdate || | ||
b.Transactions[i].TxType == tx.BookKeeper || | ||
b.Transactions[i].TxType == tx.PrivacyPayload || | ||
b.Transactions[i].TxType == tx.BookKeeping || | ||
|
@@ -774,6 +822,48 @@ func (bd *ChainStore) persist(b *Block) error { | |
} | ||
} | ||
|
||
if b.Transactions[i].TxType == tx.StateUpdate { | ||
su := b.Transactions[i].Payload.(*payload.StateUpdate) | ||
|
||
// stateKey | ||
statePrefix := []byte{byte(ST_STATES)} | ||
stateKey := append(statePrefix, su.Namespace...) | ||
stateKey = append(stateKey, su.Key...) | ||
//stateValueOld, err_get := bd.st.Get(stateKey) | ||
|
||
// stateValue | ||
//stateValue := bytes.NewBuffer(nil) | ||
//serialization.WriteVarBytes(stateValue, su.Value) | ||
|
||
// verify tx signer public is in StateUpdater list. | ||
//publicKey := b.Transactions[i].Programs[0].Parameter[1:34] | ||
log.Trace(fmt.Sprintf("StateUpdate tx publickey: %x", su.Updater)) | ||
|
||
stateUpdater, err := bd.GetStateUpdater() | ||
if err != nil { | ||
return err | ||
} | ||
|
||
findflag := false | ||
for k := 0; k < len(stateUpdater); k++ { | ||
log.Trace(fmt.Sprintf("StateUpdate updaterPublickey %d: %x %x", k, stateUpdater[k].X, stateUpdater[k].Y)) | ||
|
||
if su.Updater.X.Cmp(stateUpdater[k].X) == 0 && su.Updater.Y.Cmp(stateUpdater[k].Y) == 0 { | ||
findflag = true | ||
break | ||
} | ||
} | ||
|
||
if !findflag { | ||
return errors.New(fmt.Sprintf("[persist] stateUpdater publickey not found in store, reject. tx publickey: %x", su.Updater)) | ||
} | ||
|
||
// if not found in store, put value to the key. | ||
// if found in store, rewrite value. | ||
log.Trace(fmt.Sprintf("[persist] StateUpdate modify, key: %x, value:%x", stateKey, su.Value)) | ||
bd.st.BatchPut(stateKey, su.Value) | ||
} | ||
|
||
for index := 0; index < len(b.Transactions[i].Outputs); index++ { | ||
output := b.Transactions[i].Outputs[index] | ||
programHash := output.ProgramHash | ||
|
@@ -1291,6 +1381,45 @@ func (bd *ChainStore) GetAccount(programHash Uint160) (*account.AccountState, er | |
return accountState, nil | ||
} | ||
|
||
func (bd *ChainStore) IsStateUpdaterVaild(Tx *tx.Transaction) bool { | ||
su := Tx.Payload.(*payload.StateUpdate) | ||
|
||
stateUpdater, err := bd.GetStateUpdater() | ||
if err != nil { | ||
return false | ||
} | ||
|
||
findflag := false | ||
for k := 0; k < len(stateUpdater); k++ { | ||
log.Trace(fmt.Sprintf("StateUpdate updaterPublickey %d: %x %x", k, stateUpdater[k].X, stateUpdater[k].Y)) | ||
|
||
if su.Updater.X.Cmp(stateUpdater[k].X) == 0 && su.Updater.Y.Cmp(stateUpdater[k].Y) == 0 { | ||
findflag = true | ||
break | ||
} | ||
} | ||
|
||
if !findflag { | ||
return false | ||
} | ||
|
||
return true | ||
} | ||
|
||
func (bd *ChainStore) GetState(namespace []byte, key []byte) ([]byte, error) { | ||
|
||
// stateKey | ||
statePrefix := []byte{byte(ST_STATES)} | ||
stateKey := append(statePrefix, namespace...) | ||
stateKey = append(stateKey, key...) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this desgin may have problem since we can not figure out namespace and key from the stateKey. |
||
stateValue, err := bd.st.Get(stateKey) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
return stateValue, nil | ||
} | ||
|
||
func (bd *ChainStore) IsBlockInStore(hash Uint256) bool { | ||
|
||
var b *Block = new(Block) | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
package payload | ||
|
||
import ( | ||
"DNA/common/serialization" | ||
"DNA/crypto" | ||
. "DNA/errors" | ||
"errors" | ||
"io" | ||
) | ||
|
||
type StateUpdate struct { | ||
Namespace []byte | ||
Key []byte | ||
Value []byte | ||
Updater *crypto.PubKey | ||
} | ||
|
||
func (su *StateUpdate) Data() []byte { | ||
return []byte{0} | ||
} | ||
|
||
func (su *StateUpdate) Serialize(w io.Writer) error { | ||
err := serialization.WriteVarBytes(w, su.Namespace) | ||
if err != nil { | ||
return NewDetailErr(err, ErrNoCode, "[StateUpdate], Namespace serialize failed.") | ||
} | ||
|
||
err = serialization.WriteVarBytes(w, su.Key) | ||
if err != nil { | ||
return NewDetailErr(err, ErrNoCode, "[StateUpdate], key serialize failed.") | ||
} | ||
|
||
err = serialization.WriteVarBytes(w, su.Value) | ||
if err != nil { | ||
return NewDetailErr(err, ErrNoCode, "[StateUpdate], value serialize failed.") | ||
} | ||
|
||
su.Updater.Serialize(w) | ||
|
||
return nil | ||
} | ||
|
||
func (su *StateUpdate) Deserialize(r io.Reader) error { | ||
var err error | ||
|
||
su.Namespace, err = serialization.ReadVarBytes(r) | ||
if err != nil { | ||
return NewDetailErr(errors.New("[StateUpdate], Namespace deserialize failed."), ErrNoCode, "") | ||
} | ||
|
||
su.Key, err = serialization.ReadVarBytes(r) | ||
if err != nil { | ||
return NewDetailErr(errors.New("[StateUpdate], key deserialize failed."), ErrNoCode, "") | ||
} | ||
|
||
su.Value, err = serialization.ReadVarBytes(r) | ||
if err != nil { | ||
return NewDetailErr(errors.New("[StateUpdate], value deserialize failed."), ErrNoCode, "") | ||
} | ||
|
||
su.Updater = new(crypto.PubKey) | ||
err = su.Updater.DeSerialize(r) | ||
if err != nil { | ||
return NewDetailErr(err, ErrNoCode, "[StateUpdate], updater Deserialize failed.") | ||
} | ||
|
||
return nil | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
use Tracef, Debugf, Warnf... method instead. see #332 for more details.