Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
165 changes: 147 additions & 18 deletions lib/block/operation.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,14 @@ type BlockOperation struct {

Type operation.OperationType `json:"type"`
Source string `json:"source"`
Target string `json:"target"`
Body []byte `json:"body"`
Height uint64 `json:"block_height"`

// transaction will be used only for `Save` time.
// bellows will be used only for `Save` time.
transaction transaction.Transaction
operation operation.Operation
linked string
isSaved bool
}

Expand All @@ -47,6 +50,18 @@ func NewBlockOperationFromOperation(op operation.Operation, tx transaction.Trans
opHash := op.MakeHashString()
txHash := tx.GetHash()

target := ""
if pop, ok := op.B.(operation.Targetable); ok {
target = pop.TargetAddress()
}

linked := ""
if createAccount, ok := op.B.(*operation.CreateAccount); ok {
if createAccount.Linked != "" {
linked = createAccount.Linked
}
}

return BlockOperation{
Hash: NewBlockOperationKey(opHash, txHash),

Expand All @@ -55,13 +70,30 @@ func NewBlockOperationFromOperation(op operation.Operation, tx transaction.Trans

Type: op.H.Type,
Source: tx.B.Source,
Target: target,
Body: body,
Height: blockHeight,

transaction: tx,
operation: op,
linked: linked,
}, nil
}

func (bo *BlockOperation) hasTarget() bool {
if bo.Target != "" {
return true
}
return false
}

func (bo *BlockOperation) targetIsLinked() bool {
if bo.hasTarget() && bo.linked != "" {
return true
}
return false
}

func (bo *BlockOperation) Save(st *storage.LevelDBBackend) (err error) {
if bo.isSaved {
return errors.AlreadySaved
Expand All @@ -82,35 +114,44 @@ func (bo *BlockOperation) Save(st *storage.LevelDBBackend) (err error) {
if err = st.New(bo.NewBlockOperationTxHashKey(), bo.Hash); err != nil {
return
}

if err = st.New(bo.NewBlockOperationSourceKey(), bo.Hash); err != nil {
return
}

if err = st.New(bo.NewBlockOperationSourceAndTypeKey(), bo.Hash); err != nil {
return
}
if err = st.New(bo.NewBlockOperationPeersKey(bo.Source), bo.Hash); err != nil {
return
}
if err = st.New(bo.NewBlockOperationPeersAndTypeKey(bo.Source), bo.Hash); err != nil {
return
}
if err = st.New(bo.NewBlockOperationBlockHeightKey(), bo.Hash); err != nil {
return
}

var body operation.Body
var casted operation.CreateAccount
var ok bool
if bo.hasTarget() {
if err = st.New(bo.NewBlockOperationTargetKey(bo.Target), bo.Hash); err != nil {
return
}
if err = st.New(bo.NewBlockOperationTargetAndTypeKey(bo.Target), bo.Hash); err != nil {
return
}
if err = st.New(bo.NewBlockOperationPeersKey(bo.Target), bo.Hash); err != nil {
return
}
if err = st.New(bo.NewBlockOperationPeersAndTypeKey(bo.Target), bo.Hash); err != nil {
return
}
}

if bo.Type == operation.TypeCreateAccount {
if body, err = operation.UnmarshalBodyJSON(bo.Type, bo.Body); err != nil {
if bo.targetIsLinked() {
if err = st.New(GetBlockOperationCreateFrozenKey(bo.Target, bo.Height), bo.Hash); err != nil {
return err
}
if casted, ok = body.(operation.CreateAccount); !ok {
return errors.TypeOperationBodyNotMatched
}
if casted.Linked != "" {
if err = st.New(GetBlockOperationCreateFrozenKey(casted.Target, bo.Height), bo.Hash); err != nil {
return err
}
if err = st.New(bo.NewBlockOperationFrozenLinkedKey(casted.Linked), bo.Hash); err != nil {
return err
}
if err = st.New(bo.NewBlockOperationFrozenLinkedKey(bo.linked), bo.Hash); err != nil {
return err
}
}

Expand Down Expand Up @@ -154,13 +195,29 @@ func GetBlockOperationKeyPrefixSource(source string) string {
}

func GetBlockOperationKeyPrefixSourceAndType(source string, ty operation.OperationType) string {
return fmt.Sprintf("%s%s%s-", common.BlockOperationPrefixSource, source, string(ty))
return fmt.Sprintf("%s%s%s-", common.BlockOperationPrefixTypeSource, string(ty), source)
}

func GetBlockOperationKeyPrefixBlockHeight(height uint64) string {
return fmt.Sprintf("%s%s-", common.BlockOperationPrefixBlockHeight, common.EncodeUint64ToByteSlice(height))
}

func GetBlockOperationKeyPrefixTarget(target string) string {
return fmt.Sprintf("%s%s-", common.BlockOperationPrefixTarget, target)
}

func GetBlockOperationKeyPrefixTargetAndType(target string, ty operation.OperationType) string {
return fmt.Sprintf("%s%s%s-", common.BlockOperationPrefixTypeTarget, string(ty), target)
}

func GetBlockOperationKeyPrefixPeers(addr string) string {
return fmt.Sprintf("%s%s-", common.BlockOperationPrefixPeers, addr)
}

func GetBlockOperationKeyPrefixPeersAndType(addr string, ty operation.OperationType) string {
return fmt.Sprintf("%s%s%s-", common.BlockOperationPrefixTypePeers, string(ty), addr)
}

func (bo BlockOperation) NewBlockOperationTxHashKey() string {
return fmt.Sprintf(
"%s%s%s%s",
Expand Down Expand Up @@ -198,7 +255,45 @@ func (bo BlockOperation) NewBlockOperationSourceAndTypeKey() string {
common.GetUniqueIDFromUUID(),
)
}
func (bo BlockOperation) NewBlockOperationTargetKey(target string) string {
return fmt.Sprintf(
"%s%s%s%s",
GetBlockOperationKeyPrefixTarget(target),
common.EncodeUint64ToByteSlice(bo.Height),
common.EncodeUint64ToByteSlice(bo.transaction.B.SequenceID),
common.GetUniqueIDFromUUID(),
)
}

func (bo BlockOperation) NewBlockOperationTargetAndTypeKey(target string) string {
return fmt.Sprintf(
"%s%s%s%s",
GetBlockOperationKeyPrefixTargetAndType(target, bo.Type),
common.EncodeUint64ToByteSlice(bo.Height),
common.EncodeUint64ToByteSlice(bo.transaction.B.SequenceID),
common.GetUniqueIDFromUUID(),
)
}

func (bo BlockOperation) NewBlockOperationPeersKey(addr string) string {
return fmt.Sprintf(
"%s%s%s%s",
GetBlockOperationKeyPrefixPeers(addr),
common.EncodeUint64ToByteSlice(bo.Height),
common.EncodeUint64ToByteSlice(bo.transaction.B.SequenceID),
common.GetUniqueIDFromUUID(),
)
}

func (bo BlockOperation) NewBlockOperationPeersAndTypeKey(addr string) string {
return fmt.Sprintf(
"%s%s%s%s",
GetBlockOperationKeyPrefixPeersAndType(addr, bo.Type),
common.EncodeUint64ToByteSlice(bo.Height),
common.EncodeUint64ToByteSlice(bo.transaction.B.SequenceID),
common.GetUniqueIDFromUUID(),
)
}
func (bo BlockOperation) NewBlockOperationBlockHeightKey() string {
return fmt.Sprintf(
"%s%s%s",
Expand Down Expand Up @@ -294,6 +389,40 @@ func GetBlockOperationsBySourceAndType(st *storage.LevelDBBackend, source string
return LoadBlockOperationsInsideIterator(st, iterFunc, closeFunc)
}

func GetBlockOperationsByTarget(st *storage.LevelDBBackend, target string, options storage.ListOptions) (
func() (BlockOperation, bool, []byte),
func(),
) {
iterFunc, closeFunc := st.GetIterator(GetBlockOperationKeyPrefixTarget(target), options)

return LoadBlockOperationsInsideIterator(st, iterFunc, closeFunc)
}

func GetBlockOperationsByTargetAndType(st *storage.LevelDBBackend, target string, ty operation.OperationType, options storage.ListOptions) (
func() (BlockOperation, bool, []byte),
func(),
) {
iterFunc, closeFunc := st.GetIterator(GetBlockOperationKeyPrefixTargetAndType(target, ty), options)
return LoadBlockOperationsInsideIterator(st, iterFunc, closeFunc)
}

func GetBlockOperationsByPeers(st *storage.LevelDBBackend, addr string, options storage.ListOptions) (
func() (BlockOperation, bool, []byte),
func(),
) {
iterFunc, closeFunc := st.GetIterator(GetBlockOperationKeyPrefixPeers(addr), options)

return LoadBlockOperationsInsideIterator(st, iterFunc, closeFunc)
}

func GetBlockOperationsByPeersAndType(st *storage.LevelDBBackend, addr string, ty operation.OperationType, options storage.ListOptions) (
func() (BlockOperation, bool, []byte),
func(),
) {
iterFunc, closeFunc := st.GetIterator(GetBlockOperationKeyPrefixPeersAndType(addr, ty), options)
return LoadBlockOperationsInsideIterator(st, iterFunc, closeFunc)
}

func GetBlockOperationsByBlockHeight(st *storage.LevelDBBackend, height uint64, options storage.ListOptions) (
func() (BlockOperation, bool, []byte),
func(),
Expand Down
1 change: 1 addition & 0 deletions lib/client/response.go
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ type Operation struct {
} `json:"_links"`
Hash string `json:"hash"`
Source string `json:"source"`
Target string `json:"target"`
Type string `json:"type"`
Body interface{} `json:"body"`
}
Expand Down
9 changes: 6 additions & 3 deletions lib/common/prefix.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,12 @@ const (
BlockOperationPrefixSource = string(0x22)
BlockOperationPrefixTarget = string(0x23)
BlockOperationPrefixPeers = string(0x24)
BlockOperationPrefixCreateFrozen = string(0x25)
BlockOperationPrefixFrozenLinked = string(0x26)
BlockOperationPrefixBlockHeight = string(0x27)
BlockOperationPrefixTypeSource = string(0x25)
BlockOperationPrefixTypeTarget = string(0x26)
BlockOperationPrefixTypePeers = string(0x27)
BlockOperationPrefixCreateFrozen = string(0x28)
BlockOperationPrefixFrozenLinked = string(0x29)
BlockOperationPrefixBlockHeight = string(0x2A)
BlockAccountPrefixAddress = string(0x30)
BlockAccountPrefixCreated = string(0x31)
BlockAccountSequenceIDPrefix = string(0x32)
Expand Down
2 changes: 1 addition & 1 deletion lib/node/runner/api/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ func TriggerEvent(st *storage.LevelDBBackend, transactions []*transaction.Transa

opEvent += " " + observer.NewCondition(observer.ResourceOperation, observer.KeySource, source).Event()
opEvent += " " + observer.Conditions{observer.NewCondition(observer.ResourceOperation, observer.KeySource, source), observer.NewCondition(observer.ResourceOperation, observer.KeyType, string(op.H.Type))}.Event()
if pop, ok := op.B.(operation.Tagetable); ok {
if pop, ok := op.B.(operation.Targetable); ok {
target := pop.TargetAddress()
accountMap[target] = struct{}{}
txEvent += " " + observer.NewCondition(observer.ResourceTransaction, observer.KeyTarget, target).Event()
Expand Down
15 changes: 8 additions & 7 deletions lib/node/runner/api/base_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,8 @@ func prepareAPIServer() (*httptest.Server, *storage.LevelDBBackend) {
return ts, storage
}

func prepareOps(storage *storage.LevelDBBackend, count int) (*keypair.Full, []block.BlockOperation) {
kp, btList := prepareTxs(storage, count)
func prepareOps(storage *storage.LevelDBBackend, count int) (*keypair.Full, *keypair.Full, []block.BlockOperation) {
kp, kpTarget, btList := prepareTxs(storage, count)
var boList []block.BlockOperation
for _, bt := range btList {
bo, err := block.GetBlockOperation(storage, bt.Operations[0])
Expand All @@ -49,7 +49,7 @@ func prepareOps(storage *storage.LevelDBBackend, count int) (*keypair.Full, []bl
boList = append(boList, bo)
}

return kp, boList
return kp, kpTarget, boList
}
func prepareOpsWithoutSave(count int, st *storage.LevelDBBackend) (*keypair.Full, block.Block, []block.BlockOperation) {
kp := keypair.Random()
Expand Down Expand Up @@ -93,13 +93,14 @@ func prepareBlkTxOpWithoutSave(st *storage.LevelDBBackend) (*keypair.Full, block
return kp, theBlock, bt, bo
}

func prepareTxs(storage *storage.LevelDBBackend, count int) (*keypair.Full, []block.BlockTransaction) {
func prepareTxs(storage *storage.LevelDBBackend, count int) (*keypair.Full, *keypair.Full, []block.BlockTransaction) {
kp := keypair.Random()
kpTarget := keypair.Random()
var txs []transaction.Transaction
var txHashes []string
var btList []block.BlockTransaction
for i := 0; i < count; i++ {
tx := transaction.TestMakeTransactionWithKeypair(networkID, 1, kp)
tx := transaction.TestMakeTransactionWithKeypair(networkID, 1, kp, kpTarget)
txs = append(txs, tx)
txHashes = append(txHashes, tx.GetHash())
}
Expand All @@ -110,11 +111,11 @@ func prepareTxs(storage *storage.LevelDBBackend, count int) (*keypair.Full, []bl
bt := block.NewBlockTransactionFromTransaction(theBlock.Hash, theBlock.Height, theBlock.ProposedTime, tx)
bt.MustSave(storage)
if err := bt.SaveBlockOperations(storage); err != nil {
return nil, nil
return nil, nil, nil
}
btList = append(btList, bt)
}
return kp, btList
return kp, kpTarget, btList
}

func prepareTxsWithoutSave(count int, st *storage.LevelDBBackend) (*keypair.Full, []block.BlockTransaction) {
Expand Down
4 changes: 2 additions & 2 deletions lib/node/runner/api/operation.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,9 @@ func (api NetworkHandlerAPI) GetOperationsByAccountHandler(w http.ResponseWriter
var iterFunc func() (block.BlockOperation, bool, []byte)
var closeFunc func()
if len(oType) > 0 {
iterFunc, closeFunc = block.GetBlockOperationsBySourceAndType(api.storage, address, oType, options)
iterFunc, closeFunc = block.GetBlockOperationsByPeersAndType(api.storage, address, oType, options)
} else {
iterFunc, closeFunc = block.GetBlockOperationsBySource(api.storage, address, options)
iterFunc, closeFunc = block.GetBlockOperationsByPeers(api.storage, address, options)
}
for {
t, hasNext, c := iterFunc()
Expand Down
Loading